+
+/*****************************************************************************
+ * Control: control facility for the vout
+ *****************************************************************************/
+static int Control( vout_thread_t *p_vout, int i_query, va_list args )
+{
+ vlc_bool_t b_arg;
+ unsigned int i_width, i_height;
+ unsigned int *pi_width, *pi_height;
+
+ switch( i_query )
+ {
+ case VOUT_GET_SIZE:
+ if( p_vout->p_sys->p_win->owner_window )
+ return vout_ControlWindow( p_vout,
+ (void *)p_vout->p_sys->p_win->owner_window, i_query, args);
+
+ pi_width = va_arg( args, unsigned int * );
+ pi_height = va_arg( args, unsigned int * );
+
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+ *pi_width = p_vout->p_sys->p_win->i_width;
+ *pi_height = p_vout->p_sys->p_win->i_height;
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+ return VLC_SUCCESS;
+
+ case VOUT_SET_SIZE:
+ if( p_vout->p_sys->p_win->owner_window )
+ return vout_ControlWindow( p_vout,
+ (void *)p_vout->p_sys->p_win->owner_window, i_query, args);
+
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+
+ i_width = va_arg( args, unsigned int );
+ i_height = va_arg( args, unsigned int );
+ if( !i_width ) i_width = p_vout->i_window_width;
+ if( !i_height ) i_height = p_vout->i_window_height;
+
+ /* Update dimensions */
+ XResizeWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->p_win->base_window,
+ i_width, i_height );
+
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+ return VLC_SUCCESS;
+
+ case VOUT_CLOSE:
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+ XUnmapWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->original_window.base_window );
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+ /* Fall through */
+
+ case VOUT_REPARENT:
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+ XReparentWindow( p_vout->p_sys->p_display,
+ p_vout->p_sys->original_window.base_window,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ 0, 0 );
+ XSync( p_vout->p_sys->p_display, False );
+ p_vout->p_sys->original_window.owner_window = 0;
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+ return vout_vaControlDefault( p_vout, i_query, args );
+
+ case VOUT_SET_STAY_ON_TOP:
+ if( p_vout->p_sys->p_win->owner_window )
+ return vout_ControlWindow( p_vout,
+ (void *)p_vout->p_sys->p_win->owner_window, i_query, args);
+
+ b_arg = va_arg( args, vlc_bool_t );
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+ WindowOnTop( p_vout, b_arg );
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+ return VLC_SUCCESS;
+
+ default:
+ return vout_vaControlDefault( p_vout, i_query, args );
+ }
+}
+
+/*****************************************************************************
+ * TestNetWMSupport: tests for Extended Window Manager Hints support
+ *****************************************************************************/
+static void TestNetWMSupport( vout_thread_t *p_vout )
+{
+ int i_ret, i_format;
+ unsigned long i, i_items, i_bytesafter;
+ Atom net_wm_supported;
+ union { Atom *p_atom; unsigned char *p_char; } p_args;
+
+ p_args.p_atom = NULL;
+
+ p_vout->p_sys->b_net_wm_state_fullscreen = VLC_FALSE;
+ p_vout->p_sys->b_net_wm_state_above = VLC_FALSE;
+ p_vout->p_sys->b_net_wm_state_below = VLC_FALSE;
+ p_vout->p_sys->b_net_wm_state_stays_on_top = VLC_FALSE;
+
+ net_wm_supported =
+ XInternAtom( p_vout->p_sys->p_display, "_NET_SUPPORTED", False );
+
+ i_ret = XGetWindowProperty( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ net_wm_supported,
+ 0, 16384, False, AnyPropertyType,
+ &net_wm_supported,
+ &i_format, &i_items, &i_bytesafter,
+ (unsigned char **)&p_args );
+
+ if( i_ret != Success || i_items == 0 ) return;
+
+ msg_Dbg( p_vout, "Window manager supports NetWM" );
+
+ p_vout->p_sys->net_wm_state =
+ XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE", False );
+ p_vout->p_sys->net_wm_state_fullscreen =
+ XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_FULLSCREEN",
+ False );
+ p_vout->p_sys->net_wm_state_above =
+ XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_ABOVE", False );
+ p_vout->p_sys->net_wm_state_below =
+ XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_BELOW", False );
+ p_vout->p_sys->net_wm_state_stays_on_top =
+ XInternAtom( p_vout->p_sys->p_display, "_NET_WM_STATE_STAYS_ON_TOP",
+ False );
+
+ for( i = 0; i < i_items; i++ )
+ {
+ if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_fullscreen )
+ {
+ msg_Dbg( p_vout,
+ "Window manager supports _NET_WM_STATE_FULLSCREEN" );
+ p_vout->p_sys->b_net_wm_state_fullscreen = VLC_TRUE;
+ }
+ else if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_above )
+ {
+ msg_Dbg( p_vout, "Window manager supports _NET_WM_STATE_ABOVE" );
+ p_vout->p_sys->b_net_wm_state_above = VLC_TRUE;
+ }
+ else if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_below )
+ {
+ msg_Dbg( p_vout, "Window manager supports _NET_WM_STATE_BELOW" );
+ p_vout->p_sys->b_net_wm_state_below = VLC_TRUE;
+ }
+ else if( p_args.p_atom[i] == p_vout->p_sys->net_wm_state_stays_on_top )
+ {
+ msg_Dbg( p_vout,
+ "Window manager supports _NET_WM_STATE_STAYS_ON_TOP" );
+ p_vout->p_sys->b_net_wm_state_stays_on_top = VLC_TRUE;
+ }
+ }
+
+ XFree( p_args.p_atom );
+}
+
+/*****************************************************************************
+ * Key events handling
+ *****************************************************************************/
+static struct
+{
+ int i_x11key;
+ int i_vlckey;
+
+} x11keys_to_vlckeys[] =
+{
+ { XK_F1, KEY_F1 }, { XK_F2, KEY_F2 }, { XK_F3, KEY_F3 }, { XK_F4, KEY_F4 },
+ { XK_F5, KEY_F5 }, { XK_F6, KEY_F6 }, { XK_F7, KEY_F7 }, { XK_F8, KEY_F8 },
+ { XK_F9, KEY_F9 }, { XK_F10, KEY_F10 }, { XK_F11, KEY_F11 },
+ { XK_F12, KEY_F12 },
+
+ { XK_Return, KEY_ENTER },
+ { XK_KP_Enter, KEY_ENTER },
+ { XK_space, KEY_SPACE },
+ { XK_Escape, KEY_ESC },
+
+ { XK_Menu, KEY_MENU },
+ { XK_Left, KEY_LEFT },
+ { XK_Right, KEY_RIGHT },
+ { XK_Up, KEY_UP },
+ { XK_Down, KEY_DOWN },
+
+ { XK_Home, KEY_HOME },
+ { XK_End, KEY_END },
+ { XK_Page_Up, KEY_PAGEUP },
+ { XK_Page_Down, KEY_PAGEDOWN },
+
+ { XK_Insert, KEY_INSERT },
+ { XK_Delete, KEY_DELETE },
+
+ { 0, 0 }
+};
+
+static int ConvertKey( int i_key )
+{
+ int i;
+
+ for( i = 0; x11keys_to_vlckeys[i].i_x11key != 0; i++ )
+ {
+ if( x11keys_to_vlckeys[i].i_x11key == i_key )
+ {
+ return x11keys_to_vlckeys[i].i_vlckey;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * WindowOnTop: Switches the "always on top" state of the video window.
+ *****************************************************************************/
+static int WindowOnTop( vout_thread_t *p_vout, vlc_bool_t b_on_top )
+{
+ if( p_vout->p_sys->b_net_wm_state_stays_on_top )
+ {
+ XClientMessageEvent event;
+
+ memset( &event, 0, sizeof( XClientMessageEvent ) );
+
+ event.type = ClientMessage;
+ event.message_type = p_vout->p_sys->net_wm_state;
+ event.display = p_vout->p_sys->p_display;
+ event.window = p_vout->p_sys->p_win->base_window;
+ event.format = 32;
+ event.data.l[ 0 ] = b_on_top; /* set property */
+ event.data.l[ 1 ] = p_vout->p_sys->net_wm_state_stays_on_top;
+
+ XSendEvent( p_vout->p_sys->p_display,
+ DefaultRootWindow( p_vout->p_sys->p_display ),
+ False, SubstructureRedirectMask,
+ (XEvent*)&event );
+ }
+
+ return VLC_SUCCESS;
+}