]> git.sesse.net Git - vlc/blob - plugins/x11/vout_common.c
0c34286b3b28af83d26cfb070574cefe5e4af167
[vlc] / plugins / x11 / vout_common.c
1 /*****************************************************************************
2  * vout_common.c: Functions common to the X11 and XVideo plugins
3  *****************************************************************************
4  * Copyright (C) 1998-2001 VideoLAN
5  * $Id: vout_common.c,v 1.1 2001/12/09 17:01:37 sam Exp $
6  *
7  * Authors: Vincent Seguin <seguin@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          David Kennedy <dkennedy@tinytoad.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 #include "modules_inner.h"
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include "defs.h"
32
33 #include <errno.h>                                                 /* ENOMEM */
34 #include <stdlib.h>                                                /* free() */
35 #include <string.h>                                            /* strerror() */
36
37 #ifdef HAVE_MACHINE_PARAM_H
38 /* BSD */
39 #include <machine/param.h>
40 #include <sys/types.h>                                     /* typedef ushort */
41 #include <sys/ipc.h>
42 #endif
43
44 #ifndef WIN32
45 #include <netinet/in.h>                               /* BSD: struct in_addr */
46 #endif
47
48 #include <sys/shm.h>                                   /* shmget(), shmctl() */
49 #include <X11/Xlib.h>
50 #include <X11/Xutil.h>
51 #include <X11/keysym.h>
52 #include <X11/extensions/XShm.h>
53
54 #define x11 12
55 #define xvideo 42
56 #if ( MODULE_NAME == x11 )
57 #   define MODULE_NAME_IS_x11 1
58 #elif ( MODULE_NAME == xvideo )
59 #   define MODULE_NAME_IS_xvideo 1
60 #   include <X11/extensions/Xv.h>
61 #   include <X11/extensions/Xvlib.h>
62 #   include <X11/extensions/dpms.h>
63 #endif
64 #undef x11
65 #undef xvideo
66
67 #include "common.h"
68 #include "intf_msg.h"
69 #include "threads.h"
70 #include "mtime.h"
71 #include "tests.h"
72
73 #include "video.h"
74 #include "video_output.h"
75 #include "vout_common.h"
76
77 #include "interface.h"
78 #include "netutils.h"                                 /* network_ChannelJoin */
79
80 #include "stream_control.h"                 /* needed by input_ext-intf.h... */
81 #include "input_ext-intf.h"
82
83 #include "modules.h"
84 #include "modules_export.h"
85
86 /*****************************************************************************
87  * vout_Manage: handle X11 events
88  *****************************************************************************
89  * This function should be called regularly by video output thread. It manages
90  * X11 events and allows window resizing. It returns a non null value on
91  * error.
92  *****************************************************************************/
93 int _M( vout_Manage ) ( vout_thread_t *p_vout )
94 {
95     XEvent      xevent;                                         /* X11 event */
96     boolean_t   b_resized;                        /* window has been resized */
97     char        i_key;                                    /* ISO Latin-1 key */
98     KeySym      x_key_symbol;
99
100     /* Handle X11 events: ConfigureNotify events are parsed to know if the
101      * output window's size changed, MapNotify and UnmapNotify to know if the
102      * window is mapped (and if the display is useful), and ClientMessages
103      * to intercept window destruction requests */
104
105     b_resized = 0;
106     while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
107                               StructureNotifyMask | KeyPressMask |
108                               ButtonPressMask | ButtonReleaseMask | 
109                               PointerMotionMask | Button1MotionMask , &xevent )
110            == True )
111     {
112         /* ConfigureNotify event: prepare  */
113         if( (xevent.type == ConfigureNotify)
114           && ((xevent.xconfigure.width != p_vout->p_sys->i_window_width)
115              || (xevent.xconfigure.height != p_vout->p_sys->i_window_height)) )
116         {
117             /* Update dimensions */
118             b_resized = 1;
119             p_vout->p_sys->i_window_width = xevent.xconfigure.width;
120             p_vout->p_sys->i_window_height = xevent.xconfigure.height;
121         }
122         /* MapNotify event: change window status and disable screen saver */
123         else if( xevent.type == MapNotify)
124         {
125             if( (p_vout != NULL) && !p_vout->b_active )
126             {
127                 _M( XCommonDisableScreenSaver ) ( p_vout );
128                 p_vout->b_active = 1;
129             }
130         }
131         /* UnmapNotify event: change window status and enable screen saver */
132         else if( xevent.type == UnmapNotify )
133         {
134             if( (p_vout != NULL) && p_vout->b_active )
135             {
136                 _M( XCommonEnableScreenSaver ) ( p_vout );
137                 p_vout->b_active = 0;
138             }
139         }
140         /* Keyboard event */
141         else if( xevent.type == KeyPress )
142         {
143             /* We may have keys like F1 trough F12, ESC ... */
144             x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
145                                              xevent.xkey.keycode, 0 );
146             switch( x_key_symbol )
147             {
148                  case XK_Escape:
149                      p_main->p_intf->b_die = 1;
150                      break;
151                  case XK_Menu:
152                      p_main->p_intf->b_menu_change = 1;
153                      break;
154                  default:
155                      /* "Normal Keys"
156                       * The reason why I use this instead of XK_0 is that 
157                       * with XLookupString, we don't have to care about
158                       * keymaps. */
159
160                     if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
161                     {
162                         /* FIXME: handle stuff here */
163                         switch( i_key )
164                         {
165                         case 'q':
166                         case 'Q':
167                             p_main->p_intf->b_die = 1;
168                             break;
169                         case 'f':
170                         case 'F':
171                             p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
172                             break;
173
174                         case '0': network_ChannelJoin( 0 ); break;
175                         case '1': network_ChannelJoin( 1 ); break;
176                         case '2': network_ChannelJoin( 2 ); break;
177                         case '3': network_ChannelJoin( 3 ); break;
178                         case '4': network_ChannelJoin( 4 ); break;
179                         case '5': network_ChannelJoin( 5 ); break;
180                         case '6': network_ChannelJoin( 6 ); break;
181                         case '7': network_ChannelJoin( 7 ); break;
182                         case '8': network_ChannelJoin( 8 ); break;
183                         case '9': network_ChannelJoin( 9 ); break;
184
185                         default:
186                             intf_DbgMsg( "vout: unhandled key '%c' (%i)", 
187                                          (char)i_key, i_key );
188                             break;
189                         }
190                     }
191                 break;
192             }
193         }
194         /* Mouse click */
195         else if( xevent.type == ButtonPress )
196         {
197             switch( ((XButtonEvent *)&xevent)->button )
198             {
199                 case Button1:
200                     /* In this part we will eventually manage
201                      * clicks for DVD navigation for instance. For the
202                      * moment just pause the stream. */
203                     input_SetStatus( p_main->p_intf->p_input,
204                                      INPUT_STATUS_PAUSE );
205                     break;
206             }
207         }
208         /* Mouse release */
209         else if( xevent.type == ButtonRelease )
210         {
211             switch( ((XButtonEvent *)&xevent)->button )
212             {
213                 case Button3:
214                     /* FIXME: need locking ! */
215                     p_main->p_intf->b_menu_change = 1;
216                     break;
217             }
218         }
219         /* Mouse move */
220         else if( xevent.type == MotionNotify )
221         {
222             p_vout->p_sys->i_time_mouse_last_moved = mdate();
223             if( ! p_vout->p_sys->b_mouse_pointer_visible )
224             {
225                 _M( XCommonToggleMousePointer ) ( p_vout ); 
226             }
227         }
228         /* Other event */
229         else
230         {
231             intf_WarnMsg( 3, "vout: unhandled event %d received", xevent.type );
232         }
233     }
234
235     /* Handle events for YUV video output sub-window */
236     while( XCheckWindowEvent( p_vout->p_sys->p_display,
237                               p_vout->p_sys->yuv_window,
238                               ExposureMask, &xevent ) == True )
239     {
240         /* Window exposed (only handled if stream playback is paused) */
241         if( xevent.type == Expose )
242         {
243             if( ((XExposeEvent *)&xevent)->count == 0 )
244             {
245                 /* (if this is the last a collection of expose events...) */
246                 if( p_main->p_intf->p_input != NULL )
247                 {
248                     if( PAUSE_S ==
249                             p_main->p_intf->p_input->stream.control.i_status )
250                     {
251 /*                        XVideoDisplay( p_vout )*/;
252                     }
253                 }
254             }
255         }
256     }
257
258     /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
259      * are handled - according to the man pages, the format is always 32
260      * in this case */
261     while( XCheckTypedEvent( p_vout->p_sys->p_display,
262                              ClientMessage, &xevent ) )
263     {
264         if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
265             && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
266         {
267             p_main->p_intf->b_die = 1;
268         }
269         else
270         {
271             intf_DbgMsg( "vout: unhandled ClientMessage received" );
272         }
273     }
274
275     if ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
276     {
277         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
278
279         p_vout->b_fullscreen = !p_vout->b_fullscreen;
280
281         /* Get rid of the old window */
282         _M( XCommonDestroyWindow ) ( p_vout );
283
284         /* And create a new one */
285         if( _M( XCommonCreateWindow ) ( p_vout ) )
286         {
287             intf_ErrMsg( "vout error: cannot create X11 window" );
288             XCloseDisplay( p_vout->p_sys->p_display );
289
290             free( p_vout->p_sys );
291             return( 1 );
292         }
293
294     }
295
296 #ifdef MODULE_NAME_IS_x11
297     /*
298      * Handle vout window resizing
299      */
300     if( b_resized )
301     {
302         /* If interface window has been resized, change vout size */
303         intf_DbgMsg( "vout: resizing output window" );
304         p_vout->i_width =  p_vout->p_sys->i_width;
305         p_vout->i_height = p_vout->p_sys->i_height;
306         p_vout->i_changes |= VOUT_SIZE_CHANGE;
307     }
308     else if( (p_vout->i_width  != p_vout->p_sys->i_width) ||
309              (p_vout->i_height != p_vout->p_sys->i_height) )
310     {
311         /* If video output size has changed, change interface window size */
312         intf_DbgMsg( "vout: resizing output window" );
313         p_vout->p_sys->i_width =    p_vout->i_width;
314         p_vout->p_sys->i_height =   p_vout->i_height;
315         XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
316                        p_vout->p_sys->i_width, p_vout->p_sys->i_height );
317     }
318     /*
319      * Color/Grayscale or gamma change: in 8bpp, just change the colormap
320      */
321     if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE)
322         && (p_vout->i_screen_depth == 8) )
323     {
324         /* FIXME: clear flags ?? */
325     }
326
327     /*
328      * Size change
329      */
330     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
331     {
332         intf_DbgMsg( "vout info: resizing window" );
333         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
334
335         /* Resize window */
336         XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
337                        p_vout->i_width, p_vout->i_height );
338
339         /* Destroy XImages to change their size */
340         vout_End( p_vout );
341
342         /* Recreate XImages. If SysInit failed, the thread can't go on. */
343         if( vout_Init( p_vout ) )
344         {
345             intf_ErrMsg( "vout error: cannot resize display" );
346             return( 1 );
347        }
348
349         /* Tell the video output thread that it will need to rebuild YUV
350          * tables. This is needed since conversion buffer size may have
351          * changed */
352         p_vout->i_changes |= VOUT_YUV_CHANGE;
353         intf_Msg( "vout: video display resized (%dx%d)",
354                   p_vout->i_width, p_vout->i_height);
355     }
356 #else
357     /*
358      * Size change
359      */
360     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
361     {
362         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
363
364         p_vout->i_width = p_vout->p_sys->i_window_width;
365         p_vout->i_height = p_vout->p_sys->i_window_height;
366
367         intf_WarnMsg( 3, "vout: video display resized (%dx%d)",
368                       p_vout->i_width, p_vout->i_height );
369     }
370 #endif
371
372     /* Autohide Cursour */
373     if( mdate() - p_vout->p_sys->i_time_mouse_last_moved > 2000000 )
374     {
375         /* Hide the mouse automatically */
376         if( p_vout->p_sys->b_mouse_pointer_visible )
377         {
378             _M( XCommonToggleMousePointer ) ( p_vout ); 
379         }
380     }
381
382     return 0;
383 }
384
385 /*****************************************************************************
386  * XCommonCreateWindow: open and set-up X11 main window
387  *****************************************************************************/
388 int _M( XCommonCreateWindow ) ( vout_thread_t *p_vout )
389 {
390     XSizeHints              xsize_hints;
391     XSetWindowAttributes    xwindow_attributes;
392     XGCValues               xgcvalues;
393     XEvent                  xevent;
394     Atom                    prop;
395     mwmhints_t              mwmhints;
396
397     boolean_t               b_expose;
398     boolean_t               b_configure_notify;
399     boolean_t               b_map_notify;
400
401     /* If we're full screen, we're full screen! */
402     if( p_vout->b_fullscreen ) 
403     {
404         p_vout->p_sys->i_window_width =
405            DisplayWidth( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
406         p_vout->p_sys->i_window_height =
407            DisplayHeight( p_vout->p_sys->p_display, p_vout->p_sys->i_screen ); 
408     }
409     else
410     {
411         /* Set main window's size */
412         p_vout->p_sys->i_window_width = p_vout->i_width;
413         p_vout->p_sys->i_window_height = p_vout->i_height;
414     }
415
416     /* Prepare window manager hints and properties */
417     xsize_hints.base_width          = p_vout->p_sys->i_window_width;
418     xsize_hints.base_height         = p_vout->p_sys->i_window_height;
419     xsize_hints.flags               = PSize;
420     p_vout->p_sys->wm_protocols     = XInternAtom( p_vout->p_sys->p_display,
421                                                    "WM_PROTOCOLS", True );
422     p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
423                                                    "WM_DELETE_WINDOW", True );
424
425     /* Prepare window attributes */
426     xwindow_attributes.backing_store = Always;       /* save the hidden part */
427     xwindow_attributes.background_pixel = BlackPixel( p_vout->p_sys->p_display,
428                                                       p_vout->p_sys->i_screen );
429     xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
430     
431
432     /* Create the window and set hints - the window must receive ConfigureNotify
433      * events, and, until it is displayed, Expose and MapNotify events. */
434
435     p_vout->p_sys->window =
436         XCreateWindow( p_vout->p_sys->p_display,
437                        DefaultRootWindow( p_vout->p_sys->p_display ),
438                        0, 0,
439                        p_vout->p_sys->i_window_width,
440                        p_vout->p_sys->i_window_height,
441 #ifdef MODULE_NAME_IS_x11
442                        /* XXX - what's this ? */
443                        0,
444 #else
445                        1,
446 #endif
447                        0, InputOutput, 0,
448                        CWBackingStore | CWBackPixel | CWEventMask,
449                        &xwindow_attributes );
450
451     if ( p_vout->b_fullscreen )
452     {
453         prop = XInternAtom(p_vout->p_sys->p_display, "_MOTIF_WM_HINTS", False);
454         mwmhints.flags = MWM_HINTS_DECORATIONS;
455         mwmhints.decorations = 0;
456         XChangeProperty( p_vout->p_sys->p_display, p_vout->p_sys->window,
457                          prop, prop, 32, PropModeReplace,
458                          (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS );
459
460         XSetTransientForHint( p_vout->p_sys->p_display,
461                               p_vout->p_sys->window, None );
462         XRaiseWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
463     }
464
465     /* Set window manager hints and properties: size hints, command,
466      * window's name, and accepted protocols */
467     XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
468                        &xsize_hints );
469     XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
470                  p_main->ppsz_argv, p_main->i_argc );
471     XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
472 #ifdef MODULE_NAME_IS_x11
473                 VOUT_TITLE " (X11 output)"
474 #else
475                 VOUT_TITLE " (XVideo output)"
476 #endif
477               );
478
479     if( (p_vout->p_sys->wm_protocols == None)        /* use WM_DELETE_WINDOW */
480         || (p_vout->p_sys->wm_delete_window == None)
481         || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
482                              &p_vout->p_sys->wm_delete_window, 1 ) )
483     {
484         /* WM_DELETE_WINDOW is not supported by window manager */
485         intf_Msg( "vout error: missing or bad window manager" );
486     }
487
488     /* Creation of a graphic context that doesn't generate a GraphicsExpose
489      * event when using functions like XCopyArea */
490     xgcvalues.graphics_exposures = False;
491     p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
492                                    p_vout->p_sys->window,
493                                    GCGraphicsExposures, &xgcvalues);
494
495     /* Send orders to server, and wait until window is displayed - three
496      * events must be received: a MapNotify event, an Expose event allowing
497      * drawing in the window, and a ConfigureNotify to get the window
498      * dimensions. Once those events have been received, only ConfigureNotify
499      * events need to be received. */
500     b_expose = 0;
501     b_configure_notify = 0;
502     b_map_notify = 0;
503     XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
504     do
505     {
506         XNextEvent( p_vout->p_sys->p_display, &xevent);
507         if( (xevent.type == Expose)
508             && (xevent.xexpose.window == p_vout->p_sys->window) )
509         {
510             b_expose = 1;
511         }
512         else if( (xevent.type == MapNotify)
513                  && (xevent.xmap.window == p_vout->p_sys->window) )
514         {
515             b_map_notify = 1;
516         }
517         else if( (xevent.type == ConfigureNotify)
518                  && (xevent.xconfigure.window == p_vout->p_sys->window) )
519         {
520             b_configure_notify = 1;
521             p_vout->p_sys->i_window_width = xevent.xconfigure.width;
522             p_vout->p_sys->i_window_height = xevent.xconfigure.height;
523         }
524     } while( !( b_expose && b_configure_notify && b_map_notify ) );
525
526     XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
527                   StructureNotifyMask | KeyPressMask |
528                   ButtonPressMask | ButtonReleaseMask | 
529                   PointerMotionMask );
530
531     if( p_vout->b_fullscreen )
532     {
533         XSetInputFocus( p_vout->p_sys->p_display, p_vout->p_sys->window,
534                         RevertToNone, CurrentTime );
535         XMoveWindow( p_vout->p_sys->p_display, p_vout->p_sys->window, 0, 0 );
536     }
537
538 #ifdef MODULE_NAME_IS_x11
539     if( XDefaultDepth(p_vout->p_sys->p_display, p_vout->p_sys->i_screen) == 8 )
540     {
541         /* Allocate a new palette */
542         p_vout->p_sys->colormap =
543             XCreateColormap( p_vout->p_sys->p_display,
544                              DefaultRootWindow( p_vout->p_sys->p_display ),
545                              DefaultVisual( p_vout->p_sys->p_display,
546                                             p_vout->p_sys->i_screen ),
547                              AllocAll );
548
549         xwindow_attributes.colormap = p_vout->p_sys->colormap;
550         XChangeWindowAttributes( p_vout->p_sys->p_display,
551                                  p_vout->p_sys->window,
552                                  CWColormap, &xwindow_attributes );
553     }
554
555 #else
556     /* Create YUV output sub-window. */
557     p_vout->p_sys->yuv_window=XCreateSimpleWindow( p_vout->p_sys->p_display,
558                          p_vout->p_sys->window, 0, 0, 1, 1, 0,
559                          BlackPixel( p_vout->p_sys->p_display,
560                                          p_vout->p_sys->i_screen ),
561                          WhitePixel( p_vout->p_sys->p_display,
562                                          p_vout->p_sys->i_screen ) );
563
564     p_vout->p_sys->yuv_gc = XCreateGC( p_vout->p_sys->p_display,
565                                        p_vout->p_sys->yuv_window,
566                                        GCGraphicsExposures, &xgcvalues );
567     
568     XSetWindowBackground( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
569              BlackPixel(p_vout->p_sys->p_display, p_vout->p_sys->i_screen ) );
570     
571     XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window );
572     XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
573                   ExposureMask );
574 #endif
575
576     /* If the cursor was formerly blank than blank it again */
577     if( !p_vout->p_sys->b_mouse_pointer_visible )
578     {
579         _M( XCommonToggleMousePointer ) ( p_vout );
580         _M( XCommonToggleMousePointer ) ( p_vout );
581     }
582
583     XSync( p_vout->p_sys->p_display, False );
584
585     /* At this stage, the window is open, displayed, and ready to
586      * receive data */
587
588     return( 0 );
589 }
590
591 void _M( XCommonDestroyWindow ) ( vout_thread_t *p_vout )
592 {
593     XSync( p_vout->p_sys->p_display, False );
594
595 #ifdef MODULE_NAME_IS_xvideo
596     XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->yuv_gc );
597     XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window );
598 #endif
599
600     XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
601     XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
602     XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
603 }
604
605 /*****************************************************************************
606  * XCommonEnableScreenSaver: enable screen saver
607  *****************************************************************************
608  * This function enable the screen saver on a display after it had been
609  * disabled by XDisableScreenSaver. Both functions use a counter mechanism to
610  * know wether the screen saver can be activated or not: if n successive calls
611  * are made to XDisableScreenSaver, n successive calls to XEnableScreenSaver
612  * will be required before the screen saver could effectively be activated.
613  *****************************************************************************/
614 void _M( XCommonEnableScreenSaver ) ( vout_thread_t *p_vout )
615 {
616     intf_DbgMsg( "vout: enabling screen saver" );
617     XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
618                      p_vout->p_sys->i_ss_interval,
619                      p_vout->p_sys->i_ss_blanking,
620                      p_vout->p_sys->i_ss_exposure );
621 }
622
623 /*****************************************************************************
624  * XCommonDisableScreenSaver: disable screen saver
625  *****************************************************************************
626  * See XEnableScreenSaver
627  *****************************************************************************/
628 void _M( XCommonDisableScreenSaver ) ( vout_thread_t *p_vout )
629 {
630     /* Save screen saver informations */
631     XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
632                      &p_vout->p_sys->i_ss_interval,
633                      &p_vout->p_sys->i_ss_blanking,
634                      &p_vout->p_sys->i_ss_exposure );
635
636     /* Disable screen saver */
637     intf_DbgMsg( "vout: disabling screen saver" );
638     XSetScreenSaver( p_vout->p_sys->p_display, 0,
639                      p_vout->p_sys->i_ss_interval,
640                      p_vout->p_sys->i_ss_blanking,
641                      p_vout->p_sys->i_ss_exposure );
642
643 #ifdef MODULE_NAME_IS_xvideo
644     DPMSDisable( p_vout->p_sys->p_display );
645 #endif
646 }
647
648 /*****************************************************************************
649  * XCommonToggleMousePointer: hide or show the mouse pointer
650  *****************************************************************************
651  * This function hides the X pointer if it is visible by putting it at
652  * coordinates (32,32) and setting the pointer sprite to a blank one. To
653  * show it again, we disable the sprite and restore the original coordinates.
654  *****************************************************************************/
655 void _M( XCommonToggleMousePointer ) ( vout_thread_t *p_vout )
656 {
657     if( p_vout->p_sys->b_mouse_pointer_visible )
658     {
659         XDefineCursor( p_vout->p_sys->p_display,
660                        p_vout->p_sys->window,
661                        p_vout->p_sys->blank_cursor );
662         p_vout->p_sys->b_mouse_pointer_visible = 0;
663     }
664     else
665     {
666         XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
667         p_vout->p_sys->b_mouse_pointer_visible = 1;
668     }
669 }
670