1 /*****************************************************************
2  * gmerlin - a general purpose multimedia framework and applications
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <config.h>
23 
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 
27 #ifdef HAVE_LIBXINERAMA
28 #include <X11/extensions/Xinerama.h>
29 #endif
30 
31 #ifdef HAVE_XDPMS
32 #include <X11/extensions/dpms.h>
33 #endif
34 
35 #define SCREENSAVER_MODE_XLIB  0 // MUST be 0 (fallback)
36 #define SCREENSAVER_MODE_GNOME 1
37 #define SCREENSAVER_MODE_KDE   2
38 #define SCREENSAVER_MODE_XTEST 3
39 
40 #ifdef HAVE_GLX
41 #include <GL/glx.h>
42 #endif
43 
44 #include <X11/extensions/XShm.h>
45 
46 /* Screensaver module */
47 
48 typedef struct
49   {
50   Display * dpy;
51   int mode;
52   int disabled;
53   int was_enabled;
54   int saved_timeout;
55   int64_t last_ping_time;
56 
57   int fake_motion;
58 
59   gavl_timer_t * timer;
60 
61 #ifdef HAVE_XDPMS
62   int dpms_disabled;
63 #endif
64   } bg_x11_screensaver_t;
65 
66 void
67 bg_x11_screensaver_init(bg_x11_screensaver_t *, Display * dpy);
68 
69 void
70 bg_x11_screensaver_enable(bg_x11_screensaver_t *);
71 
72 void
73 bg_x11_screensaver_disable(bg_x11_screensaver_t *);
74 
75 void
76 bg_x11_screensaver_ping(bg_x11_screensaver_t *);
77 
78 void
79 bg_x11_screensaver_cleanup(bg_x11_screensaver_t *);
80 
81 
82 typedef struct video_driver_s video_driver_t;
83 
84 #define DRIVER_FLAG_BRIGHTNESS (1<<0)
85 #define DRIVER_FLAG_SATURATION (1<<1)
86 #define DRIVER_FLAG_CONTRAST   (1<<2)
87 
88 typedef struct
89   {
90   int flags;
91   const video_driver_t * driver;
92   gavl_pixelformat_t * pixelformats;
93   void * priv;
94   int can_scale;
95   bg_x11_window_t * win;
96 
97   /* Selected pixelformat (used by the core only) */
98   gavl_pixelformat_t pixelformat;
99   int penalty;
100   } driver_data_t;
101 
102 extern const video_driver_t ximage_driver;
103 
104 #ifdef HAVE_LIBXV
105 extern const video_driver_t xv_driver;
106 #endif
107 
108 #ifdef HAVE_GLX
109 extern const video_driver_t gl_driver;
110 #endif
111 
112 #define MAX_DRIVERS 3
113 
114 struct video_driver_s
115   {
116   const char * name;
117 
118   int can_scale;
119   int (*init)(driver_data_t* data);
120   int (*open)(driver_data_t* data);
121 
122   void (*add_overlay_stream)(driver_data_t* data);
123   void (*set_overlay)(driver_data_t* data, int stream, gavl_overlay_t * ovl);
124 
125   gavl_video_frame_t * (*create_overlay)(driver_data_t* data, int stream);
126   void (*destroy_overlay)(driver_data_t* data, int stream, gavl_video_frame_t*);
127 
128   gavl_video_frame_t * (*create_frame)(driver_data_t* data);
129 
130   void (*destroy_frame)(driver_data_t* data, gavl_video_frame_t *);
131 
132   void (*put_frame)(driver_data_t* data,
133                     gavl_video_frame_t * frame);
134 
135   void (*set_brightness)(driver_data_t* data,float brightness);
136   void (*set_saturation)(driver_data_t* data,float saturation);
137   void (*set_contrast)(driver_data_t* data,float contrast);
138 
139   void (*close)(driver_data_t* data);
140   void (*cleanup)(driver_data_t* data);
141   };
142 
143 /*
144  *  We have 2 windows: One normal window and one
145  *  fullscreen window. We optionally talk to both the
146  *  children and parents through the XEmbed protocol
147  */
148 
149 typedef struct
150   {
151   Window win;      /* Actual window */
152   Window parent;   /* Parent (if non-root we are embedded) */
153   Window child;    /* Child window */
154 
155   /* Toplevel window we are inside (e.g. window manager decoration) */
156   Window toplevel;
157 
158   /* Subwindow (created with another visual than the default) */
159   Window subwin;
160 
161   Window focus_child;  /* Focus proxy */
162 #ifdef HAVE_GLX
163   GLXWindow glx_win;
164 #endif
165   int parent_xembed;
166   int child_xembed;
167   int mapped;
168   int fullscreen;
169   bg_accelerator_map_t * child_accel_map;
170   int modality;
171   } window_t;
172 
173 struct bg_x11_window_s
174   {
175   /* User settable stuff (initialized before x11_window_create) */
176 
177   int min_width;
178   int min_height;
179 
180 #ifdef HAVE_LIBXINERAMA
181   XineramaScreenInfo *xinerama;
182   int                nxinerama;
183 #endif
184 
185   unsigned long black;
186   Display * dpy;
187   GC gc;
188 
189   int is_fullscreen;
190 
191   window_t normal;
192   window_t fullscreen;
193   window_t * current;
194 
195   Window root;
196   int window_width, window_height;
197 
198   int normal_width, normal_height;
199   int screen;
200   int window_x, window_y;
201 
202   /* Event types (set by x11_window_handle_event()) */
203 
204   int do_delete;
205 
206   /* Fullscreen stuff */
207 
208   int fullscreen_mode;
209   Pixmap fullscreen_cursor_pixmap;
210   Cursor fullscreen_cursor;
211 
212   Atom WM_DELETE_WINDOW;
213   Atom WM_TAKE_FOCUS;
214   Atom _NET_SUPPORTED;
215   Atom _NET_WM_STATE;
216   Atom _NET_WM_STATE_FULLSCREEN;
217   Atom _NET_WM_STATE_STAYS_ON_TOP;
218   Atom _NET_WM_STATE_ABOVE;
219   Atom _NET_MOVERESIZE_WINDOW;
220   Atom WIN_PROTOCOLS;
221   Atom WM_PROTOCOLS;
222   Atom WIN_LAYER;
223   Atom _XEMBED_INFO;
224   Atom _XEMBED;
225   Atom STRING;
226   Atom WM_CLASS;
227 
228   /* For hiding the mouse pointer */
229   int idle_counter;
230   int pointer_hidden;
231 
232   /* Screensaver stuff */
233 
234   int disable_screensaver_normal;
235   int disable_screensaver_fullscreen;
236 
237   char * display_string_parent;
238   char * display_string_child;
239 
240   int auto_resize;
241 
242   Colormap colormap;
243   Colormap sub_colormap;
244 
245   bg_x11_window_callbacks_t * callbacks;
246 
247   Visual * visual;
248   int depth;
249 
250   /* OpenGL stuff */
251 #ifdef HAVE_GLX
252   GLXContext glxcontext;
253 
254   GLXFBConfig * gl_fbconfigs;
255 
256   struct
257     {
258     int value;
259     int changed;
260     } gl_attributes[BG_GL_ATTRIBUTE_NUM];
261 
262   float background_color[3];
263 #endif
264 
265   /* XShm */
266 
267   int have_shm;
268   int shm_completion_type;
269   int wait_for_completion;
270 
271   gavl_video_format_t video_format;
272   int video_open;
273 
274   /* Scaling stuff */
275   gavl_video_format_t window_format;
276   gavl_video_frame_t * window_frame;
277   gavl_video_scaler_t * scaler;
278   int do_sw_scale;
279   int scaler_options_changed;
280 
281   gavl_rectangle_f_t src_rect;
282   gavl_rectangle_i_t dst_rect;
283 
284   driver_data_t drivers[MAX_DRIVERS];
285 
286   driver_data_t * current_driver;
287 
288   int drivers_initialized;
289 
290   /* For asynchronous focus grabbing */
291   int need_focus;
292   Time focus_time;
293 
294   int need_fullscreen;
295 
296   int force_hw_scale;
297 
298   /* Overlay stuff */
299   int num_overlay_streams;
300 
301   int has_overlay; /* 1 if there are overlays to blend, 0 else */
302 
303   struct
304     {
305     gavl_overlay_t * ovl;
306     unsigned long texture; /* For OpenGL only */
307     gavl_video_format_t format;
308     } * overlay_streams;
309 
310   float brightness;
311   float saturation;
312   float contrast;
313 
314   gavl_video_frame_t * still_frame;
315   int still_mode;
316 
317   Pixmap icon;
318   Pixmap icon_mask;
319 
320   /* Screensaver */
321   bg_x11_screensaver_t scr;
322 
323   };
324 
325 void bg_x11_window_put_frame_internal(bg_x11_window_t * win,
326                                       gavl_video_frame_t * frame);
327 
328 /* Private functions */
329 
330 void bg_x11_window_handle_event(bg_x11_window_t * win, XEvent * evt);
331 void bg_x11_window_ping_screensaver(bg_x11_window_t * w);
332 void bg_x11_window_get_coords(Display * dpy,
333                               Window win,
334                               int * x, int * y, int * width,
335                               int * height);
336 void bg_x11_window_init(bg_x11_window_t * w);
337 
338 gavl_pixelformat_t
339 bg_x11_window_get_pixelformat(Display * dpy, Visual * visual, int depth);
340 
341 void bg_x11_window_make_icon(bg_x11_window_t * win,
342                              const gavl_video_frame_t * icon,
343                              const gavl_video_format_t * icon_format,
344                              Pixmap * icon_ret, Pixmap * mask_ret);
345 
346 
347 int bg_x11_window_check_shm(Display * dpy, int * completion_type);
348 
349 int bg_x11_window_create_shm(bg_x11_window_t * w,
350                           XShmSegmentInfo * shminfo, int size);
351 
352 void bg_x11_window_destroy_shm(bg_x11_window_t * w,
353                             XShmSegmentInfo * shminfo);
354 
355 void bg_x11_window_size_changed(bg_x11_window_t * w);
356 
357 void bg_x11_window_cleanup_video(bg_x11_window_t * w);
358 
359 Window bg_x11_window_get_toplevel(bg_x11_window_t * w, Window win);
360 
361 void bg_x11_window_send_xembed_message(bg_x11_window_t * w, Window win, long time,
362                                        int type, int detail, int data1, int data2);
363 
364 void bg_x11_window_embed_parent(bg_x11_window_t * win,
365                                 window_t * w);
366 void bg_x11_window_embed_child(bg_x11_window_t * win,
367                                window_t * w);
368 
369 int bg_x11_window_check_embed_property(bg_x11_window_t * win,
370                                        window_t * w);
371 
372 void bg_x11_window_set_fullscreen_mapped(bg_x11_window_t * win,
373                                          window_t * w);
374 
375 void
376 bg_x11_window_set_netwm_state(Display * dpy, Window win, Window root, int action, Atom state);
377 
378 
379 void bg_x11_window_create_subwins(bg_x11_window_t * w,
380                                   int depth, Visual * v);
381 
382 void bg_x11_window_destroy_subwins(bg_x11_window_t * w);
383 
384 /* For OpenGL support */
385 
386 int bg_x11_window_init_gl(bg_x11_window_t *);
387 
388 #define XEMBED_MAPPED                   (1 << 0)
389 
390 /* XEMBED messages */
391 #define XEMBED_EMBEDDED_NOTIFY		0
392 #define XEMBED_WINDOW_ACTIVATE  	1
393 #define XEMBED_WINDOW_DEACTIVATE  	2
394 #define XEMBED_REQUEST_FOCUS	 	3
395 #define XEMBED_FOCUS_IN 	 	4
396 #define XEMBED_FOCUS_OUT  		5
397 #define XEMBED_FOCUS_NEXT 		6
398 #define XEMBED_FOCUS_PREV 		7
399 /* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */
400 #define XEMBED_MODALITY_ON 		10
401 #define XEMBED_MODALITY_OFF 		11
402 #define XEMBED_REGISTER_ACCELERATOR     12
403 #define XEMBED_UNREGISTER_ACCELERATOR   13
404 #define XEMBED_ACTIVATE_ACCELERATOR     14
405 
406 /* Modifiers field for XEMBED_REGISTER_ACCELERATOR */
407 #define XEMBED_MODIFIER_SHIFT    (1 << 0)
408 #define XEMBED_MODIFIER_CONTROL  (1 << 1)
409 #define XEMBED_MODIFIER_ALT      (1 << 2)
410 #define XEMBED_MODIFIER_SUPER    (1 << 3)
411 #define XEMBED_MODIFIER_HYPER    (1 << 4)
412 
413