/src/vlc/src/video_output/window.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * window.c: generic window management |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2009 Laurent Aimar |
5 | | * Copyright © 2009-2021 Rémi Denis-Courmont |
6 | | * |
7 | | * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | /***************************************************************************** |
25 | | * Preamble |
26 | | *****************************************************************************/ |
27 | | #ifdef HAVE_CONFIG_H |
28 | | # include "config.h" |
29 | | #endif |
30 | | #include <assert.h> |
31 | | #include <stdio.h> |
32 | | #include <stdlib.h> |
33 | | |
34 | | #include <vlc_common.h> |
35 | | #include <vlc_window.h> |
36 | | #include <vlc_modules.h> |
37 | | #include "inhibit.h" |
38 | | #include "../libvlc.h" |
39 | | |
40 | | typedef struct |
41 | | { |
42 | | vlc_window_t wnd; |
43 | | vlc_window_cfg_t cfg; |
44 | | module_t *module; |
45 | | bool inhibit_windowed; |
46 | | |
47 | | /* Screensaver inhibition state (protected by lock) */ |
48 | | vlc_inhibit_t *inhibit; |
49 | | bool active; |
50 | | bool fullscreen; |
51 | | vlc_mutex_t lock; |
52 | | } window_t; |
53 | | |
54 | | static int vlc_window_start(void *func, bool forced, va_list ap) |
55 | 0 | { |
56 | 0 | int (*activate)(vlc_window_t *) = func; |
57 | 0 | vlc_window_t *wnd = va_arg(ap, vlc_window_t *); |
58 | |
|
59 | 0 | int ret = activate(wnd); |
60 | 0 | if (ret) |
61 | 0 | vlc_objres_clear(VLC_OBJECT(wnd)); |
62 | 0 | (void) forced; |
63 | 0 | return ret; |
64 | 0 | } |
65 | | |
66 | | vlc_window_t *vlc_window_New(vlc_object_t *obj, const char *module, |
67 | | const vlc_window_owner_t *owner, |
68 | | const vlc_window_cfg_t *restrict cfg) |
69 | 0 | { |
70 | 0 | window_t *w = vlc_custom_create(obj, sizeof(*w), "window"); |
71 | 0 | vlc_window_t *window = &w->wnd; |
72 | |
|
73 | 0 | memset(&window->handle, 0, sizeof(window->handle)); |
74 | 0 | window->info.has_double_click = false; |
75 | 0 | window->sys = NULL; |
76 | 0 | assert(owner != NULL); |
77 | 0 | window->owner = *owner; |
78 | |
|
79 | 0 | w->cfg.is_fullscreen = false; |
80 | 0 | w->cfg.is_decorated = true; |
81 | 0 | w->cfg.width = 0; |
82 | 0 | w->cfg.height = 0; |
83 | |
|
84 | 0 | int dss = var_InheritInteger(obj, "disable-screensaver"); |
85 | |
|
86 | 0 | w->inhibit = NULL; |
87 | 0 | w->inhibit_windowed = dss == 1; |
88 | 0 | w->active = false; |
89 | 0 | w->fullscreen = false; |
90 | 0 | vlc_mutex_init(&w->lock); |
91 | |
|
92 | 0 | w->module = vlc_module_load(vlc_object_logger(window), "vout window", module, |
93 | 0 | false, vlc_window_start, window); |
94 | 0 | if (!w->module) { |
95 | 0 | vlc_object_delete(window); |
96 | 0 | return NULL; |
97 | 0 | } |
98 | | |
99 | | /* Hook for screensaver inhibition */ |
100 | 0 | if (dss > 0) { |
101 | 0 | vlc_inhibit_t *inh = vlc_inhibit_Create(VLC_OBJECT(window)); |
102 | |
|
103 | 0 | vlc_mutex_lock(&w->lock); |
104 | 0 | w->inhibit = inh; |
105 | 0 | vlc_mutex_unlock(&w->lock); |
106 | 0 | } |
107 | | |
108 | | /* Apply initial configuration */ |
109 | 0 | if (cfg != NULL) { |
110 | 0 | if (cfg->is_fullscreen) |
111 | 0 | vlc_window_SetFullScreen(window, NULL); |
112 | 0 | if (cfg->width != 0 && cfg->height != 0) |
113 | 0 | vlc_window_SetSize(window, cfg->width, cfg->height); |
114 | | |
115 | | /* This will be applied whence the window is enabled. */ |
116 | 0 | w->cfg.is_decorated = cfg->is_decorated; |
117 | 0 | } |
118 | |
|
119 | 0 | return window; |
120 | 0 | } |
121 | | |
122 | | int vlc_window_Enable(vlc_window_t *window) |
123 | 0 | { |
124 | 0 | window_t *w = container_of(window, window_t, wnd); |
125 | |
|
126 | 0 | if (window->ops->enable != NULL) { |
127 | 0 | int err = window->ops->enable(window, &w->cfg); |
128 | 0 | if (err) |
129 | 0 | return err; |
130 | 0 | } |
131 | | |
132 | 0 | vlc_window_SetInhibition(window, true); |
133 | 0 | return VLC_SUCCESS; |
134 | 0 | } |
135 | | |
136 | | void vlc_window_Disable(vlc_window_t *window) |
137 | 0 | { |
138 | 0 | vlc_window_SetInhibition(window, false); |
139 | |
|
140 | 0 | if (window->ops->disable != NULL) |
141 | 0 | window->ops->disable(window); |
142 | 0 | } |
143 | | |
144 | | void vlc_window_SetSize(vlc_window_t *window, unsigned width, |
145 | | unsigned height) |
146 | 0 | { |
147 | 0 | window_t *w = container_of(window, window_t, wnd); |
148 | |
|
149 | 0 | w->cfg.width = width; |
150 | 0 | w->cfg.height = height; |
151 | |
|
152 | 0 | if (window->ops->resize != NULL) |
153 | 0 | window->ops->resize(window, width, height); |
154 | 0 | } |
155 | | |
156 | | void vlc_window_Delete(vlc_window_t *window) |
157 | 0 | { |
158 | 0 | if (!window) |
159 | 0 | return; |
160 | | |
161 | 0 | window_t *w = container_of(window, window_t, wnd); |
162 | |
|
163 | 0 | if (w->inhibit != NULL) { |
164 | 0 | vlc_inhibit_t *inh = w->inhibit; |
165 | |
|
166 | 0 | assert(!w->active); |
167 | 0 | vlc_mutex_lock(&w->lock); |
168 | 0 | w->inhibit = NULL; |
169 | 0 | vlc_mutex_unlock(&w->lock); |
170 | |
|
171 | 0 | vlc_inhibit_Destroy(inh); |
172 | 0 | } |
173 | |
|
174 | 0 | if (window->ops->destroy != NULL) |
175 | 0 | window->ops->destroy(window); |
176 | |
|
177 | 0 | vlc_objres_clear(VLC_OBJECT(window)); |
178 | 0 | vlc_object_delete(window); |
179 | 0 | } |
180 | | |
181 | | static void vlc_window_UpdateInhibitionUnlocked(vlc_window_t *window) |
182 | 0 | { |
183 | 0 | window_t *w = container_of(window, window_t, wnd); |
184 | 0 | unsigned flags = VLC_INHIBIT_NONE; |
185 | |
|
186 | 0 | vlc_mutex_assert(&w->lock); |
187 | |
|
188 | 0 | if (w->active && (w->inhibit_windowed || w->fullscreen)) |
189 | 0 | flags = VLC_INHIBIT_VIDEO; |
190 | 0 | if (w->inhibit != NULL) |
191 | 0 | vlc_inhibit_Set(w->inhibit, flags); |
192 | 0 | } |
193 | | |
194 | | void vlc_window_SetInhibition(vlc_window_t *window, bool enabled) |
195 | 0 | { |
196 | 0 | window_t *w = container_of(window, window_t, wnd); |
197 | |
|
198 | 0 | vlc_mutex_lock(&w->lock); |
199 | 0 | w->active = enabled; |
200 | |
|
201 | 0 | vlc_window_UpdateInhibitionUnlocked(window); |
202 | 0 | vlc_mutex_unlock(&w->lock); |
203 | 0 | } |
204 | | |
205 | | void vlc_window_ReportWindowed(vlc_window_t *window) |
206 | 0 | { |
207 | 0 | window_t *w = container_of(window, window_t, wnd); |
208 | |
|
209 | 0 | if (!w->inhibit_windowed) { |
210 | 0 | vlc_mutex_lock(&w->lock); |
211 | 0 | w->fullscreen = false; |
212 | |
|
213 | 0 | vlc_window_UpdateInhibitionUnlocked(window); |
214 | 0 | vlc_mutex_unlock(&w->lock); |
215 | 0 | } |
216 | |
|
217 | 0 | if (window->owner.cbs->windowed != NULL) |
218 | 0 | window->owner.cbs->windowed(window); |
219 | 0 | } |
220 | | |
221 | | void vlc_window_ReportFullscreen(vlc_window_t *window, const char *id) |
222 | 0 | { |
223 | 0 | window_t *w = container_of(window, window_t, wnd); |
224 | |
|
225 | 0 | if (!w->inhibit_windowed) { |
226 | 0 | vlc_mutex_lock(&w->lock); |
227 | 0 | w->fullscreen = true; |
228 | 0 | vlc_window_UpdateInhibitionUnlocked(window); |
229 | 0 | vlc_mutex_unlock(&w->lock); |
230 | 0 | } |
231 | |
|
232 | 0 | if (window->owner.cbs->fullscreened != NULL) |
233 | 0 | window->owner.cbs->fullscreened(window, id); |
234 | 0 | } |
235 | | |
236 | | void vlc_window_UnsetFullScreen(vlc_window_t *window) |
237 | 0 | { |
238 | 0 | window_t *w = container_of(window, window_t, wnd); |
239 | |
|
240 | 0 | w->cfg.is_fullscreen = false; |
241 | |
|
242 | 0 | if (window->ops->unset_fullscreen != NULL) |
243 | 0 | window->ops->unset_fullscreen(window); |
244 | 0 | } |
245 | | |
246 | | void vlc_window_SetFullScreen(vlc_window_t *window, const char *id) |
247 | 0 | { |
248 | 0 | window_t *w = container_of(window, window_t, wnd); |
249 | |
|
250 | 0 | w->cfg.is_fullscreen = true; |
251 | |
|
252 | 0 | if (window->ops->set_fullscreen != NULL) |
253 | 0 | window->ops->set_fullscreen(window, id); |
254 | 0 | } |