1 /*****************************************************************************
2 * window.c: "vout window" management
3 *****************************************************************************
4 * Copyright (C) 2009 Laurent Aimar
5 * $Id: 36aaa9d04602c311cd2ba678f675ca612c13678b $
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
32 #include <vlc_common.h>
33 #include <vlc_vout_window.h>
34 #include <vlc_modules.h>
35 #include "inhibit.h"
36 #include <libvlc.h>
37
38 typedef struct
39 {
40 vout_window_t wnd;
41 module_t *module;
42 vlc_inhibit_t *inhibit;
43 } window_t;
44
vout_window_start(void * func,va_list ap)45 static int vout_window_start(void *func, va_list ap)
46 {
47 int (*activate)(vout_window_t *, const vout_window_cfg_t *) = func;
48 vout_window_t *wnd = va_arg(ap, vout_window_t *);
49 const vout_window_cfg_t *cfg = va_arg(ap, const vout_window_cfg_t *);
50
51 return activate(wnd, cfg);
52 }
53
vout_window_New(vlc_object_t * obj,const char * module,const vout_window_cfg_t * cfg,const vout_window_owner_t * owner)54 vout_window_t *vout_window_New(vlc_object_t *obj, const char *module,
55 const vout_window_cfg_t *cfg,
56 const vout_window_owner_t *owner)
57 {
58 window_t *w = vlc_custom_create(obj, sizeof(*w), "window");
59 vout_window_t *window = &w->wnd;
60
61 memset(&window->handle, 0, sizeof(window->handle));
62 window->info.has_double_click = false;
63 window->control = NULL;
64 window->sys = NULL;
65
66 if (owner != NULL)
67 window->owner = *owner;
68 else
69 window->owner.resized = NULL;
70
71 w->module = vlc_module_load(window, "vout window", module,
72 module && *module,
73 vout_window_start, window, cfg);
74 if (!w->module) {
75 vlc_object_release(window);
76 return NULL;
77 }
78
79 /* Hook for screensaver inhibition */
80 if (var_InheritBool(obj, "disable-screensaver") &&
81 (window->type == VOUT_WINDOW_TYPE_XID || window->type == VOUT_WINDOW_TYPE_HWND
82 || window->type == VOUT_WINDOW_TYPE_WAYLAND))
83 {
84 w->inhibit = vlc_inhibit_Create(VLC_OBJECT (window));
85 if (w->inhibit != NULL)
86 vlc_inhibit_Set(w->inhibit, VLC_INHIBIT_VIDEO);
87 }
88 else
89 w->inhibit = NULL;
90 return window;
91 }
92
vout_window_stop(void * func,va_list ap)93 static void vout_window_stop(void *func, va_list ap)
94 {
95 int (*deactivate)(vout_window_t *) = func;
96 vout_window_t *wnd = va_arg(ap, vout_window_t *);
97
98 deactivate(wnd);
99 }
100
vout_window_Delete(vout_window_t * window)101 void vout_window_Delete(vout_window_t *window)
102 {
103 if (!window)
104 return;
105
106 window_t *w = (window_t *)window;
107 if (w->inhibit)
108 {
109 vlc_inhibit_Set (w->inhibit, VLC_INHIBIT_NONE);
110 vlc_inhibit_Destroy (w->inhibit);
111 }
112
113 vlc_module_unload(window, w->module, vout_window_stop, window);
114 vlc_object_release(window);
115 }
116
vout_window_SetInhibition(vout_window_t * window,bool enabled)117 void vout_window_SetInhibition(vout_window_t *window, bool enabled)
118 {
119 window_t *w = (window_t *)window;
120 unsigned flags = enabled ? VLC_INHIBIT_VIDEO : VLC_INHIBIT_NONE;
121
122 if (w->inhibit != NULL)
123 vlc_inhibit_Set(w->inhibit, flags);
124 }
125
126 /* Video output display integration */
127 #include <vlc_vout.h>
128 #include <vlc_vout_display.h>
129 #include "window.h"
130 #include "event.h"
131
132 typedef struct vout_display_window
133 {
134 vout_display_t *vd;
135 unsigned width;
136 unsigned height;
137
138 vlc_mutex_t lock;
139 } vout_display_window_t;
140
vout_display_window_ResizeNotify(vout_window_t * window,unsigned width,unsigned height)141 static void vout_display_window_ResizeNotify(vout_window_t *window,
142 unsigned width, unsigned height)
143 {
144 vout_display_window_t *state = window->owner.sys;
145
146 msg_Dbg(window, "resized to %ux%u", width, height);
147 vlc_mutex_lock(&state->lock);
148 state->width = width;
149 state->height = height;
150
151 if (state->vd != NULL)
152 vout_display_SendEventDisplaySize(state->vd, width, height);
153 vlc_mutex_unlock(&state->lock);
154 }
155
vout_display_window_CloseNotify(vout_window_t * window)156 static void vout_display_window_CloseNotify(vout_window_t *window)
157 {
158 vout_thread_t *vout = (vout_thread_t *)window->obj.parent;
159
160 vout_SendEventClose(vout);
161 }
162
vout_display_window_MouseEvent(vout_window_t * window,const vout_window_mouse_event_t * mouse)163 static void vout_display_window_MouseEvent(vout_window_t *window,
164 const vout_window_mouse_event_t *mouse)
165 {
166 vout_thread_t *vout = (vout_thread_t *)window->obj.parent;
167 vout_WindowMouseEvent(vout, mouse);
168 }
169
170 /**
171 * Creates a video window, initially without any attached display.
172 */
vout_display_window_New(vout_thread_t * vout,const vout_window_cfg_t * cfg)173 vout_window_t *vout_display_window_New(vout_thread_t *vout,
174 const vout_window_cfg_t *cfg)
175 {
176 vout_display_window_t *state = malloc(sizeof (*state));
177 if (state == NULL)
178 return NULL;
179
180 state->vd = NULL;
181 state->width = cfg->width;
182 state->height = cfg->height;
183 vlc_mutex_init(&state->lock);
184
185 vout_window_owner_t owner = {
186 .sys = state,
187 .resized = vout_display_window_ResizeNotify,
188 .closed = vout_display_window_CloseNotify,
189 .mouse_event = vout_display_window_MouseEvent,
190 };
191 vout_window_t *window;
192
193 window = vout_window_New((vlc_object_t *)vout, "$window", cfg, &owner);
194 if (window == NULL) {
195 vlc_mutex_destroy(&state->lock);
196 free(state);
197 }
198 return window;
199 }
200
201 /**
202 * Attaches a window to a display. Window events will be dispatched to the
203 * display until they are detached.
204 */
vout_display_window_Attach(vout_window_t * window,vout_display_t * vd)205 void vout_display_window_Attach(vout_window_t *window, vout_display_t *vd)
206 {
207 vout_display_window_t *state = window->owner.sys;
208
209 vout_window_SetSize(window,
210 vd->cfg->display.width, vd->cfg->display.height);
211
212 vlc_mutex_lock(&state->lock);
213 state->vd = vd;
214
215 vout_display_SendEventDisplaySize(vd, state->width, state->height);
216 vlc_mutex_unlock(&state->lock);
217 }
218
219 /**
220 * Detaches a window from a display. Window events will no longer be dispatched
221 * (except those that do not need a display).
222 */
vout_display_window_Detach(vout_window_t * window)223 void vout_display_window_Detach(vout_window_t *window)
224 {
225 vout_display_window_t *state = window->owner.sys;
226
227 vlc_mutex_lock(&state->lock);
228 state->vd = NULL;
229 vlc_mutex_unlock(&state->lock);
230 }
231
232 /**
233 * Destroys a video window.
234 * \note The window must be detached.
235 */
vout_display_window_Delete(vout_window_t * window)236 void vout_display_window_Delete(vout_window_t *window)
237 {
238 vout_display_window_t *state = window->owner.sys;
239
240 vout_window_Delete(window);
241
242 assert(state->vd == NULL);
243 vlc_mutex_destroy(&state->lock);
244 free(state);
245 }
246