xcommon.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:122k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * xcommon.c: Functions common to the X11 and XVideo plugins
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2006 the VideoLAN team
  5.  * $Id: adc5e791cee026df57ea24f9863b536cff060a3c $
  6.  *
  7.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  8.  *          Sam Hocevar <sam@zoy.org>
  9.  *          David Kennedy <dkennedy@tinytoad.com>
  10.  *          Gildas Bazin <gbazin@videolan.org>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  25.  *****************************************************************************/
  26. /*****************************************************************************
  27.  * Preamble
  28.  *****************************************************************************/
  29. #ifdef HAVE_CONFIG_H
  30. # include "config.h"
  31. #endif
  32. #include <vlc_common.h>
  33. #include <vlc_interface.h>
  34. #include <vlc_playlist.h>
  35. #include <vlc_vout.h>
  36. #include <vlc_window.h>
  37. #include <vlc_keys.h>
  38. #include <errno.h>                                                 /* ENOMEM */
  39. #ifdef HAVE_MACHINE_PARAM_H
  40.     /* BSD */
  41. #   include <machine/param.h>
  42. #   include <sys/types.h>                                  /* typedef ushort */
  43. #   include <sys/ipc.h>
  44. #endif
  45. #ifndef WIN32
  46. #   include <netinet/in.h>                            /* BSD: struct in_addr */
  47. #endif
  48. #ifdef HAVE_XSP
  49. #include <X11/extensions/Xsp.h>
  50. #endif
  51. #ifdef HAVE_SYS_SHM_H
  52. #   include <sys/shm.h>                                /* shmget(), shmctl() */
  53. #endif
  54. #include <X11/Xlib.h>
  55. #include <X11/Xproto.h>
  56. #include <X11/Xmd.h>
  57. #include <X11/Xutil.h>
  58. #include <X11/keysym.h>
  59. #include <X11/XF86keysym.h>
  60. #ifdef HAVE_SYS_SHM_H
  61. #   include <X11/extensions/XShm.h>
  62. #endif
  63. #ifdef DPMSINFO_IN_DPMS_H
  64. #   include <X11/extensions/dpms.h>
  65. #endif
  66. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  67. #   include <X11/extensions/Xv.h>
  68. #   include <X11/extensions/Xvlib.h>
  69. #endif
  70. #ifdef MODULE_NAME_IS_glx
  71. #   include <GL/glx.h>
  72. #endif
  73. #ifdef HAVE_XINERAMA
  74. #   include <X11/extensions/Xinerama.h>
  75. #endif
  76. #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
  77. #   include <X11/extensions/xf86vmode.h>
  78. #endif
  79. #ifdef MODULE_NAME_IS_xvmc
  80. #   include <X11/extensions/vldXvMC.h>
  81. #   include "../../codec/xvmc/accel_xvmc.h"
  82. #endif
  83. #include "xcommon.h"
  84. /*****************************************************************************
  85.  * Local prototypes
  86.  *****************************************************************************/
  87. int  Activate   ( vlc_object_t * );
  88. void Deactivate ( vlc_object_t * );
  89. static int  InitVideo      ( vout_thread_t * );
  90. static void EndVideo       ( vout_thread_t * );
  91. static void DisplayVideo   ( vout_thread_t *, picture_t * );
  92. static int  ManageVideo    ( vout_thread_t * );
  93. static int  Control        ( vout_thread_t *, int, va_list );
  94. static int  InitDisplay    ( vout_thread_t * );
  95. static int  CreateWindow   ( vout_thread_t *, x11_window_t * );
  96. static void DestroyWindow  ( vout_thread_t *, x11_window_t * );
  97. static int  NewPicture     ( vout_thread_t *, picture_t * );
  98. static void FreePicture    ( vout_thread_t *, picture_t * );
  99. #ifdef HAVE_SYS_SHM_H
  100. static int i_shm_major = 0;
  101. #endif
  102. static void ToggleFullScreen      ( vout_thread_t * );
  103. static void EnableXScreenSaver    ( vout_thread_t * );
  104. static void DisableXScreenSaver   ( vout_thread_t * );
  105. static void CreateCursor   ( vout_thread_t * );
  106. static void DestroyCursor  ( vout_thread_t * );
  107. static void ToggleCursor   ( vout_thread_t * );
  108. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  109. static int  XVideoGetPort    ( vout_thread_t *, vlc_fourcc_t, picture_heap_t * );
  110. static void XVideoReleasePort( vout_thread_t *, int );
  111. #endif
  112. #ifdef MODULE_NAME_IS_x11
  113. static void SetPalette     ( vout_thread_t *,
  114.                              uint16_t *, uint16_t *, uint16_t * );
  115. #endif
  116. #ifdef MODULE_NAME_IS_xvmc
  117. static void RenderVideo    ( vout_thread_t *, picture_t * );
  118. static int  xvmc_check_yv12( Display *display, XvPortID port );
  119. static void xvmc_update_XV_DOUBLE_BUFFER( vout_thread_t *p_vout );
  120. #endif
  121. static void TestNetWMSupport( vout_thread_t * );
  122. static int ConvertKey( int );
  123. static int WindowOnTop( vout_thread_t *, bool );
  124. static int X11ErrorHandler( Display *, XErrorEvent * );
  125. #ifdef HAVE_XSP
  126. static void EnablePixelDoubling( vout_thread_t *p_vout );
  127. static void DisablePixelDoubling( vout_thread_t *p_vout );
  128. #endif
  129. #ifdef HAVE_OSSO
  130. static const int i_backlight_on_interval = 300;
  131. #endif
  132. /*****************************************************************************
  133.  * Activate: allocate X11 video thread output method
  134.  *****************************************************************************
  135.  * This function allocate and initialize a X11 vout method. It uses some of the
  136.  * vout properties to choose the window size, and change them according to the
  137.  * actual properties of the display.
  138.  *****************************************************************************/
  139. int Activate ( vlc_object_t *p_this )
  140. {
  141.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  142.     char *        psz_display;
  143. #if defined(MODULE_NAME_IS_xvmc)
  144.     char *psz_value;
  145. #endif
  146. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  147.     char *       psz_chroma;
  148.     vlc_fourcc_t i_chroma = 0;
  149.     bool   b_chroma = 0;
  150. #endif
  151.     p_vout->pf_init = InitVideo;
  152.     p_vout->pf_end = EndVideo;
  153.     p_vout->pf_manage = ManageVideo;
  154. #ifdef MODULE_NAME_IS_xvmc
  155.     p_vout->pf_render = RenderVideo;
  156. #else
  157.     p_vout->pf_render = NULL;
  158. #endif
  159.     p_vout->pf_display = DisplayVideo;
  160.     p_vout->pf_control = Control;
  161.     /* Allocate structure */
  162.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  163.     if( p_vout->p_sys == NULL )
  164.         return VLC_ENOMEM;
  165.     /* key and mouse event handling */
  166.     p_vout->p_sys->i_vout_event = var_CreateGetInteger( p_vout, "vout-event" );
  167.     /* Open display, using the "display" config variable or the DISPLAY
  168.      * environment variable */
  169.     psz_display = config_GetPsz( p_vout, MODULE_STRING "-display" );
  170.     p_vout->p_sys->p_display = XOpenDisplay( psz_display );
  171.     if( p_vout->p_sys->p_display == NULL )                         /* error */
  172.     {
  173.         msg_Err( p_vout, "cannot open display %s",
  174.                          XDisplayName( psz_display ) );
  175.         free( p_vout->p_sys );
  176.         free( psz_display );
  177.         return VLC_EGENERIC;
  178.     }
  179.     free( psz_display );
  180.     /* Replace error handler so we can intercept some non-fatal errors */
  181.     XSetErrorHandler( X11ErrorHandler );
  182.     /* Get a screen ID matching the XOpenDisplay return value */
  183.     p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
  184. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  185.     psz_chroma = config_GetPsz( p_vout, "xvideo-chroma" );
  186.     if( psz_chroma )
  187.     {
  188.         if( strlen( psz_chroma ) >= 4 )
  189.         {
  190.             /* Do not use direct assignment because we are not sure of the
  191.              * alignment. */
  192.             memcpy(&i_chroma, psz_chroma, 4);
  193.             b_chroma = 1;
  194.         }
  195.         free( psz_chroma );
  196.     }
  197.     if( b_chroma )
  198.     {
  199.         msg_Dbg( p_vout, "forcing chroma 0x%.8x (%4.4s)",
  200.                  i_chroma, (char*)&i_chroma );
  201.     }
  202.     else
  203.     {
  204.         i_chroma = p_vout->render.i_chroma;
  205.     }
  206.     /* Check that we have access to an XVideo port providing this chroma */
  207.     p_vout->p_sys->i_xvport = XVideoGetPort( p_vout, VLC2X11_FOURCC(i_chroma),
  208.                                              &p_vout->output );
  209.     if( p_vout->p_sys->i_xvport < 0 )
  210.     {
  211.         /* If a specific chroma format was requested, then we don't try to
  212.          * be cleverer than the user. He knew pretty well what he wanted. */
  213.         if( b_chroma )
  214.         {
  215.             XCloseDisplay( p_vout->p_sys->p_display );
  216.             free( p_vout->p_sys );
  217.             return VLC_EGENERIC;
  218.         }
  219.         /* It failed, but it's not completely lost ! We try to open an
  220.          * XVideo port for an YUY2 picture. We'll need to do an YUV
  221.          * conversion, but at least it has got scaling. */
  222.         p_vout->p_sys->i_xvport =
  223.                         XVideoGetPort( p_vout, X11_FOURCC('Y','U','Y','2'),
  224.                                                &p_vout->output );
  225.         if( p_vout->p_sys->i_xvport < 0 )
  226.         {
  227.             /* It failed, but it's not completely lost ! We try to open an
  228.              * XVideo port for a simple 16bpp RGB picture. We'll need to do
  229.              * an YUV conversion, but at least it has got scaling. */
  230.             p_vout->p_sys->i_xvport =
  231.                             XVideoGetPort( p_vout, X11_FOURCC('R','V','1','6'),
  232.                                                    &p_vout->output );
  233.             if( p_vout->p_sys->i_xvport < 0 )
  234.             {
  235.                 XCloseDisplay( p_vout->p_sys->p_display );
  236.                 free( p_vout->p_sys );
  237.                 return VLC_EGENERIC;
  238.             }
  239.         }
  240.     }
  241.     p_vout->output.i_chroma = X112VLC_FOURCC(p_vout->output.i_chroma);
  242. #elif defined(MODULE_NAME_IS_glx)
  243.     {
  244.         int i_opcode, i_evt, i_err = 0;
  245.         int i_maj, i_min = 0;
  246.         /* Check for GLX extension */
  247.         if( !XQueryExtension( p_vout->p_sys->p_display, "GLX",
  248.                               &i_opcode, &i_evt, &i_err ) )
  249.         {
  250.             msg_Err( p_this, "GLX extension not supported" );
  251.             XCloseDisplay( p_vout->p_sys->p_display );
  252.             free( p_vout->p_sys );
  253.             return VLC_EGENERIC;
  254.         }
  255.         if( !glXQueryExtension( p_vout->p_sys->p_display, &i_err, &i_evt ) )
  256.         {
  257.             msg_Err( p_this, "glXQueryExtension failed" );
  258.             XCloseDisplay( p_vout->p_sys->p_display );
  259.             free( p_vout->p_sys );
  260.             return VLC_EGENERIC;
  261.         }
  262.         /* Check GLX version */
  263.         if (!glXQueryVersion( p_vout->p_sys->p_display, &i_maj, &i_min ) )
  264.         {
  265.             msg_Err( p_this, "glXQueryVersion failed" );
  266.             XCloseDisplay( p_vout->p_sys->p_display );
  267.             free( p_vout->p_sys );
  268.             return VLC_EGENERIC;
  269.         }
  270.         if( i_maj <= 0 || ((i_maj == 1) && (i_min < 3)) )
  271.         {
  272.             p_vout->p_sys->b_glx13 = false;
  273.             msg_Dbg( p_this, "using GLX 1.2 API" );
  274.         }
  275.         else
  276.         {
  277.             p_vout->p_sys->b_glx13 = true;
  278.             msg_Dbg( p_this, "using GLX 1.3 API" );
  279.         }
  280.     }
  281. #endif
  282.     /* Create blank cursor (for mouse cursor autohiding) */
  283.     p_vout->p_sys->i_time_mouse_last_moved = mdate();
  284.     p_vout->p_sys->i_mouse_hide_timeout =
  285.         var_GetInteger(p_vout, "mouse-hide-timeout") * 1000;
  286.     p_vout->p_sys->b_mouse_pointer_visible = 1;
  287.     CreateCursor( p_vout );
  288.     /* Set main window's size */
  289.     p_vout->p_sys->original_window.i_width = p_vout->i_window_width;
  290.     p_vout->p_sys->original_window.i_height = p_vout->i_window_height;
  291.     var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  292.     /* Spawn base window - this window will include the video output window,
  293.      * but also command buttons, subtitles and other indicators */
  294.     if( CreateWindow( p_vout, &p_vout->p_sys->original_window ) )
  295.     {
  296.         msg_Err( p_vout, "cannot create X11 window" );
  297.         DestroyCursor( p_vout );
  298.         XCloseDisplay( p_vout->p_sys->p_display );
  299.         free( p_vout->p_sys );
  300.         return VLC_EGENERIC;
  301.     }
  302.     /* Open and initialize device. */
  303.     if( InitDisplay( p_vout ) )
  304.     {
  305.         msg_Err( p_vout, "cannot initialize X11 display" );
  306.         DestroyCursor( p_vout );
  307.         DestroyWindow( p_vout, &p_vout->p_sys->original_window );
  308.         XCloseDisplay( p_vout->p_sys->p_display );
  309.         free( p_vout->p_sys );
  310.         return VLC_EGENERIC;
  311.     }
  312.     /* Disable screen saver */
  313.     DisableXScreenSaver( p_vout );
  314.     /* Misc init */
  315.     p_vout->p_sys->b_altfullscreen = 0;
  316.     p_vout->p_sys->i_time_button_last_pressed = 0;
  317.     TestNetWMSupport( p_vout );
  318. #ifdef MODULE_NAME_IS_xvmc
  319.     p_vout->p_sys->p_last_subtitle_save = NULL;
  320.     psz_value = config_GetPsz( p_vout, "xvmc-deinterlace-mode" );
  321.     /* Look what method was requested */
  322.     //var_Create( p_vout, "xvmc-deinterlace-mode", VLC_VAR_STRING );
  323.     //var_Change( p_vout, "xvmc-deinterlace-mode", VLC_VAR_INHERITVALUE, &val, NULL );
  324.     if( psz_value )
  325.     {
  326.         if( (strcmp(psz_value, "bob") == 0) ||
  327.             (strcmp(psz_value, "blend") == 0) )
  328.            p_vout->p_sys->xvmc_deinterlace_method = 2;
  329.         else if (strcmp(psz_value, "discard") == 0)
  330.            p_vout->p_sys->xvmc_deinterlace_method = 1;
  331.         else
  332.            p_vout->p_sys->xvmc_deinterlace_method = 0;
  333.         free(psz_value );
  334.     }
  335.     else
  336.         p_vout->p_sys->xvmc_deinterlace_method = 0;
  337.     /* Look what method was requested */
  338.     //var_Create( p_vout, "xvmc-crop-style", VLC_VAR_STRING );
  339.     //var_Change( p_vout, "xvmc-crop-style", VLC_VAR_INHERITVALUE, &val, NULL );
  340.     psz_value = config_GetPsz( p_vout, "xvmc-crop-style" );
  341.     if( psz_value )
  342.     {
  343.         if( strncmp( psz_value, "eq", 2 ) == 0 )
  344.            p_vout->p_sys->xvmc_crop_style = 1;
  345.         else if( strncmp( psz_value, "4-16", 4 ) == 0)
  346.            p_vout->p_sys->xvmc_crop_style = 2;
  347.         else if( strncmp( psz_value, "16-4", 4 ) == 0)
  348.            p_vout->p_sys->xvmc_crop_style = 3;
  349.         else
  350.            p_vout->p_sys->xvmc_crop_style = 0;
  351.         free( psz_value );
  352.     }
  353.     else
  354.         p_vout->p_sys->xvmc_crop_style = 0;
  355.     msg_Dbg(p_vout, "Deinterlace = %d", p_vout->p_sys->xvmc_deinterlace_method);
  356.     msg_Dbg(p_vout, "Crop = %d", p_vout->p_sys->xvmc_crop_style);
  357.     if( checkXvMCCap( p_vout ) == VLC_EGENERIC )
  358.     {
  359.         msg_Err( p_vout, "no XVMC capability found" );
  360.         Deactivate( p_this );
  361.         return VLC_EGENERIC;
  362.     }
  363.     subpicture_t sub_pic;
  364.     sub_pic.p_sys = NULL;
  365.     p_vout->p_sys->last_date = 0;
  366. #endif
  367. #ifdef HAVE_XSP
  368.     p_vout->p_sys->i_hw_scale = 1;
  369. #endif
  370. #ifdef HAVE_OSSO
  371.     p_vout->p_sys->i_backlight_on_counter = i_backlight_on_interval;
  372.     p_vout->p_sys->p_octx = osso_initialize( "vlc", VERSION, 0, NULL );
  373.     if ( p_vout->p_sys->p_octx == NULL ) {
  374.         msg_Err( p_vout, "Could not get osso context" );
  375.     } else {
  376.         msg_Dbg( p_vout, "Initialized osso context" );
  377.     }
  378. #endif
  379.     /* Variable to indicate if the window should be on top of others */
  380.     /* Trigger a callback right now */
  381.     var_TriggerCallback( p_vout, "video-on-top" );
  382.     return VLC_SUCCESS;
  383. }
  384. /*****************************************************************************
  385.  * Deactivate: destroy X11 video thread output method
  386.  *****************************************************************************
  387.  * Terminate an output method created by Open
  388.  *****************************************************************************/
  389. void Deactivate ( vlc_object_t *p_this )
  390. {
  391.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  392.     /* If the fullscreen window is still open, close it */
  393.     if( p_vout->b_fullscreen )
  394.     {
  395.         ToggleFullScreen( p_vout );
  396.     }
  397.     /* Restore cursor if it was blanked */
  398.     if( !p_vout->p_sys->b_mouse_pointer_visible )
  399.     {
  400.         ToggleCursor( p_vout );
  401.     }
  402. #ifdef MODULE_NAME_IS_x11
  403.     /* Destroy colormap */
  404.     if( XDefaultDepth(p_vout->p_sys->p_display, p_vout->p_sys->i_screen) == 8 )
  405.     {
  406.         XFreeColormap( p_vout->p_sys->p_display, p_vout->p_sys->colormap );
  407.     }
  408. #elif defined(MODULE_NAME_IS_xvideo)
  409.     XVideoReleasePort( p_vout, p_vout->p_sys->i_xvport );
  410. #elif defined(MODULE_NAME_IS_xvmc)
  411.     if( p_vout->p_sys->xvmc_cap )
  412.     {
  413.         xvmc_context_writer_lock( &p_vout->p_sys->xvmc_lock );
  414.         xxmc_dispose_context( p_vout );
  415.         if( p_vout->p_sys->old_subpic )
  416.         {
  417.             xxmc_xvmc_free_subpicture( p_vout, p_vout->p_sys->old_subpic );
  418.             p_vout->p_sys->old_subpic = NULL;
  419.         }
  420.         if( p_vout->p_sys->new_subpic )
  421.         {
  422.             xxmc_xvmc_free_subpicture( p_vout, p_vout->p_sys->new_subpic );
  423.             p_vout->p_sys->new_subpic = NULL;
  424.         }
  425.         free( p_vout->p_sys->xvmc_cap );
  426.         xvmc_context_writer_unlock( &p_vout->p_sys->xvmc_lock );
  427.     }
  428. #endif
  429. #ifdef HAVE_XSP
  430.     DisablePixelDoubling(p_vout);
  431. #endif
  432.     DestroyCursor( p_vout );
  433.     EnableXScreenSaver( p_vout );
  434.     DestroyWindow( p_vout, &p_vout->p_sys->original_window );
  435.     XCloseDisplay( p_vout->p_sys->p_display );
  436.     /* Destroy structure */
  437. #ifdef MODULE_NAME_IS_xvmc
  438.     free_context_lock( &p_vout->p_sys->xvmc_lock );
  439. #endif
  440. #ifdef HAVE_OSSO
  441.     if ( p_vout->p_sys->p_octx != NULL ) {
  442.         msg_Dbg( p_vout, "Deinitializing osso context" );
  443.         osso_deinitialize( p_vout->p_sys->p_octx );
  444.     }
  445. #endif
  446.     free( p_vout->p_sys );
  447. }
  448. #ifdef MODULE_NAME_IS_xvmc
  449. #define XINE_IMGFMT_YV12 (('2'<<24)|('1'<<16)|('V'<<8)|'Y')
  450. /* called xlocked */
  451. static int xvmc_check_yv12( Display *display, XvPortID port )
  452. {
  453.     XvImageFormatValues *formatValues;
  454.     int                  formats;
  455.     int                  i;
  456.     formatValues = XvListImageFormats( display, port, &formats );
  457.     for( i = 0; i < formats; i++ )
  458.     {
  459.         if( ( formatValues[i].id == XINE_IMGFMT_YV12 ) &&
  460.             ( !( strncmp( formatValues[i].guid, "YV12", 4 ) ) ) )
  461.         {
  462.             XFree (formatValues);
  463.             return 0;
  464.         }
  465.     }
  466.     XFree (formatValues);
  467.     return 1;
  468. }
  469. static void xvmc_sync_surface( vout_thread_t *p_vout, XvMCSurface * srf )
  470. {
  471.     XvMCSyncSurface( p_vout->p_sys->p_display, srf );
  472. }
  473. static void xvmc_update_XV_DOUBLE_BUFFER( vout_thread_t *p_vout )
  474. {
  475.     Atom         atom;
  476.     int          xv_double_buffer;
  477.     xv_double_buffer = 1;
  478.     XLockDisplay( p_vout->p_sys->p_display );
  479.     atom = XInternAtom( p_vout->p_sys->p_display, "XV_DOUBLE_BUFFER", False );
  480. #if 0
  481.     XvSetPortAttribute (p_vout->p_sys->p_display, p_vout->p_sys->i_xvport, atom, xv_double_buffer);
  482. #endif
  483.     XvMCSetAttribute( p_vout->p_sys->p_display, &p_vout->p_sys->context, atom, xv_double_buffer );
  484.     XUnlockDisplay( p_vout->p_sys->p_display );
  485.     //xprintf(this->xine, XINE_VERBOSITY_DEBUG,
  486.     //    "video_out_xxmc: double buffering mode = %dn", xv_double_buffer);
  487. }
  488. static void RenderVideo( vout_thread_t *p_vout, picture_t *p_pic )
  489. {
  490.     vlc_xxmc_t *xxmc = NULL;
  491.     xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
  492.     xxmc = &p_pic->p_sys->xxmc_data;
  493.     if( (!xxmc->decoded ||
  494.         !xxmc_xvmc_surface_valid( p_vout, p_pic->p_sys->xvmc_surf )) )
  495.     {
  496.         xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  497.         return;
  498.     }
  499. #if 0
  500.     vlc_mutex_lock( &p_vout->lastsubtitle_lock );
  501.     if (p_vout->p_sys->p_last_subtitle != NULL)
  502.     {
  503.         if( p_vout->p_sys->p_last_subtitle_save != p_vout->p_sys->p_last_subtitle )
  504.         {
  505.             p_vout->p_sys->new_subpic =
  506.                 xxmc_xvmc_alloc_subpicture( p_vout, &p_vout->p_sys->context,
  507.                     p_vout->p_sys->xvmc_width,
  508.                     p_vout->p_sys->xvmc_height,
  509.                     p_vout->p_sys->xvmc_cap[p_vout->p_sys->xvmc_cur_cap].subPicType.id );
  510.             if (p_vout->p_sys->new_subpic)
  511.             {
  512.                 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
  513.                 XvMCClearSubpicture( p_vout->p_sys->p_display,
  514.                         p_vout->p_sys->new_subpic,
  515.                         0,
  516.                         0,
  517.                         p_vout->p_sys->xvmc_width,
  518.                         p_vout->p_sys->xvmc_height,
  519.                         0x00 );
  520.                 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
  521.                 clear_xx44_palette( &p_vout->p_sys->palette );
  522.                 if( sub_pic.p_sys == NULL )
  523.                 {
  524.                     sub_pic.p_sys = malloc( sizeof( picture_sys_t ) );
  525.                     if( sub_pic.p_sys != NULL )
  526.                     {
  527.                         sub_pic.p_sys->p_vout = p_vout;
  528.                         sub_pic.p_sys->xvmc_surf = NULL;
  529.                         sub_pic.p_sys->p_image = p_vout->p_sys->subImage;
  530.                     }
  531.                 }
  532.                 sub_pic.p_sys->p_image = p_vout->p_sys->subImage;
  533.                 sub_pic.p->p_pixels = sub_pic.p_sys->p_image->data;
  534.                 sub_pic.p->i_pitch = p_vout->output.i_width;
  535.                 memset( p_vout->p_sys->subImage->data, 0,
  536.                         (p_vout->p_sys->subImage->width * p_vout->p_sys->subImage->height) );
  537.                 if (p_vout->p_last_subtitle != NULL)
  538.                 {
  539.                     blend_xx44( p_vout->p_sys->subImage->data,
  540.                                 p_vout->p_last_subtitle,
  541.                                 p_vout->p_sys->subImage->width,
  542.                                 p_vout->p_sys->subImage->height,
  543.                                 p_vout->p_sys->subImage->width,
  544.                                 &p_vout->p_sys->palette,
  545.                                 (p_vout->p_sys->subImage->id == FOURCC_IA44) );
  546.                 }
  547.                 XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
  548.                 XvMCCompositeSubpicture( p_vout->p_sys->p_display,
  549.                                          p_vout->p_sys->new_subpic,
  550.                                          p_vout->p_sys->subImage,
  551.                                          0, /* overlay->x */
  552.                                          0, /* overlay->y */
  553.                                          p_vout->output.i_width, /* overlay->width, */
  554.                                          p_vout->output.i_height, /* overlay->height */
  555.                                          0, /* overlay->x */
  556.                                          0 ); /*overlay->y */
  557.                 XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
  558.                 if (p_vout->p_sys->old_subpic)
  559.                 {
  560.                     xxmc_xvmc_free_subpicture( p_vout,
  561.                                                p_vout->p_sys->old_subpic);
  562.                     p_vout->p_sys->old_subpic = NULL;
  563.                 }
  564.                 if (p_vout->p_sys->new_subpic)
  565.                 {
  566.                     p_vout->p_sys->old_subpic = p_vout->p_sys->new_subpic;
  567.                     p_vout->p_sys->new_subpic = NULL;
  568.                     xx44_to_xvmc_palette( &p_vout->p_sys->palette,
  569.                             p_vout->p_sys->xvmc_palette,
  570.                             0,
  571.                             p_vout->p_sys->old_subpic->num_palette_entries,
  572.                             p_vout->p_sys->old_subpic->entry_bytes,
  573.                             p_vout->p_sys->old_subpic->component_order );
  574.                     XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
  575.                     XvMCSetSubpicturePalette( p_vout->p_sys->p_display,
  576.                                               p_vout->p_sys->old_subpic,
  577.                                               p_vout->p_sys->xvmc_palette );
  578.                     XvMCFlushSubpicture( p_vout->p_sys->p_display,
  579.                                          p_vout->p_sys->old_subpic);
  580.                     XvMCSyncSubpicture( p_vout->p_sys->p_display,
  581.                                         p_vout->p_sys->old_subpic );
  582.                     XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
  583.                 }
  584.                 XVMCLOCKDISPLAY( p_vout->p_sys->p_display);
  585.                 if (p_vout->p_sys->xvmc_backend_subpic )
  586.                 {
  587.                     XvMCBlendSubpicture( p_vout->p_sys->p_display,
  588.                                          p_pic->p_sys->xvmc_surf,
  589.                                          p_vout->p_sys->old_subpic,
  590.                                          0,
  591.                                          0,
  592.                                          p_vout->p_sys->xvmc_width,
  593.                                          p_vout->p_sys->xvmc_height,
  594.                                          0,
  595.                                          0,
  596.                                          p_vout->p_sys->xvmc_width,
  597.                                          p_vout->p_sys->xvmc_height );
  598.                 }
  599.                 else
  600.                 {
  601.                     XvMCBlendSubpicture2( p_vout->p_sys->p_display,
  602.                                           p_pic->p_sys->xvmc_surf,
  603.                                           p_pic->p_sys->xvmc_surf,
  604.                                           p_vout->p_sys->old_subpic,
  605.                                           0,
  606.                                           0,
  607.                                           p_vout->p_sys->xvmc_width,
  608.                                           p_vout->p_sys->xvmc_height,
  609.                                           0,
  610.                                           0,
  611.                                           p_vout->p_sys->xvmc_width,
  612.                                           p_vout->p_sys->xvmc_height );
  613.                }
  614.                XVMCUNLOCKDISPLAY(p_vout->p_sys->p_display);
  615.             }
  616.         }
  617.         else
  618.         {
  619.             XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
  620.             if( p_vout->p_sys->xvmc_backend_subpic )
  621.             {
  622.                 XvMCBlendSubpicture( p_vout->p_sys->p_display,
  623.                                      p_pic->p_sys->xvmc_surf,
  624.                                      p_vout->p_sys->old_subpic,
  625.                                      0, 0,
  626.                                      p_vout->p_sys->xvmc_width,
  627.                                      p_vout->p_sys->xvmc_height,
  628.                                      0, 0,
  629.                                      p_vout->p_sys->xvmc_width,
  630.                                      p_vout->p_sys->xvmc_height );
  631.             }
  632.             else
  633.             {
  634.                 XvMCBlendSubpicture2( p_vout->p_sys->p_display,
  635.                                       p_pic->p_sys->xvmc_surf,
  636.                                       p_pic->p_sys->xvmc_surf,
  637.                                       p_vout->p_sys->old_subpic,
  638.                                       0, 0,
  639.                                       p_vout->p_sys->xvmc_width,
  640.                                       p_vout->p_sys->xvmc_height,
  641.                                       0, 0,
  642.                                       p_vout->p_sys->xvmc_width,
  643.                                       p_vout->p_sys->xvmc_height );
  644.             }
  645.             XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
  646.         }
  647.     }
  648.     p_vout->p_sys->p_last_subtitle_save = p_vout->p_last_subtitle;
  649.     vlc_mutex_unlock( &p_vout->lastsubtitle_lock );
  650. #endif
  651.     xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  652. }
  653. #endif
  654. #ifdef HAVE_XSP
  655. /*****************************************************************************
  656.  * EnablePixelDoubling: Enables pixel doubling
  657.  *****************************************************************************
  658.  * Checks if the double size image fits in current window, and enables pixel
  659.  * doubling accordingly. The i_hw_scale is the integer scaling factor.
  660.  *****************************************************************************/
  661. static void EnablePixelDoubling( vout_thread_t *p_vout )
  662. {
  663.     int i_hor_scale = ( p_vout->p_sys->p_win->i_width ) / p_vout->render.i_width;
  664.     int i_vert_scale =  ( p_vout->p_sys->p_win->i_height ) / p_vout->render.i_height;
  665.     if ( ( i_hor_scale > 1 ) && ( i_vert_scale > 1 ) ) {
  666.         p_vout->p_sys->i_hw_scale = 2;
  667.         msg_Dbg( p_vout, "Enabling pixel doubling, scaling factor %d", p_vout->p_sys->i_hw_scale );
  668.         XSPSetPixelDoubling( p_vout->p_sys->p_display, 0, 1 );
  669.     }
  670. }
  671. /*****************************************************************************
  672.  * DisablePixelDoubling: Disables pixel doubling
  673.  *****************************************************************************
  674.  * The scaling factor i_hw_scale is reset to the no-scaling value 1.
  675.  *****************************************************************************/
  676. static void DisablePixelDoubling( vout_thread_t *p_vout )
  677. {
  678.     if ( p_vout->p_sys->i_hw_scale > 1 ) {
  679.         msg_Dbg( p_vout, "Disabling pixel doubling" );
  680.         XSPSetPixelDoubling( p_vout->p_sys->p_display, 0, 0 );
  681.         p_vout->p_sys->i_hw_scale = 1;
  682.     }
  683. }
  684. #endif
  685. /*****************************************************************************
  686.  * InitVideo: initialize X11 video thread output method
  687.  *****************************************************************************
  688.  * This function create the XImages needed by the output thread. It is called
  689.  * at the beginning of the thread, but also each time the window is resized.
  690.  *****************************************************************************/
  691. static int InitVideo( vout_thread_t *p_vout )
  692. {
  693.     unsigned int i_index = 0;
  694.     picture_t *p_pic;
  695.     I_OUTPUTPICTURES = 0;
  696. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  697.     /* Initialize the output structure; we already found an XVideo port,
  698.      * and the corresponding chroma we will be using. Since we can
  699.      * arbitrary scale, stick to the coordinates and aspect. */
  700.     p_vout->output.i_width  = p_vout->render.i_width;
  701.     p_vout->output.i_height = p_vout->render.i_height;
  702.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  703.     p_vout->fmt_out = p_vout->fmt_in;
  704.     p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
  705. #if XvVersion < 2 || ( XvVersion == 2 && XvRevision < 2 )
  706.     switch( p_vout->output.i_chroma )
  707.     {
  708.         case VLC_FOURCC('R','V','1','6'):
  709. #if defined( WORDS_BIGENDIAN )
  710.             p_vout->output.i_rmask = 0xf800;
  711.             p_vout->output.i_gmask = 0x07e0;
  712.             p_vout->output.i_bmask = 0x001f;
  713. #else
  714.             p_vout->output.i_rmask = 0x001f;
  715.             p_vout->output.i_gmask = 0x07e0;
  716.             p_vout->output.i_bmask = 0xf800;
  717. #endif
  718.             break;
  719.         case VLC_FOURCC('R','V','1','5'):
  720. #if defined( WORDS_BIGENDIAN )
  721.             p_vout->output.i_rmask = 0x7c00;
  722.             p_vout->output.i_gmask = 0x03e0;
  723.             p_vout->output.i_bmask = 0x001f;
  724. #else
  725.             p_vout->output.i_rmask = 0x001f;
  726.             p_vout->output.i_gmask = 0x03e0;
  727.             p_vout->output.i_bmask = 0x7c00;
  728. #endif
  729.             break;
  730.     }
  731. #endif
  732. #elif defined(MODULE_NAME_IS_x11)
  733.     /* Initialize the output structure: RGB with square pixels, whatever
  734.      * the input format is, since it's the only format we know */
  735.     switch( p_vout->p_sys->i_screen_depth )
  736.     {
  737.         case 8: /* FIXME: set the palette */
  738.             p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break;
  739.         case 15:
  740.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break;
  741.         case 16:
  742.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break;
  743.         case 24:
  744.         case 32:
  745.             p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break;
  746.         default:
  747.             msg_Err( p_vout, "unknown screen depth %i",
  748.                      p_vout->p_sys->i_screen_depth );
  749.             return VLC_SUCCESS;
  750.     }
  751. #ifdef HAVE_XSP
  752.     vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width  / p_vout->p_sys->i_hw_scale,
  753.                        p_vout->p_sys->p_win->i_height  / p_vout->p_sys->i_hw_scale,
  754.                        &i_index, &i_index,
  755.                        &p_vout->fmt_out.i_visible_width,
  756.                        &p_vout->fmt_out.i_visible_height );
  757. #else
  758.     vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
  759.                        p_vout->p_sys->p_win->i_height,
  760.                        &i_index, &i_index,
  761.                        &p_vout->fmt_out.i_visible_width,
  762.                        &p_vout->fmt_out.i_visible_height );
  763. #endif
  764.     p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
  765.     p_vout->output.i_width = p_vout->fmt_out.i_width =
  766.         p_vout->fmt_out.i_visible_width * p_vout->fmt_in.i_width /
  767.         p_vout->fmt_in.i_visible_width;
  768.     p_vout->output.i_height = p_vout->fmt_out.i_height =
  769.         p_vout->fmt_out.i_visible_height * p_vout->fmt_in.i_height /
  770.         p_vout->fmt_in.i_visible_height;
  771.     p_vout->fmt_out.i_x_offset =
  772.         p_vout->fmt_out.i_visible_width * p_vout->fmt_in.i_x_offset /
  773.         p_vout->fmt_in.i_visible_width;
  774.     p_vout->fmt_out.i_y_offset =
  775.         p_vout->fmt_out.i_visible_height * p_vout->fmt_in.i_y_offset /
  776.         p_vout->fmt_in.i_visible_height;
  777.     p_vout->fmt_out.i_sar_num = p_vout->fmt_out.i_sar_den = 1;
  778.     p_vout->output.i_aspect = p_vout->fmt_out.i_aspect =
  779.         p_vout->fmt_out.i_width * VOUT_ASPECT_FACTOR /p_vout->fmt_out.i_height;
  780.     msg_Dbg( p_vout, "x11 image size %ix%i (%i,%i,%ix%i)",
  781.              p_vout->fmt_out.i_width, p_vout->fmt_out.i_height,
  782.              p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset,
  783.              p_vout->fmt_out.i_visible_width,
  784.              p_vout->fmt_out.i_visible_height );
  785. #endif
  786.     /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
  787.     while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
  788.     {
  789.         p_pic = NULL;
  790.         /* Find an empty picture slot */
  791.         for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
  792.         {
  793.           if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
  794.             {
  795.                 p_pic = p_vout->p_picture + i_index;
  796.                 break;
  797.             }
  798.         }
  799.         /* Allocate the picture */
  800.         if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
  801.         {
  802.             break;
  803.         }
  804.         p_pic->i_status = DESTROYED_PICTURE;
  805.         p_pic->i_type   = DIRECT_PICTURE;
  806.         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
  807.         I_OUTPUTPICTURES++;
  808.     }
  809.     if( p_vout->output.i_chroma == VLC_FOURCC('Y','V','1','2') )
  810.     {
  811.         /* U and V inverted compared to I420
  812.          * Fixme: this should be handled by the vout core */
  813.         p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
  814.         p_vout->fmt_out.i_chroma = VLC_FOURCC('I','4','2','0');
  815.     }
  816.     return VLC_SUCCESS;
  817. }
  818. /*****************************************************************************
  819.  * DisplayVideo: displays previously rendered output
  820.  *****************************************************************************
  821.  * This function sends the currently rendered image to X11 server.
  822.  * (The Xv extension takes care of "double-buffering".)
  823.  *****************************************************************************/
  824. static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
  825. {
  826.     unsigned int i_width, i_height, i_x, i_y;
  827.     vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
  828.                        p_vout->p_sys->p_win->i_height,
  829.                        &i_x, &i_y, &i_width, &i_height );
  830. #ifdef MODULE_NAME_IS_xvmc
  831.     xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
  832.     vlc_xxmc_t *xxmc = &p_pic->p_sys->xxmc_data;
  833.     if( !xxmc->decoded ||
  834.         !xxmc_xvmc_surface_valid( p_vout, p_pic->p_sys->xvmc_surf ) )
  835.     {
  836.       msg_Dbg( p_vout, "DisplayVideo decoded=%dtsurfacevalid=%d",
  837.                xxmc->decoded,
  838.                xxmc_xvmc_surface_valid( p_vout, p_pic->p_sys->xvmc_surf ) );
  839.       xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  840.       return;
  841.     }
  842.     int src_width = p_vout->output.i_width;
  843.     int src_height = p_vout->output.i_height;
  844.     int src_x, src_y;
  845.     if( p_vout->p_sys->xvmc_crop_style == 1 )
  846.     {
  847.         src_x = 20;
  848.         src_y = 20;
  849.         src_width -= 40;
  850.         src_height -= 40;
  851.     }
  852.     else if( p_vout->p_sys->xvmc_crop_style == 2 )
  853.     {
  854.         src_x = 20;
  855.         src_y = 40;
  856.         src_width -= 40;
  857.         src_height -= 80;
  858.     }
  859.     else if( p_vout->p_sys->xvmc_crop_style == 3 )
  860.     {
  861.         src_x = 40;
  862.         src_y = 20;
  863.         src_width -= 80;
  864.         src_height -= 40;
  865.     }
  866.     else
  867.     {
  868.         src_x = 0;
  869.         src_y = 0;
  870.     }
  871.     int first_field;
  872.     if( p_vout->p_sys->xvmc_deinterlace_method > 0 )
  873.     {   /* BOB DEINTERLACE */
  874.         if( (p_pic->p_sys->nb_display == 0) ||
  875.             (p_vout->p_sys->xvmc_deinterlace_method == 1) )
  876.         {
  877.             first_field = (p_pic->b_top_field_first) ?
  878.                                 XVMC_BOTTOM_FIELD : XVMC_TOP_FIELD;
  879.         }
  880.         else
  881.         {
  882.             first_field = (p_pic->b_top_field_first) ?
  883.                                 XVMC_TOP_FIELD : XVMC_BOTTOM_FIELD;
  884.         }
  885.     }
  886.     else
  887.     {
  888.         first_field = XVMC_FRAME_PICTURE;
  889.      }
  890.     XVMCLOCKDISPLAY( p_vout->p_sys->p_display );
  891.     XvMCFlushSurface( p_vout->p_sys->p_display, p_pic->p_sys->xvmc_surf );
  892.     /* XvMCSyncSurface(p_vout->p_sys->p_display, p_picture->p_sys->xvmc_surf); */
  893.     XvMCPutSurface( p_vout->p_sys->p_display,
  894.                     p_pic->p_sys->xvmc_surf,
  895.                     p_vout->p_sys->p_win->video_window,
  896.                     src_x,
  897.                     src_y,
  898.                     src_width,
  899.                     src_height,
  900.                     0 /*dest_x*/,
  901.                     0 /*dest_y*/,
  902.                     i_width,
  903.                     i_height,
  904.                     first_field);
  905.     XVMCUNLOCKDISPLAY( p_vout->p_sys->p_display );
  906.     if( p_vout->p_sys->xvmc_deinterlace_method == 2 )
  907.     {   /* BOB DEINTERLACE */
  908.         if( p_pic->p_sys->nb_display == 0 )/* && ((t2-t1) < 15000)) */
  909.         {
  910.             mtime_t last_date = p_pic->date;
  911.             vlc_mutex_lock( &p_vout->picture_lock );
  912.             if( !p_vout->p_sys->last_date )
  913.             {
  914.                 p_pic->date += 20000;
  915.             }
  916.             else
  917.             {
  918.                 p_pic->date = ((3 * p_pic->date -
  919.                                     p_vout->p_sys->last_date) / 2 );
  920.             }
  921.             p_vout->p_sys->last_date = last_date;
  922.             p_pic->b_force = 1;
  923.             p_pic->p_sys->nb_display = 1;
  924.             vlc_mutex_unlock( &p_vout->picture_lock );
  925.         }
  926.         else
  927.         {
  928.             p_pic->p_sys->nb_display = 0;
  929.             p_pic->b_force = 0;
  930.         }
  931.     }
  932.     xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  933. #endif
  934. #ifdef HAVE_SYS_SHM_H
  935.     if( p_vout->p_sys->i_shm_opcode )
  936.     {
  937.         /* Display rendered image using shared memory extension */
  938. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  939.         XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
  940.                        p_vout->p_sys->p_win->video_window,
  941.                        p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
  942.                        p_vout->fmt_out.i_x_offset,
  943.                        p_vout->fmt_out.i_y_offset,
  944.                        p_vout->fmt_out.i_visible_width,
  945.                        p_vout->fmt_out.i_visible_height,
  946.                        0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height,
  947.                        False /* Don't put True here or you'll waste your CPU */ );
  948. #else
  949.         XShmPutImage( p_vout->p_sys->p_display,
  950.                       p_vout->p_sys->p_win->video_window,
  951.                       p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
  952.                       p_vout->fmt_out.i_x_offset,
  953.                       p_vout->fmt_out.i_y_offset,
  954.                       0 /*dest_x*/, 0 /*dest_y*/,
  955.                       p_vout->fmt_out.i_visible_width,
  956.                       p_vout->fmt_out.i_visible_height,
  957.                       False /* Don't put True here ! */ );
  958. #endif
  959.     }
  960.     else
  961. #endif /* HAVE_SYS_SHM_H */
  962.     {
  963.         /* Use standard XPutImage -- this is gonna be slow ! */
  964. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  965.         XvPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
  966.                     p_vout->p_sys->p_win->video_window,
  967.                     p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
  968.                     p_vout->fmt_out.i_x_offset,
  969.                     p_vout->fmt_out.i_y_offset,
  970.                     p_vout->fmt_out.i_visible_width,
  971.                     p_vout->fmt_out.i_visible_height,
  972.                     0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height );
  973. #else
  974.         XPutImage( p_vout->p_sys->p_display,
  975.                    p_vout->p_sys->p_win->video_window,
  976.                    p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image,
  977.                    p_vout->fmt_out.i_x_offset,
  978.                    p_vout->fmt_out.i_y_offset,
  979.                    0 /*dest_x*/, 0 /*dest_y*/,
  980.                    p_vout->fmt_out.i_visible_width,
  981.                    p_vout->fmt_out.i_visible_height );
  982. #endif
  983.     }
  984.     /* Make sure the command is sent now - do NOT use XFlush !*/
  985.     XSync( p_vout->p_sys->p_display, False );
  986. }
  987. /*****************************************************************************
  988.  * ManageVideo: handle X11 events
  989.  *****************************************************************************
  990.  * This function should be called regularly by video output thread. It manages
  991.  * X11 events and allows window resizing. It returns a non null value on
  992.  * error.
  993.  *****************************************************************************/
  994. static int ManageVideo( vout_thread_t *p_vout )
  995. {
  996.     XEvent      xevent;                                         /* X11 event */
  997.     vlc_value_t val;
  998. #ifdef MODULE_NAME_IS_xvmc
  999.     xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
  1000. #endif
  1001.     /* Handle events from the owner window */
  1002.     if( p_vout->p_sys->p_win->owner_window )
  1003.     {
  1004.         while( XCheckWindowEvent( p_vout->p_sys->p_display,
  1005.                                 p_vout->p_sys->p_win->owner_window->handle.xid,
  1006.                                   StructureNotifyMask, &xevent ) == True )
  1007.         {
  1008.             /* ConfigureNotify event: prepare  */
  1009.             if( xevent.type == ConfigureNotify )
  1010.             {
  1011.                 /* Update dimensions */
  1012.                 XResizeWindow( p_vout->p_sys->p_display,
  1013.                                p_vout->p_sys->p_win->base_window,
  1014.                                xevent.xconfigure.width,
  1015.                                xevent.xconfigure.height );
  1016.             }
  1017.         }
  1018.     }
  1019.     /* Handle X11 events: ConfigureNotify events are parsed to know if the
  1020.      * output window's size changed, MapNotify and UnmapNotify to know if the
  1021.      * window is mapped (and if the display is useful), and ClientMessages
  1022.      * to intercept window destruction requests */
  1023.     while( XCheckWindowEvent( p_vout->p_sys->p_display,
  1024.                               p_vout->p_sys->p_win->base_window,
  1025.                               StructureNotifyMask | KeyPressMask |
  1026.                               ButtonPressMask | ButtonReleaseMask |
  1027.                               PointerMotionMask | Button1MotionMask , &xevent )
  1028.            == True )
  1029.     {
  1030.         /* ConfigureNotify event: prepare  */
  1031.         if( xevent.type == ConfigureNotify )
  1032.         {
  1033.             if( (unsigned int)xevent.xconfigure.width
  1034.                    != p_vout->p_sys->p_win->i_width
  1035.               || (unsigned int)xevent.xconfigure.height
  1036.                     != p_vout->p_sys->p_win->i_height )
  1037.             {
  1038.                 /* Update dimensions */
  1039.                 p_vout->i_changes |= VOUT_SIZE_CHANGE;
  1040.                 p_vout->p_sys->p_win->i_width = xevent.xconfigure.width;
  1041.                 p_vout->p_sys->p_win->i_height = xevent.xconfigure.height;
  1042.             }
  1043.         }
  1044.         /* Keyboard event */
  1045.         else if( xevent.type == KeyPress )
  1046.         {
  1047.             unsigned int state = xevent.xkey.state;
  1048.             KeySym x_key_symbol;
  1049.             char i_key;                                   /* ISO Latin-1 key */
  1050.             /* We may have keys like F1 trough F12, ESC ... */
  1051.             x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
  1052.                                              xevent.xkey.keycode, 0 );
  1053.             val.i_int = ConvertKey( (int)x_key_symbol );
  1054.             xevent.xkey.state &= ~ShiftMask;
  1055.             xevent.xkey.state &= ~ControlMask;
  1056.             xevent.xkey.state &= ~Mod1Mask;
  1057.             if( !val.i_int &&
  1058.                 XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
  1059.             {
  1060.                 /* "Normal Keys"
  1061.                  * The reason why I use this instead of XK_0 is that
  1062.                  * with XLookupString, we don't have to care about
  1063.                  * keymaps. */
  1064.                 val.i_int = i_key;
  1065.             }
  1066.             if( val.i_int )
  1067.             {
  1068.                 if( state & ShiftMask )
  1069.                 {
  1070.                     val.i_int |= KEY_MODIFIER_SHIFT;
  1071.                 }
  1072.                 if( state & ControlMask )
  1073.                 {
  1074.                     val.i_int |= KEY_MODIFIER_CTRL;
  1075.                 }
  1076.                 if( state & Mod1Mask )
  1077.                 {
  1078.                     val.i_int |= KEY_MODIFIER_ALT;
  1079.                 }
  1080.                 var_Set( p_vout->p_libvlc, "key-pressed", val );
  1081.             }
  1082.         }
  1083.         /* Mouse click */
  1084.         else if( xevent.type == ButtonPress )
  1085.         {
  1086.             switch( ((XButtonEvent *)&xevent)->button )
  1087.             {
  1088.                 case Button1:
  1089.                     var_Get( p_vout, "mouse-button-down", &val );
  1090.                     val.i_int |= 1;
  1091.                     var_Set( p_vout, "mouse-button-down", val );
  1092.                     var_SetBool( p_vout->p_libvlc, "intf-popupmenu", false );
  1093.                     /* detect double-clicks */
  1094.                     if( ( ((XButtonEvent *)&xevent)->time -
  1095.                           p_vout->p_sys->i_time_button_last_pressed ) < 300 )
  1096.                     {
  1097.                         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
  1098.                     }
  1099.                     p_vout->p_sys->i_time_button_last_pressed =
  1100.                         ((XButtonEvent *)&xevent)->time;
  1101.                     break;
  1102.                 case Button2:
  1103.                     var_Get( p_vout, "mouse-button-down", &val );
  1104.                     val.i_int |= 2;
  1105.                     var_Set( p_vout, "mouse-button-down", val );
  1106.                     break;
  1107.                 case Button3:
  1108.                     var_Get( p_vout, "mouse-button-down", &val );
  1109.                     val.i_int |= 4;
  1110.                     var_Set( p_vout, "mouse-button-down", val );
  1111.                     var_SetBool( p_vout->p_libvlc, "intf-popupmenu", true );
  1112.                     break;
  1113.                 case Button4:
  1114.                     var_Get( p_vout, "mouse-button-down", &val );
  1115.                     val.i_int |= 8;
  1116.                     var_Set( p_vout, "mouse-button-down", val );
  1117.                     break;
  1118.                 case Button5:
  1119.                     var_Get( p_vout, "mouse-button-down", &val );
  1120.                     val.i_int |= 16;
  1121.                     var_Set( p_vout, "mouse-button-down", val );
  1122.                     break;
  1123.             }
  1124.         }
  1125.         /* Mouse release */
  1126.         else if( xevent.type == ButtonRelease )
  1127.         {
  1128.             switch( ((XButtonEvent *)&xevent)->button )
  1129.             {
  1130.                 case Button1:
  1131.                     {
  1132.                         var_Get( p_vout, "mouse-button-down", &val );
  1133.                         val.i_int &= ~1;
  1134.                         var_Set( p_vout, "mouse-button-down", val );
  1135.                         var_SetBool( p_vout, "mouse-clicked", true );
  1136.                     }
  1137.                     break;
  1138.                 case Button2:
  1139.                     {
  1140.                         var_Get( p_vout, "mouse-button-down", &val );
  1141.                         val.i_int &= ~2;
  1142.                         var_Set( p_vout, "mouse-button-down", val );
  1143.                         var_Get( p_vout->p_libvlc, "intf-show", &val );
  1144.                         val.b_bool = !val.b_bool;
  1145.                         var_Set( p_vout->p_libvlc, "intf-show", val );
  1146.                     }
  1147.                     break;
  1148.                 case Button3:
  1149.                     {
  1150.                         var_Get( p_vout, "mouse-button-down", &val );
  1151.                         val.i_int &= ~4;
  1152.                         var_Set( p_vout, "mouse-button-down", val );
  1153.                     }
  1154.                     break;
  1155.                 case Button4:
  1156.                     var_Get( p_vout, "mouse-button-down", &val );
  1157.                     val.i_int &= ~8;
  1158.                     var_Set( p_vout, "mouse-button-down", val );
  1159.                     break;
  1160.                 case Button5:
  1161.                     var_Get( p_vout, "mouse-button-down", &val );
  1162.                     val.i_int &= ~16;
  1163.                     var_Set( p_vout, "mouse-button-down", val );
  1164.                     break;
  1165.             }
  1166.         }
  1167.         /* Mouse move */
  1168.         else if( xevent.type == MotionNotify )
  1169.         {
  1170.             unsigned int i_width, i_height, i_x, i_y;
  1171.             /* somewhat different use for vout_PlacePicture:
  1172.              * here the values are needed to give to mouse coordinates
  1173.              * in the original picture space */
  1174.             vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
  1175.                                p_vout->p_sys->p_win->i_height,
  1176.                                &i_x, &i_y, &i_width, &i_height );
  1177.             /* Compute the x coordinate and check if the value is
  1178.                in [0,p_vout->fmt_in.i_visible_width] */
  1179.             val.i_int = ( xevent.xmotion.x - i_x ) *
  1180.                 p_vout->fmt_in.i_visible_width / i_width +
  1181.                 p_vout->fmt_in.i_x_offset;
  1182.             if( (int)(xevent.xmotion.x - i_x) < 0 )
  1183.                 val.i_int = 0;
  1184.             else if( (unsigned int)val.i_int > p_vout->fmt_in.i_visible_width )
  1185.                 val.i_int = p_vout->fmt_in.i_visible_width;
  1186.             var_Set( p_vout, "mouse-x", val );
  1187.             /* compute the y coordinate and check if the value is
  1188.                in [0,p_vout->fmt_in.i_visible_height] */
  1189.             val.i_int = ( xevent.xmotion.y - i_y ) *
  1190.                 p_vout->fmt_in.i_visible_height / i_height +
  1191.                 p_vout->fmt_in.i_y_offset;
  1192.             if( (int)(xevent.xmotion.y - i_y) < 0 )
  1193.                 val.i_int = 0;
  1194.             else if( (unsigned int)val.i_int > p_vout->fmt_in.i_visible_height )
  1195.                 val.i_int = p_vout->fmt_in.i_visible_height;
  1196.             var_Set( p_vout, "mouse-y", val );
  1197.             var_SetBool( p_vout, "mouse-moved", true );
  1198.             p_vout->p_sys->i_time_mouse_last_moved = mdate();
  1199.             if( ! p_vout->p_sys->b_mouse_pointer_visible )
  1200.             {
  1201.                 ToggleCursor( p_vout );
  1202.             }
  1203.         }
  1204.         else if( xevent.type == ReparentNotify /* XXX: why do we get this? */
  1205.                   || xevent.type == MapNotify
  1206.                   || xevent.type == UnmapNotify )
  1207.         {
  1208.             /* Ignore these events */
  1209.         }
  1210.         else /* Other events */
  1211.         {
  1212.             msg_Warn( p_vout, "unhandled event %d received", xevent.type );
  1213.         }
  1214.     }
  1215.     /* Handle events for video output sub-window */
  1216.     while( XCheckWindowEvent( p_vout->p_sys->p_display,
  1217.                               p_vout->p_sys->p_win->video_window,
  1218.                               ExposureMask, &xevent ) == True )
  1219.     {
  1220.         /* Window exposed (only handled if stream playback is paused) */
  1221.         if( xevent.type == Expose )
  1222.         {
  1223.             if( ((XExposeEvent *)&xevent)->count == 0 )
  1224.             {
  1225.                 /* (if this is the last a collection of expose events...) */
  1226. #if defined(MODULE_NAME_IS_xvideo)
  1227.                 x11_window_t *p_win = p_vout->p_sys->p_win;
  1228.                 /* Paint the colour key if needed */
  1229.                 if( p_vout->p_sys->b_paint_colourkey &&
  1230.                     xevent.xexpose.window == p_win->video_window )
  1231.                 {
  1232.                     XSetForeground( p_vout->p_sys->p_display,
  1233.                                     p_win->gc, p_vout->p_sys->i_colourkey );
  1234.                     XFillRectangle( p_vout->p_sys->p_display,
  1235.                                     p_win->video_window, p_win->gc, 0, 0,
  1236.                                     p_win->i_width, p_win->i_height );
  1237.                 }
  1238. #endif
  1239. #if 0
  1240.                 if( p_vout->p_libvlc->p_input_bank->pp_input[0] != NULL )
  1241.                 {
  1242.                     if( PAUSE_S == p_vout->p_libvlc->p_input_bank->pp_input[0]
  1243.                                                    ->stream.control.i_status )
  1244.                     {
  1245.                         /* XVideoDisplay( p_vout )*/;
  1246.                     }
  1247.                 }
  1248. #endif
  1249.             }
  1250.         }
  1251.     }
  1252.     /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
  1253.      * are handled - according to the man pages, the format is always 32
  1254.      * in this case */
  1255.     while( XCheckTypedEvent( p_vout->p_sys->p_display,
  1256.                              ClientMessage, &xevent ) )
  1257.     {
  1258.         if( (xevent.xclient.message_type == p_vout->p_sys->p_win->wm_protocols)
  1259.                && ((Atom)xevent.xclient.data.l[0]
  1260.                      == p_vout->p_sys->p_win->wm_delete_window ) )
  1261.         {
  1262.             /* the user wants to close the window */
  1263.             playlist_t * p_playlist = pl_Hold( p_vout );
  1264.             if( p_playlist != NULL )
  1265.             {
  1266.                 playlist_Stop( p_playlist );
  1267.                 pl_Release( p_vout );
  1268.             }
  1269.         }
  1270.     }
  1271.     /*
  1272.      * Fullscreen Change
  1273.      */
  1274.     if ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
  1275.     {
  1276.         /* Update the object variable and trigger callback */
  1277.         var_SetBool( p_vout, "fullscreen", !p_vout->b_fullscreen );
  1278.         ToggleFullScreen( p_vout );
  1279.         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
  1280.     }
  1281.     /* autoscale toggle */
  1282.     if( p_vout->i_changes & VOUT_SCALE_CHANGE )
  1283.     {
  1284.         p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
  1285.         p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
  1286.         p_vout->i_zoom = ZOOM_FP_FACTOR;
  1287.         p_vout->i_changes |= VOUT_SIZE_CHANGE;
  1288.     }
  1289.     /* scaling factor */
  1290.     if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
  1291.     {
  1292.         p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
  1293.         p_vout->b_autoscale = false;
  1294.         p_vout->i_zoom =
  1295.             (int)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale" ) );
  1296.         p_vout->i_changes |= VOUT_SIZE_CHANGE;
  1297.     }
  1298.     if( p_vout->i_changes & VOUT_CROP_CHANGE ||
  1299.         p_vout->i_changes & VOUT_ASPECT_CHANGE )
  1300.     {
  1301.         p_vout->i_changes &= ~VOUT_CROP_CHANGE;
  1302.         p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
  1303.         p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset;
  1304.         p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset;
  1305.         p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width;
  1306.         p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height;
  1307.         p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect;
  1308.         p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num;
  1309.         p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den;
  1310.         p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
  1311.         p_vout->i_changes |= VOUT_SIZE_CHANGE;
  1312.     }
  1313.     /*
  1314.      * Size change
  1315.      *
  1316.      * (Needs to be placed after VOUT_FULLSREEN_CHANGE because we can activate
  1317.      *  the size flag inside the fullscreen routine)
  1318.      */
  1319.     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
  1320.     {
  1321.         unsigned int i_width, i_height, i_x, i_y;
  1322. #ifdef MODULE_NAME_IS_x11
  1323.         /* We need to signal the vout thread about the size change because it
  1324.          * is doing the rescaling */
  1325. #else
  1326.         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
  1327. #endif
  1328.         vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
  1329.                            p_vout->p_sys->p_win->i_height,
  1330.                            &i_x, &i_y, &i_width, &i_height );
  1331.         XMoveResizeWindow( p_vout->p_sys->p_display,
  1332.                            p_vout->p_sys->p_win->video_window,
  1333.                            i_x, i_y, i_width, i_height );
  1334.     }
  1335.     /* cursor hiding depending on --vout-event option
  1336.      *      activated if:
  1337.      *            value = 1 (Fullsupport) (default value)
  1338.      *         or value = 2 (Fullscreen-Only) and condition met
  1339.      */
  1340.     bool b_vout_event = (   ( p_vout->p_sys->i_vout_event == 1 )
  1341.                          || ( p_vout->p_sys->i_vout_event == 2 && p_vout->b_fullscreen )
  1342.                         );
  1343.     /* Autohide Cursour */
  1344.     if( mdate() - p_vout->p_sys->i_time_mouse_last_moved >
  1345.         p_vout->p_sys->i_mouse_hide_timeout )
  1346.     {
  1347.         /* Hide the mouse automatically */
  1348.         if( b_vout_event && p_vout->p_sys->b_mouse_pointer_visible )
  1349.         {
  1350.             ToggleCursor( p_vout );
  1351.         }
  1352.     }
  1353. #ifdef MODULE_NAME_IS_xvmc
  1354.     xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  1355. #endif
  1356. #ifdef HAVE_OSSO
  1357.     if ( p_vout->p_sys->p_octx != NULL ) {
  1358.         if ( p_vout->p_sys->i_backlight_on_counter == i_backlight_on_interval ) {
  1359.             if ( osso_display_blanking_pause( p_vout->p_sys->p_octx ) != OSSO_OK ) {
  1360.                 msg_Err( p_vout, "Could not disable backlight blanking" );
  1361.         } else {
  1362.                 msg_Dbg( p_vout, "Backlight blanking disabled" );
  1363.             }
  1364.             p_vout->p_sys->i_backlight_on_counter = 0;
  1365.         } else {
  1366.             p_vout->p_sys->i_backlight_on_counter ++;
  1367.         }
  1368.     }
  1369. #endif
  1370.     return 0;
  1371. }
  1372. /*****************************************************************************
  1373.  * EndVideo: terminate X11 video thread output method
  1374.  *****************************************************************************
  1375.  * Destroy the X11 XImages created by Init. It is called at the end of
  1376.  * the thread, but also each time the window is resized.
  1377.  *****************************************************************************/
  1378. static void EndVideo( vout_thread_t *p_vout )
  1379. {
  1380.     int i_index;
  1381.     /* Free the direct buffers we allocated */
  1382.     for( i_index = I_OUTPUTPICTURES ; i_index ; )
  1383.     {
  1384.         i_index--;
  1385.         FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
  1386.     }
  1387. }
  1388. /* following functions are local */
  1389. /*****************************************************************************
  1390.  * CreateWindow: open and set-up X11 main window
  1391.  *****************************************************************************/
  1392. static int CreateWindow( vout_thread_t *p_vout, x11_window_t *p_win )
  1393. {
  1394.     XSizeHints              xsize_hints;
  1395.     XSetWindowAttributes    xwindow_attributes;
  1396.     XGCValues               xgcvalues;
  1397.     XEvent                  xevent;
  1398.     bool              b_map_notify = false;
  1399.     vlc_value_t             val;
  1400.     /* Prepare window manager hints and properties */
  1401.     p_win->wm_protocols =
  1402.              XInternAtom( p_vout->p_sys->p_display, "WM_PROTOCOLS", True );
  1403.     p_win->wm_delete_window =
  1404.              XInternAtom( p_vout->p_sys->p_display, "WM_DELETE_WINDOW", True );
  1405.     /* Never have a 0-pixel-wide window */
  1406.     xsize_hints.min_width = 2;
  1407.     xsize_hints.min_height = 1;
  1408.     /* Prepare window attributes */
  1409.     xwindow_attributes.backing_store = Always;       /* save the hidden part */
  1410.     xwindow_attributes.background_pixel = BlackPixel(p_vout->p_sys->p_display,
  1411.                                                      p_vout->p_sys->i_screen);
  1412.     xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
  1413.     if( !p_vout->b_fullscreen )
  1414.     {
  1415.         p_win->owner_window = vout_RequestXWindow( p_vout, &p_win->i_x,
  1416.                               &p_win->i_y, &p_win->i_width, &p_win->i_height );
  1417.         xsize_hints.base_width  = xsize_hints.width = p_win->i_width;
  1418.         xsize_hints.base_height = xsize_hints.height = p_win->i_height;
  1419.         xsize_hints.flags       = PSize | PMinSize;
  1420.         if( p_win->i_x >=0 || p_win->i_y >= 0 )
  1421.         {
  1422.             xsize_hints.x = p_win->i_x;
  1423.             xsize_hints.y = p_win->i_y;
  1424.             xsize_hints.flags |= PPosition;
  1425.         }
  1426.     }
  1427.     else
  1428.     {
  1429.         /* Fullscreen window size and position */
  1430.         p_win->owner_window = NULL;
  1431.         p_win->i_x = p_win->i_y = 0;
  1432.         p_win->i_width =
  1433.             DisplayWidth( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
  1434.         p_win->i_height =
  1435.             DisplayHeight( p_vout->p_sys->p_display, p_vout->p_sys->i_screen );
  1436.     }
  1437.     if( !p_win->owner_window )
  1438.     {
  1439.         /* Create the window and set hints - the window must receive
  1440.          * ConfigureNotify events, and until it is displayed, Expose and
  1441.          * MapNotify events. */
  1442.         p_win->base_window =
  1443.             XCreateWindow( p_vout->p_sys->p_display,
  1444.                            DefaultRootWindow( p_vout->p_sys->p_display ),
  1445.                            p_win->i_x, p_win->i_y,
  1446.                            p_win->i_width, p_win->i_height,
  1447.                            0,
  1448.                            0, InputOutput, 0,
  1449.                            CWBackingStore | CWBackPixel | CWEventMask,
  1450.                            &xwindow_attributes );
  1451.         var_Get( p_vout, "video-title", &val );
  1452.         if( !val.psz_string || !*val.psz_string )
  1453.         {
  1454.             XStoreName( p_vout->p_sys->p_display, p_win->base_window,
  1455. #ifdef MODULE_NAME_IS_x11
  1456.                         VOUT_TITLE " (X11 output)"
  1457. #elif defined(MODULE_NAME_IS_glx)
  1458.                         VOUT_TITLE " (GLX output)"
  1459. #else
  1460.                         VOUT_TITLE " (XVideo output)"
  1461. #endif
  1462.               );
  1463.         }
  1464.         else
  1465.         {
  1466.             XStoreName( p_vout->p_sys->p_display,
  1467.                         p_win->base_window, val.psz_string );
  1468.         }
  1469.         free( val.psz_string );
  1470.         if( !p_vout->b_fullscreen )
  1471.         {
  1472.             const char *argv[] = { "vlc", NULL };
  1473.             /* Set window manager hints and properties: size hints, command,
  1474.              * window's name, and accepted protocols */
  1475.             XSetWMNormalHints( p_vout->p_sys->p_display,
  1476.                                p_win->base_window, &xsize_hints );
  1477.             XSetCommand( p_vout->p_sys->p_display, p_win->base_window,
  1478.                          (char**)argv, 1 );
  1479.             if( !var_GetBool( p_vout, "video-deco") )
  1480.             {
  1481.                 Atom prop;
  1482.                 mwmhints_t mwmhints;
  1483.                 mwmhints.flags = MWM_HINTS_DECORATIONS;
  1484.                 mwmhints.decorations = False;
  1485.                 prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
  1486.                                     False );
  1487.                 XChangeProperty( p_vout->p_sys->p_display,
  1488.                                  p_win->base_window,
  1489.                                  prop, prop, 32, PropModeReplace,
  1490.                                  (unsigned char *)&mwmhints,
  1491.                                  PROP_MWM_HINTS_ELEMENTS );
  1492.             }
  1493.         }
  1494.     }
  1495.     else
  1496.     {
  1497.         Window dummy1;
  1498.         int dummy2, dummy3;
  1499.         unsigned int dummy4, dummy5;
  1500.         /* Select events we are interested in. */
  1501.         XSelectInput( p_vout->p_sys->p_display,
  1502.                       p_win->owner_window->handle.xid, StructureNotifyMask );
  1503.         /* Get the parent window's geometry information */
  1504.         XGetGeometry( p_vout->p_sys->p_display,
  1505.                       p_win->owner_window->handle.xid,
  1506.                       &dummy1, &dummy2, &dummy3,
  1507.                       &p_win->i_width,
  1508.                       &p_win->i_height,
  1509.                       &dummy4, &dummy5 );
  1510.         /* From man XSelectInput: only one client at a time can select a
  1511.          * ButtonPress event, so we need to open a new window anyway. */
  1512.         p_win->base_window =
  1513.             XCreateWindow( p_vout->p_sys->p_display,
  1514.                            p_win->owner_window->handle.xid,
  1515.                            0, 0,
  1516.                            p_win->i_width, p_win->i_height,
  1517.                            0,
  1518.                            0, CopyFromParent, 0,
  1519.                            CWBackingStore | CWBackPixel | CWEventMask,
  1520.                            &xwindow_attributes );
  1521.     }
  1522.     if( (p_win->wm_protocols == None)        /* use WM_DELETE_WINDOW */
  1523.         || (p_win->wm_delete_window == None)
  1524.         || !XSetWMProtocols( p_vout->p_sys->p_display, p_win->base_window,
  1525.                              &p_win->wm_delete_window, 1 ) )
  1526.     {
  1527.         /* WM_DELETE_WINDOW is not supported by window manager */
  1528.         msg_Warn( p_vout, "missing or bad window manager" );
  1529.     }
  1530.     /* Creation of a graphic context that doesn't generate a GraphicsExpose
  1531.      * event when using functions like XCopyArea */
  1532.     xgcvalues.graphics_exposures = False;
  1533.     p_win->gc = XCreateGC( p_vout->p_sys->p_display,
  1534.                            p_win->base_window,
  1535.                            GCGraphicsExposures, &xgcvalues );
  1536.     /* Wait till the window is mapped */
  1537.     XMapWindow( p_vout->p_sys->p_display, p_win->base_window );
  1538.     do
  1539.     {
  1540.         XWindowEvent( p_vout->p_sys->p_display, p_win->base_window,
  1541.                       SubstructureNotifyMask | StructureNotifyMask, &xevent);
  1542.         if( (xevent.type == MapNotify)
  1543.                  && (xevent.xmap.window == p_win->base_window) )
  1544.         {
  1545.             b_map_notify = true;
  1546.         }
  1547.         else if( (xevent.type == ConfigureNotify)
  1548.                  && (xevent.xconfigure.window == p_win->base_window) )
  1549.         {
  1550.             p_win->i_width = xevent.xconfigure.width;
  1551.             p_win->i_height = xevent.xconfigure.height;
  1552.         }
  1553.     } while( !b_map_notify );
  1554.     /* key and mouse events handling depending on --vout-event option
  1555.      *      activated if:
  1556.      *            value = 1 (Fullsupport) (default value)
  1557.      *         or value = 2 (Fullscreen-Only) and condition met
  1558.      */
  1559.     bool b_vout_event = (   ( p_vout->p_sys->i_vout_event == 1 )
  1560.                          || ( p_vout->p_sys->i_vout_event == 2 && p_vout->b_fullscreen )
  1561.                         );
  1562.     if ( b_vout_event )
  1563.         XSelectInput( p_vout->p_sys->p_display, p_win->base_window,
  1564.                       StructureNotifyMask | KeyPressMask |
  1565.                       ButtonPressMask | ButtonReleaseMask |
  1566.                       PointerMotionMask );
  1567. #ifdef MODULE_NAME_IS_x11
  1568.     if( XDefaultDepth(p_vout->p_sys->p_display, p_vout->p_sys->i_screen) == 8 )
  1569.     {
  1570.         /* Allocate a new palette */
  1571.         p_vout->p_sys->colormap =
  1572.             XCreateColormap( p_vout->p_sys->p_display,
  1573.                              DefaultRootWindow( p_vout->p_sys->p_display ),
  1574.                              DefaultVisual( p_vout->p_sys->p_display,
  1575.                                             p_vout->p_sys->i_screen ),
  1576.                              AllocAll );
  1577.         xwindow_attributes.colormap = p_vout->p_sys->colormap;
  1578.         XChangeWindowAttributes( p_vout->p_sys->p_display, p_win->base_window,
  1579.                                  CWColormap, &xwindow_attributes );
  1580.     }
  1581. #endif
  1582.     /* Create video output sub-window. */
  1583.     p_win->video_window =  XCreateSimpleWindow(
  1584.                                       p_vout->p_sys->p_display,
  1585.                                       p_win->base_window, 0, 0,
  1586.                                       p_win->i_width, p_win->i_height,
  1587.                                       0,
  1588.                                       BlackPixel( p_vout->p_sys->p_display,
  1589.                                                   p_vout->p_sys->i_screen ),
  1590.                                       WhitePixel( p_vout->p_sys->p_display,
  1591.                                                   p_vout->p_sys->i_screen ) );
  1592.     XSetWindowBackground( p_vout->p_sys->p_display, p_win->video_window,
  1593.                           BlackPixel( p_vout->p_sys->p_display,
  1594.                                       p_vout->p_sys->i_screen ) );
  1595.     XMapWindow( p_vout->p_sys->p_display, p_win->video_window );
  1596.     XSelectInput( p_vout->p_sys->p_display, p_win->video_window,
  1597.                   ExposureMask );
  1598.     /* make sure the video window will be centered in the next ManageVideo() */
  1599.     p_vout->i_changes |= VOUT_SIZE_CHANGE;
  1600.     /* If the cursor was formerly blank than blank it again */
  1601.     if( !p_vout->p_sys->b_mouse_pointer_visible )
  1602.     {
  1603.         ToggleCursor( p_vout );
  1604.         ToggleCursor( p_vout );
  1605.     }
  1606.     /* Do NOT use XFlush here ! */
  1607.     XSync( p_vout->p_sys->p_display, False );
  1608.     /* At this stage, the window is open, displayed, and ready to
  1609.      * receive data */
  1610.     p_vout->p_sys->p_win = p_win;
  1611.     return VLC_SUCCESS;
  1612. }
  1613. /*****************************************************************************
  1614.  * DestroyWindow: destroy the window
  1615.  *****************************************************************************
  1616.  *
  1617.  *****************************************************************************/
  1618. static void DestroyWindow( vout_thread_t *p_vout, x11_window_t *p_win )
  1619. {
  1620.     /* Do NOT use XFlush here ! */
  1621.     XSync( p_vout->p_sys->p_display, False );
  1622.     if( p_win->video_window != None )
  1623.         XDestroyWindow( p_vout->p_sys->p_display, p_win->video_window );
  1624.     XFreeGC( p_vout->p_sys->p_display, p_win->gc );
  1625.     XUnmapWindow( p_vout->p_sys->p_display, p_win->base_window );
  1626.     XDestroyWindow( p_vout->p_sys->p_display, p_win->base_window );
  1627.     /* make sure base window is destroyed before proceeding further */
  1628.     bool b_destroy_notify = false;
  1629.     do
  1630.     {
  1631.         XEvent      xevent;
  1632.         XWindowEvent( p_vout->p_sys->p_display, p_win->base_window,
  1633.                       SubstructureNotifyMask | StructureNotifyMask, &xevent);
  1634.         if( (xevent.type == DestroyNotify)
  1635.                  && (xevent.xmap.window == p_win->base_window) )
  1636.         {
  1637.             b_destroy_notify = true;
  1638.         }
  1639.     } while( !b_destroy_notify );
  1640.     vout_ReleaseWindow( p_win->owner_window );
  1641. }
  1642. /*****************************************************************************
  1643.  * NewPicture: allocate a picture
  1644.  *****************************************************************************
  1645.  * Returns 0 on success, -1 otherwise
  1646.  *****************************************************************************/
  1647. static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
  1648. {
  1649. #ifndef MODULE_NAME_IS_glx
  1650. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  1651.     int i_plane;
  1652. #endif
  1653.     /* We know the chroma, allocate a buffer which will be used
  1654.      * directly by the decoder */
  1655.     p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
  1656.     if( p_pic->p_sys == NULL )
  1657.     {
  1658.         return -1;
  1659.     }
  1660. #ifdef MODULE_NAME_IS_xvmc
  1661.     p_pic->p_sys->p_vout = p_vout;
  1662.     p_pic->p_sys->xvmc_surf = NULL;
  1663.     p_pic->p_sys->xxmc_data.decoded = 0;
  1664.     p_pic->p_sys->xxmc_data.proc_xxmc_update_frame = xxmc_do_update_frame;
  1665.     //    p_pic->p_accel_data = &p_pic->p_sys->xxmc_data;
  1666.     p_pic->p_sys->nb_display = 0;
  1667. #endif
  1668.     /* Fill in picture_t fields */
  1669.     vout_InitPicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma,
  1670.                       p_vout->output.i_width, p_vout->output.i_height,
  1671.                       p_vout->output.i_aspect );
  1672. #ifdef HAVE_SYS_SHM_H
  1673.     if( p_vout->p_sys->i_shm_opcode )
  1674.     {
  1675.         /* Create image using XShm extension */
  1676.         p_pic->p_sys->p_image =
  1677.             CreateShmImage( p_vout, p_vout->p_sys->p_display,
  1678. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  1679.                             p_vout->p_sys->i_xvport,
  1680.                             VLC2X11_FOURCC(p_vout->output.i_chroma),
  1681. #else
  1682.                             p_vout->p_sys->p_visual,
  1683.                             p_vout->p_sys->i_screen_depth,
  1684. #endif
  1685.                             &p_pic->p_sys->shminfo,
  1686.                             p_vout->output.i_width, p_vout->output.i_height );
  1687.     }
  1688.     if( !p_vout->p_sys->i_shm_opcode || !p_pic->p_sys->p_image )
  1689. #endif /* HAVE_SYS_SHM_H */
  1690.     {
  1691.         /* Create image without XShm extension */
  1692.         p_pic->p_sys->p_image =
  1693.             CreateImage( p_vout, p_vout->p_sys->p_display,
  1694. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  1695.                          p_vout->p_sys->i_xvport,
  1696.                          VLC2X11_FOURCC(p_vout->output.i_chroma),
  1697.                          p_pic->format.i_bits_per_pixel,
  1698. #else
  1699.                          p_vout->p_sys->p_visual,
  1700.                          p_vout->p_sys->i_screen_depth,
  1701.                          p_vout->p_sys->i_bytes_per_pixel,
  1702. #endif
  1703.                          p_vout->output.i_width, p_vout->output.i_height );
  1704. #ifdef HAVE_SYS_SHM_H
  1705.         if( p_pic->p_sys->p_image && p_vout->p_sys->i_shm_opcode )
  1706.         {
  1707.             msg_Warn( p_vout, "couldn't create SHM image, disabling SHM" );
  1708.             p_vout->p_sys->i_shm_opcode = 0;
  1709.         }
  1710. #endif /* HAVE_SYS_SHM_H */
  1711.     }
  1712.     if( p_pic->p_sys->p_image == NULL )
  1713.     {
  1714.         free( p_pic->p_sys );
  1715.         return -1;
  1716.     }
  1717.     switch( p_vout->output.i_chroma )
  1718.     {
  1719. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  1720.         case VLC_FOURCC('I','4','2','0'):
  1721.         case VLC_FOURCC('Y','V','1','2'):
  1722.         case VLC_FOURCC('Y','2','1','1'):
  1723.         case VLC_FOURCC('Y','U','Y','2'):
  1724.         case VLC_FOURCC('U','Y','V','Y'):
  1725.         case VLC_FOURCC('R','V','1','5'):
  1726.         case VLC_FOURCC('R','V','1','6'):
  1727.         case VLC_FOURCC('R','V','2','4'): /* Fixme: pixel pitch == 4 ? */
  1728.         case VLC_FOURCC('R','V','3','2'):
  1729.             for( i_plane = 0; i_plane < p_pic->p_sys->p_image->num_planes;
  1730.                  i_plane++ )
  1731.             {
  1732.                 p_pic->p[i_plane].p_pixels = (uint8_t*)p_pic->p_sys->p_image->data
  1733.                     + p_pic->p_sys->p_image->offsets[i_plane];
  1734.                 p_pic->p[i_plane].i_pitch =
  1735.                     p_pic->p_sys->p_image->pitches[i_plane];
  1736.             }
  1737.             if( p_vout->output.i_chroma == VLC_FOURCC('Y','V','1','2') )
  1738.             {
  1739.                 /* U and V inverted compared to I420
  1740.                  * Fixme: this should be handled by the vout core */
  1741.                 p_pic->U_PIXELS = (uint8_t*)p_pic->p_sys->p_image->data
  1742.                     + p_pic->p_sys->p_image->offsets[2];
  1743.                 p_pic->V_PIXELS = (uint8_t*)p_pic->p_sys->p_image->data
  1744.                     + p_pic->p_sys->p_image->offsets[1];
  1745.             }
  1746.             break;
  1747. #else
  1748.         case VLC_FOURCC('R','G','B','2'):
  1749.         case VLC_FOURCC('R','V','1','6'):
  1750.         case VLC_FOURCC('R','V','1','5'):
  1751.         case VLC_FOURCC('R','V','2','4'):
  1752.         case VLC_FOURCC('R','V','3','2'):
  1753.             p_pic->p->i_lines = p_pic->p_sys->p_image->height;
  1754.             p_pic->p->i_visible_lines = p_pic->p_sys->p_image->height;
  1755.             p_pic->p->p_pixels = (uint8_t*)p_pic->p_sys->p_image->data
  1756.                                   + p_pic->p_sys->p_image->xoffset;
  1757.             p_pic->p->i_pitch = p_pic->p_sys->p_image->bytes_per_line;
  1758.             /* p_pic->p->i_pixel_pitch = 4 for RV24 but this should be set
  1759.              * properly by vout_InitPicture() */
  1760.             p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch
  1761.                                          * p_pic->p_sys->p_image->width;
  1762.             break;
  1763. #endif
  1764.         default:
  1765.             /* Unknown chroma, tell the guy to get lost */
  1766.             IMAGE_FREE( p_pic->p_sys->p_image );
  1767.             free( p_pic->p_sys );
  1768.             msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
  1769.                      p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
  1770.             p_pic->i_planes = 0;
  1771.             return -1;
  1772.     }
  1773. #else
  1774.     VLC_UNUSED(p_vout); VLC_UNUSED(p_pic);
  1775. #endif /* !MODULE_NAME_IS_glx */
  1776.     return 0;
  1777. }
  1778. /*****************************************************************************
  1779.  * FreePicture: destroy a picture allocated with NewPicture
  1780.  *****************************************************************************
  1781.  * Destroy XImage AND associated data. If using Shm, detach shared memory
  1782.  * segment from server and process, then free it. The XDestroyImage manpage
  1783.  * says that both the image structure _and_ the data pointed to by the
  1784.  * image structure are freed, so no need to free p_image->data.
  1785.  *****************************************************************************/
  1786. static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
  1787. {
  1788.     /* The order of operations is correct */
  1789. #ifdef HAVE_SYS_SHM_H
  1790.     if( p_vout->p_sys->i_shm_opcode )
  1791.     {
  1792.         XShmDetach( p_vout->p_sys->p_display, &p_pic->p_sys->shminfo );
  1793.         IMAGE_FREE( p_pic->p_sys->p_image );
  1794.         shmctl( p_pic->p_sys->shminfo.shmid, IPC_RMID, 0 );
  1795.         if( shmdt( p_pic->p_sys->shminfo.shmaddr ) )
  1796.         {
  1797.             msg_Err( p_vout, "cannot detach shared memory (%m)" );
  1798.         }
  1799.     }
  1800.     else
  1801. #endif
  1802.     {
  1803.         IMAGE_FREE( p_pic->p_sys->p_image );
  1804.     }
  1805. #ifdef MODULE_NAME_IS_xvmc
  1806.     if( p_pic->p_sys->xvmc_surf != NULL )
  1807.     {
  1808.         xxmc_xvmc_free_surface(p_vout , p_pic->p_sys->xvmc_surf);
  1809.         p_pic->p_sys->xvmc_surf = NULL;
  1810.     }
  1811. #endif
  1812.     /* Do NOT use XFlush here ! */
  1813.     XSync( p_vout->p_sys->p_display, False );
  1814.     free( p_pic->p_sys );
  1815. }
  1816. /*****************************************************************************
  1817.  * ToggleFullScreen: Enable or disable full screen mode
  1818.  *****************************************************************************
  1819.  * This function will switch between fullscreen and window mode.
  1820.  *****************************************************************************/
  1821. static void ToggleFullScreen ( vout_thread_t *p_vout )
  1822. {
  1823.     Atom prop;
  1824.     mwmhints_t mwmhints;
  1825.     XSetWindowAttributes attributes;
  1826. #ifdef HAVE_XINERAMA
  1827.     int i_d1, i_d2;
  1828. #endif
  1829.     p_vout->b_fullscreen = !p_vout->b_fullscreen;
  1830.     if( p_vout->b_fullscreen )
  1831.     {
  1832.         msg_Dbg( p_vout, "entering fullscreen mode" );
  1833.         /* Getting current window position */
  1834.         Window root_win;
  1835.         Window* child_windows;
  1836.         unsigned int num_child_windows;
  1837.         Window parent_win;
  1838.         Window child_win;
  1839.         XWindowAttributes win_attr;
  1840.         int screen_x,screen_y,win_width,win_height;
  1841.         XGetWindowAttributes(
  1842.                 p_vout->p_sys->p_display,
  1843.                 p_vout->p_sys->p_win->video_window,
  1844.                 &win_attr);
  1845.         XQueryTree(
  1846.                 p_vout->p_sys->p_display,
  1847.                 p_vout->p_sys->p_win->video_window,
  1848.                 &root_win,
  1849.                 &parent_win,
  1850.                 &child_windows,
  1851.                 &num_child_windows);
  1852.         XFree(child_windows);
  1853.         XTranslateCoordinates(
  1854.                 p_vout->p_sys->p_display,
  1855.                 parent_win, win_attr.root,
  1856.                 win_attr.x,win_attr.y,
  1857.                 &screen_x,&screen_y,
  1858.                 &child_win);
  1859.         win_width = p_vout->p_sys->p_win->i_width;
  1860.         win_height = p_vout->p_sys->p_win->i_height;
  1861.         msg_Dbg( p_vout, "X %d/%d Y %d/%d",
  1862.             win_width, screen_x, win_height, screen_y );
  1863.         /* screen_x and screen_y are current position */
  1864.         p_vout->p_sys->b_altfullscreen =
  1865.             config_GetInt( p_vout, MODULE_STRING "-altfullscreen" );
  1866.         XUnmapWindow( p_vout->p_sys->p_display,
  1867.                       p_vout->p_sys->p_win->base_window );
  1868.         p_vout->p_sys->p_win = &p_vout->p_sys->fullscreen_window;
  1869.         CreateWindow( p_vout, p_vout->p_sys->p_win );
  1870.         XDestroyWindow( p_vout->p_sys->p_display,
  1871.                         p_vout->p_sys->fullscreen_window.video_window );
  1872.         XReparentWindow( p_vout->p_sys->p_display,
  1873.                          p_vout->p_sys->original_window.video_window,
  1874.                          p_vout->p_sys->fullscreen_window.base_window, 0, 0 );
  1875.         p_vout->p_sys->fullscreen_window.video_window =
  1876.             p_vout->p_sys->original_window.video_window;
  1877.         /* To my knowledge there are two ways to create a borderless window.
  1878.          * There's the generic way which is to tell x to bypass the window
  1879.          * manager, but this creates problems with the focus of other
  1880.          * applications.
  1881.          * The other way is to use the motif property "_MOTIF_WM_HINTS" which
  1882.          * luckily seems to be supported by most window managers. */
  1883.         if( !p_vout->p_sys->b_altfullscreen )
  1884.         {
  1885.             mwmhints.flags = MWM_HINTS_DECORATIONS;
  1886.             mwmhints.decorations = False;
  1887.             prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
  1888.                                 False );
  1889.             XChangeProperty( p_vout->p_sys->p_display,
  1890.                              p_vout->p_sys->p_win->base_window,
  1891.                              prop, prop, 32, PropModeReplace,
  1892.                              (unsigned char *)&mwmhints,
  1893.                              PROP_MWM_HINTS_ELEMENTS );
  1894.         }
  1895.         else
  1896.         {
  1897.             /* brute force way to remove decorations */
  1898.             attributes.override_redirect = True;
  1899.             XChangeWindowAttributes( p_vout->p_sys->p_display,
  1900.                                      p_vout->p_sys->p_win->base_window,
  1901.                                      CWOverrideRedirect,
  1902.                                      &attributes);
  1903.         }
  1904.         /* Make sure the change is effective */
  1905.         XReparentWindow( p_vout->p_sys->p_display,
  1906.                          p_vout->p_sys->p_win->base_window,
  1907.                          DefaultRootWindow( p_vout->p_sys->p_display ), 0, 0 );
  1908.         if( p_vout->p_sys->b_net_wm_state_fullscreen )
  1909.         {
  1910.             XClientMessageEvent event = {
  1911.                 .type = ClientMessage,
  1912.                 .window = p_vout->p_sys->p_win->base_window,
  1913.                 .message_type = p_vout->p_sys->net_wm_state,
  1914.                 .format = 32,
  1915.                 .data = {
  1916.                     .l = {
  1917.                         1, /* set property */
  1918.                         p_vout->p_sys->net_wm_state_fullscreen,
  1919.                         0,
  1920.                         1,
  1921.                     },
  1922.                 },
  1923.             };
  1924.             XSendEvent( p_vout->p_sys->p_display,
  1925.                         DefaultRootWindow( p_vout->p_sys->p_display ),
  1926.                         False, SubstructureNotifyMask|SubstructureRedirectMask,
  1927.                         (XEvent*)&event );
  1928.         }
  1929. /* "bad fullscreen" - set this to 0. doing fullscreen this way is problematic
  1930.  * for many reasons and basically fights with the window manager as the wm
  1931.  * reparents AND vlc goes and reparents - multiple times. don't do it. it just
  1932.  * makes it more inefficient and less "nice" to the x11 citizenry. this turns
  1933.  * it off */
  1934. #define BADFS 0
  1935. /* explicitly asking for focus when you fullscreened is a little silly. the
  1936.  * window manager SHOULD be handling this itself based on its own focus
  1937.  * policies. if the user is "using" a given xinerama/xrandr screen or x11
  1938.  * multihead screen AND vlc wants to fullscreen the wm should also focus it
  1939.  * as its the only thing on the screen. if vlc fullscreens and its on
  1940.  * "another monitor" to the one the user is using - this may "steal" the focus
  1941.  * as really the wm should be deciding if, on fullscreening of a window
  1942.  * the focus should go there or not, so let the wm decided */
  1943. #define APPFOCUS 0
  1944. #ifdef HAVE_XINERAMA
  1945.         if( XineramaQueryExtension( p_vout->p_sys->p_display, &i_d1, &i_d2 ) &&
  1946.             XineramaIsActive( p_vout->p_sys->p_display ) )
  1947.         {
  1948.             XineramaScreenInfo *screens;   /* infos for xinerama */
  1949.             int i_num_screens;
  1950.             msg_Dbg( p_vout, "using XFree Xinerama extension");
  1951. #define SCREEN p_vout->p_sys->p_win->i_screen
  1952.             /* Get Information about Xinerama (num of screens) */
  1953.             screens = XineramaQueryScreens( p_vout->p_sys->p_display,
  1954.                                             &i_num_screens );
  1955.             SCREEN = config_GetInt( p_vout,
  1956.                                         MODULE_STRING "-xineramascreen" );
  1957.             /* just check that user has entered a good value,
  1958.              * otherwise use that screen where window is */
  1959.             if( SCREEN >= i_num_screens || SCREEN < 0 )
  1960.             {
  1961.                 int overlapping=0;
  1962.                 int rightmost_left=0;
  1963.                 int leftmost_right=0;
  1964.                 int bottommost_top=0;
  1965.                 int topmost_bottom=0;
  1966.                 int best_screen=0;
  1967.                 int best_overlapping=0;
  1968.                 int dx,dy;
  1969.                 msg_Dbg( p_vout, "requested screen number invalid (%d/%d)", SCREEN, i_num_screens );
  1970. #define left ( screens[SCREEN].x_org )
  1971. #define right ( left + screens[SCREEN].width )
  1972. #define top screens[SCREEN].y_org
  1973. #define bottom ( top + screens[SCREEN].height )
  1974.                 /* Code mostly same as http://superswitcher.googlecode.com/svn/trunk/src/xinerama.c
  1975.                  * by Nigel Tao, as it was pretty clean implemention what's needed here. Checks what display
  1976.                  * contains most of the window, and use that as fullscreen screen instead screen what
  1977.                  * contains videowindows 0.0 */
  1978.                  for( SCREEN = i_num_screens-1; SCREEN >= 0; SCREEN--)
  1979.                  {
  1980.                      rightmost_left = __MAX( left, screen_x );
  1981.                      leftmost_right = __MIN( right, screen_x + win_width );
  1982.                      bottommost_top = __MAX( top, screen_y );
  1983.                      topmost_bottom = __MIN( bottom , screen_y + win_height );
  1984.                      dx = leftmost_right - rightmost_left;
  1985.                      dy = topmost_bottom - bottommost_top;
  1986.                      overlapping=0;
  1987.                      if ( dx > 0 && dy > 0 )
  1988.                          overlapping = dx*dy;
  1989.                      if( SCREEN == (i_num_screens-1) ||
  1990.                              overlapping > best_overlapping )
  1991.                      {
  1992.                          best_overlapping = overlapping;
  1993.                          best_screen = SCREEN;
  1994.                      }
  1995.                  }
  1996.                  msg_Dbg( p_vout, "setting best screen to %d", best_screen );
  1997.                  SCREEN = best_screen;
  1998. #undef bottom
  1999. #undef top
  2000. #undef right
  2001. #undef left
  2002.             }
  2003.             /* Get the X/Y upper left corner coordinate of the above screen */
  2004.             p_vout->p_sys->p_win->i_x = screens[SCREEN].x_org;
  2005.             p_vout->p_sys->p_win->i_y = screens[SCREEN].y_org;
  2006.             /* Set the Height/width to the screen resolution */
  2007.             p_vout->p_sys->p_win->i_width = screens[SCREEN].width;
  2008.             p_vout->p_sys->p_win->i_height = screens[SCREEN].height;
  2009.             XFree(screens);
  2010. #undef SCREEN
  2011.         }
  2012.         else
  2013. #endif
  2014.         {
  2015.             /* The window wasn't necessarily created at the requested size */
  2016.             p_vout->p_sys->p_win->i_x = p_vout->p_sys->p_win->i_y = 0;
  2017. #ifdef HAVE_XF86VIDMODE
  2018.             XF86VidModeModeLine mode;
  2019.             int i_dummy;
  2020.             if( XF86VidModeGetModeLine( p_vout->p_sys->p_display,
  2021.                                         p_vout->p_sys->i_screen, &i_dummy,
  2022.                                         &mode ) )
  2023.             {
  2024.                 p_vout->p_sys->p_win->i_width = mode.hdisplay;
  2025.                 p_vout->p_sys->p_win->i_height = mode.vdisplay;
  2026.                 /* move cursor to the middle of the window to prevent
  2027.                  * unwanted display move if the display is smaller than the
  2028.                  * full desktop */
  2029.                 XWarpPointer( p_vout->p_sys->p_display, None,
  2030.                               p_vout->p_sys->p_win->base_window, 0, 0, 0, 0,
  2031.                               mode.hdisplay / 2 , mode.vdisplay / 2 );
  2032.                 /* force desktop view to upper left corner */
  2033.                 XF86VidModeSetViewPort( p_vout->p_sys->p_display,
  2034.                                         p_vout->p_sys->i_screen, 0, 0 );
  2035.             }
  2036.             else
  2037. #endif
  2038.             {
  2039.                 p_vout->p_sys->p_win->i_width =
  2040.                     DisplayWidth( p_vout->p_sys->p_display,
  2041.                                 p_vout->p_sys->i_screen );
  2042.                 p_vout->p_sys->p_win->i_height =
  2043.                     DisplayHeight( p_vout->p_sys->p_display,
  2044.                                 p_vout->p_sys->i_screen );
  2045.             }
  2046.         }
  2047.         XMoveResizeWindow( p_vout->p_sys->p_display,
  2048.                            p_vout->p_sys->p_win->base_window,
  2049.                            p_vout->p_sys->p_win->i_x,
  2050.                            p_vout->p_sys->p_win->i_y,
  2051.                            p_vout->p_sys->p_win->i_width,
  2052.                            p_vout->p_sys->p_win->i_height );
  2053. #ifdef HAVE_XSP
  2054.         EnablePixelDoubling( p_vout );
  2055. #endif
  2056. #if APPFOCUS // RASTER: let the wm do focus policy
  2057.         /* Activate the window (give it the focus) */
  2058.         XClientMessageEvent event;
  2059.         memset( &event, 0, sizeof( XClientMessageEvent ) );
  2060.         event.type = ClientMessage;
  2061.         event.message_type =
  2062.            XInternAtom( p_vout->p_sys->p_display, "_NET_ACTIVE_WINDOW", False );
  2063.         event.display = p_vout->p_sys->p_display;
  2064.         event.window = p_vout->p_sys->p_win->base_window;
  2065.         event.format = 32;
  2066.         event.data.l[ 0 ] = 1; /* source indication (1 = from an application */
  2067.         event.data.l[ 1 ] = 0; /* timestamp */
  2068.         event.data.l[ 2 ] = 0; /* requestor's currently active window */
  2069.         /* XXX: window manager would be more likely to obey if we already have
  2070.          * an active window (and give it to the event), such as an interface */
  2071.         XSendEvent( p_vout->p_sys->p_display,
  2072.                     DefaultRootWindow( p_vout->p_sys->p_display ),
  2073.                     False, SubstructureRedirectMask,
  2074.                     (XEvent*)&event );
  2075. #endif
  2076.     }
  2077.     else
  2078.     {
  2079.         msg_Dbg( p_vout, "leaving fullscreen mode" );
  2080. #ifdef HAVE_XSP
  2081.         DisablePixelDoubling( p_vout );
  2082. #endif
  2083.         XReparentWindow( p_vout->p_sys->p_display,
  2084.                          p_vout->p_sys->original_window.video_window,
  2085.                          p_vout->p_sys->original_window.base_window, 0, 0 );
  2086.         p_vout->p_sys->fullscreen_window.video_window = None;
  2087.         DestroyWindow( p_vout, &p_vout->p_sys->fullscreen_window );
  2088.         p_vout->p_sys->p_win = &p_vout->p_sys->original_window;
  2089.         XMapWindow( p_vout->p_sys->p_display,
  2090.                     p_vout->p_sys->p_win->base_window );
  2091.     }
  2092.     /* Unfortunately, using XSync() here is not enough to ensure the
  2093.      * window has already been mapped because the XMapWindow() request
  2094.      * has not necessarily been sent directly to our window (remember,
  2095.      * the call is first redirected to the window manager) */
  2096. #if BADFS // RASTER: this is silly... if we have already mapped before
  2097.     XEvent xevent;
  2098.     do
  2099.     {
  2100.         XWindowEvent( p_vout->p_sys->p_display,
  2101.                       p_vout->p_sys->p_win->base_window,
  2102.                       StructureNotifyMask, &xevent );
  2103.     } while( xevent.type != MapNotify );
  2104. #else
  2105.    XSync(p_vout->p_sys->p_display, False);
  2106. #endif
  2107.     /* Be careful, this can generate a BadMatch error if the window is not
  2108.      * already mapped by the server (see above) */
  2109.     XSetInputFocus(p_vout->p_sys->p_display,
  2110.                    p_vout->p_sys->p_win->base_window,
  2111.                    RevertToParent,
  2112.                    CurrentTime);
  2113.     /* signal that the size needs to be updated */
  2114.     p_vout->i_changes |= VOUT_SIZE_CHANGE;
  2115. }
  2116. /*****************************************************************************
  2117.  * EnableXScreenSaver: enable screen saver
  2118.  *****************************************************************************
  2119.  * This function enables the screen saver on a display after it has been
  2120.  * disabled by XDisableScreenSaver.
  2121.  * FIXME: what happens if multiple vlc sessions are running at the same
  2122.  *        time ???
  2123.  *****************************************************************************/
  2124. static void EnableXScreenSaver( vout_thread_t *p_vout )
  2125. {
  2126. #ifdef DPMSINFO_IN_DPMS_H
  2127.     int dummy;
  2128. #endif
  2129.     if( p_vout->p_sys->i_ss_timeout )
  2130.     {
  2131.         XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
  2132.                          p_vout->p_sys->i_ss_interval,
  2133.                          p_vout->p_sys->i_ss_blanking,
  2134.                          p_vout->p_sys->i_ss_exposure );
  2135.     }
  2136.     /* Restore DPMS settings */
  2137. #ifdef DPMSINFO_IN_DPMS_H
  2138.     if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
  2139.     {
  2140.         if( p_vout->p_sys->b_ss_dpms )
  2141.         {
  2142.             DPMSEnable( p_vout->p_sys->p_display );
  2143.         }
  2144.     }
  2145. #endif
  2146. }
  2147. /*****************************************************************************
  2148.  * DisableXScreenSaver: disable screen saver
  2149.  *****************************************************************************
  2150.  * See XEnableXScreenSaver
  2151.  *****************************************************************************/
  2152. static void DisableXScreenSaver( vout_thread_t *p_vout )
  2153. {
  2154. #ifdef DPMSINFO_IN_DPMS_H
  2155.     int dummy;
  2156. #endif
  2157.     /* Save screen saver information */
  2158.     XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
  2159.                      &p_vout->p_sys->i_ss_interval,
  2160.                      &p_vout->p_sys->i_ss_blanking,
  2161.                      &p_vout->p_sys->i_ss_exposure );
  2162.     /* Disable screen saver */
  2163.     if( p_vout->p_sys->i_ss_timeout )
  2164.     {
  2165.         XSetScreenSaver( p_vout->p_sys->p_display, 0,
  2166.                          p_vout->p_sys->i_ss_interval,
  2167.                          p_vout->p_sys->i_ss_blanking,
  2168.                          p_vout->p_sys->i_ss_exposure );
  2169.     }
  2170.     /* Disable DPMS */
  2171. #ifdef DPMSINFO_IN_DPMS_H
  2172.     if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
  2173.     {
  2174.         CARD16 unused;
  2175.         /* Save DPMS current state */
  2176.         DPMSInfo( p_vout->p_sys->p_display, &unused,
  2177.                   &p_vout->p_sys->b_ss_dpms );
  2178.         DPMSDisable( p_vout->p_sys->p_display );
  2179.    }
  2180. #endif
  2181. }
  2182. /*****************************************************************************
  2183.  * CreateCursor: create a blank mouse pointer
  2184.  *****************************************************************************/
  2185. static void CreateCursor( vout_thread_t *p_vout )
  2186. {
  2187.     XColor cursor_color;
  2188.     p_vout->p_sys->cursor_pixmap =
  2189.         XCreatePixmap( p_vout->p_sys->p_display,
  2190.                        DefaultRootWindow( p_vout->p_sys->p_display ),
  2191.                        1, 1, 1 );
  2192.     XParseColor( p_vout->p_sys->p_display,
  2193.                  XCreateColormap( p_vout->p_sys->p_display,
  2194.                                   DefaultRootWindow(
  2195.                                                     p_vout->p_sys->p_display ),
  2196.                                   DefaultVisual(
  2197.                                                 p_vout->p_sys->p_display,
  2198.                                                 p_vout->p_sys->i_screen ),
  2199.                                   AllocNone ),
  2200.                  "black", &cursor_color );
  2201.     p_vout->p_sys->blank_cursor =
  2202.         XCreatePixmapCursor( p_vout->p_sys->p_display,
  2203.                              p_vout->p_sys->cursor_pixmap,
  2204.                              p_vout->p_sys->cursor_pixmap,
  2205.                              &cursor_color, &cursor_color, 1, 1 );
  2206. }
  2207. /*****************************************************************************
  2208.  * DestroyCursor: destroy the blank mouse pointer
  2209.  *****************************************************************************/
  2210. static void DestroyCursor( vout_thread_t *p_vout )
  2211. {
  2212.     XFreePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap );
  2213. }
  2214. /*****************************************************************************
  2215.  * ToggleCursor: hide or show the mouse pointer
  2216.  *****************************************************************************
  2217.  * This function hides the X pointer if it is visible by setting the pointer
  2218.  * sprite to a blank one. To show it again, we disable the sprite.
  2219.  *****************************************************************************/
  2220. static void ToggleCursor( vout_thread_t *p_vout )
  2221. {
  2222.     if( p_vout->p_sys->b_mouse_pointer_visible )
  2223.     {
  2224.         XDefineCursor( p_vout->p_sys->p_display,
  2225.                        p_vout->p_sys->p_win->base_window,
  2226.                        p_vout->p_sys->blank_cursor );
  2227.         p_vout->p_sys->b_mouse_pointer_visible = 0;
  2228.     }
  2229.     else
  2230.     {
  2231.         XUndefineCursor( p_vout->p_sys->p_display,
  2232.                          p_vout->p_sys->p_win->base_window );
  2233.         p_vout->p_sys->b_mouse_pointer_visible = 1;
  2234.     }
  2235. }
  2236. #if defined(MODULE_NAME_IS_xvideo) || defined(MODULE_NAME_IS_xvmc)
  2237. /*****************************************************************************
  2238.  * XVideoGetPort: get YUV12 port
  2239.  *****************************************************************************/
  2240. static int XVideoGetPort( vout_thread_t *p_vout,
  2241.                           vlc_fourcc_t i_chroma, picture_heap_t *p_heap )
  2242. {
  2243.     XvAdaptorInfo *p_adaptor;
  2244.     unsigned int i;
  2245.     unsigned int i_adaptor, i_num_adaptors;
  2246.     int i_requested_adaptor;
  2247.     int i_selected_port;
  2248.     switch( XvQueryExtension( p_vout->p_sys->p_display, &i, &i, &i, &i, &i ) )
  2249.     {
  2250.         case Success:
  2251.             break;
  2252.         case XvBadExtension:
  2253.             msg_Warn( p_vout, "XvBadExtension" );
  2254.             return -1;
  2255.         case XvBadAlloc:
  2256.             msg_Warn( p_vout, "XvBadAlloc" );
  2257.             return -1;
  2258.         default:
  2259.             msg_Warn( p_vout, "XvQueryExtension failed" );
  2260.             return -1;
  2261.     }
  2262.     switch( XvQueryAdaptors( p_vout->p_sys->p_display,
  2263.                              DefaultRootWindow( p_vout->p_sys->p_display ),
  2264.                              &i_num_adaptors, &p_adaptor ) )
  2265.     {
  2266.         case Success:
  2267.             break;
  2268.         case XvBadExtension:
  2269.             msg_Warn( p_vout, "XvBadExtension for XvQueryAdaptors" );
  2270.             return -1;
  2271.         case XvBadAlloc:
  2272.             msg_Warn( p_vout, "XvBadAlloc for XvQueryAdaptors" );
  2273.             return -1;
  2274.         default:
  2275.             msg_Warn( p_vout, "XvQueryAdaptors failed" );
  2276.             return -1;
  2277.     }
  2278.     i_selected_port = -1;
  2279. #ifdef MODULE_NAME_IS_xvmc
  2280.     i_requested_adaptor = config_GetInt( p_vout, "xvmc-adaptor" );
  2281. #else
  2282.     i_requested_adaptor = config_GetInt( p_vout, "xvideo-adaptor" );
  2283. #endif
  2284.     for( i_adaptor = 0; i_adaptor < i_num_adaptors; ++i_adaptor )
  2285.     {
  2286.         XvImageFormatValues *p_formats;
  2287.         int i_format, i_num_formats;
  2288.         int i_port;
  2289.         /* If we requested an adaptor and it's not this one, we aren't
  2290.          * interested */
  2291.         if( i_requested_adaptor != -1 && ((int)i_adaptor != i_requested_adaptor) )
  2292.         {
  2293.             continue;
  2294.         }
  2295.         /* If the adaptor doesn't have the required properties, skip it */
  2296.         if( !( p_adaptor[ i_adaptor ].type & XvInputMask ) ||
  2297.             !( p_adaptor[ i_adaptor ].type & XvImageMask ) )
  2298.         {
  2299.             continue;
  2300.         }
  2301.         /* Check that adaptor supports our requested format... */
  2302.         p_formats = XvListImageFormats( p_vout->p_sys->p_display,
  2303.                                         p_adaptor[i_adaptor].base_id,
  2304.                                         &i_num_formats );
  2305.         for( i_format = 0;
  2306.              i_format < i_num_formats && ( i_selected_port == -1 );
  2307.              i_format++ )
  2308.         {
  2309.             XvAttribute     *p_attr;
  2310.             int             i_attr, i_num_attributes;
  2311.             Atom            autopaint = None, colorkey = None;
  2312.             /* If this is not the format we want, or at least a
  2313.              * similar one, forget it */
  2314.             if( !vout_ChromaCmp( p_formats[ i_format ].id, i_chroma ) )
  2315.             {
  2316.                 continue;
  2317.             }
  2318.             /* Look for the first available port supporting this format */
  2319.             for( i_port = p_adaptor[i_adaptor].base_id;
  2320.                  ( i_port < (int)(p_adaptor[i_adaptor].base_id
  2321.                                    + p_adaptor[i_adaptor].num_ports) )
  2322.                    && ( i_selected_port == -1 );
  2323.                  i_port++ )
  2324.             {
  2325.                 if( XvGrabPort( p_vout->p_sys->p_display, i_port, CurrentTime )
  2326.                      == Success )
  2327.                 {
  2328.                     i_selected_port = i_port;
  2329.                     p_heap->i_chroma = p_formats[ i_format ].id;
  2330. #if XvVersion > 2 || ( XvVersion == 2 && XvRevision >= 2 )
  2331.                     p_heap->i_rmask = p_formats[ i_format ].red_mask;
  2332.                     p_heap->i_gmask = p_formats[ i_format ].green_mask;
  2333.                     p_heap->i_bmask = p_formats[ i_format ].blue_mask;
  2334. #endif
  2335.                 }
  2336.             }
  2337.             /* If no free port was found, forget it */
  2338.             if( i_selected_port == -1 )
  2339.             {
  2340.                 continue;
  2341.             }
  2342.             /* If we found a port, print information about it */
  2343.             msg_Dbg( p_vout, "adaptor %i, port %i, format 0x%x (%4.4s) %s",
  2344.                      i_adaptor, i_selected_port, p_formats[ i_format ].id,
  2345.                      (char *)&p_formats[ i_format ].id,
  2346.                      ( p_formats[ i_format ].format == XvPacked ) ?
  2347.                          "packed" : "planar" );
  2348.             /* Use XV_AUTOPAINT_COLORKEY if supported, otherwise we will
  2349.              * manually paint the colour key */
  2350.             p_attr = XvQueryPortAttributes( p_vout->p_sys->p_display,
  2351.                                             i_selected_port,
  2352.                                             &i_num_attributes );
  2353.             for( i_attr = 0; i_attr < i_num_attributes; i_attr++ )
  2354.             {
  2355.                 if( !strcmp( p_attr[i_attr].name, "XV_AUTOPAINT_COLORKEY" ) )
  2356.                 {
  2357.                     autopaint = XInternAtom( p_vout->p_sys->p_display,
  2358.                                              "XV_AUTOPAINT_COLORKEY", False );
  2359.                     XvSetPortAttribute( p_vout->p_sys->p_display,
  2360.                                         i_selected_port, autopaint, 1 );
  2361.                 }
  2362.                 if( !strcmp( p_attr[i_attr].name, "XV_COLORKEY" ) )
  2363.                 {
  2364.                     /* Find out the default colour key */
  2365.                     colorkey = XInternAtom( p_vout->p_sys->p_display,
  2366.                                             "XV_COLORKEY", False );
  2367.                     XvGetPortAttribute( p_vout->p_sys->p_display,
  2368.                                         i_selected_port, colorkey,
  2369.                                         &p_vout->p_sys->i_colourkey );
  2370.                 }
  2371.             }
  2372.             p_vout->p_sys->b_paint_colourkey =
  2373.                 autopaint == None && colorkey != None;
  2374.             if( p_attr != NULL )
  2375.             {
  2376.                 XFree( p_attr );
  2377.             }
  2378.         }
  2379.         if( p_formats != NULL )
  2380.         {
  2381.             XFree( p_formats );
  2382.         }
  2383.     }
  2384.     if( i_num_adaptors > 0 )
  2385.     {
  2386.         XvFreeAdaptorInfo( p_adaptor );
  2387.     }
  2388.     if( i_selected_port == -1 )
  2389.     {
  2390.         int i_chroma_tmp = X112VLC_FOURCC( i_chroma );
  2391.         if( i_requested_adaptor == -1 )
  2392.         {
  2393.             msg_Warn( p_vout, "no free XVideo port found for format "
  2394.                       "0x%.8x (%4.4s)", i_chroma_tmp, (char*)&i_chroma_tmp );
  2395.         }
  2396.         else
  2397.         {
  2398.             msg_Warn( p_vout, "XVideo adaptor %i does not have a free "
  2399.                       "XVideo port for format 0x%.8x (%4.4s)",
  2400.                       i_requested_adaptor, i_chroma_tmp, (char*)&i_chroma_tmp );
  2401.         }
  2402.     }
  2403.     return i_selected_port;
  2404. }
  2405. /*****************************************************************************
  2406.  * XVideoReleasePort: release YUV12 port
  2407.  *****************************************************************************/
  2408. static void XVideoReleasePort( vout_thread_t *p_vout, int i_port )
  2409. {
  2410.     XvUngrabPort( p_vout->p_sys->p_display, i_port, CurrentTime );
  2411. }
  2412. #endif
  2413. /*****************************************************************************
  2414.  * InitDisplay: open and initialize X11 device
  2415.  *****************************************************************************
  2416.  * Create a window according to video output given size, and set other
  2417.  * properties according to the display properties.
  2418.  *****************************************************************************/
  2419. static int InitDisplay( vout_thread_t *p_vout )
  2420. {
  2421. #ifdef MODULE_NAME_IS_x11
  2422.     XPixmapFormatValues *       p_formats;                 /* pixmap formats */
  2423.     XVisualInfo *               p_xvisual;            /* visuals information */
  2424.     XVisualInfo                 xvisual_template;         /* visual template */
  2425.     int                         i_count, i;                    /* array size */
  2426. #endif
  2427. #ifdef HAVE_SYS_SHM_H
  2428.     p_vout->p_sys->i_shm_opcode = 0;
  2429. #ifndef MODULE_NAME_IS_glx
  2430.     if( config_GetInt( p_vout, MODULE_STRING "-shm" ) > 0 )
  2431.     {
  2432.         int major, evt, err;
  2433.         if( XQueryExtension( p_vout->p_sys->p_display, "MIT-SHM", &major,
  2434.                              &evt, &err )
  2435.          && XShmQueryExtension( p_vout->p_sys->p_display ) )
  2436.             p_vout->p_sys->i_shm_opcode = major;
  2437.         if( p_vout->p_sys->i_shm_opcode )
  2438.         {
  2439.             int minor;
  2440.             Bool pixmaps;
  2441.             XShmQueryVersion( p_vout->p_sys->p_display, &major, &minor,
  2442.                               &pixmaps );
  2443.             msg_Dbg( p_vout, "XShm video extension v%d.%d "
  2444.                      "(with%s pixmaps, opcode: %d)",
  2445.                      major, minor, pixmaps ? "" : "out",
  2446.                      p_vout->p_sys->i_shm_opcode );
  2447.         }
  2448.         else
  2449.             msg_Warn( p_vout, "XShm video extension not available" );
  2450.     }
  2451.     else
  2452.         msg_Dbg( p_vout, "XShm video extension disabled" );
  2453. #endif
  2454. #endif
  2455. #ifdef MODULE_NAME_IS_xvideo
  2456.     /* XXX The brightness and contrast values should be read from environment
  2457.      * XXX variables... */
  2458. #if 0
  2459.     XVideoSetAttribute( p_vout, "XV_BRIGHTNESS", 0.5 );
  2460.     XVideoSetAttribute( p_vout, "XV_CONTRAST",   0.5 );
  2461. #endif
  2462. #endif
  2463. #ifdef MODULE_NAME_IS_x11
  2464.     /* Initialize structure */
  2465.     p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
  2466.     /* Get screen depth */
  2467.     p_vout->p_sys->i_screen_depth = XDefaultDepth( p_vout->p_sys->p_display,
  2468.                                                    p_vout->p_sys->i_screen );
  2469.     switch( p_vout->p_sys->i_screen_depth )
  2470.     {
  2471.     case 8:
  2472.         /*
  2473.          * Screen depth is 8bpp. Use PseudoColor visual with private colormap.
  2474.          */
  2475.         xvisual_template.screen =   p_vout->p_sys->i_screen;
  2476.         xvisual_template.class =    DirectColor;
  2477.         p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display,
  2478.                                     VisualScreenMask | VisualClassMask,
  2479.                                     &xvisual_template, &i_count );
  2480.         if( p_xvisual == NULL )
  2481.         {
  2482.             msg_Err( p_vout, "no PseudoColor visual available" );
  2483.             return VLC_EGENERIC;
  2484.         }
  2485.         p_vout->p_sys->i_bytes_per_pixel = 1;
  2486.         p_vout->output.pf_setpalette = SetPalette;
  2487.         break;
  2488.     case 15:
  2489.     case 16:
  2490.     case 24:
  2491.     default:
  2492.         /*
  2493.          * Screen depth is higher than 8bpp. TrueColor visual is used.
  2494.          */
  2495.         xvisual_template.screen =   p_vout->p_sys->i_screen;
  2496.         xvisual_template.class =    TrueColor;
  2497. /* In some cases, we get a truecolor class adaptor that has a different
  2498.    color depth. So try to get a real true color one first */
  2499.         xvisual_template.depth =    p_vout->p_sys->i_screen_depth;
  2500.         p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display,
  2501.                                     VisualScreenMask | VisualClassMask |
  2502.                                     VisualDepthMask,
  2503.                                     &xvisual_template, &i_count );
  2504.         if( p_xvisual == NULL )
  2505.         {
  2506.             msg_Warn( p_vout, "No screen matching the required color depth" );
  2507.             p_xvisual = XGetVisualInfo( p_vout->p_sys->p_display,
  2508.                                     VisualScreenMask | VisualClassMask,
  2509.                                     &xvisual_template, &i_count );
  2510.             if( p_xvisual == NULL )
  2511.             {
  2512.                 msg_Err( p_vout, "no TrueColor visual available" );
  2513.                 return VLC_EGENERIC;
  2514.             }
  2515.         }
  2516.         p_vout->output.i_rmask = p_xvisual->red_mask;
  2517.         p_vout->output.i_gmask = p_xvisual->green_mask;
  2518.         p_vout->output.i_bmask = p_xvisual->blue_mask;
  2519.         /* There is no difference yet between 3 and 4 Bpp. The only way
  2520.          * to find the actual number of bytes per pixel is to list supported
  2521.          * pixmap formats. */
  2522.         p_formats = XListPixmapFormats( p_vout->p_sys->p_display, &i_count );
  2523.         p_vout->p_sys->i_bytes_per_pixel = 0;
  2524.         for( i = 0; i < i_count; i++ )
  2525.         {
  2526.             /* Under XFree4.0, the list contains pixmap formats available
  2527.              * through all video depths ; so we have to check against current
  2528.              * depth. */
  2529.             if( p_formats[i].depth == (int)p_vout->p_sys->i_screen_depth )
  2530.             {
  2531.                 if( p_formats[i].bits_per_pixel / 8
  2532.                         > (int)p_vout->p_sys->i_bytes_per_pixel )
  2533.                 {
  2534.                     p_vout->p_sys->i_bytes_per_pixel =
  2535.                         p_formats[i].bits_per_pixel / 8;
  2536.                 }
  2537.             }
  2538.         }
  2539.         if( p_formats ) XFree( p_formats );
  2540.         break;
  2541.     }
  2542.     p_vout->p_sys->p_visual = p_xvisual->visual;
  2543.     XFree( p_xvisual );
  2544. #endif
  2545.     return VLC_SUCCESS;
  2546. }
  2547. #ifndef MODULE_NAME_IS_glx
  2548. #ifdef HAVE_SYS_SHM_H
  2549. /*****************************************************************************
  2550.  * CreateShmImage: create an XImage or XvImage using shared memory extension
  2551.  *****************************************************************************
  2552.  * Prepare an XImage or XvImage for display function.
  2553.  * The order of the operations respects the recommandations of the mit-shm
  2554.  * document by J.Corbet and K.Packard. Most of the parameters were copied from
  2555.  * there. See http://ftp.xfree86.org/pub/XFree86/4.0/doc/mit-shm.TXT
  2556.  *****************************************************************************/
  2557. IMAGE_TYPE * CreateShmImage( vout_thread_t *p_vout,
  2558.                                     Display* p_display, EXTRA_ARGS_SHM,
  2559.                                     int i_width, int i_height )
  2560. {
  2561.     IMAGE_TYPE *p_image;
  2562.     Status result;
  2563.     /* Create XImage / XvImage */
  2564. #ifdef MODULE_NAME_IS_xvideo
  2565.     p_image = XvShmCreateImage( p_display, i_xvport, i_chroma, 0,
  2566.                                 i_width, i_height, p_shm );
  2567. #elif defined(MODULE_NAME_IS_xvmc)
  2568.     p_image = XvShmCreateImage( p_display, i_xvport, i_chroma, 0,
  2569.                                 i_width, i_height, p_shm );
  2570. #else
  2571.     p_image = XShmCreateImage( p_display, p_visual, i_depth, ZPixmap, 0,
  2572.                                p_shm, i_width, i_height );
  2573. #endif
  2574.     if( p_image == NULL )
  2575.     {
  2576.         msg_Err( p_vout, "image creation failed" );
  2577.         return NULL;
  2578.     }
  2579.     /* For too big image, the buffer returned is sometimes too small, prevent
  2580.      * VLC to segfault because of it
  2581.      * FIXME is it normal ? Is there a way to detect it
  2582.      * before (XvQueryBestSize did not) ? */
  2583.     if( p_image->width < i_width || p_image->height < i_height )
  2584.     {
  2585.         msg_Err( p_vout, "cannot allocate shared image data with the right size "
  2586.                          "(%dx%d instead of %dx%d)",
  2587.                          p_image->width, p_image->height,
  2588.                          i_width, i_height );
  2589.         IMAGE_FREE( p_image );
  2590.         return NULL;
  2591.     }
  2592.     /* Allocate shared memory segment. */
  2593.     p_shm->shmid = shmget( IPC_PRIVATE, DATA_SIZE(p_image), IPC_CREAT | 0600 );
  2594.     if( p_shm->shmid < 0 )
  2595.     {
  2596.         msg_Err( p_vout, "cannot allocate shared image data (%m)" );
  2597.         IMAGE_FREE( p_image );
  2598.         return NULL;
  2599.     }
  2600.     /* Attach shared memory segment to process (read/write) */
  2601.     p_shm->shmaddr = p_image->data = shmat( p_shm->shmid, 0, 0 );
  2602.     if(! p_shm->shmaddr )
  2603.     {
  2604.         msg_Err( p_vout, "cannot attach shared memory (%m)" );
  2605.         IMAGE_FREE( p_image );
  2606.         shmctl( p_shm->shmid, IPC_RMID, 0 );
  2607.         return NULL;
  2608.     }
  2609.     /* Read-only data. We won't be using XShmGetImage */
  2610.     p_shm->readOnly = True;
  2611.     /* Attach shared memory segment to X server */
  2612.     XSynchronize( p_display, True );
  2613.     i_shm_major = p_vout->p_sys->i_shm_opcode;
  2614.     result = XShmAttach( p_display, p_shm );
  2615.     if( result == False || !i_shm_major )
  2616.     {
  2617.         msg_Err( p_vout, "cannot attach shared memory to X server" );
  2618.         IMAGE_FREE( p_image );
  2619.         shmctl( p_shm->shmid, IPC_RMID, 0 );
  2620.         shmdt( p_shm->shmaddr );
  2621.         return NULL;
  2622.     }
  2623.     XSynchronize( p_display, False );
  2624.     /* Send image to X server. This instruction is required, since having
  2625.      * built a Shm XImage and not using it causes an error on XCloseDisplay,
  2626.      * and remember NOT to use XFlush ! */
  2627.     XSync( p_display, False );
  2628. #if 0
  2629.     /* Mark the shm segment to be removed when there are no more
  2630.      * attachements, so it is automatic on process exit or after shmdt */
  2631.     shmctl( p_shm->shmid, IPC_RMID, 0 );
  2632. #endif
  2633.     return p_image;
  2634. }
  2635. #endif
  2636. /*****************************************************************************
  2637.  * CreateImage: create an XImage or XvImage
  2638.  *****************************************************************************
  2639.  * Create a simple image used as a buffer.
  2640.  *****************************************************************************/
  2641. static IMAGE_TYPE * CreateImage( vout_thread_t *p_vout,
  2642.                                  Display *p_display, EXTRA_ARGS,
  2643.                                  int i_width, int i_height )
  2644. {
  2645.     uint8_t *    p_data;                          /* image data storage zone */
  2646.     IMAGE_TYPE *p_image;
  2647. #ifdef MODULE_NAME_IS_x11
  2648.     int         i_quantum;                     /* XImage quantum (see below) */
  2649.     int         i_bytes_per_line;
  2650. #endif
  2651.     /* Allocate memory for image */
  2652. #ifdef MODULE_NAME_IS_xvideo
  2653.     p_data = malloc( i_width * i_height * i_bits_per_pixel / 8 );
  2654. #elif defined(MODULE_NAME_IS_x11)
  2655.     i_bytes_per_line = i_width * i_bytes_per_pixel;
  2656.     p_data = malloc( i_bytes_per_line * i_height );
  2657. #endif
  2658.     if( !p_data )
  2659.         return NULL;
  2660. #ifdef MODULE_NAME_IS_x11
  2661.     /* Optimize the quantum of a scanline regarding its size - the quantum is
  2662.        a diviser of the number of bits between the start of two scanlines. */
  2663.     if( i_bytes_per_line & 0xf )
  2664.     {
  2665.         i_quantum = 0x8;
  2666.     }
  2667.     else if( i_bytes_per_line & 0x10 )
  2668.     {
  2669.         i_quantum = 0x10;
  2670.     }
  2671.     else
  2672.     {
  2673.         i_quantum = 0x20;
  2674.     }
  2675. #endif
  2676.     /* Create XImage. p_data will be automatically freed */
  2677. #ifdef MODULE_NAME_IS_xvideo
  2678.     p_image = XvCreateImage( p_display, i_xvport, i_chroma,
  2679.                              (char *)p_data, i_width, i_height );
  2680. #elif defined(MODULE_NAME_IS_x11)
  2681.     p_image = XCreateImage( p_display, p_visual, i_depth, ZPixmap, 0,
  2682.                             (char *)p_data, i_width, i_height, i_quantum, 0 );
  2683. #endif
  2684.     if( p_image == NULL )
  2685.     {
  2686.         msg_Err( p_vout, "XCreateImage() failed" );
  2687.         free( p_data );
  2688.         return NULL;
  2689.     }
  2690.     return p_image;
  2691. }
  2692. #endif
  2693. /*****************************************************************************
  2694.  * X11ErrorHandler: replace error handler so we can intercept some of them
  2695.  *****************************************************************************/
  2696. static int X11ErrorHandler( Display * display, XErrorEvent * event )
  2697. {
  2698.     char txt[1024];
  2699.     XGetErrorText( display, event->error_code, txt, sizeof( txt ) );
  2700.     fprintf( stderr,
  2701.              "[????????] x11 video output error: X11 request %u.%u failed "
  2702.               "with error code %u:n %sn",
  2703.              event->request_code, event->minor_code, event->error_code, txt );
  2704.     switch( event->request_code )
  2705.     {
  2706.     case X_SetInputFocus:
  2707.         /* Ignore errors on XSetInputFocus()
  2708.          * (they happen when a window is not yet mapped) */
  2709.         return 0;
  2710.     }
  2711. #ifdef HAVE_SYS_SHM_H
  2712.     if( event->request_code == i_shm_major ) /* MIT-SHM */
  2713.     {
  2714.         fprintf( stderr,
  2715.                  "[????????] x11 video output notice:"
  2716.                  " buggy X11 server claims shared memoryn"
  2717.                  "[????????] x11 video output notice:"
  2718.                  " support though it does not work (OpenSSH?)n" );
  2719.         return i_shm_major = 0;
  2720.     }
  2721. #endif
  2722. #ifndef HAVE_OSSO
  2723.     XSetErrorHandler(NULL);
  2724.     return (XSetErrorHandler(X11ErrorHandler))( display, event );
  2725. #else
  2726.     /* Work-around Maemo Xvideo bug */
  2727.     return 0;
  2728. #endif
  2729. }
  2730. #ifdef MODULE_NAME_IS_x11
  2731. /*****************************************************************************
  2732.  * SetPalette: sets an 8 bpp palette
  2733.  *****************************************************************************
  2734.  * This function sets the palette given as an argument. It does not return
  2735.  * anything, but could later send information on which colors it was unable
  2736.  * to set.
  2737.  *****************************************************************************/
  2738. static void SetPalette( vout_thread_t *p_vout,
  2739.                         uint16_t *red, uint16_t *green, uint16_t *blue )
  2740. {
  2741.     int i;
  2742.     XColor p_colors[255];
  2743.     /* allocate palette */
  2744.     for( i = 0; i < 255; i++ )
  2745.     {
  2746.         /* kludge: colors are indexed reversely because color 255 seems
  2747.          * to be reserved for black even if we try to set it to white */
  2748.         p_colors[ i ].pixel = 255 - i;
  2749.         p_colors[ i ].pad   = 0;
  2750.         p_colors[ i ].flags = DoRed | DoGreen | DoBlue;
  2751.         p_colors[ i ].red   = red[ 255 - i ];
  2752.         p_colors[ i ].blue  = blue[ 255 - i ];
  2753.         p_colors[ i ].green = green[ 255 - i ];
  2754.     }
  2755.     XStoreColors( p_vout->p_sys->p_display,
  2756.                   p_vout->p_sys->colormap, p_colors, 255 );
  2757. }
  2758. #endif
  2759. /*****************************************************************************
  2760.  * Control: control facility for the vout
  2761.  *****************************************************************************/
  2762. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  2763. {
  2764.     bool b_arg;
  2765.     unsigned int i_width, i_height;
  2766.     switch( i_query )
  2767.     {
  2768.         case VOUT_SET_SIZE:
  2769.             if( p_vout->p_sys->p_win->owner_window )
  2770.                 return vout_ControlWindow( p_vout->p_sys->p_win->owner_window,
  2771.                                            i_query, args);
  2772.             i_width  = va_arg( args, unsigned int );
  2773.             i_height = va_arg( args, unsigned int );
  2774.             if( !i_width ) i_width = p_vout->i_window_width;
  2775.             if( !i_height ) i_height = p_vout->i_window_height;
  2776. #ifdef MODULE_NAME_IS_xvmc
  2777.             xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
  2778. #endif
  2779.             /* Update dimensions */
  2780.             XResizeWindow( p_vout->p_sys->p_display,
  2781.                            p_vout->p_sys->p_win->base_window,
  2782.                            i_width, i_height );
  2783. #ifdef MODULE_NAME_IS_xvmc
  2784.             xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  2785. #endif
  2786.             return VLC_SUCCESS;
  2787.         case VOUT_SET_STAY_ON_TOP:
  2788.             if( p_vout->p_sys->p_win->owner_window )
  2789.                 return vout_ControlWindow( p_vout->p_sys->p_win->owner_window,
  2790.                                            i_query, args);
  2791.             b_arg = (bool) va_arg( args, int );
  2792. #ifdef MODULE_NAME_IS_xvmc
  2793.             xvmc_context_reader_lock( &p_vout->p_sys->xvmc_lock );
  2794. #endif
  2795.             WindowOnTop( p_vout, b_arg );
  2796. #ifdef MODULE_NAME_IS_xvmc
  2797.             xvmc_context_reader_unlock( &p_vout->p_sys->xvmc_lock );
  2798. #endif
  2799.             return VLC_SUCCESS;
  2800.        default:
  2801.             return VLC_EGENERIC;
  2802.     }
  2803. }
  2804. /*****************************************************************************
  2805.  * TestNetWMSupport: tests for Extended Window Manager Hints support
  2806.  *****************************************************************************/
  2807. static void TestNetWMSupport( vout_thread_t *p_vout )
  2808. {
  2809.     int i_ret, i_format;
  2810.     unsigned long i, i_items, i_bytesafter;
  2811.     Atom net_wm_supported;
  2812.     union { Atom *p_atom; unsigned char *p_char; } p_args;
  2813.     p_args.p_atom = NULL;
  2814.     p_vout->p_sys->b_net_wm_state_fullscreen =
  2815.     p_vout->p_sys->b_net_wm_state_above =
  2816.     p_vout->p_sys->b_net_wm_state_below =
  2817.     p_vout->p_sys->b_net_wm_state_stays_on_top =
  2818.         false;
  2819.     net_wm_supported =
  2820.         XInternAtom( p_vout->p_sys->p_display, "_NET_SUPPORTED", False );
  2821.     i_ret = XGetWindowProperty( p_vout->p_sys->p_display,
  2822.                                 DefaultRootWindow( p_vout->p_sys->p_display ),
  2823.                                 net_wm_supported,
  2824.                                 0, 16384, False, AnyPropertyType,
  2825.                                 &net_wm_supported,
  2826.                                 &i_format, &i_items, &i_bytesafter,
  2827.                                 (unsigned char **)&p_args );
  2828.     if( i_ret != Success || i_items == 0 ) return;
  2829.     msg_Dbg( p_vout, "Window manager supports NetWM" );
  2830.     p_vout->p_sys->net_wm_state =
  2831.         XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE", False );
  2832.     p_vout->p_sys->net_wm_state_fullscreen =
  2833.         XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_FULLSCREEN",
  2834.                      False );
  2835.     p_vout->p_sys->net_wm_state_above =
  2836.         XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_ABOVE", False );
  2837.     p_vout->p_sys->net_wm_state_below =
  2838.         XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_BELOW", False );
  2839.     p_vout->p_sys->net_wm_state_stays_on_top =
  2840.         XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_STAYS_ON_TOP",
  2841.                      False );
  2842.     for( i = 0; i < i_items; i++ )
  2843.     {
  2844.         if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_fullscreen )
  2845.         {
  2846.             msg_Dbg( p_vout,
  2847.                      "Window manager supports _NET_WM_STATE_FULLSCREEN" );
  2848.             p_vout->p_sys->b_net_wm_state_fullscreen = true;
  2849.         }
  2850.         else if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_above )
  2851.         {
  2852.             msg_Dbg( p_vout, "Window manager supports _NET_WM_STATE_ABOVE" );
  2853.             p_vout->p_sys->b_net_wm_state_above = true;
  2854.         }
  2855.         else if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_below )
  2856.         {
  2857.             msg_Dbg( p_vout, "Window manager supports _NET_WM_STATE_BELOW" );
  2858.             p_vout->p_sys->b_net_wm_state_below = true;
  2859.         }
  2860.         else if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_stays_on_top )
  2861.         {
  2862.             msg_Dbg( p_vout,
  2863.                      "Window manager supports _NET_WM_STATE_STAYS_ON_TOP" );
  2864.             p_vout->p_sys->b_net_wm_state_stays_on_top = true;
  2865.         }
  2866.     }
  2867.     XFree( p_args.p_atom );
  2868. }
  2869. /*****************************************************************************
  2870.  * Key events handling
  2871.  *****************************************************************************/
  2872. static const struct
  2873. {
  2874.     int i_x11key;
  2875.     int i_vlckey;
  2876. } x11keys_to_vlckeys[] =
  2877. {
  2878.     { XK_F1, KEY_F1 }, { XK_F2, KEY_F2 }, { XK_F3, KEY_F3 }, { XK_F4, KEY_F4 },
  2879.     { XK_F5, KEY_F5 }, { XK_F6, KEY_F6 }, { XK_F7, KEY_F7 }, { XK_F8, KEY_F8 },
  2880.     { XK_F9, KEY_F9 }, { XK_F10, KEY_F10 }, { XK_F11, KEY_F11 },
  2881.     { XK_F12, KEY_F12 },
  2882.     { XK_Return, KEY_ENTER },
  2883.     { XK_KP_Enter, KEY_ENTER },
  2884.     { XK_space, KEY_SPACE },
  2885.     { XK_Escape, KEY_ESC },
  2886.     { XK_Menu, KEY_MENU },
  2887.     { XK_Left, KEY_LEFT },
  2888.     { XK_Right, KEY_RIGHT },
  2889.     { XK_Up, KEY_UP },
  2890.     { XK_Down, KEY_DOWN },
  2891.     { XK_Home, KEY_HOME },
  2892.     { XK_End, KEY_END },
  2893.     { XK_Page_Up, KEY_PAGEUP },
  2894.     { XK_Page_Down, KEY_PAGEDOWN },
  2895.     { XK_Insert, KEY_INSERT },
  2896.     { XK_Delete, KEY_DELETE },
  2897.     { XF86XK_AudioNext, KEY_MEDIA_NEXT_TRACK},
  2898.     { XF86XK_AudioPrev, KEY_MEDIA_PREV_TRACK},
  2899.     { XF86XK_AudioMute, KEY_VOLUME_MUTE },
  2900.     { XF86XK_AudioLowerVolume, KEY_VOLUME_DOWN },
  2901.     { XF86XK_AudioRaiseVolume, KEY_VOLUME_UP },
  2902.     { XF86XK_AudioPlay, KEY_MEDIA_PLAY_PAUSE },
  2903.     { XF86XK_AudioPause, KEY_MEDIA_PLAY_PAUSE },
  2904.     { 0, 0 }
  2905. };
  2906. static int ConvertKey( int i_key )
  2907. {
  2908.     int i;
  2909.     for( i = 0; x11keys_to_vlckeys[i].i_x11key != 0; i++ )
  2910.     {
  2911.         if( x11keys_to_vlckeys[i].i_x11key == i_key )
  2912.         {
  2913.             return x11keys_to_vlckeys[i].i_vlckey;
  2914.         }
  2915.     }
  2916.     return 0;
  2917. }
  2918. /*****************************************************************************
  2919.  * WindowOnTop: Switches the "always on top" state of the video window.
  2920.  *****************************************************************************/
  2921. static int WindowOnTop( vout_thread_t *p_vout, bool b_on_top )
  2922. {
  2923.     XClientMessageEvent event;
  2924.     memset( &event, 0, sizeof( XClientMessageEvent ) );
  2925.     event.type = ClientMessage;
  2926.     event.message_type = p_vout->p_sys->net_wm_state;
  2927.     event.display = p_vout->p_sys->p_display;
  2928.     event.window = p_vout->p_sys->p_win->base_window;
  2929.     event.format = 32;
  2930.     event.data.l[ 0 ] = b_on_top; /* set property */
  2931.     if( p_vout->p_sys->b_net_wm_state_stays_on_top )
  2932.         event.data.l[ 1 ] = p_vout->p_sys->net_wm_state_stays_on_top;
  2933.     else if( p_vout->p_sys->b_net_wm_state_above )
  2934.         /* use _NET_WM_STATE_ABOVE if window manager
  2935.          * doesn't handle _NET_WM_STATE_STAYS_ON_TOP */
  2936.         event.data.l[ 1 ] = p_vout->p_sys->net_wm_state_above;
  2937.     else
  2938.         return VLC_EGENERIC;
  2939.     XSendEvent( p_vout->p_sys->p_display,
  2940.                 DefaultRootWindow( p_vout->p_sys->p_display ),
  2941.                 False, SubstructureRedirectMask,
  2942.                 (XEvent*)&event );
  2943.     return VLC_SUCCESS;
  2944. }