1 /*
2  * Copyright (C) 2000-2019 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * video window handling functions
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <sys/time.h>
31 #include <sys/wait.h>
32 #include <X11/Xlib.h>
33 #include <X11/cursorfont.h>
34 #include <X11/keysym.h>
35 #ifdef HAVE_XINERAMA
36 #include <X11/extensions/Xinerama.h>
37 #endif
38 #ifdef HAVE_XF86VIDMODE
39 #include <X11/extensions/xf86vmode.h>
40 #endif
41 #ifdef HAVE_XTESTEXTENSION
42 #include <X11/extensions/XTest.h>
43 #endif
44 #ifdef HAVE_XSSAVEREXTENSION
45 #include <X11/extensions/scrnsaver.h>
46 #endif
47 
48 #include "common.h"
49 #include "oxine/oxine.h"
50 
51 #define EST_KEEP_VALID  10	  /* #frames to allow for changing fps */
52 #define EST_MAX_JITTER  0.01	  /* maximum jitter to detect valid fps */
53 #define EST_MAX_DIFF    0.01      /* maximum diff to detect valid fps */
54 #define ABS(x) ((x)>0?(x):-(x))
55 
56 
57 /* Video window private structure */
58 struct xui_vwin_st {
59   gGui_t                *gui;
60 
61   xitk_widget_list_t    *wl;
62 
63   char                   window_title[1024];
64   int                    current_cursor;  /* arrow or hand */
65   int                    cursor_visible;
66   int                    cursor_timer;
67   Visual	        *visual;          /* Visual for video window               */
68   Colormap	         colormap;        /* Colormap for video window		   */
69   XClassHint            *xclasshint;
70   XClassHint            *xclasshint_fullscreen;
71   XClassHint            *xclasshint_borderless;
72   GC                     gc;
73 
74   int                    video_width;     /* size of currently displayed video     */
75   int                    video_height;
76 
77   int                    frame_width;     /* frame size, from xine-lib */
78   int                    frame_height;
79 
80   double                 video_duration;  /* frame duratrion in seconds */
81   double                 video_average;   /* average frame duration in seconds */
82   double                 use_duration;    /* duration used for tv mode selection */
83   int                    video_duration_valid; /* is use_duration trustable? */
84   int                    win_width;       /* size of non-fullscreen window         */
85   int                    win_height;
86   int                    old_win_width;
87   int                    old_win_height;
88   int                    output_width;    /* output video window width/height      */
89   int                    output_height;
90 
91   int                    stream_resize_window; /* Boolean, 1 if new stream resize output window */
92   int                    zoom_small_stream; /* Boolean, 1 to double size small streams */
93 
94   int                    fullscreen_mode; /* bitfield:                                      */
95   int                    fullscreen_req;  /* WINDOWED_MODE, FULLSCR_MODE or FULLSCR_XI_MODE */
96   int                    fullscreen_width;
97   int                    fullscreen_height;
98 
99   int                    xinerama_fullscreen_x; /* will contain paramaters for very
100 						   fullscreen in xinerama mode */
101   int                    xinerama_fullscreen_y;
102   int                    xinerama_fullscreen_width;
103   int                    xinerama_fullscreen_height;
104 
105   int                    visible_width;   /* Size of currently visible portion of screen */
106   int                    visible_height;  /* May differ from fullscreen_* e.g. for TV mode */
107   double                 visible_aspect;  /* Pixel ratio of currently visible screen */
108 
109   int                    using_xinerama;
110 #ifdef HAVE_XINERAMA
111   XineramaScreenInfo    *xinerama;   /* pointer to xinerama struct, or NULL */
112   int                    xinerama_cnt;    /* number of screens in Xinerama */
113 #endif
114 
115   int                    xwin;            /* current X location */
116   int                    ywin;            /* current Y location */
117   int                    old_xwin;
118   int                    old_ywin;
119 
120   int                    desktopWidth;    /* desktop width */
121   int                    desktopHeight;   /* desktop height */
122   int                    depth;
123   int                    show;
124   int                    borderless;      /* borderless window (for windowed mode)? */
125 
126   Bool                   have_xtest;
127 #ifdef HAVE_XTESTEXTENSION
128   int                    fake_key_cur;
129   KeyCode                fake_keys[2];    /* Fake key to send */
130 #endif
131 
132   XWMHints              *wm_hint;
133 
134   xitk_register_key_t    widget_key;
135   xitk_register_key_t    old_widget_key;
136 
137 #ifdef HAVE_XF86VIDMODE
138   /* XF86VidMode Extension stuff */
139   XF86VidModeModeInfo**  XF86_modelines;
140   int                    XF86_modelines_count;
141 #endif
142 
143   int                    hide_on_start; /* user use '-H' arg, don't map
144 					   video window the first time */
145 
146   struct timeval         click_time;
147 
148   pthread_t              second_display_thread;
149   int                    second_display_running;
150 
151   int                    logo_synthetic;
152 
153   pthread_mutex_t        mutex;
154 
155 };
156 
157 /* safe external actions */
video_window_lock(xui_vwin_t * vwin,int lock_or_unlock)158 void video_window_lock (xui_vwin_t *vwin, int lock_or_unlock) {
159   if (!vwin)
160     return;
161   if (lock_or_unlock == 1)
162     pthread_mutex_lock (&vwin->mutex);
163   else if (lock_or_unlock == 0)
164     pthread_mutex_unlock (&vwin->mutex);
165 }
166 
video_window_set_transient_for(xui_vwin_t * vwin,Window w)167 void video_window_set_transient_for (xui_vwin_t *vwin, Window w) {
168   if (!vwin)
169     return;
170   if (vwin->gui->use_root_window || (vwin->gui->video_display != vwin->gui->display))
171     return;
172   pthread_mutex_lock (&vwin->mutex);
173   vwin->gui->x_lock_display (vwin->gui->display);
174   XSetTransientForHint (vwin->gui->display, w, vwin->gui->video_window);
175   vwin->gui->x_unlock_display (vwin->gui->display);
176   pthread_mutex_unlock (&vwin->mutex);
177 }
178 
179 
180 static void video_window_handle_event (XEvent *event, void *data);
181 static void video_window_adapt_size (xui_vwin_t *vwin);
182 static int  video_window_check_mag (xui_vwin_t *vwin);
183 static void video_window_calc_mag_win_size (xui_vwin_t *vwin, float xmag, float ymag);
184 
_video_window_resize_cb(void * data,xine_cfg_entry_t * cfg)185 static void _video_window_resize_cb(void *data, xine_cfg_entry_t *cfg) {
186   xui_vwin_t *vwin = data;
187   vwin->stream_resize_window = cfg->num_value;
188 }
189 
_video_window_zoom_small_cb(void * data,xine_cfg_entry_t * cfg)190 static void _video_window_zoom_small_cb(void *data, xine_cfg_entry_t *cfg) {
191   xui_vwin_t *vwin = data;
192   vwin->zoom_small_stream = cfg->num_value;
193 }
194 
have_xtestextention(xui_vwin_t * vwin)195 static Bool have_xtestextention (xui_vwin_t *vwin) {
196   Bool xtestext = False;
197 #ifdef HAVE_XTESTEXTENSION
198   int dummy1 = 0, dummy2 = 0, dummy3 = 0, dummy4 = 0;
199 
200   vwin->gui->x_lock_display (vwin->gui->video_display);
201   xtestext = XTestQueryExtension (vwin->gui->video_display, &dummy1, &dummy2, &dummy3, &dummy4);
202   vwin->gui->x_unlock_display (vwin->gui->video_display);
203 #else
204   (void)vwin;
205 #endif
206   return xtestext;
207 }
208 
_set_window_title(xui_vwin_t * vwin)209 static void _set_window_title (xui_vwin_t *vwin) {
210   XmbSetWMProperties (vwin->gui->video_display, vwin->gui->video_window,
211     vwin->window_title, vwin->window_title, NULL, 0, NULL, NULL, NULL);
212   XSync (vwin->gui->video_display, False);
213 }
214 
215 /*
216  * very small X event loop for the second display
217  */
second_display_loop(void * data)218 static __attribute__((noreturn)) void *second_display_loop (void *data) {
219   xui_vwin_t *vwin = data;
220 
221   while (vwin->second_display_running) {
222     XEvent   xevent;
223     int      got_event;
224 
225     xine_usec_sleep(20000);
226 
227     do {
228         vwin->gui->x_lock_display (vwin->gui->video_display);
229         got_event = XPending (vwin->gui->video_display);
230         if( got_event )
231           XNextEvent (vwin->gui->video_display, &xevent);
232         vwin->gui->x_unlock_display (vwin->gui->video_display);
233 
234         if (got_event && vwin->gui->stream) {
235           video_window_handle_event (&xevent, vwin);
236         }
237     } while (got_event);
238 
239   }
240 
241   pthread_exit(NULL);
242 }
243 
244 
video_window_find_visual(xui_vwin_t * vwin,Visual ** visual_return,int * depth_return)245 static void video_window_find_visual (xui_vwin_t *vwin, Visual **visual_return, int *depth_return) {
246   XWindowAttributes  attribs;
247   XVisualInfo	    *vinfo;
248   XVisualInfo	     vinfo_tmpl;
249   int		     num_visuals;
250   int		     depth = 0;
251   Visual	    *visual = NULL;
252 
253   if (vwin->gui->prefered_visual_id == None) {
254     /*
255      * List all available TrueColor visuals, pick the best one for xine.
256      * We prefer visuals of depth 15/16 (fast).  Depth 24/32 may be OK,
257      * but could be slow.
258      */
259     vinfo_tmpl.screen = vwin->gui->video_screen;
260     vinfo_tmpl.class  = (vwin->gui->prefered_visual_class != -1
261 			 ? vwin->gui->prefered_visual_class : TrueColor);
262     vinfo = XGetVisualInfo (vwin->gui->video_display,
263 			   VisualScreenMask | VisualClassMask,
264 			   &vinfo_tmpl, &num_visuals);
265     if (vinfo != NULL) {
266       int i, pref;
267       int best_visual_index = -1;
268       int best_visual = -1;
269 
270       for (i = 0; i < num_visuals; i++) {
271 	if (vinfo[i].depth == 15 || vinfo[i].depth == 16)
272 	  pref = 3;
273 	else if (vinfo[i].depth > 16)
274 	  pref = 2;
275 	else
276 	  pref = 1;
277 
278 	if (pref > best_visual) {
279 	  best_visual = pref;
280 	  best_visual_index = i;
281 	}
282       }
283 
284       if (best_visual_index != -1) {
285 	depth = vinfo[best_visual_index].depth;
286 	visual = vinfo[best_visual_index].visual;
287       }
288 
289       XFree(vinfo);
290     }
291   } else {
292     /*
293      * Use the visual specified by the user.
294      */
295     vinfo_tmpl.visualid = vwin->gui->prefered_visual_id;
296     vinfo = XGetVisualInfo (vwin->gui->video_display,
297 			   VisualIDMask, &vinfo_tmpl,
298 			   &num_visuals);
299     if (vinfo == NULL) {
300       printf(_("gui_main: selected visual %#lx does not exist, trying default visual\n"),
301 	     (long) vwin->gui->prefered_visual_id);
302     } else {
303       depth = vinfo[0].depth;
304       visual = vinfo[0].visual;
305       XFree(vinfo);
306     }
307   }
308 
309   if (depth == 0) {
310     XVisualInfo vinfo;
311 
312     XGetWindowAttributes (vwin->gui->video_display, (DefaultRootWindow (vwin->gui->video_display)), &attribs);
313 
314     depth = attribs.depth;
315 
316     if (XMatchVisualInfo (vwin->gui->video_display, vwin->gui->video_screen, depth, TrueColor, &vinfo)) {
317       visual = vinfo.visual;
318     } else {
319       printf (_("gui_main: couldn't find true color visual.\n"));
320 
321       depth = DefaultDepth (vwin->gui->video_display, vwin->gui->video_screen);
322       visual = DefaultVisual (vwin->gui->video_display, vwin->gui->video_screen);
323     }
324   }
325 
326   if (depth_return != NULL)
327     *depth_return = depth;
328   if (visual_return != NULL)
329     *visual_return = visual;
330 }
331 
332 
333 /*
334  * Let the video driver override the selected visual
335  */
video_window_select_visual(xui_vwin_t * vwin)336 void video_window_select_visual (xui_vwin_t *vwin) {
337   XVisualInfo *vinfo = (XVisualInfo *) -1;
338 
339   if (vwin->gui->vo_port && vwin->gui->video_display == vwin->gui->display) {
340 
341     xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_SELECT_VISUAL, &vinfo);
342 
343     if (vinfo != (XVisualInfo *) -1) {
344       if (! vinfo) {
345         fprintf (stderr, _("videowin: output driver cannot select a working visual\n"));
346         exit (1);
347       }
348       vwin->gui->visual = vinfo->visual;
349       vwin->gui->depth  = vinfo->depth;
350     }
351     if (vwin->gui->visual != vwin->visual) {
352       printf (_("videowin: output driver overrides selected visual to visual id 0x%lx\n"), vwin->gui->visual->visualid);
353       vwin->gui->x_lock_display (vwin->gui->display);
354       gui_init_imlib (vwin->gui, vwin->gui->visual);
355       vwin->gui->x_unlock_display (vwin->gui->display);
356       pthread_mutex_lock (&vwin->mutex);
357       video_window_adapt_size (vwin);
358       pthread_mutex_unlock (&vwin->mutex);
359     }
360   }
361 }
362 
363 /*
364  * Lock the video window against WM-initiated transparency changes.
365  * At the time of writing (2006-06-29), only xfwm4 SVN understands this.
366  * Ref. http://bugzilla.xfce.org/show_bug.cgi?id=1958
367  */
video_window_lock_opacity(xui_vwin_t * vwin)368 static void video_window_lock_opacity (xui_vwin_t *vwin) {
369   Atom opacity_lock = XInternAtom (vwin->gui->video_display, "_NET_WM_WINDOW_OPACITY_LOCKED", False);
370 
371   /* This shouldn't happen, but was reported in bug #1573056 */
372   if (opacity_lock == None)
373     return;
374 
375   XChangeProperty (vwin->gui->video_display, vwin->gui->video_window,
376 		  opacity_lock,
377 		  XA_CARDINAL, 32, PropModeReplace,
378 		  (unsigned char *)vwin->gui, 1);
379 }
380 
381 /*
382  * will modify/create video output window based on
383  *
384  * - fullscreen flags
385  * - win_width/win_height
386  *
387  * will set
388  * output_width/output_height
389  * visible_width/visible_height/visible_aspect
390  */
video_window_adapt_size(xui_vwin_t * vwin)391 static void video_window_adapt_size (xui_vwin_t *vwin) {
392   XSizeHints            hint;
393   XWMHints             *wm_hint;
394   XSetWindowAttributes  attr;
395   Atom                  prop;
396   Atom                  wm_delete_window;
397   MWMHints              mwmhints;
398   XGCValues             xgcv;
399   Window                old_video_window = None;
400   int                   border_width;
401 
402   vwin->gui->x_lock_display (vwin->gui->video_display);
403 
404   if (vwin->gui->use_root_window) { /* Using root window, but not really */
405 
406     vwin->xwin = vwin->ywin = 0;
407     vwin->output_width    = vwin->fullscreen_width;
408     vwin->output_height   = vwin->fullscreen_height;
409     vwin->visible_width   = vwin->fullscreen_width;
410     vwin->visible_height  = vwin->fullscreen_height;
411     vwin->visible_aspect  = vwin->gui->pixel_aspect = 1.0;
412 
413     if (vwin->gui->video_window == None) {
414       XGCValues   gcv;
415       Window      wparent;
416       Window      rootwindow = None;
417 
418       vwin->fullscreen_mode = FULLSCR_MODE;
419       vwin->visual          = vwin->gui->visual;
420       vwin->depth           = vwin->gui->depth;
421       vwin->colormap        = vwin->gui->colormap;
422 
423       if (vwin->gui->video_display != vwin->gui->display) {
424         video_window_find_visual (vwin, &vwin->visual, &vwin->depth);
425         vwin->colormap = DefaultColormap (vwin->gui->video_display, vwin->gui->video_screen);
426       }
427 
428       /* This couldn't happen, but we're paranoid ;-) */
429       if ((rootwindow = xitk_get_desktop_root_window (vwin->gui->video_display,
430         vwin->gui->video_screen, &wparent)) == None)
431         rootwindow = DefaultRootWindow (vwin->gui->video_display);
432 
433       attr.override_redirect = True;
434       attr.background_pixel  = vwin->gui->black.pixel;
435 
436       border_width = 0;
437 
438       if (vwin->gui->wid)
439         vwin->gui->video_window = vwin->gui->wid;
440       else
441         vwin->gui->video_window = XCreateWindow (vwin->gui->video_display, rootwindow,
442           0, 0, vwin->fullscreen_width, vwin->fullscreen_height, border_width,
443           CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel | CWOverrideRedirect, &attr);
444 
445       if (vwin->gui->video_display == vwin->gui->display)
446         xitk_widget_list_set (vwin->wl, WIDGET_LIST_WINDOW, (void *)vwin->gui->video_window);
447 
448       if (vwin->gui->vo_port) {
449         vwin->gui->x_unlock_display (vwin->gui->video_display);
450         xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void*)vwin->gui->video_window);
451         vwin->gui->x_lock_display (vwin->gui->video_display);
452       }
453 
454       if (!(vwin->gui->no_mouse))
455         XSelectInput (vwin->gui->video_display, vwin->gui->video_window, ExposureMask);
456       else
457         XSelectInput (vwin->gui->video_display, vwin->gui->video_window,
458           ExposureMask & (~(ButtonPressMask | ButtonReleaseMask)));
459 
460       _set_window_title (vwin);
461 
462       gcv.foreground         = vwin->gui->black.pixel;
463       gcv.background         = vwin->gui->black.pixel;
464       gcv.graphics_exposures = False;
465       vwin->gc = XCreateGC (vwin->gui->video_display, vwin->gui->video_window,
466         GCForeground | GCBackground | GCGraphicsExposures, &gcv);
467 
468       if (vwin->gui->video_display == vwin->gui->display)
469         xitk_widget_list_set (vwin->wl, WIDGET_LIST_GC, vwin->gc);
470 
471       hint.flags  = USSize | USPosition | PPosition | PSize;
472       hint.x      = 0;
473       hint.y      = 0;
474       hint.width  = vwin->fullscreen_width;
475       hint.height = vwin->fullscreen_height;
476       XSetNormalHints (vwin->gui->video_display, vwin->gui->video_window, &hint);
477 
478       video_window_lock_opacity (vwin);
479 
480       XClearWindow (vwin->gui->video_display, vwin->gui->video_window);
481 
482       XMapWindow (vwin->gui->video_display, vwin->gui->video_window);
483 
484       XLowerWindow (vwin->gui->video_display, vwin->gui->video_window);
485 
486       vwin->old_widget_key = vwin->widget_key;
487 
488       vwin->gui->x_unlock_display (vwin->gui->video_display);
489 
490       if (vwin->gui->video_display == vwin->gui->display)
491         vwin->widget_key = xitk_register_event_handler ("video_window",
492           vwin->gui->video_window, video_window_handle_event,
493           NULL, gui_dndcallback, NULL, vwin);
494 
495       return;
496     }
497 
498     vwin->gui->x_unlock_display (vwin->gui->video_display);
499 
500     return;
501   }
502 
503 
504 #ifdef HAVE_XF86VIDMODE
505   /* XF86VidMode Extension
506    * In case a fullscreen request is received or if already in fullscreen, the
507    * appropriate modeline will be looked up and used.
508    */
509   if (((!(vwin->fullscreen_req & WINDOWED_MODE)) || (!(vwin->fullscreen_mode & WINDOWED_MODE)))
510      && (vwin->XF86_modelines_count > 1)) {
511     int search = 0;
512 
513     /* skipping first entry because it is the current modeline */
514     for (search = 1; search < vwin->XF86_modelines_count; search++) {
515        if (vwin->XF86_modelines[search]->hdisplay >= vwin->video_width)
516 	 break;
517     }
518 
519     /*
520      * in case we have a request for a resolution higher than any available
521      * ones we take the highest currently available.
522      */
523     if ((!(vwin->fullscreen_mode & WINDOWED_MODE)) && (search >= vwin->XF86_modelines_count))
524        search = 0;
525 
526     /* just switching to a different modeline if necessary */
527     if (!(search >= vwin->XF86_modelines_count)) {
528        if (XF86VidModeSwitchToMode (vwin->gui->video_display, XDefaultScreen (vwin->gui->video_display),
529         vwin->XF86_modelines[search])) {
530 	  double res_h, res_v;
531 #ifdef HAVE_XINERAMA
532 	  int dummy_event, dummy_error;
533 #endif
534 
535           vwin->gui->XF86VidMode_fullscreen = 1;
536           vwin->fullscreen_width  = vwin->XF86_modelines[search]->hdisplay;
537           vwin->fullscreen_height = vwin->XF86_modelines[search]->vdisplay;
538 
539 	  /* update pixel aspect */
540           res_h = (DisplayWidth (vwin->gui->video_display, vwin->gui->video_screen) * 1000
541             / DisplayWidthMM (vwin->gui->video_display, vwin->gui->video_screen));
542           res_v = (DisplayHeight (vwin->gui->video_display, vwin->gui->video_screen) * 1000
543             / DisplayHeightMM (vwin->gui->video_display, vwin->gui->video_screen));
544 
545 	  vwin->gui->pixel_aspect    = res_v / res_h;
546 #ifdef HAVE_XINERAMA
547           if (XineramaQueryExtension (vwin->gui->video_display, &dummy_event, &dummy_error)) {
548 	    int count = 1;
549             XineramaQueryScreens (vwin->gui->video_display, &count);
550 	    if (count > 1)
551 	      /* multihead -> assuming square pixels */
552 	      vwin->gui->pixel_aspect = 1.0;
553 	  }
554 #endif
555 #ifdef DEBUG
556           printf ("pixel_aspect: %f\n", vwin->gui->pixel_aspect);
557 #endif
558 
559 	  // TODO
560 	  /*
561 	   * just in case the mouse pointer is off the visible area, move it
562 	   * to the middle of the video window
563 	   */
564           XWarpPointer (vwin->gui->video_display, None, vwin->gui->video_window,
565             0, 0, 0, 0, vwin->fullscreen_width / 2, vwin->fullscreen_height / 2);
566 
567           XF86VidModeSetViewPort (vwin->gui->video_display, XDefaultScreen (vwin->gui->video_display), 0, 0);
568 
569 	  /*
570 	   * if this is true, we are back at the original resolution, so there
571 	   * is no need to further worry about anything.
572 	   */
573           if ((!(vwin->fullscreen_mode & WINDOWED_MODE)) && (search == 0))
574             vwin->gui->XF86VidMode_fullscreen = 0;
575        } else {
576 	  xine_error(_("XF86VidMode Extension: modeline switching failed.\n"));
577        }
578     }
579   }
580 #endif/* HAVE_XF86VIDMODE */
581 
582 #ifdef HAVE_XINERAMA
583   if (vwin->xinerama) {
584     int           i;
585     int           knowLocation = 0;
586     Window        root_win, dummy_win;
587     int           x_mouse,y_mouse;
588     int           dummy_x,dummy_y;
589     unsigned int  dummy_opts;
590 
591     /* someday this could also use the centre of the window as the
592      * test point I guess.  Right now it's the upper-left.
593      */
594     if (vwin->gui->video_window != None) {
595       if (vwin->xwin >= 0 && vwin->ywin >= 0 &&
596         vwin->xwin < vwin->desktopWidth && vwin->ywin < vwin->desktopHeight) {
597 	knowLocation = 1;
598       }
599     }
600 
601     if (vwin->fullscreen_req & FULLSCR_XI_MODE) {
602       hint.x = vwin->xinerama_fullscreen_x;
603       hint.y = vwin->xinerama_fullscreen_y;
604       hint.width  = vwin->xinerama_fullscreen_width;
605       hint.height = vwin->xinerama_fullscreen_height;
606       vwin->fullscreen_width = hint.width;
607       vwin->fullscreen_height = hint.height;
608     }
609     else {
610       /* Get mouse cursor position */
611       XQueryPointer (vwin->gui->video_display, RootWindow (vwin->gui->video_display, vwin->gui->video_screen),
612 		    &root_win, &dummy_win, &x_mouse, &y_mouse, &dummy_x, &dummy_y, &dummy_opts);
613 
614       for (i = 0; i < vwin->xinerama_cnt; i++) {
615 	if (
616 	    (knowLocation == 1 &&
617              vwin->xwin >= vwin->xinerama[i].x_org &&
618              vwin->ywin >= vwin->xinerama[i].y_org &&
619              vwin->xwin < vwin->xinerama[i].x_org + vwin->xinerama[i].width &&
620              vwin->ywin < vwin->xinerama[i].y_org + vwin->xinerama[i].height) ||
621 	    (knowLocation == 0 &&
622              x_mouse >= vwin->xinerama[i].x_org &&
623              y_mouse >= vwin->xinerama[i].y_org &&
624              x_mouse < vwin->xinerama[i].x_org + vwin->xinerama[i].width &&
625              y_mouse < vwin->xinerama[i].y_org + vwin->xinerama[i].height)) {
626           /*  vwin->xinerama[i].screen_number ==
627               XScreenNumberOfScreen (XDefaultScreenOfDisplay (vwin->gui->video_display)))) {*/
628           hint.x = vwin->xinerama[i].x_org;
629           hint.y = vwin->xinerama[i].y_org;
630 
631 	  if(knowLocation == 0) {
632             vwin->old_xwin = hint.x;
633             vwin->old_ywin = hint.y;
634 	  }
635 
636           if (!(vwin->fullscreen_req & WINDOWED_MODE)) {
637             hint.width  = vwin->xinerama[i].width;
638             hint.height = vwin->xinerama[i].height;
639             vwin->fullscreen_width = hint.width;
640             vwin->fullscreen_height = hint.height;
641 	  }
642 	  else {
643             hint.width  = vwin->video_width;
644             hint.height = vwin->video_height;
645 	  }
646 	  break;
647 	}
648       }
649     }
650   }
651   else {
652     hint.x = 0;
653     hint.y = 0;
654     if (!(vwin->fullscreen_req & WINDOWED_MODE)) {
655       hint.width  = vwin->fullscreen_width;
656       hint.height = vwin->fullscreen_height;
657     } else {
658       hint.width  = vwin->win_width;
659       hint.height = vwin->win_height;
660     }
661   }
662 #else /* HAVE_XINERAMA */
663   hint.x = 0;
664   hint.y = 0;   /* for now -- could change later */
665 #endif /* HAVE_XINERAMA */
666 
667   vwin->visible_width  = vwin->fullscreen_width;
668   vwin->visible_height = vwin->fullscreen_height;
669   vwin->visible_aspect = vwin->gui->pixel_aspect;
670 
671   /* Retrieve size/aspect from tvout backend, if it should be set */
672   if (vwin->gui->tvout) {
673     tvout_get_size_and_aspect (vwin->gui->tvout,
674       &vwin->visible_width, &vwin->visible_height, &vwin->visible_aspect);
675     tvout_get_size_and_aspect (vwin->gui->tvout,
676       &hint.width, &hint.height, NULL);
677     tvout_set_fullscreen_mode (vwin->gui->tvout,
678       !(vwin->fullscreen_req & WINDOWED_MODE) ? 1 : 0, vwin->visible_width, vwin->visible_height);
679   }
680 
681 #ifdef HAVE_XINERAMA
682   /* ask for xinerama fullscreen mode */
683   if (vwin->xinerama && (vwin->fullscreen_req & FULLSCR_XI_MODE)) {
684 
685     if (vwin->gui->video_window) {
686       int dummy;
687 
688       if ((vwin->fullscreen_mode & FULLSCR_XI_MODE) && vwin->gui->visual == vwin->visual) {
689         if (vwin->visible_width != vwin->output_width || vwin->visible_height != vwin->output_height) {
690           /*
691            * resizing the video window may be necessary if the modeline or tv mode has
692            * just been switched
693            */
694           XMoveResizeWindow (vwin->gui->video_display, vwin->gui->video_window, hint.x, hint.y,
695             vwin->visible_width, vwin->visible_height);
696           vwin->output_width  = vwin->visible_width;
697           vwin->output_height = vwin->visible_height;
698         }
699         vwin->fullscreen_mode = vwin->fullscreen_req;
700         vwin->gui->x_unlock_display (vwin->gui->video_display);
701 
702         return;
703       }
704 
705       xitk_get_window_position (vwin->gui->video_display, vwin->gui->video_window,
706         &vwin->old_xwin, &vwin->old_ywin, &dummy, &dummy);
707 
708       if (vwin->gui->video_display == vwin->gui->display)
709         xitk_unregister_event_handler (&vwin->old_widget_key);
710       old_video_window = vwin->gui->video_window;
711     }
712 
713     vwin->fullscreen_mode = vwin->fullscreen_req;
714     vwin->visual   = vwin->gui->visual;
715     vwin->depth    = vwin->gui->depth;
716     vwin->colormap = vwin->gui->colormap;
717     if (vwin->gui->video_display != vwin->gui->display) {
718       video_window_find_visual (vwin, &vwin->visual, &vwin->depth);
719       vwin->colormap = DefaultColormap (vwin->gui->video_display, vwin->gui->video_screen);
720     }
721     /*
722      * open fullscreen window
723      */
724 
725     attr.background_pixel  = vwin->gui->black.pixel;
726     attr.border_pixel      = vwin->gui->black.pixel;
727     attr.colormap	   = vwin->colormap;
728 
729     border_width           = 0;
730     if(vwin->gui->wid)
731       vwin->gui->video_window = vwin->gui->wid;
732     else
733       vwin->gui->video_window = XCreateWindow (vwin->gui->video_display,
734         DefaultRootWindow (vwin->gui->video_display),
735         hint.x, hint.y, vwin->visible_width, vwin->visible_height,
736         border_width, vwin->depth, InputOutput, vwin->visual, CWBackPixel | CWBorderPixel | CWColormap, &attr);
737 
738     if (vwin->gui->video_display == vwin->gui->display)
739       xitk_widget_list_set (vwin->wl, WIDGET_LIST_WINDOW, (void *)vwin->gui->video_window);
740 
741     if (vwin->gui->vo_port) {
742       vwin->gui->x_unlock_display (vwin->gui->video_display);
743       xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void*)vwin->gui->video_window);
744       vwin->gui->x_lock_display (vwin->gui->video_display);
745     }
746 
747     if (vwin->xclasshint_fullscreen != NULL)
748       XSetClassHint (vwin->gui->video_display, vwin->gui->video_window, vwin->xclasshint_fullscreen);
749 
750     hint.win_gravity = StaticGravity;
751     hint.flags  = PPosition | PSize | PWinGravity;
752 
753     _set_window_title (vwin);
754 
755     XSetWMNormalHints (vwin->gui->video_display, vwin->gui->video_window, &hint);
756 
757     XSetWMHints (vwin->gui->video_display, vwin->gui->video_window, vwin->wm_hint);
758 
759     video_window_lock_opacity (vwin);
760 
761     vwin->output_width    = hint.width;
762     vwin->output_height   = hint.height;
763 
764     /*
765      * wm, no borders please
766      */
767     memset(&mwmhints, 0, sizeof(mwmhints));
768     prop = XInternAtom (vwin->gui->video_display, "_MOTIF_WM_HINTS", False);
769     mwmhints.flags = MWM_HINTS_DECORATIONS;
770     mwmhints.decorations = 0;
771     XChangeProperty (vwin->gui->video_display, vwin->gui->video_window, prop, prop, 32,
772       PropModeReplace, (unsigned char *) &mwmhints, PROP_MWM_HINTS_ELEMENTS);
773 
774   } else
775 #endif /* HAVE_XINERAMA */
776   if (!(vwin->fullscreen_req & WINDOWED_MODE)) {
777 
778     if (vwin->gui->video_window) {
779       int dummy;
780 
781       if ((!(vwin->fullscreen_mode & WINDOWED_MODE)) && (vwin->gui->visual == vwin->visual)) {
782 //#ifdef HAVE_XF86VIDMODE
783 //	if(vwin->XF86_modelines_count > 1) {
784         if ((vwin->visible_width != vwin->output_width) || (vwin->visible_height != vwin->output_height)) {
785 	   /*
786 	    * resizing the video window may be necessary if the modeline or tv mode has
787 	    * just been switched
788 	    */
789           XResizeWindow (vwin->gui->video_display, vwin->gui->video_window,
790             vwin->visible_width, vwin->visible_height);
791           vwin->output_width    = vwin->visible_width;
792           vwin->output_height   = vwin->visible_height;
793 	}
794 //#endif
795         vwin->fullscreen_mode = vwin->fullscreen_req;
796 	vwin->gui->x_unlock_display (vwin->gui->video_display);
797 
798 	return;
799       }
800 
801       xitk_get_window_position (vwin->gui->video_display, vwin->gui->video_window,
802         &vwin->old_xwin, &vwin->old_ywin, &dummy, &dummy);
803 
804       if (vwin->gui->video_display == vwin->gui->display)
805         xitk_unregister_event_handler(&vwin->old_widget_key);
806       old_video_window = vwin->gui->video_window;
807     }
808 
809     vwin->fullscreen_mode = vwin->fullscreen_req;
810     vwin->visual   = vwin->gui->visual;
811     vwin->depth    = vwin->gui->depth;
812     vwin->colormap = vwin->gui->colormap;
813 
814     if (vwin->gui->video_display != vwin->gui->display) {
815       video_window_find_visual (vwin, &vwin->visual, &vwin->depth);
816       vwin->colormap = DefaultColormap (vwin->gui->video_display, vwin->gui->video_screen);
817     }
818 
819     /*
820      * open fullscreen window
821      */
822 
823     attr.background_pixel  = vwin->gui->black.pixel;
824     attr.border_pixel      = vwin->gui->black.pixel;
825     attr.colormap	   = vwin->colormap;
826 
827     border_width           = 0;
828 
829     if (vwin->gui->wid)
830       vwin->gui->video_window = vwin->gui->wid;
831     else
832       vwin->gui->video_window = XCreateWindow (vwin->gui->video_display,
833         DefaultRootWindow(vwin->gui->video_display),
834         hint.x, hint.y, vwin->visible_width, vwin->visible_height,
835         border_width, vwin->depth, InputOutput, vwin->visual,
836         CWBackPixel | CWBorderPixel | CWColormap, &attr);
837 
838     if (vwin->gui->video_display == vwin->gui->display)
839       xitk_widget_list_set (vwin->wl, WIDGET_LIST_WINDOW, (void *) vwin->gui->video_window);
840 
841     if (vwin->gui->vo_port) {
842       vwin->gui->x_unlock_display (vwin->gui->video_display);
843       xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void*)vwin->gui->video_window);
844       vwin->gui->x_lock_display (vwin->gui->video_display);
845     }
846 
847     if (vwin->xclasshint_fullscreen != NULL)
848       XSetClassHint (vwin->gui->video_display, vwin->gui->video_window, vwin->xclasshint_fullscreen);
849 
850 #ifndef HAVE_XINERAMA
851     hint.x      = 0;
852     hint.y      = 0;
853     hint.width  = vwin->visible_width;
854     hint.height = vwin->visible_height;
855 #endif
856     hint.win_gravity = StaticGravity;
857     hint.flags  = PPosition | PSize | PWinGravity;
858 
859     _set_window_title (vwin);
860 
861     XSetWMNormalHints (vwin->gui->video_display, vwin->gui->video_window, &hint);
862 
863     XSetWMHints (vwin->gui->video_display, vwin->gui->video_window, vwin->wm_hint);
864 
865     video_window_lock_opacity (vwin);
866 
867     vwin->output_width    = hint.width;
868     vwin->output_height   = hint.height;
869 
870     /*
871      * wm, no borders please
872      */
873     memset(&mwmhints, 0, sizeof(mwmhints));
874     prop = XInternAtom (vwin->gui->video_display, "_MOTIF_WM_HINTS", False);
875     mwmhints.flags = MWM_HINTS_DECORATIONS;
876     mwmhints.decorations = 0;
877     XChangeProperty (vwin->gui->video_display, vwin->gui->video_window, prop, prop, 32,
878       PropModeReplace, (unsigned char *) &mwmhints, PROP_MWM_HINTS_ELEMENTS);
879 
880   }
881   else {
882 
883 #ifndef HAVE_XINERAMA
884     hint.x           = 0;
885     hint.y           = 0;
886     hint.width       = vwin->win_width;
887     hint.height      = vwin->win_height;
888 #endif
889     hint.flags       = PPosition | PSize;
890 
891     /*
892      * user sets window geom, move back to original location.
893      */
894     if (vwin->stream_resize_window == 0) {
895       hint.x = vwin->old_xwin;
896       hint.y = vwin->old_ywin;
897     }
898 
899     vwin->old_win_width  = hint.width;
900     vwin->old_win_height = hint.height;
901 
902     vwin->output_width  = hint.width;
903     vwin->output_height = hint.height;
904 
905     if (vwin->gui->video_window) {
906 
907       if ((!(vwin->fullscreen_mode & WINDOWED_MODE)) || (vwin->visual != vwin->gui->visual)) {
908 #ifdef HAVE_XF86VIDMODE
909 	/*
910 	 * toggling from fullscreen to window mode - time to switch back to
911 	 * the original modeline
912 	 */
913         if (vwin->XF86_modelines_count > 1) {
914           double res_h, res_v;
915 #ifdef HAVE_XINERAMA
916           int dummy_event, dummy_error;
917 #endif
918 
919           XF86VidModeSwitchToMode (vwin->gui->video_display, XDefaultScreen (vwin->gui->video_display), vwin->XF86_modelines[0]);
920           XF86VidModeSetViewPort (vwin->gui->video_display, XDefaultScreen (vwin->gui->video_display), 0, 0);
921 
922           vwin->gui->XF86VidMode_fullscreen = 0;
923 
924           vwin->fullscreen_width  = vwin->XF86_modelines[0]->hdisplay;
925           vwin->fullscreen_height = vwin->XF86_modelines[0]->vdisplay;
926 
927           /* update pixel aspect */
928           res_h = (DisplayWidth (vwin->gui->video_display, vwin->gui->video_screen) * 1000
929             / DisplayWidthMM (vwin->gui->video_display, vwin->gui->video_screen));
930           res_v = (DisplayHeight (vwin->gui->video_display, vwin->gui->video_screen) * 1000
931             / DisplayHeightMM (vwin->gui->video_display, vwin->gui->video_screen));
932 
933           vwin->gui->pixel_aspect = res_v / res_h;
934 #ifdef HAVE_XINERAMA
935           if (XineramaQueryExtension (vwin->gui->video_display, &dummy_event, &dummy_error)) {
936             int count = 1;
937             XineramaQueryScreens (vwin->gui->video_display, &count);
938             if (count > 1)
939               /* multihead -> assuming square pixels */
940               vwin->gui->pixel_aspect = 1.0;
941           }
942 #endif
943 #ifdef DEBUG
944           printf ("pixel_aspect: %f\n", vwin->gui->pixel_aspect);
945 #endif
946 	}
947 #endif
948 
949         if (vwin->gui->video_display == vwin->gui->display)
950           xitk_unregister_event_handler (&vwin->old_widget_key);
951         old_video_window = vwin->gui->video_window;
952       }
953       else {
954 
955 	/* Update window size hints with the new size */
956         XSetNormalHints (vwin->gui->video_display, vwin->gui->video_window, &hint);
957 
958         XResizeWindow (vwin->gui->video_display, vwin->gui->video_window,
959           vwin->win_width, vwin->win_height);
960 
961         vwin->gui->x_unlock_display (vwin->gui->video_display);
962 
963 	return;
964       }
965     }
966 
967     vwin->fullscreen_mode   = WINDOWED_MODE;
968     vwin->visual            = vwin->gui->visual;
969     vwin->depth             = vwin->gui->depth;
970     vwin->colormap          = vwin->gui->colormap;
971 
972     if (vwin->gui->video_display != vwin->gui->display) {
973       video_window_find_visual (vwin, &vwin->visual, &vwin->depth);
974       vwin->colormap = DefaultColormap (vwin->gui->video_display, vwin->gui->video_screen);
975     }
976     attr.background_pixel  = vwin->gui->black.pixel;
977     attr.border_pixel      = vwin->gui->black.pixel;
978     attr.colormap	   = vwin->colormap;
979 
980     if (vwin->borderless)
981       border_width = 0;
982     else
983       border_width = 4;
984 
985     if (vwin->gui->wid)
986       vwin->gui->video_window = vwin->gui->wid;
987     else
988       vwin->gui->video_window = XCreateWindow (vwin->gui->video_display,
989         DefaultRootWindow (vwin->gui->video_display),
990         hint.x, hint.y, hint.width, hint.height, border_width,
991         vwin->depth, InputOutput, vwin->visual, CWBackPixel | CWBorderPixel | CWColormap, &attr);
992 
993     if (vwin->gui->video_display == vwin->gui->display)
994       xitk_widget_list_set (vwin->wl, WIDGET_LIST_WINDOW, (void *) vwin->gui->video_window);
995 
996     if (vwin->gui->vo_port) {
997       vwin->gui->x_unlock_display (vwin->gui->video_display);
998       xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void*)vwin->gui->video_window);
999       vwin->gui->x_lock_display (vwin->gui->video_display);
1000     }
1001 
1002     if (vwin->borderless) {
1003       if (vwin->xclasshint_borderless != NULL)
1004         XSetClassHint (vwin->gui->video_display, vwin->gui->video_window, vwin->xclasshint_borderless);
1005     }
1006     else {
1007 
1008       if (vwin->xclasshint != NULL)
1009         XSetClassHint (vwin->gui->video_display, vwin->gui->video_window, vwin->xclasshint);
1010     }
1011 
1012     _set_window_title (vwin);
1013 
1014     XSetWMNormalHints (vwin->gui->video_display, vwin->gui->video_window, &hint);
1015 
1016     XSetWMHints (vwin->gui->video_display, vwin->gui->video_window, vwin->wm_hint);
1017 
1018     video_window_lock_opacity (vwin);
1019 
1020     if (vwin->borderless) {
1021       memset(&mwmhints, 0, sizeof(mwmhints));
1022       prop = XInternAtom (vwin->gui->video_display, "_MOTIF_WM_HINTS", False);
1023       mwmhints.flags = MWM_HINTS_DECORATIONS;
1024       mwmhints.decorations = 0;
1025       XChangeProperty (vwin->gui->video_display, vwin->gui->video_window, prop, prop, 32,
1026         PropModeReplace, (unsigned char *) &mwmhints, PROP_MWM_HINTS_ELEMENTS);
1027     }
1028   }
1029 
1030   if (!(vwin->gui->no_mouse))
1031     XSelectInput (vwin->gui->video_display, vwin->gui->video_window, INPUT_MOTION | KeymapStateMask);
1032   else
1033     XSelectInput (vwin->gui->video_display, vwin->gui->video_window,
1034       (INPUT_MOTION | KeymapStateMask) & (~(ButtonPressMask | ButtonReleaseMask)));
1035 
1036   wm_hint = XAllocWMHints();
1037   if (wm_hint != NULL) {
1038     wm_hint->input = True;
1039     wm_hint->initial_state = NormalState;
1040     wm_hint->icon_pixmap = vwin->gui->icon;
1041     wm_hint->flags = InputHint | StateHint | IconPixmapHint;
1042     XSetWMHints (vwin->gui->video_display, vwin->gui->video_window, wm_hint);
1043     XFree(wm_hint);
1044   }
1045 
1046   wm_delete_window = XInternAtom (vwin->gui->video_display, "WM_DELETE_WINDOW", False);
1047   XSetWMProtocols (vwin->gui->video_display, vwin->gui->video_window, &wm_delete_window, 1);
1048 
1049   if (vwin->hide_on_start == 1) {
1050     vwin->hide_on_start = -1;
1051     vwin->show = 0;
1052   }
1053   else {
1054     /* Map window. */
1055 
1056     if ((vwin->gui->always_layer_above ||
1057       ((!(vwin->fullscreen_mode & WINDOWED_MODE)) && is_layer_above())) && !wm_not_ewmh_only()) {
1058       xitk_set_layer_above (vwin->gui->video_window);
1059     }
1060 
1061     XRaiseWindow (vwin->gui->video_display, vwin->gui->video_window);
1062     XMapWindow (vwin->gui->video_display, vwin->gui->video_window);
1063 
1064     while (!xitk_is_window_visible (vwin->gui->video_display, vwin->gui->video_window))
1065       xine_usec_sleep(5000);
1066 
1067     if ((vwin->gui->always_layer_above ||
1068       ((!(vwin->fullscreen_mode & WINDOWED_MODE)) && is_layer_above())) && wm_not_ewmh_only()) {
1069       xitk_set_layer_above (vwin->gui->video_window);
1070     }
1071 
1072     /* inform the window manager that we are fullscreen. This info musn't be set for xinerama-fullscreen,
1073        otherwise there are 2 different window size for one fullscreen mode ! (kwin doesn't accept this) */
1074     if (!(vwin->fullscreen_mode & WINDOWED_MODE)
1075      && !(vwin->fullscreen_mode & FULLSCR_XI_MODE)
1076      && wm_not_ewmh_only())
1077       xitk_set_ewmh_fullscreen (vwin->gui->video_window);
1078 
1079   }
1080 
1081   XSync (vwin->gui->video_display, False);
1082 
1083   if (vwin->gc != None)
1084     XFreeGC (vwin->gui->video_display, vwin->gc);
1085 
1086   vwin->gc = XCreateGC (vwin->gui->video_display, vwin->gui->video_window, 0L, &xgcv);
1087   if (vwin->gui->video_display == vwin->gui->display)
1088     xitk_widget_list_set (vwin->wl, WIDGET_LIST_GC, vwin->gc);
1089 
1090   if ((!(vwin->fullscreen_mode & WINDOWED_MODE))) {
1091     /* Waiting for visibility, avoid X error on some cases */
1092 
1093     try_to_set_input_focus (vwin->gui->video_window);
1094 
1095 #ifdef HAVE_XINERAMA
1096     if (vwin->xinerama)
1097       XMoveWindow (vwin->gui->video_display, vwin->gui->video_window, hint.x, hint.y);
1098     else
1099       XMoveWindow (vwin->gui->video_display, vwin->gui->video_window, 0, 0);
1100 #else
1101     XMoveWindow (vwin->gui->video_display, vwin->gui->video_window, 0, 0);
1102 #endif
1103   }
1104 
1105   /* Update WM_TRANSIENT_FOR hints on other windows for the new video_window */
1106   if ((vwin->gui->panel_window != None) && (!vwin->gui->use_root_window))
1107     XSetTransientForHint (vwin->gui->video_display, vwin->gui->panel_window,vwin->gui->video_window);
1108 
1109   /* The old window should be destroyed now */
1110   if(old_video_window != None) {
1111     XDestroyWindow (vwin->gui->video_display, old_video_window);
1112 
1113     if (vwin->gui->cursor_grabbed)
1114       XGrabPointer (vwin->gui->video_display, vwin->gui->video_window, 1,
1115         None, GrabModeAsync, GrabModeAsync, vwin->gui->video_window, None, CurrentTime);
1116   }
1117 
1118   vwin->gui->x_unlock_display (vwin->gui->video_display);
1119 
1120   vwin->old_widget_key = vwin->widget_key;
1121 
1122   if (vwin->gui->video_display == vwin->gui->display)
1123     vwin->widget_key = xitk_register_event_handler ("video_window",
1124       vwin->gui->video_window, video_window_handle_event, NULL, gui_dndcallback,
1125       NULL, vwin);
1126 
1127   /* take care about window decoration/pos */
1128   {
1129     Window tmp_win;
1130 
1131     vwin->gui->x_lock_display (vwin->gui->video_display);
1132     XTranslateCoordinates (vwin->gui->video_display, vwin->gui->video_window,
1133       DefaultRootWindow (vwin->gui->video_display), 0, 0, &vwin->xwin, &vwin->ywin, &tmp_win);
1134     vwin->gui->x_unlock_display (vwin->gui->video_display);
1135   }
1136 
1137   oxine_adapt();
1138 }
1139 
get_default_mag(xui_vwin_t * vwin,int video_width,int video_height,float * xmag,float * ymag)1140 static void get_default_mag (xui_vwin_t *vwin, int video_width, int video_height, float *xmag, float *ymag) {
1141   if (vwin->zoom_small_stream && video_width < 300 && video_height < 300)
1142     *xmag = *ymag = 2.0f;
1143   else
1144     *xmag = *ymag = 1.0f;
1145 }
1146 
1147 /*
1148  *
1149  */
video_window_dest_size_cb(void * data,int video_width,int video_height,double video_pixel_aspect,int * dest_width,int * dest_height,double * dest_pixel_aspect)1150 void video_window_dest_size_cb (void *data,
1151 				int video_width, int video_height,
1152 				double video_pixel_aspect,
1153 				int *dest_width, int *dest_height,
1154 				double *dest_pixel_aspect)  {
1155   xui_vwin_t *vwin = data;
1156 
1157   if (!vwin)
1158     return;
1159   pthread_mutex_lock (&vwin->mutex);
1160 
1161   vwin->frame_width = video_width;
1162   vwin->frame_height = video_height;
1163 
1164   /* correct size with video_pixel_aspect */
1165   if (video_pixel_aspect >= vwin->gui->pixel_aspect)
1166     video_width  = video_width * video_pixel_aspect / vwin->gui->pixel_aspect + .5;
1167   else
1168     video_height = video_height * vwin->gui->pixel_aspect / video_pixel_aspect + .5;
1169 
1170   if (vwin->stream_resize_window && (vwin->fullscreen_mode & WINDOWED_MODE)) {
1171 
1172     if (vwin->video_width != video_width || vwin->video_height != video_height) {
1173 
1174       if ((video_width > 0) && (video_height > 0)) {
1175 	float xmag, ymag;
1176 
1177         get_default_mag (vwin, video_width, video_height, &xmag, &ymag);
1178 
1179         /* FIXME: this is supposed to give the same results as if a
1180          * video_window_set_mag(xmag, ymag) was called. Since video_window_adapt_size()
1181          * check several other details (like border, xinerama, etc) this
1182          * may produce wrong values in some cases. (?)
1183          */
1184         *dest_width  = (int) ((float) video_width * xmag + 0.5f);
1185         *dest_height = (int) ((float) video_height * ymag + 0.5f);
1186         *dest_pixel_aspect = vwin->gui->pixel_aspect;
1187         pthread_mutex_unlock (&vwin->mutex);
1188         return;
1189       }
1190     }
1191   }
1192 
1193   if (!(vwin->fullscreen_mode & WINDOWED_MODE)) {
1194     *dest_width  = vwin->visible_width;
1195     *dest_height = vwin->visible_height;
1196     *dest_pixel_aspect = vwin->visible_aspect;
1197   } else {
1198     *dest_width  = vwin->output_width;
1199     *dest_height = vwin->output_height;
1200     *dest_pixel_aspect = vwin->gui->pixel_aspect;
1201   }
1202 
1203   pthread_mutex_unlock (&vwin->mutex);
1204 }
1205 
1206 /*
1207  *
1208  */
video_window_frame_output_cb(void * data,int video_width,int video_height,double video_pixel_aspect,int * dest_x,int * dest_y,int * dest_width,int * dest_height,double * dest_pixel_aspect,int * win_x,int * win_y)1209 void video_window_frame_output_cb (void *data,
1210 				   int video_width, int video_height,
1211 				   double video_pixel_aspect,
1212 				   int *dest_x, int *dest_y,
1213 				   int *dest_width, int *dest_height,
1214 				   double *dest_pixel_aspect,
1215 				   int *win_x, int *win_y) {
1216   xui_vwin_t *vwin = data;
1217 
1218   if (!vwin)
1219     return;
1220   pthread_mutex_lock (&vwin->mutex);
1221 
1222   vwin->frame_width = video_width;
1223   vwin->frame_height = video_height;
1224 
1225   /* correct size with video_pixel_aspect */
1226   if (video_pixel_aspect >= vwin->gui->pixel_aspect)
1227     video_width  = video_width * video_pixel_aspect / vwin->gui->pixel_aspect + .5;
1228   else
1229     video_height = video_height * vwin->gui->pixel_aspect / video_pixel_aspect + .5;
1230 
1231   /* Please do NOT remove, support will be added soon! */
1232 #if 0
1233   double jitter;
1234   vwin->video_duration = video_duration;
1235   vwin->video_average  = 0.5 * vwin->video_average + 0.5 video_duration;
1236   jitter = ABS (video_duration - vwin->video_average) / vwin->video_average;
1237   if (jitter > EST_MAX_JITTER) {
1238     if (vwin->duration_valid > -EST_KEEP_VALID)
1239       vwin->duration_valid--;
1240   } else {
1241     if (vwin->duration_valid < EST_KEEP_VALID)
1242       vwin->duration_valid++;
1243     if (ABS (video_duration - vwin->use_duration) / video_duration > EST_MAX_DIFF)
1244       vwin->use_duration = video_duration;
1245   }
1246 #endif
1247 
1248   if (vwin->video_width != video_width || vwin->video_height != video_height) {
1249 
1250     vwin->video_width  = video_width;
1251     vwin->video_height = video_height;
1252 
1253     if (vwin->stream_resize_window && video_width > 0 && video_height > 0) {
1254       float xmag, ymag;
1255 
1256       /* Prepare window size */
1257       get_default_mag (vwin, video_width, video_height, &xmag, &ymag);
1258       video_window_calc_mag_win_size (vwin, xmag, ymag);
1259       /* If actually ready to adapt window size, do it now */
1260       if (video_window_check_mag (vwin))
1261         video_window_adapt_size (vwin);
1262     }
1263 
1264     oxine_adapt();
1265   }
1266 
1267   *dest_x = 0;
1268   *dest_y = 0;
1269 
1270   if (!(vwin->fullscreen_mode & WINDOWED_MODE)) {
1271     *dest_width  = vwin->visible_width;
1272     *dest_height = vwin->visible_height;
1273     *dest_pixel_aspect = vwin->visible_aspect;
1274     /* TODO: check video size/fps/ar if tv mode and call video_window_adapt_size if necessary */
1275   } else {
1276     *dest_width  = vwin->output_width;
1277     *dest_height = vwin->output_height;
1278     *dest_pixel_aspect = vwin->gui->pixel_aspect;
1279   }
1280 
1281   *win_x = (vwin->xwin < 0) ? 0 : vwin->xwin;
1282   *win_y = (vwin->ywin < 0) ? 0 : vwin->ywin;
1283 
1284   pthread_mutex_unlock (&vwin->mutex);
1285 }
1286 
1287 /*
1288  *
1289  */
video_window_set_fullscreen_mode(xui_vwin_t * vwin,int req_fullscreen)1290 void video_window_set_fullscreen_mode (xui_vwin_t *vwin, int req_fullscreen) {
1291 
1292   if (!vwin)
1293     return;
1294   pthread_mutex_lock (&vwin->mutex);
1295 
1296   if (!(vwin->fullscreen_mode & req_fullscreen)) {
1297 
1298 #ifdef HAVE_XINERAMA
1299     if ((req_fullscreen & FULLSCR_XI_MODE) && (!vwin->xinerama)) {
1300       if (vwin->fullscreen_mode & FULLSCR_MODE)
1301         vwin->fullscreen_req = WINDOWED_MODE;
1302       else
1303         vwin->fullscreen_req = FULLSCR_MODE;
1304     }
1305     else
1306 #endif
1307       vwin->fullscreen_req = req_fullscreen;
1308 
1309   }
1310   else {
1311 
1312     if ((req_fullscreen & FULLSCR_MODE) && (vwin->fullscreen_mode & FULLSCR_MODE))
1313       vwin->fullscreen_req = WINDOWED_MODE;
1314 #ifdef HAVE_XINERAMA
1315     else if ((req_fullscreen & FULLSCR_XI_MODE) && (vwin->fullscreen_mode & FULLSCR_XI_MODE))
1316       vwin->fullscreen_req = WINDOWED_MODE;
1317 #endif
1318 
1319   }
1320 
1321   video_window_adapt_size (vwin);
1322 
1323   try_to_set_input_focus (vwin->gui->video_window);
1324   osd_update_osd();
1325 
1326   pthread_mutex_unlock (&vwin->mutex);
1327 }
1328 
1329 /*
1330  *
1331  */
video_window_get_fullscreen_mode(xui_vwin_t * vwin)1332 int video_window_get_fullscreen_mode (xui_vwin_t *vwin) {
1333   return vwin ? vwin->fullscreen_mode : 0;
1334 }
1335 
1336 #if 0
1337 /*
1338  * set/reset xine in xinerama fullscreen
1339  * ie: try to expend display on further screens
1340  */
1341 void video_window_set_xinerama_fullscreen_mode (xui_vwin_t *vwin, int req_fullscreen) {
1342 
1343   pthread_mutex_lock (&vwin->mutex);
1344   vwin->fullscreen_req = req_fullscreen;
1345   video_window_adapt_size (vwin);
1346   pthread_mutex_unlock (&vwin->mutex);
1347 }
1348 
1349 /*
1350  *
1351  */
1352 int video_window_get_xinerama_fullscreen_mode (xui_vwin_t *vwin) {
1353   return vwin->fullscreen_mode;
1354 }
1355 #endif
1356 
1357 /*
1358  * Set cursor
1359  */
video_window_set_cursor(xui_vwin_t * vwin,int cursor)1360 void video_window_set_cursor (xui_vwin_t *vwin, int cursor) {
1361 
1362   if (vwin && cursor) {
1363     vwin->current_cursor = cursor;
1364 
1365     if (vwin->cursor_visible) {
1366       vwin->cursor_timer = 0;
1367       switch (vwin->current_cursor) {
1368       case 0:
1369         xitk_cursors_define_window_cursor (vwin->gui->video_display, vwin->gui->video_window, xitk_cursor_invisible);
1370 	break;
1371       case CURSOR_ARROW:
1372         xitk_cursors_restore_window_cursor (vwin->gui->video_display, vwin->gui->video_window);
1373 	break;
1374       case CURSOR_HAND:
1375         xitk_cursors_define_window_cursor (vwin->gui->video_display, vwin->gui->video_window, xitk_cursor_hand2);
1376 	break;
1377       }
1378     }
1379   }
1380 
1381 }
1382 
1383 /*
1384  * hide/show cursor in video window
1385  */
video_window_set_cursor_visibility(xui_vwin_t * vwin,int show_cursor)1386 void video_window_set_cursor_visibility (xui_vwin_t *vwin, int show_cursor) {
1387 
1388   if (!vwin)
1389     return;
1390   if (vwin->gui->use_root_window)
1391     return;
1392 
1393   vwin->cursor_visible = show_cursor;
1394 
1395   if (show_cursor)
1396     vwin->cursor_timer = 0;
1397 
1398   if (show_cursor) {
1399     if (vwin->current_cursor == CURSOR_ARROW)
1400       xitk_cursors_restore_window_cursor (vwin->gui->video_display, vwin->gui->video_window);
1401     else
1402       xitk_cursors_define_window_cursor (vwin->gui->video_display, vwin->gui->video_window, xitk_cursor_hand1);
1403   }
1404   else
1405     xitk_cursors_define_window_cursor (vwin->gui->video_display, vwin->gui->video_window, xitk_cursor_invisible);
1406 
1407 }
1408 
1409 /*
1410  * Get cursor visiblity (boolean)
1411  */
video_window_is_cursor_visible(xui_vwin_t * vwin)1412 int video_window_is_cursor_visible (xui_vwin_t *vwin) {
1413   return vwin ? vwin->cursor_visible : 0;
1414 }
1415 
video_window_get_cursor_timer(xui_vwin_t * vwin)1416 int video_window_get_cursor_timer (xui_vwin_t *vwin) {
1417   return vwin ? vwin->cursor_timer : 0;
1418 }
1419 
video_window_set_cursor_timer(xui_vwin_t * vwin,int timer)1420 void video_window_set_cursor_timer (xui_vwin_t *vwin, int timer) {
1421   if (vwin)
1422     vwin->cursor_timer = timer;
1423 }
1424 
1425 /*
1426  * hide/show video window
1427  */
video_window_set_visibility(xui_vwin_t * vwin,int show_window)1428 void video_window_set_visibility (xui_vwin_t *vwin, int show_window) {
1429 
1430   if (!vwin)
1431     return;
1432   if (vwin->gui->use_root_window)
1433     return;
1434 
1435   xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_VIDEOWIN_VISIBLE, (void *)(intptr_t)show_window);
1436 
1437   pthread_mutex_lock (&vwin->mutex);
1438 
1439   vwin->show = show_window;
1440 
1441   /* Switching to visible: If new window size requested meanwhile, adapt window */
1442   if ((vwin->show) && (vwin->fullscreen_mode & WINDOWED_MODE) &&
1443      (vwin->win_width != vwin->old_win_width || vwin->win_height != vwin->old_win_height))
1444     video_window_adapt_size (vwin);
1445 
1446   vwin->gui->x_lock_display (vwin->gui->video_display);
1447 
1448   if (vwin->show == 1) {
1449 
1450     if ((vwin->gui->always_layer_above ||
1451       (((!(vwin->fullscreen_mode & WINDOWED_MODE)) && is_layer_above()) &&
1452       (vwin->hide_on_start == 0))) && (!wm_not_ewmh_only())) {
1453       xitk_set_layer_above (vwin->gui->video_window);
1454     }
1455 
1456     XRaiseWindow (vwin->gui->video_display, vwin->gui->video_window);
1457     XMapWindow (vwin->gui->video_display, vwin->gui->video_window);
1458 
1459     if ((vwin->gui->always_layer_above ||
1460       (((!(vwin->fullscreen_mode & WINDOWED_MODE)) && is_layer_above()) &&
1461       (vwin->hide_on_start == 0))) && (wm_not_ewmh_only())) {
1462       xitk_set_layer_above(vwin->gui->video_window);
1463     }
1464 
1465     /* inform the window manager that we are fullscreen. This info musn't be set for xinerama-fullscreen,
1466        otherwise there are 2 different window size for one fullscreen mode ! (kwin doesn't accept this) */
1467     if (!(vwin->fullscreen_mode & WINDOWED_MODE)
1468      && !(vwin->fullscreen_mode & FULLSCR_XI_MODE)
1469      && wm_not_ewmh_only())
1470       xitk_set_ewmh_fullscreen (vwin->gui->video_window);
1471   }
1472   else
1473     XUnmapWindow (vwin->gui->video_display, vwin->gui->video_window);
1474 
1475   vwin->gui->x_unlock_display (vwin->gui->video_display);
1476 
1477   /* User used '-H', now he want to show video window */
1478   if (vwin->hide_on_start == -1)
1479     vwin->hide_on_start = 0;
1480 
1481   pthread_mutex_unlock (&vwin->mutex);
1482 }
1483 
1484 /*
1485  *
1486  */
video_window_is_visible(xui_vwin_t * vwin)1487 int video_window_is_visible (xui_vwin_t *vwin) {
1488   return vwin ? vwin->show : 0;
1489 }
1490 
1491 /*
1492  * check if screen_number is in the list
1493  */
screen_is_in_xinerama_fullscreen_list(const char * list,int screen_number)1494 static int screen_is_in_xinerama_fullscreen_list (const char *list, int screen_number) {
1495   const char *buffer;
1496   int         dummy;
1497 
1498   buffer = list;
1499 
1500   do {
1501     if((sscanf(buffer,"%d", &dummy) == 1) && (screen_number == dummy))
1502       return 1;
1503   } while((buffer = strchr(buffer,' ')) && (++buffer < (list + strlen(list))));
1504 
1505   return 0;
1506 }
1507 
1508 /*
1509  *
1510  */
video_window_init(gGui_t * gui,window_attributes_t * window_attribute,int hide_on_start)1511 xui_vwin_t *video_window_init (gGui_t *gui, window_attributes_t *window_attribute, int hide_on_start) {
1512   xui_vwin_t           *vwin;
1513   int                   i;
1514 #ifdef HAVE_XINERAMA
1515   int                   screens;
1516   int                   dummy_a, dummy_b;
1517   XineramaScreenInfo   *screeninfo = NULL;
1518   const char           *screens_list;
1519 #endif
1520 #ifdef HAVE_XF86VIDMODE
1521   int                   dummy_query_event, dummy_query_error;
1522 #endif
1523 
1524   if (!gui)
1525     return NULL;
1526   vwin = calloc (1, sizeof (*vwin));
1527   if (!vwin)
1528     return NULL;
1529 
1530   vwin->gui = gui;
1531   pthread_mutex_init (&vwin->mutex, NULL);
1532 
1533   if (vwin->gui->video_display == vwin->gui->display) {
1534     vwin->wl = xitk_widget_list_new ();
1535   }
1536 
1537   vwin->fullscreen_req     = WINDOWED_MODE;
1538   vwin->fullscreen_mode    = WINDOWED_MODE;
1539   vwin->gui->video_window  = None;
1540   vwin->show               = 1;
1541   vwin->widget_key         =
1542   vwin->old_widget_key     = 0;
1543   vwin->gc                 = None;
1544   vwin->borderless         = window_attribute->borderless;
1545   vwin->have_xtest         = have_xtestextention (vwin);
1546   vwin->hide_on_start      = hide_on_start;
1547 
1548   vwin->depth              = vwin->gui->depth;
1549   vwin->visual             = vwin->gui->visual;
1550   vwin->colormap           = vwin->gui->colormap;
1551   /* Currently, there no plugin loaded so far, but that might change */
1552   video_window_select_visual (vwin);
1553 
1554   if (vwin->gui->video_display != vwin->gui->display) {
1555     video_window_find_visual (vwin, &vwin->visual, &vwin->depth);
1556     vwin->colormap = DefaultColormap (vwin->gui->video_display, vwin->gui->video_screen);
1557   }
1558 
1559   vwin->xwin               = window_attribute->x;
1560   vwin->ywin               = window_attribute->y;
1561 
1562   vwin->gui->x_lock_display (vwin->gui->video_display);
1563   vwin->desktopWidth       = DisplayWidth(vwin->gui->video_display, vwin->gui->video_screen);
1564   vwin->desktopHeight      = DisplayHeight(vwin->gui->video_display, vwin->gui->video_screen);
1565 
1566 #ifdef HAVE_XTESTEXTENSION
1567   vwin->fake_keys[0] = XKeysymToKeycode (vwin->gui->video_display, XK_Shift_L);
1568   vwin->fake_keys[1] = XKeysymToKeycode (vwin->gui->video_display, XK_Control_L);
1569   vwin->fake_key_cur = 0;
1570 #endif
1571 
1572   memcpy (vwin->window_title, "xine", 5);
1573 
1574   gettimeofday (&vwin->click_time, 0);
1575 
1576   vwin->using_xinerama = 0;
1577 #ifdef HAVE_XINERAMA
1578   vwin->xinerama       = NULL;
1579   vwin->xinerama_cnt   = 0;
1580   /* Spark
1581    * some Xinerama stuff
1582    * I want to figure out what fullscreen means for this setup
1583    */
1584 
1585   if ((XineramaQueryExtension (vwin->gui->video_display, &dummy_a, &dummy_b))
1586       && (screeninfo = XineramaQueryScreens (vwin->gui->video_display, &screens))) {
1587     /* Xinerama Detected */
1588 #ifdef DEBUG
1589     printf ("videowin: display is using xinerama with %d screens\n", screens);
1590     printf ("videowin: going to assume we are using the first screen.\n");
1591     printf ("videowin: size of the first screen is %dx%d.\n",
1592 	     screeninfo[0].width, screeninfo[0].height);
1593 #endif
1594     if (XineramaIsActive(vwin->gui->video_display)) {
1595       vwin->using_xinerama = 1;
1596       vwin->fullscreen_width  = screeninfo[0].width;
1597       vwin->fullscreen_height = screeninfo[0].height;
1598       vwin->xinerama = screeninfo;
1599       vwin->xinerama_cnt = screens;
1600 
1601       screens_list = xine_config_register_string (vwin->gui->xine, "gui.xinerama_use_screens",
1602         "0 1",
1603         _("Screens to use in order to do a very fullscreen in xinerama mode. (example 0 2 3)"),
1604         _("Example, if you want the display to expand on screen 0, 2 and 3, enter 0 2 3"),
1605         CONFIG_LEVEL_EXP, CONFIG_NO_CB, CONFIG_NO_DATA);
1606 
1607       if((sscanf(screens_list,"%d",&dummy_a) == 1) && (dummy_a >= 0) && (dummy_a < screens)) {
1608 
1609         /* try to calculate the best maximum size for xinerama fullscreen */
1610         vwin->xinerama_fullscreen_x = screeninfo[dummy_a].x_org;
1611         vwin->xinerama_fullscreen_y = screeninfo[dummy_a].y_org;
1612         vwin->xinerama_fullscreen_width = screeninfo[dummy_a].width;
1613         vwin->xinerama_fullscreen_height = screeninfo[dummy_a].height;
1614 
1615         i = dummy_a;
1616         while(i < screens) {
1617 
1618           if(screen_is_in_xinerama_fullscreen_list(screens_list, i)) {
1619             if(screeninfo[i].x_org < vwin->xinerama_fullscreen_x)
1620 	      vwin->xinerama_fullscreen_x = screeninfo[i].x_org;
1621             if(screeninfo[i].y_org < vwin->xinerama_fullscreen_y)
1622 	      vwin->xinerama_fullscreen_y = screeninfo[i].y_org;
1623           }
1624 
1625           i++;
1626         }
1627 
1628         i = dummy_a;
1629         while(i < screens) {
1630 
1631           if(screen_is_in_xinerama_fullscreen_list(screens_list, i)) {
1632             if((screeninfo[i].width + screeninfo[i].x_org) >
1633 	       (vwin->xinerama_fullscreen_x + vwin->xinerama_fullscreen_width)) {
1634 	      vwin->xinerama_fullscreen_width =
1635 		screeninfo[i].width + screeninfo[i].x_org - vwin->xinerama_fullscreen_x;
1636 	    }
1637 
1638             if((screeninfo[i].height + screeninfo[i].y_org) >
1639 	       (vwin->xinerama_fullscreen_y + vwin->xinerama_fullscreen_height)) {
1640 	      vwin->xinerama_fullscreen_height =
1641 		screeninfo[i].height + screeninfo[i].y_org - vwin->xinerama_fullscreen_y;
1642 	    }
1643           }
1644 
1645           i++;
1646         }
1647       } else {
1648         /* we can't find screens to use, so we use screen 0 */
1649         vwin->xinerama_fullscreen_x      = screeninfo[0].x_org;
1650         vwin->xinerama_fullscreen_y      = screeninfo[0].y_org;
1651         vwin->xinerama_fullscreen_width  = screeninfo[0].width;
1652         vwin->xinerama_fullscreen_height = screeninfo[0].height;
1653       }
1654 
1655       dummy_a = xine_config_register_num (vwin->gui->xine, "gui.xinerama_fullscreen_x",
1656         -8192,
1657         _("x coordinate for xinerama fullscreen (-8192 = autodetect)"),
1658         CONFIG_NO_HELP, CONFIG_LEVEL_EXP, CONFIG_NO_CB, CONFIG_NO_DATA);
1659       if(dummy_a > -8192)
1660         vwin->xinerama_fullscreen_x = dummy_a;
1661 
1662       dummy_a = xine_config_register_num (vwin->gui->xine, "gui.xinerama_fullscreen_y",
1663         -8192,
1664         _("y coordinate for xinerama fullscreen (-8192 = autodetect)"),
1665         CONFIG_NO_HELP, CONFIG_LEVEL_EXP, CONFIG_NO_CB, CONFIG_NO_DATA);
1666       if(dummy_a > -8192)
1667         vwin->xinerama_fullscreen_y = dummy_a;
1668 
1669       dummy_a = xine_config_register_num (vwin->gui->xine, "gui.xinerama_fullscreen_width",
1670         -8192,
1671         _("width for xinerama fullscreen (-8192 = autodetect)"),
1672         CONFIG_NO_HELP, CONFIG_LEVEL_EXP, CONFIG_NO_CB, CONFIG_NO_DATA);
1673       if(dummy_a > -8192)
1674         vwin->xinerama_fullscreen_width = dummy_a;
1675 
1676       dummy_a = xine_config_register_num (vwin->gui->xine, "gui.xinerama_fullscreen_height",
1677         -8192,
1678         _("height for xinerama fullscreen (-8192 = autodetect)"),
1679         CONFIG_NO_HELP, CONFIG_LEVEL_EXP, CONFIG_NO_CB, CONFIG_NO_DATA);
1680       if(dummy_a > -8192)
1681         vwin->xinerama_fullscreen_height = dummy_a;
1682 
1683 #ifdef DEBUG
1684       printf ("videowin: Xinerama fullscreen parameters: X_origin=%d Y_origin=%d Width=%d Height=%d\n",
1685         vwin->xinerama_fullscreen_x, vwin->xinerama_fullscreen_y,
1686         vwin->xinerama_fullscreen_width, vwin->xinerama_fullscreen_height);
1687 #endif
1688     }
1689     else {
1690       vwin->fullscreen_width           = DisplayWidth  (vwin->gui->video_display, vwin->gui->video_screen);
1691       vwin->fullscreen_height          = DisplayHeight (vwin->gui->video_display, vwin->gui->video_screen);
1692       vwin->xinerama_fullscreen_x      = 0;
1693       vwin->xinerama_fullscreen_y      = 0;
1694       vwin->xinerama_fullscreen_width  = vwin->fullscreen_width;
1695       vwin->xinerama_fullscreen_height = vwin->fullscreen_height;
1696     }
1697 
1698   } else
1699 #endif
1700   {
1701     /* no Xinerama */
1702     if (__xineui_global_verbosity)
1703       printf ("Display is not using Xinerama.\n");
1704     vwin->fullscreen_width  = DisplayWidth (vwin->gui->video_display, vwin->gui->video_screen);
1705     vwin->fullscreen_height = DisplayHeight (vwin->gui->video_display, vwin->gui->video_screen);
1706   }
1707   vwin->visible_width  = vwin->fullscreen_width;
1708   vwin->visible_height = vwin->fullscreen_height;
1709 
1710   /* create xclass hint for video window */
1711 
1712   if ((vwin->xclasshint = XAllocClassHint()) != NULL) {
1713     vwin->xclasshint->res_name  = _("xine Video Window");
1714     vwin->xclasshint->res_class = "xine";
1715   }
1716   if ((vwin->xclasshint_fullscreen = XAllocClassHint()) != NULL) {
1717     vwin->xclasshint_fullscreen->res_name  = _("xine Video Fullscreen Window");
1718     vwin->xclasshint_fullscreen->res_class = "xine";
1719   }
1720   if ((vwin->xclasshint_borderless = XAllocClassHint()) != NULL) {
1721     vwin->xclasshint_borderless->res_name  = _("xine Video Borderless Window");
1722     vwin->xclasshint_borderless->res_class = "xine";
1723   }
1724 
1725   vwin->current_cursor = CURSOR_ARROW;
1726   vwin->cursor_timer   = 0;
1727 
1728   /*
1729    * wm hints
1730    */
1731 
1732   vwin->wm_hint = XAllocWMHints();
1733   if (!vwin->wm_hint) {
1734     printf (_("XAllocWMHints() failed\n"));
1735     exit (1);
1736   }
1737 
1738   vwin->wm_hint->input         = True;
1739   vwin->wm_hint->initial_state = NormalState;
1740   vwin->wm_hint->icon_pixmap   = vwin->gui->icon;
1741   vwin->wm_hint->flags         = InputHint | StateHint | IconPixmapHint;
1742 
1743   vwin->gui->x_unlock_display (vwin->gui->video_display);
1744 
1745   vwin->stream_resize_window = xine_config_register_bool (vwin->gui->xine, "gui.stream_resize_window",
1746     1,
1747     _("New stream sizes resize output window"),
1748     CONFIG_NO_HELP, CONFIG_LEVEL_ADV, _video_window_resize_cb, vwin);
1749 
1750   vwin->zoom_small_stream = xine_config_register_bool (vwin->gui->xine, "gui.zoom_small_stream",
1751     0,
1752     _("Double size for small streams (require stream_resize_window)"),
1753     CONFIG_NO_HELP, CONFIG_LEVEL_ADV, _video_window_zoom_small_cb, vwin);
1754 
1755   if ((window_attribute->width > 0) && (window_attribute->height > 0)) {
1756     vwin->video_width  = window_attribute->width;
1757     vwin->video_height = window_attribute->height;
1758     /*
1759      * Force to keep window size.
1760      * I don't update the config file, i think this window geometry
1761      * user defined can be temporary.
1762      */
1763     vwin->stream_resize_window = 0;
1764   }
1765   else {
1766     vwin->video_width  = 768;
1767     vwin->video_height = 480;
1768   }
1769   vwin->old_win_width  = vwin->win_width  = vwin->video_width;
1770   vwin->old_win_height = vwin->win_height = vwin->video_height;
1771 
1772 #ifdef HAVE_XF86VIDMODE
1773   if (xine_config_register_bool (vwin->gui->xine, "gui.use_xvidext",
1774     0,
1775     _("use XVidModeExtension when switching to fullscreen"),
1776     CONFIG_NO_HELP, CONFIG_LEVEL_EXP, CONFIG_NO_CB, CONFIG_NO_DATA)) {
1777     /*
1778      * without the "stream resizes window" behavior, the XVidMode support
1779      * won't work correctly, so we force it for each session the user wants
1780      * to have XVideMode on...
1781      *
1782      * FIXME: maybe display a warning message or so?!
1783      */
1784     vwin->stream_resize_window = 1;
1785 
1786     vwin->gui->x_lock_display (vwin->gui->video_display);
1787 
1788     if (XF86VidModeQueryExtension (vwin->gui->video_display, &dummy_query_event, &dummy_query_error)) {
1789       XF86VidModeModeInfo* XF86_modelines_swap;
1790       int                  mode, major, minor, sort_x, sort_y;
1791 
1792       XF86VidModeQueryVersion (vwin->gui->video_display, &major, &minor);
1793       printf (_("XF86VidMode Extension (%d.%d) detected, trying to use it.\n"), major, minor);
1794 
1795       if (XF86VidModeGetAllModeLines (vwin->gui->video_display, XDefaultScreen(vwin->gui->video_display),
1796         &(vwin->XF86_modelines_count), &(vwin->XF86_modelines))) {
1797         printf (_("XF86VidMode Extension: %d modelines found.\n"), vwin->XF86_modelines_count);
1798 
1799 	/* first, kick off unsupported modes */
1800         for (mode = 1; mode < vwin->XF86_modelines_count; mode++) {
1801 
1802           if (!XF86VidModeValidateModeLine (vwin->gui->video_display, vwin->gui->video_screen,
1803             vwin->XF86_modelines[mode])) {
1804 	    int wrong_mode;
1805 
1806 	    printf(_("XF86VidModeModeLine %dx%d isn't valid: discarded.\n"),
1807               vwin->XF86_modelines[mode]->hdisplay,
1808               vwin->XF86_modelines[mode]->vdisplay);
1809 
1810             for (wrong_mode = mode; wrong_mode < vwin->XF86_modelines_count; wrong_mode++)
1811 	      vwin->XF86_modelines[wrong_mode] = vwin->XF86_modelines[wrong_mode + 1];
1812 
1813             vwin->XF86_modelines[wrong_mode] = NULL;
1814             vwin->XF86_modelines_count--;
1815 	    mode--;
1816 	  }
1817 	}
1818 
1819 	/*
1820 	 * sorting modelines, skipping first entry because it is the current
1821 	 * modeline in use - this is important so we know to which modeline
1822 	 * we have to switch to when toggling fullscreen mode.
1823 	 */
1824         for (sort_x = 1; sort_x < vwin->XF86_modelines_count; sort_x++) {
1825 
1826           for (sort_y = sort_x+1; sort_y < vwin->XF86_modelines_count; sort_y++) {
1827 
1828             if (vwin->XF86_modelines[sort_x]->hdisplay > vwin->XF86_modelines[sort_y]->hdisplay) {
1829               XF86_modelines_swap = vwin->XF86_modelines[sort_y];
1830               vwin->XF86_modelines[sort_y] = vwin->XF86_modelines[sort_x];
1831               vwin->XF86_modelines[sort_x] = XF86_modelines_swap;
1832 	    }
1833 	  }
1834 	}
1835       } else {
1836         vwin->XF86_modelines_count = 0;
1837 	printf(_("XF86VidMode Extension: could not get list of available modelines. Failed.\n"));
1838       }
1839     } else {
1840       printf(_("XF86VidMode Extension: initialization failed, not using it.\n"));
1841     }
1842     vwin->gui->x_unlock_display (vwin->gui->video_display);
1843   }
1844   else
1845     vwin->XF86_modelines_count = 0;
1846 
1847 #endif
1848 
1849   /*
1850    * Create initial video window with the geometry constructed above.
1851    */
1852   video_window_adapt_size (vwin);
1853 
1854   /*
1855    * for plugins that aren't really bind to the window, it's necessary that the
1856    * vwin->xwin and vwin->ywin variables are set to *real* values, otherwise the
1857    * overlay will be displayed somewhere outside the window
1858    */
1859   if (vwin->gui->video_window) {
1860     Window tmp_win;
1861 
1862     vwin->gui->x_lock_display (vwin->gui->video_display);
1863     if((window_attribute->x > -8192) && (window_attribute->y > -8192)) {
1864       vwin->xwin = vwin->old_xwin = window_attribute->x;
1865       vwin->ywin = vwin->old_ywin = window_attribute->y;
1866 
1867       XMoveResizeWindow (vwin->gui->video_display, vwin->gui->video_window,
1868         vwin->xwin, vwin->ywin, vwin->video_width, vwin->video_height);
1869 
1870     }
1871     else {
1872 
1873       XTranslateCoordinates (vwin->gui->video_display, vwin->gui->video_window,
1874         DefaultRootWindow (vwin->gui->video_display), 0, 0, &vwin->xwin, &vwin->ywin, &tmp_win);
1875     }
1876     vwin->gui->x_unlock_display (vwin->gui->video_display);
1877 
1878   }
1879 
1880   if (vwin->gui->video_display != vwin->gui->display) {
1881     vwin->second_display_running = 1;
1882     pthread_create (&vwin->second_display_thread, NULL, second_display_loop, vwin);
1883   }
1884 
1885   vwin->gui->vwin = vwin;
1886   return vwin;
1887 }
1888 
1889 
1890 /*
1891  * Necessary cleanup
1892  */
video_window_exit(xui_vwin_t * vwin)1893 void video_window_exit (xui_vwin_t *vwin) {
1894 
1895   if (!vwin)
1896     return;
1897 
1898 #ifdef HAVE_XINE_CONFIG_UNREGISTER_CALLBACKS
1899   xine_config_unregister_callbacks (vwin->gui->xine, NULL, NULL, vwin, sizeof (*vwin));
1900 #endif
1901 
1902 #ifdef HAVE_XF86VIDMODE
1903   /* Restore original VidMode */
1904   if (vwin->gui->XF86VidMode_fullscreen) {
1905     vwin->gui->x_lock_display (vwin->gui->video_display);
1906     XF86VidModeSwitchToMode (vwin->gui->video_display, XDefaultScreen (vwin->gui->video_display), vwin->XF86_modelines[0]);
1907     XF86VidModeSetViewPort (vwin->gui->video_display, XDefaultScreen (vwin->gui->video_display), 0, 0);
1908     vwin->gui->x_unlock_display (vwin->gui->video_display);
1909   }
1910 #endif
1911 
1912   vwin->second_display_running = 0;
1913   if (vwin->gui->use_root_window || vwin->gui->video_display != vwin->gui->display) {
1914     union {
1915       XExposeEvent expose;
1916       XEvent event;
1917     } event;
1918 
1919     vwin->gui->x_lock_display (vwin->gui->video_display);
1920     XClearWindow (vwin->gui->video_display, vwin->gui->video_window);
1921     event.expose.type       = Expose;
1922     event.expose.send_event = True;
1923     event.expose.display    = vwin->gui->video_display;
1924     event.expose.window     = vwin->gui->video_window;
1925     event.expose.x          = 0;
1926     event.expose.y          = 0;
1927     event.expose.width      = vwin->video_width;
1928     event.expose.height     = vwin->video_height;
1929     XSendEvent (vwin->gui->video_display, vwin->gui->video_window, False, Expose, &event.event);
1930     vwin->gui->x_unlock_display (vwin->gui->video_display);
1931   }
1932 
1933   if (vwin->gui->video_display == vwin->gui->display) {
1934     xitk_unregister_event_handler (&vwin->widget_key);
1935     XITK_WIDGET_LIST_FREE (vwin->wl);
1936     vwin->wl = NULL;
1937   } else
1938     pthread_join (vwin->second_display_thread, NULL);
1939 
1940   pthread_mutex_destroy (&vwin->mutex);
1941   vwin->gui->vwin = NULL;
1942 
1943   if (vwin->xclasshint != NULL)
1944     XFree (vwin->xclasshint);
1945   if (vwin->xclasshint_fullscreen != NULL)
1946     XFree (vwin->xclasshint_fullscreen);
1947   if (vwin->xclasshint_borderless != NULL)
1948     XFree (vwin->xclasshint_borderless);
1949   if (vwin->wm_hint != NULL)
1950     XFree (vwin->wm_hint);
1951 
1952   free (vwin);
1953 }
1954 
1955 
1956 /*
1957  * Translate screen coordinates to video coordinates
1958  */
video_window_translate_point(xui_vwin_t * vwin,int gui_x,int gui_y,int * video_x,int * video_y)1959 static int video_window_translate_point (xui_vwin_t *vwin,
1960   int gui_x, int gui_y, int *video_x, int *video_y) {
1961   x11_rectangle_t rect;
1962   int             xwin, ywin;
1963   unsigned int    wwin, hwin, bwin, dwin;
1964   float           xf,yf;
1965   float           scale, width_scale, height_scale,aspect;
1966   Window          rootwin;
1967 
1968   if (!vwin)
1969     return 0;
1970 
1971   rect.x = gui_x;
1972   rect.y = gui_y;
1973   rect.w = 0;
1974   rect.h = 0;
1975 
1976   if (xine_port_send_gui_data (vwin->gui->vo_port,
1977     XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void*)&rect) != -1) {
1978     /* driver implements vwin->gui->video coordinate space translation, use it */
1979     *video_x = rect.x;
1980     *video_y = rect.y;
1981     return 1;
1982   }
1983 
1984   /* Driver cannot convert vwin->gui->video space, fall back to old code... */
1985 
1986   pthread_mutex_lock (&vwin->mutex);
1987 
1988   vwin->gui->x_lock_display (vwin->gui->video_display);
1989   if (XGetGeometry (vwin->gui->video_display, vwin->gui->video_window, &rootwin,
1990     &xwin, &ywin, &wwin, &hwin, &bwin, &dwin) == BadDrawable) {
1991     vwin->gui->x_unlock_display (vwin->gui->video_display);
1992     pthread_mutex_unlock (&vwin->mutex);
1993     return 0;
1994   }
1995   vwin->gui->x_unlock_display (vwin->gui->video_display);
1996 
1997   /* Scale co-ordinate to image dimensions. */
1998   height_scale = (float)vwin->video_height / (float)hwin;
1999   width_scale  = (float)vwin->video_width / (float)wwin;
2000   aspect       = (float)vwin->video_width / (float)vwin->video_height;
2001   if (((float)wwin / (float)hwin) < aspect) {
2002     scale    = width_scale;
2003     xf       = (float)gui_x * scale;
2004     yf       = (float)gui_y * scale;
2005     /* wwin=wwin * scale; */
2006     hwin     = hwin * scale;
2007     /* FIXME: The 1.25 should really come from the NAV packets. */
2008     *video_x = xf * 1.25 / aspect;
2009     *video_y = yf - ((hwin - vwin->video_height) / 2);
2010     /* printf("wscale:a=%f, s=%f, x=%d, y=%d\n",aspect, scale,*video_x,*video_y);  */
2011   } else {
2012     scale    = height_scale;
2013     xf       = (float)gui_x * scale;
2014     yf       = (float)gui_y * scale;
2015     wwin     = wwin * scale;
2016     /* FIXME: The 1.25 should really come from the NAV packets. */
2017     *video_x = (xf - ((wwin - vwin->video_width) /2)) * 1.25 / aspect;
2018     *video_y = yf;
2019     /* printf("hscale:a=%f s=%f x=%d, y=%d\n",aspect,scale,*video_x,*video_y);  */
2020   }
2021 
2022   pthread_mutex_unlock (&vwin->mutex);
2023 
2024   return 1;
2025 }
2026 
2027 /*
2028  * Set/Get magnification.
2029  */
video_window_check_mag(xui_vwin_t * vwin)2030 static int video_window_check_mag (xui_vwin_t *vwin) {
2031   if (!vwin)
2032     return 0;
2033 
2034   if ((!(vwin->fullscreen_mode & WINDOWED_MODE))
2035 /*
2036  * Currently, no support for magnification in fullscreen mode.
2037  * Commented out in order to not mess up current mag for windowed mode.
2038  *
2039 #ifdef HAVE_XF86VIDMODE
2040      && !(vwin->XF86_modelines_count > 1)
2041 #endif
2042  */
2043     )
2044     return 0;
2045 
2046   /* Allow mag only if video win is visible, so don't do something we can't see. */
2047   return (xitk_is_window_visible (vwin->gui->video_display, vwin->gui->video_window));
2048 }
2049 
video_window_calc_mag_win_size(xui_vwin_t * vwin,float xmag,float ymag)2050 static void video_window_calc_mag_win_size (xui_vwin_t *vwin, float xmag, float ymag) {
2051   vwin->win_width  = (int) ((float) vwin->video_width * xmag + 0.5f);
2052   vwin->win_height = (int) ((float) vwin->video_height * ymag + 0.5f);
2053 }
2054 
video_window_set_mag(xui_vwin_t * vwin,float xmag,float ymag)2055 int video_window_set_mag (xui_vwin_t *vwin, float xmag, float ymag) {
2056   if (!vwin)
2057     return 0;
2058 
2059   pthread_mutex_lock (&vwin->mutex);
2060 
2061   if (!video_window_check_mag (vwin)) {
2062     pthread_mutex_unlock (&vwin->mutex);
2063     return 0;
2064   }
2065   video_window_calc_mag_win_size (vwin, xmag, ymag);
2066   video_window_adapt_size (vwin);
2067 
2068   pthread_mutex_unlock (&vwin->mutex);
2069 
2070   return 1;
2071 }
2072 
video_window_get_mag(xui_vwin_t * vwin,float * xmag,float * ymag)2073 void video_window_get_mag (xui_vwin_t *vwin, float *xmag, float *ymag) {
2074   if (!vwin)
2075     return;
2076 
2077   /* compute current mag */
2078   pthread_mutex_lock (&vwin->mutex);
2079   *xmag = (float) vwin->output_width / (float) vwin->video_width;
2080   *ymag = (float) vwin->output_height / (float) vwin->video_height;
2081   pthread_mutex_unlock (&vwin->mutex);
2082 }
2083 
2084 /*
2085  * Change displayed logo, if selected skin want to customize it.
2086  */
video_window_update_logo(xui_vwin_t * vwin)2087 void video_window_update_logo (xui_vwin_t *vwin) {
2088   xine_cfg_entry_t     cfg_entry;
2089   const char          *skin_logo;
2090   int                  cfg_err_result;
2091 
2092   if (!vwin)
2093     return;
2094 
2095   cfg_err_result = xine_config_lookup_entry (vwin->gui->xine, "gui.logo_mrl", &cfg_entry);
2096   skin_logo = xitk_skin_get_logo (vwin->gui->skin_config);
2097 
2098   if(skin_logo) {
2099 
2100     if((cfg_err_result) && cfg_entry.str_value) {
2101       /* Old and new logo are same, don't reload */
2102       if(!strcmp(cfg_entry.str_value, skin_logo))
2103 	goto __done;
2104     }
2105 
2106     config_update_string("gui.logo_mrl", skin_logo);
2107     goto __play_logo_now;
2108 
2109   }
2110   else { /* Skin don't use logo feature, set to xine's default */
2111 
2112     /*
2113      * Back to default logo only on a skin
2114      * change, not at the first skin loading.
2115      **/
2116 #ifdef XINE_LOGO2_MRL
2117 #  define USE_XINE_LOGO_MRL XINE_LOGO2_MRL
2118 #else
2119 #  define USE_XINE_LOGO_MRL XINE_LOGO_MRL
2120 #endif
2121     if (vwin->logo_synthetic && (cfg_err_result) && (strcmp (cfg_entry.str_value, USE_XINE_LOGO_MRL))) {
2122         config_update_string ("gui.logo_mrl", USE_XINE_LOGO_MRL);
2123 
2124     __play_logo_now:
2125 
2126       sleep(1);
2127 
2128       if (vwin->gui->logo_mode) {
2129         if (xine_get_status (vwin->gui->stream) == XINE_STATUS_PLAY) {
2130           vwin->gui->ignore_next = 1;
2131           xine_stop (vwin->gui->stream);
2132           vwin->gui->ignore_next = 0;
2133 	}
2134         if (vwin->gui->display_logo) {
2135           if ((!xine_open (vwin->gui->stream, vwin->gui->logo_mrl))
2136             || (!xine_play (vwin->gui->stream, 0, 0))) {
2137             gui_handle_xine_error (vwin->gui->stream, (char *)vwin->gui->logo_mrl);
2138 	    goto __done;
2139 	  }
2140 	}
2141         vwin->gui->logo_mode = 1;
2142       }
2143     }
2144   }
2145 
2146  __done:
2147   vwin->gui->logo_has_changed--;
2148 }
2149 
video_window_change_skins(xui_vwin_t * vwin,int synthetic)2150 void video_window_change_skins (xui_vwin_t *vwin, int synthetic) {
2151   if (!vwin)
2152     return;
2153   vwin->logo_synthetic = (synthetic ? 1 : 0);
2154   vwin->gui->logo_has_changed++;
2155 }
2156 
2157 /*
2158  *
2159  */
video_window_handle_event(XEvent * event,void * data)2160 static void video_window_handle_event (XEvent *event, void *data) {
2161   xui_vwin_t *vwin = data;
2162 
2163   switch(event->type) {
2164 
2165   case DestroyNotify:
2166     if (vwin->gui->video_window == event->xany.window)
2167       gui_exit (NULL, vwin->gui);
2168     break;
2169 
2170   case KeyPress:
2171     gui_handle_event (event, vwin->gui);
2172     break;
2173 
2174   case MotionNotify: {
2175     XMotionEvent *mevent = (XMotionEvent *) event;
2176     xine_event_t event;
2177     xine_input_data_t input;
2178     int x, y;
2179 
2180     /* printf("Mouse event:mx=%d my=%d\n",mevent->x, mevent->y); */
2181 
2182     if (!vwin->gui->cursor_visible) {
2183       vwin->gui->cursor_visible = !vwin->gui->cursor_visible;
2184       video_window_set_cursor_visibility (vwin, vwin->gui->cursor_visible);
2185     }
2186 
2187     event.type            = XINE_EVENT_INPUT_MOUSE_MOVE;
2188     if (!oxine_mouse_event(event.type, mevent->x, mevent->y) ) {
2189       if (video_window_translate_point (vwin, mevent->x, mevent->y, &x, &y)) {
2190         event.stream      = vwin->gui->stream;
2191         event.data        = &input;
2192         event.data_length = sizeof(input);
2193         gettimeofday(&event.tv, NULL);
2194         input.button      = 0; /*  No buttons, just motion. */
2195         input.x           = x;
2196         input.y           = y;
2197 
2198         xine_event_send (vwin->gui->stream, &event);
2199       }
2200     }
2201   }
2202   break;
2203 
2204   case ButtonPress: {
2205     XButtonEvent       *bevent = (XButtonEvent *) event;
2206     xine_input_data_t   input;
2207     xine_event_t        event;
2208     int                 x, y;
2209 
2210     if (!vwin->gui->cursor_visible) {
2211       vwin->gui->cursor_visible = !vwin->gui->cursor_visible;
2212       video_window_set_cursor_visibility (vwin, vwin->gui->cursor_visible);
2213     }
2214 
2215     if (bevent->button == Button3 && vwin->gui->display == vwin->gui->video_display)
2216       video_window_menu (vwin->gui, vwin->wl);
2217     else if (bevent->button == Button2)
2218       panel_toggle_visibility (NULL, vwin->gui->panel);
2219     else if (bevent->button == Button1) {
2220       struct timeval  old_click_time, tm_diff;
2221       long int        click_diff;
2222 
2223       timercpy (&vwin->click_time, &old_click_time);
2224       gettimeofday (&vwin->click_time, 0);
2225 
2226       timercpy (&old_click_time, &event.tv);
2227 
2228       timersub (&vwin->click_time, &old_click_time, &tm_diff);
2229       click_diff = (tm_diff.tv_sec * 1000) + (tm_diff.tv_usec / 1000.0);
2230 
2231       if (click_diff < (xitk_get_timer_dbl_click())) {
2232         gui_execute_action_id (vwin->gui, ACTID_TOGGLE_FULLSCREEN);
2233         vwin->click_time.tv_sec -= (xitk_get_timer_dbl_click() / 1000.0);
2234         vwin->click_time.tv_usec -= (xitk_get_timer_dbl_click() * 1000.0);
2235       }
2236 
2237     }
2238 
2239     event.type            = XINE_EVENT_INPUT_MOUSE_BUTTON;
2240     if( bevent->button != Button1 ||
2241         !oxine_mouse_event(event.type, bevent->x, bevent->y) ) {
2242       if (video_window_translate_point (vwin, bevent->x, bevent->y, &x, &y)) {
2243         event.stream      = vwin->gui->stream;
2244         event.data        = &input;
2245         event.data_length = sizeof(input);
2246         input.button      = bevent->button;
2247         input.x           = x;
2248         input.y           = y;
2249 
2250         xine_event_send (vwin->gui->stream, &event);
2251       }
2252     }
2253   }
2254   break;
2255 
2256   case ButtonRelease:
2257     gui_handle_event (event, vwin->gui);
2258     break;
2259 
2260   case Expose: {
2261     XExposeEvent * xev = (XExposeEvent *) event;
2262 
2263     if (xev->count == 0) {
2264 
2265       if (event->xany.window == vwin->gui->video_window) {
2266         xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_EXPOSE_EVENT, event);
2267       }
2268     }
2269   }
2270   break;
2271 
2272   case ConfigureNotify:
2273     if (event->xany.window == vwin->gui->video_window) {
2274       XConfigureEvent *cev = (XConfigureEvent *) event;
2275       Window           tmp_win;
2276       int              h, w;
2277 
2278       pthread_mutex_lock (&vwin->mutex);
2279 
2280       h = vwin->output_height;
2281       w = vwin->output_width;
2282       vwin->output_width  = cev->width;
2283       vwin->output_height = cev->height;
2284 
2285       if ((cev->x == 0) && (cev->y == 0)) {
2286         vwin->gui->x_lock_display (cev->display);
2287         XTranslateCoordinates(cev->display, cev->window, DefaultRootWindow(cev->display),
2288                               0, 0, &vwin->xwin, &vwin->ywin, &tmp_win);
2289         vwin->gui->x_unlock_display (cev->display);
2290       }
2291       else {
2292         vwin->xwin = cev->x;
2293         vwin->ywin = cev->y;
2294       }
2295 
2296       /* Keep geometry memory of windowed mode in sync. */
2297       if (vwin->fullscreen_mode & WINDOWED_MODE) {
2298         vwin->old_win_width  = vwin->win_width  = vwin->output_width;
2299         vwin->old_win_height = vwin->win_height = vwin->output_height;
2300       }
2301 
2302       if ((h != vwin->output_height) || (w != vwin->output_width))
2303 	osd_update_osd();
2304 
2305       oxine_adapt();
2306 
2307       pthread_mutex_unlock (&vwin->mutex);
2308     }
2309     break;
2310 
2311   }
2312 }
2313 
video_window_get_ssaver_idle(xui_vwin_t * vwin)2314 long int video_window_get_ssaver_idle (xui_vwin_t *vwin) {
2315   if (!vwin)
2316     return 0;
2317 
2318 #ifdef HAVE_XSSAVEREXTENSION
2319   {
2320     long int ssaver_idle = -1;
2321     int dummy = 0;
2322     vwin->gui->x_lock_display (vwin->gui->video_display);
2323     if (XScreenSaverQueryExtension (vwin->gui->video_display, &dummy, &dummy)) {
2324       XScreenSaverInfo *ssaverinfo = XScreenSaverAllocInfo();
2325       XScreenSaverQueryInfo (vwin->gui->video_display, (DefaultRootWindow (vwin->gui->video_display)), ssaverinfo);
2326       ssaver_idle = ssaverinfo->idle / 1000;
2327       XFree(ssaverinfo);
2328     }
2329     vwin->gui->x_unlock_display (vwin->gui->video_display);
2330     if (ssaver_idle != -1)
2331       return ssaver_idle;
2332   }
2333 #endif
2334 
2335   return xitk_get_last_keypressed_time();
2336 }
2337 
2338 
video_window_reset_ssaver(xui_vwin_t * vwin)2339 long int video_window_reset_ssaver (xui_vwin_t *vwin) {
2340 
2341   /* fprintf(stderr, "Idletime %d, timeout %d\n", video_window_get_ssaver_idle(), (long int) vwin->gui->ssaver_timeout); */
2342 
2343   long int idle = 0;
2344 
2345   if (!vwin)
2346     return 0;
2347 
2348   if (vwin->gui->ssaver_enabled && ((idle = video_window_get_ssaver_idle (vwin)) >= (long int) vwin->gui->ssaver_timeout)) {
2349     idle = 0;
2350     /* fprintf(stderr, "resetting ssaver\n"); */
2351 
2352 #ifdef HAVE_XTESTEXTENSION
2353     if (vwin->have_xtest == True) {
2354 
2355       vwin->fake_key_cur++;
2356 
2357       if (vwin->fake_key_cur >= 2)
2358         vwin->fake_key_cur = 0;
2359 
2360       vwin->gui->x_lock_display (vwin->gui->video_display);
2361       XTestFakeKeyEvent (vwin->gui->video_display, vwin->fake_keys[vwin->fake_key_cur], True, CurrentTime);
2362       XTestFakeKeyEvent (vwin->gui->video_display, vwin->fake_keys[vwin->fake_key_cur], False, CurrentTime);
2363       XSync (vwin->gui->video_display, False);
2364       vwin->gui->x_unlock_display (vwin->gui->video_display);
2365     }
2366     else
2367 #endif
2368     {
2369       /* Reset the gnome screensaver. Look up the command in PATH only once to save time, */
2370       /* assuming its location and permission will not change during run time of xine-ui. */
2371       {
2372         static char *const gssaver_args[] = { "gnome-screensaver-command", "--poke", NULL };
2373         static const char *gssaver_path   = NULL;
2374 
2375 	if(!gssaver_path) {
2376           const char *path = getenv("PATH");
2377 
2378 	  if(!path)
2379 	    path = "/usr/local/bin:/usr/bin";
2380 	  do {
2381             const char *p;
2382             char *pbuf;
2383 	    int   plen;
2384 
2385 	    for(p = path; *path && *path != ':'; path++)
2386 	      ;
2387 	    if(p == path)
2388 	      plen = 1, p = ".";
2389 	    else
2390 	      plen = path - p;
2391 	    pbuf = xitk_asprintf("%.*s/%s", plen, p, gssaver_args[0]);
2392 	    if ( pbuf && access(pbuf, X_OK) ) {
2393 	      free(pbuf);
2394 	      gssaver_path = "";
2395 	    } else
2396 	      gssaver_path = pbuf;
2397 	  } while(!gssaver_path[0] && *path++);
2398 	}
2399 	if (gssaver_path[0]) {
2400 	  pid_t pid = fork();
2401 
2402 	  if (pid == 0) {
2403 	    if (fork() == 0) {
2404 	      execv(gssaver_path, gssaver_args);
2405 	    }
2406 	    _exit(0);
2407 	  } else if (pid > 0) {
2408 	    waitpid(pid, NULL, 0);
2409 	  }
2410 	}
2411       }
2412 
2413       vwin->gui->x_lock_display (vwin->gui->video_display);
2414       XResetScreenSaver (vwin->gui->video_display);
2415       vwin->gui->x_unlock_display (vwin->gui->video_display);
2416     }
2417   }
2418   return idle;
2419 }
2420 
video_window_get_frame_size(xui_vwin_t * vwin,int * w,int * h)2421 void video_window_get_frame_size (xui_vwin_t *vwin, int *w, int *h) {
2422   if (!vwin)
2423     return;
2424 
2425   if(w)
2426     *w = vwin->frame_width;
2427   if(h)
2428     *h = vwin->frame_height;
2429   if (!vwin->frame_width && !vwin->frame_height) {
2430     /* fall back to meta info */
2431     if (w) {
2432       *w = xine_get_stream_info (vwin->gui->stream, XINE_STREAM_INFO_VIDEO_WIDTH);
2433     }
2434     if (h) {
2435       *h = xine_get_stream_info (vwin->gui->stream, XINE_STREAM_INFO_VIDEO_HEIGHT);
2436     }
2437   }
2438 }
2439 
video_window_get_visible_size(xui_vwin_t * vwin,int * w,int * h)2440 void video_window_get_visible_size (xui_vwin_t *vwin, int *w, int *h) {
2441   if (!vwin)
2442     return;
2443   if(w)
2444     *w = vwin->visible_width;
2445   if(h)
2446     *h = vwin->visible_height;
2447 }
2448 
video_window_get_output_size(xui_vwin_t * vwin,int * w,int * h)2449 void video_window_get_output_size (xui_vwin_t *vwin, int *w, int *h) {
2450   if (!vwin)
2451     return;
2452   if(w)
2453     *w = vwin->output_width;
2454   if(h)
2455     *h = vwin->output_height;
2456 }
2457 
video_window_set_mrl(xui_vwin_t * vwin,char * mrl)2458 void video_window_set_mrl (xui_vwin_t *vwin, char *mrl) {
2459   if (!vwin || !mrl)
2460     return;
2461   if (!mrl[0])
2462     return;
2463   if (!memcmp (vwin->window_title, "xine: ", 6) && !strcmp (vwin->window_title + 6, mrl))
2464     return;
2465   memcpy (vwin->window_title, "xine: ", 6);
2466   strlcpy (vwin->window_title + 6, mrl, sizeof (vwin->window_title) - 6);
2467   vwin->gui->x_lock_display (vwin->gui->video_display);
2468   _set_window_title (vwin);
2469   vwin->gui->x_unlock_display (vwin->gui->video_display);
2470 }
2471 
video_window_toggle_border(xui_vwin_t * vwin)2472 void video_window_toggle_border (xui_vwin_t *vwin) {
2473   if (!vwin)
2474     return;
2475 
2476   if (!vwin->gui->use_root_window && (vwin->fullscreen_mode & WINDOWED_MODE)) {
2477     Atom         prop;
2478     MWMHints     mwmhints;
2479     XClassHint  *xclasshint;
2480 
2481     vwin->borderless = !vwin->borderless;
2482 
2483     vwin->gui->x_lock_display (vwin->gui->video_display);
2484 
2485     memset(&mwmhints, 0, sizeof(mwmhints));
2486     prop                 = XInternAtom (vwin->gui->video_display, "_MOTIF_WM_HINTS", False);
2487     mwmhints.flags       = MWM_HINTS_DECORATIONS;
2488     mwmhints.decorations = vwin->borderless ? 0 : 1;
2489     xclasshint           = vwin->borderless ? vwin->xclasshint_borderless : vwin->xclasshint;
2490 
2491     XChangeProperty (vwin->gui->video_display, vwin->gui->video_window, prop, prop, 32,
2492       PropModeReplace, (unsigned char *) &mwmhints, PROP_MWM_HINTS_ELEMENTS);
2493 
2494     if(xclasshint != NULL)
2495       XSetClassHint (vwin->gui->video_display, vwin->gui->video_window, xclasshint);
2496 
2497     vwin->gui->x_unlock_display (vwin->gui->video_display);
2498 
2499     xine_port_send_gui_data (vwin->gui->vo_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void *)vwin->gui->video_window);
2500   }
2501 }
2502 
2503