diff options
Diffstat (limited to 'src/backends/x11/meta-keymap-x11.c')
-rw-r--r-- | src/backends/x11/meta-keymap-x11.c | 949 |
1 files changed, 0 insertions, 949 deletions
diff --git a/src/backends/x11/meta-keymap-x11.c b/src/backends/x11/meta-keymap-x11.c deleted file mode 100644 index 994ad8594..000000000 --- a/src/backends/x11/meta-keymap-x11.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Emmanuele Bassi <ebassi@linux.intel.com> - */ - -#include "config.h" - -#include <X11/Xatom.h> -#include <X11/XKBlib.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-keymap-x11.h" -#include "clutter/clutter.h" -#include "clutter/clutter-keymap-private.h" -#include "clutter/clutter-mutter.h" - -typedef struct _DirectionCacheEntry DirectionCacheEntry; -typedef struct _ClutterKeymapKey ClutterKeymapKey; - -struct _ClutterKeymapKey -{ - uint32_t keycode; - uint32_t group; - uint32_t level; -}; - -struct _DirectionCacheEntry -{ - uint32_t serial; - Atom group_atom; - PangoDirection direction; -}; - -struct _MetaKeymapX11 -{ - ClutterKeymap parent_instance; - - ClutterBackend *backend; - - int min_keycode; - int max_keycode; - - ClutterModifierType modmap[8]; - - ClutterModifierType num_lock_mask; - ClutterModifierType scroll_lock_mask; - ClutterModifierType level3_shift_mask; - - PangoDirection current_direction; - - XkbDescPtr xkb_desc; - int xkb_event_base; - uint32_t xkb_map_serial; - Atom current_group_atom; - uint32_t current_cache_serial; - DirectionCacheEntry group_direction_cache[4]; - int current_group; - - GHashTable *reserved_keycodes; - GQueue *available_keycodes; - - uint32_t keymap_serial; - - uint32_t has_direction : 1; - - uint32_t use_xkb : 1; - uint32_t have_xkb_autorepeat : 1; -}; - -enum -{ - PROP_0, - - PROP_BACKEND, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST] = { NULL, }; - -G_DEFINE_TYPE (MetaKeymapX11, meta_keymap_x11, CLUTTER_TYPE_KEYMAP) - -/* code adapted from gdk/x11/gdkkeys-x11.c - update_modmap */ -static void -update_modmap (Display *display, - MetaKeymapX11 *keymap_x11) -{ - static struct { - const char *name; - Atom atom; - ClutterModifierType mask; - } vmods[] = { - { "Meta", 0, CLUTTER_META_MASK }, - { "Super", 0, CLUTTER_SUPER_MASK }, - { "Hyper", 0, CLUTTER_HYPER_MASK }, - { NULL, 0, 0 } - }; - - int i, j, k; - - if (vmods[0].atom == 0) - for (i = 0; vmods[i].name; i++) - vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE); - - for (i = 0; i < 8; i++) - keymap_x11->modmap[i] = 1 << i; - - for (i = 0; i < XkbNumVirtualMods; i++) - { - for (j = 0; vmods[j].atom; j++) - { - if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom) - { - for (k = 0; k < 8; k++) - { - if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k)) - keymap_x11->modmap[k] |= vmods[j].mask; - } - } - } - } -} - -static XkbDescPtr -get_xkb (MetaKeymapX11 *keymap_x11) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - - if (keymap_x11->max_keycode == 0) - XDisplayKeycodes (xdisplay, - &keymap_x11->min_keycode, - &keymap_x11->max_keycode); - - if (keymap_x11->xkb_desc == NULL) - { - int flags = XkbKeySymsMask - | XkbKeyTypesMask - | XkbModifierMapMask - | XkbVirtualModsMask; - - keymap_x11->xkb_desc = XkbGetMap (xdisplay, flags, XkbUseCoreKbd); - if (G_UNLIKELY (keymap_x11->xkb_desc == NULL)) - { - g_error ("Failed to get the keymap from XKB"); - return NULL; - } - - flags = XkbGroupNamesMask | XkbVirtualModNamesMask; - XkbGetNames (xdisplay, flags, keymap_x11->xkb_desc); - - update_modmap (xdisplay, keymap_x11); - } - else if (keymap_x11->xkb_map_serial != keymap_x11->keymap_serial) - { - int flags = XkbKeySymsMask - | XkbKeyTypesMask - | XkbModifierMapMask - | XkbVirtualModsMask; - - XkbGetUpdatedMap (xdisplay, flags, keymap_x11->xkb_desc); - - flags = XkbGroupNamesMask | XkbVirtualModNamesMask; - XkbGetNames (xdisplay, flags, keymap_x11->xkb_desc); - - update_modmap (xdisplay, keymap_x11); - - keymap_x11->xkb_map_serial = keymap_x11->keymap_serial; - } - - if (keymap_x11->num_lock_mask == 0) - keymap_x11->num_lock_mask = XkbKeysymToModifiers (xdisplay, XK_Num_Lock); - - if (keymap_x11->scroll_lock_mask == 0) - keymap_x11->scroll_lock_mask = XkbKeysymToModifiers (xdisplay, - XK_Scroll_Lock); - if (keymap_x11->level3_shift_mask == 0) - keymap_x11->level3_shift_mask = XkbKeysymToModifiers (xdisplay, - XK_ISO_Level3_Shift); - - return keymap_x11->xkb_desc; -} - -static void -update_locked_mods (MetaKeymapX11 *keymap_x11, - int locked_mods) -{ - ClutterKeymap *keymap = CLUTTER_KEYMAP (keymap_x11); - gboolean caps_lock_state; - gboolean num_lock_state; - gboolean old_num_lock_state; - - caps_lock_state = !!(locked_mods & CLUTTER_LOCK_MASK); - num_lock_state = !!(locked_mods & keymap_x11->num_lock_mask); - - old_num_lock_state = clutter_keymap_get_num_lock_state (keymap); - clutter_keymap_set_lock_modifier_state (CLUTTER_KEYMAP (keymap_x11), - caps_lock_state, - num_lock_state); - - if (num_lock_state != old_num_lock_state) - { - MetaBackend *backend; - MetaInputSettings *input_settings; - - backend = meta_get_backend (); - input_settings = meta_backend_get_input_settings (backend); - - if (input_settings) - { - meta_input_settings_maybe_save_numlock_state (input_settings, - num_lock_state); - } - } -} - -/* the code to retrieve the keymap direction and cache it - * is taken from GDK: - * gdk/x11/gdkkeys-x11.c - */ -static PangoDirection -get_direction (XkbDescPtr xkb, - int group) -{ - int rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */ - int code; - - for (code = xkb->min_key_code; - code <= xkb->max_key_code; - code += 1) - { - int level = 0; - KeySym sym = XkbKeySymEntry (xkb, code, level, group); - PangoDirection dir = - _clutter_pango_unichar_direction (clutter_keysym_to_unicode (sym)); - - switch (dir) - { - case PANGO_DIRECTION_RTL: - rtl_minus_ltr++; - break; - - case PANGO_DIRECTION_LTR: - rtl_minus_ltr--; - break; - - default: - break; - } - } - - if (rtl_minus_ltr > 0) - return PANGO_DIRECTION_RTL; - - return PANGO_DIRECTION_LTR; -} - -static PangoDirection -get_direction_from_cache (MetaKeymapX11 *keymap_x11, - XkbDescPtr xkb, - int group) -{ - Atom group_atom = xkb->names->groups[group]; - gboolean cache_hit = FALSE; - DirectionCacheEntry *cache = keymap_x11->group_direction_cache; - PangoDirection direction = PANGO_DIRECTION_NEUTRAL; - int i; - - if (keymap_x11->has_direction) - { - /* look up in the cache */ - for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) - { - if (cache[i].group_atom == group_atom) - { - cache_hit = TRUE; - cache[i].serial = keymap_x11->current_cache_serial++; - direction = cache[i].direction; - group_atom = cache[i].group_atom; - break; - } - } - } - else - { - /* initialize the cache */ - for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) - { - cache[i].group_atom = 0; - cache[i].direction = PANGO_DIRECTION_NEUTRAL; - cache[i].serial = keymap_x11->current_cache_serial; - } - - keymap_x11->current_cache_serial += 1; - } - - /* insert the new entry in the cache */ - if (!cache_hit) - { - int oldest = 0; - - direction = get_direction (xkb, group); - - /* replace the oldest entry */ - for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) - { - if (cache[i].serial < cache[oldest].serial) - oldest = i; - } - - cache[oldest].group_atom = group_atom; - cache[oldest].direction = direction; - cache[oldest].serial = keymap_x11->current_cache_serial++; - } - - return direction; -} - -static void -update_direction (MetaKeymapX11 *keymap_x11, - int group) -{ - XkbDescPtr xkb = get_xkb (keymap_x11); - Atom group_atom; - - group_atom = xkb->names->groups[group]; - - if (!keymap_x11->has_direction || keymap_x11->current_group_atom != group_atom) - { - keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group); - keymap_x11->current_group_atom = group_atom; - keymap_x11->has_direction = TRUE; - } -} - -static void -meta_keymap_x11_constructed (GObject *object) -{ - MetaKeymapX11 *keymap_x11 = META_KEYMAP_X11 (object); - Display *xdisplay = meta_clutter_x11_get_default_display (); - int xkb_major = XkbMajorVersion; - int xkb_minor = XkbMinorVersion; - - g_assert (keymap_x11->backend != NULL); - - if (XkbLibraryVersion (&xkb_major, &xkb_minor)) - { - xkb_major = XkbMajorVersion; - xkb_minor = XkbMinorVersion; - - if (XkbQueryExtension (xdisplay, - NULL, - &keymap_x11->xkb_event_base, - NULL, - &xkb_major, &xkb_minor)) - { - Bool detectable_autorepeat_supported; - - keymap_x11->use_xkb = TRUE; - - XkbSelectEvents (xdisplay, - XkbUseCoreKbd, - XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, - XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask); - - XkbSelectEventDetails (xdisplay, - XkbUseCoreKbd, XkbStateNotify, - XkbAllStateComponentsMask, - XkbGroupLockMask | XkbModifierLockMask); - - /* enable XKB autorepeat */ - XkbSetDetectableAutoRepeat (xdisplay, - True, - &detectable_autorepeat_supported); - - keymap_x11->have_xkb_autorepeat = detectable_autorepeat_supported; - } - } -} - -static void -meta_keymap_x11_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaKeymapX11 *keymap = META_KEYMAP_X11 (object); - - switch (prop_id) - { - case PROP_BACKEND: - keymap->backend = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_keymap_x11_refresh_reserved_keycodes (MetaKeymapX11 *keymap_x11) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - uint32_t reserved_keycode = GPOINTER_TO_UINT (key); - uint32_t reserved_keysym = GPOINTER_TO_UINT (value); - uint32_t actual_keysym = XkbKeycodeToKeysym (xdisplay, reserved_keycode, 0, 0); - - /* If an available keycode is no longer mapped to the stored keysym, then - * the keycode should not be considered available anymore and should be - * removed both from the list of available and reserved keycodes. - */ - if (reserved_keysym != actual_keysym) - { - g_hash_table_iter_remove (&iter); - g_queue_remove (keymap_x11->available_keycodes, key); - } - } -} - -static gboolean -meta_keymap_x11_replace_keycode (MetaKeymapX11 *keymap_x11, - KeyCode keycode, - KeySym keysym) -{ - if (keymap_x11->use_xkb) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - XkbDescPtr xkb = get_xkb (keymap_x11); - XkbMapChangesRec changes; - - XFlush (xdisplay); - - xkb->device_spec = XkbUseCoreKbd; - memset (&changes, 0, sizeof(changes)); - - if (keysym != NoSymbol) - { - int types[XkbNumKbdGroups] = { XkbOneLevelIndex }; - XkbChangeTypesOfKey (xkb, keycode, 1, XkbGroup1Mask, types, &changes); - XkbKeySymEntry (xkb, keycode, 0, 0) = keysym; - } - else - { - /* Reset to NoSymbol */ - XkbChangeTypesOfKey (xkb, keycode, 0, XkbGroup1Mask, NULL, &changes); - } - - changes.changed = XkbKeySymsMask | XkbKeyTypesMask; - changes.first_key_sym = keycode; - changes.num_key_syms = 1; - changes.first_type = 0; - changes.num_types = xkb->map->num_types; - XkbChangeMap (xdisplay, xkb, &changes); - - XFlush (xdisplay); - - return TRUE; - } - - return FALSE; -} - -static void -meta_keymap_x11_finalize (GObject *object) -{ - MetaKeymapX11 *keymap; - GHashTableIter iter; - gpointer key, value; - - keymap = META_KEYMAP_X11 (object); - - meta_keymap_x11_refresh_reserved_keycodes (keymap); - g_hash_table_iter_init (&iter, keymap->reserved_keycodes); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - uint32_t keycode = GPOINTER_TO_UINT (key); - meta_keymap_x11_replace_keycode (keymap, keycode, NoSymbol); - } - - g_hash_table_destroy (keymap->reserved_keycodes); - g_queue_free (keymap->available_keycodes); - - if (keymap->xkb_desc != NULL) - XkbFreeKeyboard (keymap->xkb_desc, XkbAllComponentsMask, True); - - G_OBJECT_CLASS (meta_keymap_x11_parent_class)->finalize (object); -} - -static PangoDirection -meta_keymap_x11_get_direction (ClutterKeymap *keymap) -{ - MetaKeymapX11 *keymap_x11; - - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap), PANGO_DIRECTION_NEUTRAL); - - keymap_x11 = META_KEYMAP_X11 (keymap); - - if (keymap_x11->use_xkb) - { - if (!keymap_x11->has_direction) - { - XkbStateRec state_rec; - - XkbGetState (meta_clutter_x11_get_default_display (), - XkbUseCoreKbd, &state_rec); - update_direction (keymap_x11, XkbStateGroup (&state_rec)); - } - - return keymap_x11->current_direction; - } - else - { - return PANGO_DIRECTION_NEUTRAL; - } -} - -static void -meta_keymap_x11_class_init (MetaKeymapX11Class *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterKeymapClass *keymap_class = CLUTTER_KEYMAP_CLASS (klass); - - obj_props[PROP_BACKEND] = - g_param_spec_object ("backend", - "Backend", - "The Clutter backend", - CLUTTER_TYPE_BACKEND, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); - - gobject_class->constructed = meta_keymap_x11_constructed; - gobject_class->set_property = meta_keymap_x11_set_property; - gobject_class->finalize = meta_keymap_x11_finalize; - - keymap_class->get_direction = meta_keymap_x11_get_direction; - - g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); -} - -static void -meta_keymap_x11_init (MetaKeymapX11 *keymap) -{ - keymap->current_direction = PANGO_DIRECTION_NEUTRAL; - keymap->current_group = -1; - keymap->reserved_keycodes = g_hash_table_new (NULL, NULL); - keymap->available_keycodes = g_queue_new (); -} - -gboolean -meta_keymap_x11_handle_event (MetaKeymapX11 *keymap_x11, - XEvent *xevent) -{ - gboolean retval; - - if (!keymap_x11->use_xkb) - return FALSE; - - retval = FALSE; - - if (xevent->type == keymap_x11->xkb_event_base) - { - XkbEvent *xkb_event = (XkbEvent *) xevent; - - switch (xkb_event->any.xkb_type) - { - case XkbStateNotify: - g_debug ("Updating keyboard state"); - keymap_x11->current_group = XkbStateGroup (&xkb_event->state); - update_direction (keymap_x11, keymap_x11->current_group); - update_locked_mods (keymap_x11, xkb_event->state.locked_mods); - retval = TRUE; - break; - - case XkbNewKeyboardNotify: - case XkbMapNotify: - g_debug ("Updating keyboard mapping"); - XkbRefreshKeyboardMapping (&xkb_event->map); - keymap_x11->keymap_serial += 1; - retval = TRUE; - break; - - default: - break; - } - } - else if (xevent->type == MappingNotify) - { - XRefreshKeyboardMapping (&xevent->xmapping); - keymap_x11->keymap_serial += 1; - retval = TRUE; - } - - return retval; -} - -int -meta_keymap_x11_get_key_group (MetaKeymapX11 *keymap, - ClutterModifierType state) -{ - return XkbGroupForCoreState (state); -} - -G_GNUC_BEGIN_IGNORE_DEPRECATIONS - -/* XXX - yes, I know that XKeycodeToKeysym() has been deprecated; hopefully, - * this code will never get run on any decent system that is also able to - * run Clutter. I just don't want to copy the implementation inside GDK for - * a fallback path. - */ -static int -translate_keysym (MetaKeymapX11 *keymap, - uint32_t hardware_keycode) -{ - int retval; - - retval = XKeycodeToKeysym (meta_clutter_x11_get_default_display (), - hardware_keycode, 0); - return retval; -} - -G_GNUC_END_IGNORE_DEPRECATIONS - -int -meta_keymap_x11_translate_key_state (MetaKeymapX11 *keymap, - uint32_t hardware_keycode, - ClutterModifierType *modifier_state_p, - ClutterModifierType *mods_p) -{ - ClutterModifierType unconsumed_modifiers = 0; - ClutterModifierType modifier_state = *modifier_state_p; - int retval; - - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap), 0); - - if (keymap->use_xkb) - { - XkbDescRec *xkb = get_xkb (keymap); - KeySym tmp_keysym; - - if (XkbTranslateKeyCode (xkb, hardware_keycode, modifier_state, - &unconsumed_modifiers, - &tmp_keysym)) - { - retval = tmp_keysym; - } - else - retval = 0; - } - else - retval = translate_keysym (keymap, hardware_keycode); - - if (mods_p) - *mods_p = unconsumed_modifiers; - - *modifier_state_p = modifier_state & ~(keymap->num_lock_mask | - keymap->scroll_lock_mask | - LockMask); - - return retval; -} - -gboolean -meta_keymap_x11_get_is_modifier (MetaKeymapX11 *keymap, - int keycode) -{ - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap), FALSE); - - if (keycode < keymap->min_keycode || keycode > keymap->max_keycode) - return FALSE; - - if (keymap->use_xkb) - { - XkbDescRec *xkb = get_xkb (keymap); - - if (xkb->map->modmap && xkb->map->modmap[keycode] != 0) - return TRUE; - } - - return FALSE; -} - -static gboolean -meta_keymap_x11_get_entries_for_keyval (MetaKeymapX11 *keymap_x11, - uint32_t keyval, - ClutterKeymapKey **keys, - int *n_keys) -{ - if (keymap_x11->use_xkb) - { - XkbDescRec *xkb = get_xkb (keymap_x11); - GArray *retval; - int keycode; - - keycode = keymap_x11->min_keycode; - retval = g_array_new (FALSE, FALSE, sizeof (ClutterKeymapKey)); - - while (keycode <= keymap_x11->max_keycode) - { - int max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); - int group = 0; - int level = 0; - int total_syms = XkbKeyNumSyms (xkb, keycode); - int i = 0; - KeySym *entry; - - /* entry is an array with all syms for group 0, all - * syms for group 1, etc. and for each group the - * shift level syms are in order - */ - entry = XkbKeySymsPtr (xkb, keycode); - - while (i < total_syms) - { - g_assert (i == (group * max_shift_levels + level)); - - if (entry[i] == keyval) - { - ClutterKeymapKey key; - - key.keycode = keycode; - key.group = group; - key.level = level; - - g_array_append_val (retval, key); - - g_assert (XkbKeySymEntry (xkb, keycode, level, group) == - keyval); - } - - ++level; - - if (level == max_shift_levels) - { - level = 0; - ++group; - } - - ++i; - } - - ++keycode; - } - - if (retval->len > 0) - { - *keys = (ClutterKeymapKey*) retval->data; - *n_keys = retval->len; - } - else - { - *keys = NULL; - *n_keys = 0; - } - - g_array_free (retval, retval->len > 0 ? FALSE : TRUE); - - return *n_keys > 0; - } - else - { - return FALSE; - } -} - -static uint32_t -meta_keymap_x11_get_available_keycode (MetaKeymapX11 *keymap_x11) -{ - if (keymap_x11->use_xkb) - { - meta_keymap_x11_refresh_reserved_keycodes (keymap_x11); - - if (g_hash_table_size (keymap_x11->reserved_keycodes) < 5) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - XkbDescPtr xkb = get_xkb (keymap_x11); - uint32_t i; - - for (i = xkb->max_key_code; i >= xkb->min_key_code; --i) - { - if (XkbKeycodeToKeysym (xdisplay, i, 0, 0) == NoSymbol) - return i; - } - } - - return GPOINTER_TO_UINT (g_queue_pop_head (keymap_x11->available_keycodes)); - } - - return 0; -} - -gboolean -meta_keymap_x11_reserve_keycode (MetaKeymapX11 *keymap_x11, - uint32_t keyval, - uint32_t *keycode_out) -{ - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap_x11), FALSE); - g_return_val_if_fail (keyval != 0, FALSE); - g_return_val_if_fail (keycode_out != NULL, FALSE); - - *keycode_out = meta_keymap_x11_get_available_keycode (keymap_x11); - - if (*keycode_out == NoSymbol) - { - g_warning ("Cannot reserve a keycode for keyval %d: no available keycode", keyval); - return FALSE; - } - - if (!meta_keymap_x11_replace_keycode (keymap_x11, *keycode_out, keyval)) - { - g_warning ("Failed to remap keycode %d to keyval %d", *keycode_out, keyval); - return FALSE; - } - - g_hash_table_insert (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (*keycode_out), GUINT_TO_POINTER (keyval)); - g_queue_remove (keymap_x11->available_keycodes, GUINT_TO_POINTER (*keycode_out)); - - return TRUE; -} - -void -meta_keymap_x11_release_keycode_if_needed (MetaKeymapX11 *keymap_x11, - uint32_t keycode) -{ - g_return_if_fail (META_IS_KEYMAP_X11 (keymap_x11)); - - if (!g_hash_table_contains (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (keycode)) || - g_queue_index (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)) != -1) - return; - - g_queue_push_tail (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)); -} - -void -meta_keymap_x11_latch_modifiers (MetaKeymapX11 *keymap_x11, - uint32_t level, - gboolean enable) -{ - uint32_t modifiers[] = { - 0, - ShiftMask, - keymap_x11->level3_shift_mask, - keymap_x11->level3_shift_mask | ShiftMask, - }; - uint32_t value = 0; - - if (!keymap_x11->use_xkb) - return; - - level = CLAMP (level, 0, G_N_ELEMENTS (modifiers) - 1); - - if (enable) - value = modifiers[level]; - else - value = 0; - - XkbLatchModifiers (meta_clutter_x11_get_default_display (), - XkbUseCoreKbd, modifiers[level], - value); -} - -static uint32_t -meta_keymap_x11_get_current_group (MetaKeymapX11 *keymap_x11) -{ - XkbStateRec state_rec; - - if (keymap_x11->current_group >= 0) - return keymap_x11->current_group; - - XkbGetState (meta_clutter_x11_get_default_display (), - XkbUseCoreKbd, &state_rec); - return XkbStateGroup (&state_rec); -} - -gboolean -meta_keymap_x11_keycode_for_keyval (MetaKeymapX11 *keymap_x11, - uint32_t keyval, - uint32_t *keycode_out, - uint32_t *level_out) -{ - ClutterKeymapKey *keys; - int i, n_keys, group; - gboolean found = FALSE; - - g_return_val_if_fail (keycode_out != NULL, FALSE); - g_return_val_if_fail (level_out != NULL, FALSE); - - group = meta_keymap_x11_get_current_group (keymap_x11); - - if (!meta_keymap_x11_get_entries_for_keyval (keymap_x11, keyval, &keys, &n_keys)) - return FALSE; - - for (i = 0; i < n_keys && !found; i++) - { - if (keys[i].group == group) - { - *keycode_out = keys[i].keycode; - *level_out = keys[i].level; - found = TRUE; - } - } - - if (!found) - { - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes); - while (!found && g_hash_table_iter_next (&iter, &key, &value)) - { - uint32_t reserved_keycode = GPOINTER_TO_UINT (key); - uint32_t reserved_keysym = GPOINTER_TO_UINT (value); - - if (keyval == reserved_keysym) - { - *keycode_out = reserved_keycode; - *level_out = 0; - found = TRUE; - } - } - } - - g_free (keys); - return found; -} |