summaryrefslogtreecommitdiff
path: root/src/backends/x11/meta-keymap-x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/x11/meta-keymap-x11.c')
-rw-r--r--src/backends/x11/meta-keymap-x11.c949
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;
-}