diff options
Diffstat (limited to 'libxklavier/xklavier_xmm.c')
-rwxr-xr-x | libxklavier/xklavier_xmm.c | 481 |
1 files changed, 271 insertions, 210 deletions
diff --git a/libxklavier/xklavier_xmm.c b/libxklavier/xklavier_xmm.c index 83818a1..e37b3d8 100755 --- a/libxklavier/xklavier_xmm.c +++ b/libxklavier/xklavier_xmm.c @@ -2,10 +2,10 @@ #include <stdlib.h> #include <string.h> +#include <X11/Xmd.h> #include <X11/Xatom.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include <X11/Xlibint.h> #include <X11/keysym.h> #include "config.h" @@ -15,264 +15,325 @@ #define SHORTCUT_OPTION_PREFIX "grp:" -char* currentXmmRules = NULL; +const gchar ** +xkl_xmm_get_groups_names(XklEngine * engine) +{ + return (const gchar **) xkl_engine_backend(engine, XklXmm, + current_config).layouts; +} + +void +xkl_xmm_shortcuts_grab(XklEngine * engine) +{ + const XmmShortcut *shortcut; + const XmmSwitchOption *option = + xkl_xmm_shortcut_get_current(engine); -XklConfigRec currentXmmConfig; + xkl_debug(150, "Found shortcut option: %p\n", option); + if (option == NULL) + return; -Atom xmmStateAtom; + shortcut = option->shortcuts; + while (shortcut->keysym != XK_VoidSymbol) { + int keycode = + XKeysymToKeycode(xkl_engine_get_display(engine), + shortcut->keysym); + xkl_xmm_grab_ignoring_indicators(engine, keycode, + shortcut->modifiers); + shortcut++; + } +} -const char **_XklXmmGetGroupNames( void ) +void +xkl_xmm_shortcuts_ungrab(XklEngine * engine) { - return (const char **)currentXmmConfig.layouts; + const XmmShortcut *shortcut; + const XmmSwitchOption *option = + xkl_xmm_shortcut_get_current(engine); + + if (option == NULL) + return; + + shortcut = option->shortcuts; + while (shortcut->keysym != XK_VoidSymbol) { + int keycode = + XKeysymToKeycode(xkl_engine_get_display(engine), + shortcut->keysym); + xkl_xmm_ungrab_ignoring_indicators(engine, keycode, + shortcut->modifiers); + shortcut++; + } } -void _XklXmmGrabShortcuts( void ) +XmmSwitchOption * +xkl_xmm_shortcut_get_current(XklEngine * engine) { - int i; - XmmShortcutPtr shortcut; - const XmmSwitchOptionPtr option = _XklXmmGetCurrentShortcut(); - - XklDebug( 150, "Found shortcut option: %p\n", option ); - if( option == NULL ) - return; - - shortcut = option->shortcuts; - for( i = option->numShortcuts; --i >= 0; shortcut++ ) - { - int keycode = XKeysymToKeycode( _xklDpy, shortcut->keysym ); - _XklXmmGrabIgnoringIndicators( keycode, - shortcut->modifiers ); - } + const gchar *option_name = + xkl_xmm_shortcut_get_current_option_name(engine); + + xkl_debug(150, "Configured switch option: [%s]\n", option_name); + + if (option_name == NULL) + return NULL; + + return (XmmSwitchOption *) + g_hash_table_lookup(xkl_engine_backend + (engine, XklXmm, switch_options), + (gconstpointer) option_name); } -void _XklXmmUngrabShortcuts( void ) +const gchar * +xkl_xmm_shortcut_get_current_option_name(XklEngine * engine) { - int i; - XmmShortcutPtr shortcut; - const XmmSwitchOptionPtr option = _XklXmmGetCurrentShortcut(); - - if( option == NULL ) - return; - - shortcut = option->shortcuts; - for( i = option->numShortcuts; --i >= 0; shortcut++ ) - { - int keycode = XKeysymToKeycode( _xklDpy, shortcut->keysym ); - _XklXmmUngrabIgnoringIndicators( keycode, - shortcut->modifiers ); - } + gchar **option = + xkl_engine_backend(engine, XklXmm, current_config).options; + if (option == NULL) + return NULL; + + while (*option != NULL) { + /* starts with "grp:" */ + if (strstr(*option, SHORTCUT_OPTION_PREFIX) != NULL) { + return *option + sizeof SHORTCUT_OPTION_PREFIX - 1; + } + option++; + } + return NULL; } -XmmSwitchOptionPtr _XklXmmGetCurrentShortcut( void ) +const XmmSwitchOption * +xkl_xmm_find_switch_option(XklEngine * engine, gint keycode, + guint state, gint * current_shortcut_rv) { - const char* optionName = _XklXmmGetCurrentShortcutOptionName(); - XmmSwitchOptionPtr switchOption = allSwitchOptions; - XklDebug( 150, "Configured switch option: [%s]\n", optionName ); - if( optionName == NULL ) - return NULL; - while( switchOption->optionName != NULL ) - { - if( !strcmp( switchOption->optionName, optionName ) ) - return switchOption; - switchOption++; - } - return NULL; + const XmmSwitchOption *rv = xkl_xmm_shortcut_get_current(engine); + + if (rv != NULL) { + XmmShortcut *sc = rv->shortcuts; + while (sc->keysym != XK_VoidSymbol) { + if ((XKeysymToKeycode + (xkl_engine_get_display(engine), + sc->keysym) == keycode) + && ((state & sc->modifiers) == sc->modifiers)) { + return rv; + } + sc++; + } + } + return NULL; } -const char* _XklXmmGetCurrentShortcutOptionName( void ) +gint +xkl_xmm_resume_listen(XklEngine * engine) { - int i; - char** option = currentXmmConfig.options; - for( i = currentXmmConfig.numOptions; --i >= 0; option++ ) - { - /* starts with "grp:" */ - if( strstr( *option, SHORTCUT_OPTION_PREFIX ) != NULL ) - { - return *option + sizeof SHORTCUT_OPTION_PREFIX - 1; - } - } - return NULL; + if (xkl_engine_priv(engine, listener_type) & XKLL_MANAGE_LAYOUTS) + xkl_xmm_shortcuts_grab(engine); + return 0; } -XmmSwitchOptionPtr _XklXmmFindSwitchOption( unsigned keycode, - unsigned state, - int* currentShortcut_rv ) +gint +xkl_xmm_pause_listen(XklEngine * engine) { - const XmmSwitchOptionPtr rv = _XklXmmGetCurrentShortcut(); - int i; - - if( rv != NULL ) - { - XmmShortcutPtr sc = rv->shortcuts; - for( i=rv->numShortcuts; --i>=0; sc++ ) - { - if( ( XKeysymToKeycode( _xklDpy, sc->keysym ) == keycode ) && - ( ( state & sc->modifiers ) == sc->modifiers ) ) - { - return rv; - } - } - } - return NULL; + if (xkl_engine_priv(engine, listener_type) & XKLL_MANAGE_LAYOUTS) + xkl_xmm_shortcuts_ungrab(engine); + return 0; } -int _XklXmmResumeListen( void ) +guint +xkl_xmm_get_max_num_groups(XklEngine * engine) { - if( _xklListenerType & XKLL_MANAGE_LAYOUTS ) - _XklXmmGrabShortcuts(); - return 0; + return 0; } -int _XklXmmPauseListen( void ) +guint +xkl_xmm_get_num_groups(XklEngine * engine) { - if( _xklListenerType & XKLL_MANAGE_LAYOUTS ) - _XklXmmUngrabShortcuts(); - return 0; + gint rv = 0; + gchar **p = + xkl_engine_backend(engine, XklXmm, current_config).layouts; + if (p != NULL) + while (*p++ != NULL) + rv++; + return rv; } -unsigned _XklXmmGetMaxNumGroups( void ) +void +xkl_xmm_free_all_info(XklEngine * engine) { - return 0; + gchar *current_rules = + xkl_engine_backend(engine, XklXmm, current_rules); + if (current_rules != NULL) { + g_free(current_rules); + current_rules = NULL; + xkl_engine_backend(engine, XklXmm, current_rules) = NULL; + } + xkl_config_rec_reset(&xkl_engine_backend + (engine, XklXmm, current_config)); } -unsigned _XklXmmGetNumGroups( void ) +gboolean +xkl_xmm_if_cached_info_equals_actual(XklEngine * engine) { - return currentXmmConfig.numLayouts; + return FALSE; } - -void _XklXmmFreeAllInfo( void ) + +gboolean +xkl_xmm_load_all_info(XklEngine * engine) { - if( currentXmmRules != NULL ) - { - free( currentXmmRules ); - currentXmmRules = NULL; - } - XklConfigRecReset( ¤tXmmConfig ); + return + xkl_config_rec_get_full_from_server(&xkl_engine_backend + (engine, XklXmm, + current_rules), + &xkl_engine_backend(engine, + XklXmm, + current_config), + engine); } -Bool _XklXmmIfCachedInfoEqualsActual( void ) +void +xkl_xmm_get_server_state(XklEngine * engine, XklState * state) { - return False; + unsigned char *propval = NULL; + Atom actual_type; + int actual_format; + unsigned long bytes_remaining; + unsigned long actual_items; + int result; + + memset(state, 0, sizeof(*state)); + + result = + XGetWindowProperty(xkl_engine_get_display(engine), + xkl_engine_priv(engine, root_window), + xkl_engine_backend(engine, XklXmm, + state_atom), 0L, 1L, + False, XA_INTEGER, &actual_type, + &actual_format, &actual_items, + &bytes_remaining, &propval); + + if (Success == result) { + if (actual_format == 32 || actual_items == 1) { + state->group = *(CARD32 *) propval; + } else { + xkl_debug(160, + "Could not get the xmodmap current group\n"); + } + XFree(propval); + } else { + xkl_debug(160, + "Could not get the xmodmap current group: %d\n", + result); + } } -Bool _XklXmmLoadAllInfo( ) +void +xkl_xmm_actualize_group(XklEngine * engine, gint group) { - return _XklConfigGetFullFromServer( ¤tXmmRules, ¤tXmmConfig ); + char cmd[1024]; + int res; + const gchar *layout_name = NULL; + + if (xkl_xmm_get_num_groups(engine) < group) + return; + + layout_name = + xkl_engine_backend(engine, XklXmm, + current_config).layouts[group]; + + snprintf(cmd, sizeof cmd, + "xmodmap %s/xmodmap.%s", XMODMAP_BASE, layout_name); + + res = system(cmd); + if (res > 0) { + xkl_debug(0, "xmodmap error %d\n", res); + } else if (res < 0) { + xkl_debug(0, "Could not execute xmodmap: %d\n", res); + } + XSync(xkl_engine_get_display(engine), False); } -void _XklXmmGetRealState( XklState * state ) +void +xkl_xmm_lock_group(XklEngine * engine, gint group) { - unsigned char *propval = NULL; - Atom actualType; - int actualFormat; - unsigned long bytesRemaining; - unsigned long actualItems; - int result; - - memset( state, 0, sizeof( *state ) ); - - result = XGetWindowProperty( _xklDpy, _xklRootWindow, xmmStateAtom, 0L, 1L, - False, XA_INTEGER, &actualType, &actualFormat, - &actualItems, &bytesRemaining, - &propval ); - - if( Success == result ) - { - if( actualFormat == 32 || actualItems == 1 ) - { - state->group = *(CARD32*)propval; - } else - { - XklDebug( 160, "Could not get the xmodmap current group\n" ); - } - XFree( propval ); - } else - { - XklDebug( 160, "Could not get the xmodmap current group: %d\n", result ); - } + CARD32 propval; + + if (xkl_xmm_get_num_groups(engine) < group) + return; + + /* updating the status property */ + propval = group; + Display *display = xkl_engine_get_display(engine); + XChangeProperty(display, xkl_engine_priv(engine, root_window), + xkl_engine_backend(engine, XklXmm, state_atom), + XA_INTEGER, 32, PropModeReplace, + (unsigned char *) &propval, 1); + XSync(display, False); } -void _XklXmmActualizeGroup( int group ) +void +xkl_xmm_set_indicators(XklEngine * engine, const XklState * window_state) { - char cmd[1024]; - int res; - const char* layoutName = NULL; - - if( currentXmmConfig.numLayouts < group ) - return; - - layoutName = currentXmmConfig.layouts[group]; - - snprintf( cmd, sizeof cmd, - "xmodmap %s/xmodmap.%s", - XMODMAP_BASE, layoutName ); - - res = system( cmd ); - if( res > 0 ) - { - XklDebug( 0, "xmodmap error %d\n", res ); - } else if( res < 0 ) - { - XklDebug( 0, "Could not execute xmodmap: %d\n", res ); - } - XSync( _xklDpy, False ); } -void _XklXmmLockGroup( int group ) + +gint +xkl_xmm_init(XklEngine * engine) { - CARD32 propval; - - if( currentXmmConfig.numLayouts < group ) - return; - - /* updating the status property */ - propval = group; - XChangeProperty( _xklDpy, _xklRootWindow, xmmStateAtom, - XA_INTEGER, 32, PropModeReplace, - (unsigned char*)&propval, 1 ); - XSync( _xklDpy, False ); + xkl_engine_priv(engine, backend_id) = "xmodmap"; + xkl_engine_priv(engine, features) = + XKLF_MULTIPLE_LAYOUTS_SUPPORTED | + XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT; + xkl_engine_priv(engine, activate_config_rec) = + xkl_xmm_activate_config_rec; + xkl_engine_priv(engine, init_config_registry) = + xkl_xmm_init_config_registry; + xkl_engine_priv(engine, load_config_registry) = + xkl_xmm_load_config_registry; + xkl_engine_priv(engine, write_config_rec_to_file) = NULL; + + xkl_engine_priv(engine, get_groups_names) = + xkl_xmm_get_groups_names; + xkl_engine_priv(engine, get_max_num_groups) = + xkl_xmm_get_max_num_groups; + xkl_engine_priv(engine, get_num_groups) = xkl_xmm_get_num_groups; + xkl_engine_priv(engine, lock_group) = xkl_xmm_lock_group; + + xkl_engine_priv(engine, process_x_event) = xkl_xmm_process_x_event; + xkl_engine_priv(engine, free_all_info) = xkl_xmm_free_all_info; + xkl_engine_priv(engine, if_cached_info_equals_actual) = + xkl_xmm_if_cached_info_equals_actual; + xkl_engine_priv(engine, load_all_info) = xkl_xmm_load_all_info; + xkl_engine_priv(engine, get_server_state) = + xkl_xmm_get_server_state; + xkl_engine_priv(engine, pause_listen) = xkl_xmm_pause_listen; + xkl_engine_priv(engine, resume_listen) = xkl_xmm_resume_listen; + xkl_engine_priv(engine, set_indicators) = xkl_xmm_set_indicators; + xkl_engine_priv(engine, finalize) = xkl_xmm_term; + + if (getenv("XKL_XMODMAP_DISABLE") != NULL) + return -1; + + Display *display = xkl_engine_get_display(engine); + xkl_engine_priv(engine, base_config_atom) = + XInternAtom(display, "_XMM_NAMES", False); + xkl_engine_priv(engine, backup_config_atom) = + XInternAtom(display, "_XMM_NAMES_BACKUP", False); + + xkl_engine_priv(engine, backend) = g_new0(XklXmm, 1); + + xkl_engine_backend(engine, XklXmm, state_atom) = + XInternAtom(display, "_XMM_STATE", False); + + xkl_engine_priv(engine, default_model) = "generic"; + xkl_engine_priv(engine, default_layout) = "us"; + + xkl_xmm_init_switch_options((XklXmm *) + xkl_engine_priv(engine, backend)); + + return 0; } -int _XklXmmInit( void ) +void +xkl_xmm_term(XklEngine * engine) { - static XklVTable xklXmmVTable = - { - "xmodmap", - XKLF_MULTIPLE_LAYOUTS_SUPPORTED | - XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT, - _XklXmmConfigActivate, - _XklXmmConfigInit, - _XklXmmConfigLoadRegistry, - NULL, - _XklXmmEventHandler, - _XklXmmFreeAllInfo, - _XklXmmGetGroupNames, - _XklXmmGetMaxNumGroups, - _XklXmmGetNumGroups, - _XklXmmGetRealState, - _XklXmmIfCachedInfoEqualsActual, - _XklXmmLoadAllInfo, - _XklXmmLockGroup, - _XklXmmPauseListen, - _XklXmmResumeListen, - NULL, - }; - - if( getenv( "XKL_XMODMAP_DISABLE" ) != NULL ) - return -1; - - xklXmmVTable.baseConfigAtom = - XInternAtom( _xklDpy, "_XMM_NAMES", False ); - xklXmmVTable.backupConfigAtom = - XInternAtom( _xklDpy, "_XMM_NAMES_BACKUP", False ); - - xmmStateAtom = - XInternAtom( _xklDpy, "_XMM_STATE", False ); - - xklXmmVTable.defaultModel = "generic"; - xklXmmVTable.defaultLayout = "us"; - - xklVTable = &xklXmmVTable; - - return 0; + xkl_xmm_term_switch_options((XklXmm *) + xkl_engine_priv(engine, backend)); } |