#include <vlc_plugin.h>
#include <vlc_interface.h>
#include <vlc_keys.h>
-#include <ctype.h>
+#include <errno.h>
#include <xcb/xcb.h>
#include <xcb/xcb_keysyms.h>
typedef struct
{
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
xcb_keycode_t i_x11;
+#else
+ xcb_keycode_t *p_keys;
+#endif
unsigned i_modifier;
int i_action;
} hotkey_mapping_t;
hotkey_mapping_t *p_map;
};
-static void Mapping( intf_thread_t *p_intf );
+static bool Mapping( intf_thread_t *p_intf );
static void Register( intf_thread_t *p_intf );
-static void Unregister( intf_thread_t *p_intf );
static void *Thread( void *p_data );
/*****************************************************************************
{
intf_thread_t *p_intf = (intf_thread_t *)p_this;
intf_sys_t *p_sys;
+ int ret = VLC_EGENERIC;
p_intf->p_sys = p_sys = calloc( 1, sizeof(*p_sys) );
if( !p_sys )
p_sys->p_connection = xcb_connect( psz_display, &i_screen_default );
free( psz_display );
- if( !p_sys->p_connection )
+ if( xcb_connection_has_error( p_sys->p_connection ) )
goto error;
/* Get the root windows of the default screen */
- memset( &p_sys->root, 0, sizeof( p_sys->root ) );
- xcb_screen_iterator_t iter = xcb_setup_roots_iterator( xcb_get_setup( p_sys->p_connection ) );
+ const xcb_setup_t* xcbsetup = xcb_get_setup( p_sys->p_connection );
+ if( !xcbsetup )
+ goto error;
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator( xcbsetup );
for( int i = 0; i < i_screen_default; i++ )
{
if( !iter.rem )
if( !p_sys->p_symbols )
goto error;
- Mapping( p_intf );
+ if( !Mapping( p_intf ) )
+ {
+ ret = VLC_SUCCESS;
+ p_intf->p_sys = NULL; /* for Close() */
+ goto error;
+ }
Register( p_intf );
if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) )
{
- Unregister( p_intf );
+#ifndef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
+ if( p_sys->p_map )
+ free( p_sys->p_map->p_keys );
+#endif
free( p_sys->p_map );
goto error;
}
error:
if( p_sys->p_symbols )
xcb_key_symbols_free( p_sys->p_symbols );
- if( p_sys->p_connection )
- xcb_disconnect( p_sys->p_connection );
+ xcb_disconnect( p_sys->p_connection );
free( p_sys );
- return VLC_EGENERIC;
+ return ret;
}
/*****************************************************************************
intf_thread_t *p_intf = (intf_thread_t *)p_this;
intf_sys_t *p_sys = p_intf->p_sys;
+ if( !p_sys )
+ return; /* if we were running disabled */
+
vlc_cancel( p_sys->thread );
vlc_join( p_sys->thread, NULL );
- Unregister( p_intf );
+#ifndef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
+ if( p_sys->p_map )
+ free( p_sys->p_map->p_keys );
+#endif
free( p_sys->p_map );
xcb_key_symbols_free( p_sys->p_symbols );
static unsigned GetModifier( xcb_connection_t *p_connection, xcb_key_symbols_t *p_symbols, xcb_keysym_t sym )
{
static const unsigned pi_mask[8] = {
- XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, XCB_MOD_MASK_1,
- XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, XCB_MOD_MASK_5
+ XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL,
+ XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3,
+ XCB_MOD_MASK_4, XCB_MOD_MASK_5
};
+ if( sym == 0 )
+ return 0; /* no modifier */
+
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
const xcb_keycode_t key = xcb_key_symbols_get_keycode( p_symbols, sym );
if( key == 0 )
return 0;
+#else
+ const xcb_keycode_t *p_keys = xcb_key_symbols_get_keycode( p_symbols, sym );
+ if( !p_keys )
+ return 0;
- xcb_get_modifier_mapping_cookie_t r = xcb_get_modifier_mapping( p_connection );
- xcb_get_modifier_mapping_reply_t *p_map = xcb_get_modifier_mapping_reply( p_connection, r, NULL );
+ int i = 0;
+ bool no_modifier = true;
+ while( p_keys[i] != XCB_NO_SYMBOL )
+ {
+ if( p_keys[i] != 0 )
+ {
+ no_modifier = false;
+ break;
+ }
+ i++;
+ }
+
+ if( no_modifier )
+ return 0;
+#endif
+
+ xcb_get_modifier_mapping_cookie_t r =
+ xcb_get_modifier_mapping( p_connection );
+ xcb_get_modifier_mapping_reply_t *p_map =
+ xcb_get_modifier_mapping_reply( p_connection, r, NULL );
if( !p_map )
return 0;
if( !p_keycode )
return 0;
- unsigned i_mask = 0;
for( int i = 0; i < 8; i++ )
- {
for( int j = 0; j < p_map->keycodes_per_modifier; j++ )
- {
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
if( p_keycode[i * p_map->keycodes_per_modifier + j] == key )
- i_mask = pi_mask[i];
- }
- }
+ {
+ free( p_map );
+ return pi_mask[i];
+ }
+#else
+ for( int k = 0; p_keys[k] != XCB_NO_SYMBOL; k++ )
+ if( p_keycode[i*p_map->keycodes_per_modifier + j] == p_keys[k])
+ {
+ free( p_map );
+ return pi_mask[i];
+ }
+#endif
free( p_map ); // FIXME to check
- return i_mask;
+ return 0;
}
-static unsigned GetX11Modifier( xcb_connection_t *p_connection, xcb_key_symbols_t *p_symbols, unsigned i_vlc )
+
+
+static unsigned GetX11Modifier( xcb_connection_t *p_connection,
+ xcb_key_symbols_t *p_symbols, unsigned i_vlc )
{
unsigned i_mask = 0;
} 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 },
- { XF86XK_AudioNext, KEY_MEDIA_NEXT_TRACK},
- { XF86XK_AudioPrev, KEY_MEDIA_PREV_TRACK},
- { XF86XK_AudioMute, KEY_VOLUME_MUTE },
- { XF86XK_AudioLowerVolume, KEY_VOLUME_DOWN },
- { XF86XK_AudioRaiseVolume, KEY_VOLUME_UP },
- { XF86XK_AudioPlay, KEY_MEDIA_PLAY_PAUSE },
- { XF86XK_AudioPause, KEY_MEDIA_PLAY_PAUSE },
-
+#include "../../video_output/xcb/xcb_keysym.h"
{ 0, 0 }
};
static xcb_keysym_t GetX11Key( unsigned i_vlc )
{
+ /* X11 and VLC use ASCII for printable ASCII characters */
+ if( i_vlc >= 32 && i_vlc <= 127 )
+ return i_vlc;
+
for( int i = 0; x11keys_to_vlckeys[i].i_vlc != 0; i++ )
{
if( x11keys_to_vlckeys[i].i_vlc == i_vlc )
return x11keys_to_vlckeys[i].i_x11;
}
- /* Copied from xcb, it seems that xcb use ascii code for ascii characters */
- if( isascii( i_vlc ) )
- return i_vlc;
-
return XK_VoidSymbol;
}
-static void Mapping( intf_thread_t *p_intf )
+static bool Mapping( intf_thread_t *p_intf )
{
static const xcb_keysym_t p_x11_modifier_ignored[] = {
0,
};
intf_sys_t *p_sys = p_intf->p_sys;
+ bool active = false;
p_sys->i_map = 0;
p_sys->p_map = NULL;
/* Registering of Hotkeys */
- for( struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
+ for( const struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
p_hotkey->psz_action != NULL;
p_hotkey++ )
{
break;
const int i_vlc_action = p_hotkey->i_action;
- const int i_vlc_key = config_GetInt( p_intf, psz_hotkey );
-
+ const int i_vlc_key = var_InheritInteger( p_intf, psz_hotkey );
free( psz_hotkey );
if( !i_vlc_key )
continue;
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
+ const xcb_keycode_t key = xcb_key_symbols_get_keycode(
+ p_sys->p_symbols, GetX11Key( i_vlc_key & ~KEY_MODIFIER ) );
+#else
+ xcb_keycode_t *p_keys = xcb_key_symbols_get_keycode(
+ p_sys->p_symbols, GetX11Key( i_vlc_key & ~KEY_MODIFIER ) );
+ if( !p_keys )
+ continue;
+#endif
+ const unsigned i_modifier = GetX11Modifier( p_sys->p_connection,
+ p_sys->p_symbols, i_vlc_key & KEY_MODIFIER );
- const xcb_keycode_t key = xcb_key_symbols_get_keycode( p_sys->p_symbols, GetX11Key( i_vlc_key & ~KEY_MODIFIER ) );
- const unsigned i_modifier = GetX11Modifier( p_sys->p_connection, p_sys->p_symbols, i_vlc_key & KEY_MODIFIER );
-
- for( int j = 0; j < sizeof(p_x11_modifier_ignored)/sizeof(*p_x11_modifier_ignored); j++ )
+ const size_t max = sizeof(p_x11_modifier_ignored) /
+ sizeof(*p_x11_modifier_ignored);
+ for( unsigned int i = 0; i < max; i++ )
{
- const unsigned i_ignored = GetModifier( p_sys->p_connection, p_sys->p_symbols, p_x11_modifier_ignored[j] );
- if( j != 0 && i_ignored == 0x00)
+ const unsigned i_ignored = GetModifier( p_sys->p_connection,
+ p_sys->p_symbols, p_x11_modifier_ignored[i] );
+ if( i != 0 && i_ignored == 0)
continue;
hotkey_mapping_t *p_map_old = p_sys->p_map;
- p_sys->p_map = realloc( p_sys->p_map, sizeof(*p_sys->p_map) * (p_sys->i_map+1) );
+ p_sys->p_map = realloc( p_sys->p_map,
+ sizeof(*p_sys->p_map) * (p_sys->i_map+1) );
if( !p_sys->p_map )
{
p_sys->p_map = p_map_old;
}
hotkey_mapping_t *p_map = &p_sys->p_map[p_sys->i_map++];
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
p_map->i_x11 = key;
+#else
+ p_map->p_keys = p_keys;
+#endif
p_map->i_modifier = i_modifier|i_ignored;
p_map->i_action = i_vlc_action;
+ active = true;
}
}
+ return active;
}
static void Register( intf_thread_t *p_intf )
for( int i = 0; i < p_sys->i_map; i++ )
{
const hotkey_mapping_t *p_map = &p_sys->p_map[i];
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
xcb_grab_key( p_sys->p_connection, true, p_sys->root,
p_map->i_modifier, p_map->i_x11,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC );
- }
-}
-static void Unregister( intf_thread_t *p_intf )
-{
- intf_sys_t *p_sys = p_intf->p_sys;
-
- for( int i = 0; i < p_sys->i_map; i++ )
- {
- const hotkey_mapping_t *p_map = &p_sys->p_map[i];
- xcb_ungrab_key( p_sys->p_connection, p_map->i_x11, p_sys->root, p_map->i_modifier );
+#else
+ for( int j = 0; p_map->p_keys[j] != XCB_NO_SYMBOL; j++ )
+ {
+ xcb_grab_key( p_sys->p_connection, true, p_sys->root,
+ p_map->i_modifier, p_map->p_keys[j],
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC );
+ }
+#endif
}
}
{
hotkey_mapping_t *p_map = &p_sys->p_map[i];
+#ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */
if( p_map->i_x11 == e->detail &&
p_map->i_modifier == e->state )
{
- var_SetInteger( p_intf->p_libvlc, "key-action", p_map->i_action );
+ var_SetInteger( p_intf->p_libvlc, "key-action",
+ p_map->i_action );
break;
}
+#else
+ bool loop_break = false;
+ for( int j = 0; p_map->p_keys[j] != XCB_NO_SYMBOL; j++ )
+ if( p_map->p_keys[j] == e->detail &&
+ p_map->i_modifier == e->state )
+ {
+ var_SetInteger( p_intf->p_libvlc, "key-action",
+ p_map->i_action );
+ loop_break = true;
+ break;
+ }
+ if( loop_break )
+ break;
+#endif
}
free( p_event );
}