[mutter] keybindings: Rewrite the modmap code so that it uses libxkbcommon



commit 3645c63c0842f4c416d20c36601c0b4fb91e08a4
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Aug 15 16:23:15 2014 -0400

    keybindings: Rewrite the modmap code so that it uses libxkbcommon
    
    This removes our Xwayland dependency in the native path. The direct
    grabs are still there for the X11 backend and are a bit disgusting,
    but that's OK. We can refactor it out later.
    
    This introduces some pretty lousy hackery because it depends on
    https://github.com/xkbcommon/libxkbcommon/pull/10 , and I really
    don't want to wait on that to squash this dep.

 src/Makefile.am                |    2 +
 src/core/keybindings-private.h |    9 ++--
 src/core/keybindings.c         |   95 +++++++++-------------------------
 src/core/xkbcommon-hacks.c     |  112 ++++++++++++++++++++++++++++++++++++++++
 src/core/xkbcommon-hacks.h     |   34 ++++++++++++
 5 files changed, 178 insertions(+), 74 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index a6606ee..a333113 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -153,6 +153,8 @@ libmutter_la_SOURCES =                              \
        meta/gradient.h                         \
        core/meta-gesture-tracker.c             \
        core/meta-gesture-tracker-private.h     \
+       core/xkbcommon-hacks.c                  \
+       core/xkbcommon-hacks.h                  \
        core/keybindings.c                      \
        core/keybindings-private.h              \
        core/main.c                             \
diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h
index 5cd8c0e..9dfa4e8 100644
--- a/src/core/keybindings-private.h
+++ b/src/core/keybindings-private.h
@@ -29,6 +29,7 @@
 
 #include <gio/gio.h>
 #include <meta/keybindings.h>
+#include <xkbcommon/xkbcommon.h>
 
 typedef struct _MetaKeyHandler MetaKeyHandler;
 struct _MetaKeyHandler
@@ -97,10 +98,10 @@ typedef struct
   int             max_keycode;
   KeySym *keymap;
   int keysyms_per_keycode;
-  unsigned int ignored_modifier_mask;
-  unsigned int hyper_mask;
-  unsigned int super_mask;
-  unsigned int meta_mask;
+  xkb_mod_mask_t ignored_modifier_mask;
+  xkb_mod_mask_t hyper_mask;
+  xkb_mod_mask_t super_mask;
+  xkb_mod_mask_t meta_mask;
   MetaKeyCombo overlay_key_combo;
   gboolean overlay_key_only_pressed;
   MetaKeyCombo *iso_next_group_combos;
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index d0ff8e0..684899c 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -39,11 +39,10 @@
 #include "screen-private.h"
 #include <meta/prefs.h>
 #include "meta-accel-parse.h"
+#include "xkbcommon-hacks.h"
 
 #include <linux/input.h>
 
-#include <xkbcommon/xkbcommon.h>
-
 #include "backends/x11/meta-backend-x11.h"
 #include "x11/window-x11.h"
 
@@ -201,73 +200,31 @@ keysym_name (xkb_keysym_t keysym)
 static void
 reload_modmap (MetaKeyBindingManager *keys)
 {
-  XModifierKeymap *modmap;
-  int map_size;
-  int i;
-  int scroll_lock_mask = 0;
-
-  modmap = XGetModifierMapping (keys->xdisplay);
-  keys->ignored_modifier_mask = 0;
-
-  /* Multiple bits may get set in each of these */
-  keys->meta_mask = 0;
-  keys->hyper_mask = 0;
-  keys->super_mask = 0;
-
-  /* there are 8 modifiers, and the first 3 are shift, shift lock,
-   * and control
-   */
-  map_size = 8 * modmap->max_keypermod;
-  i = 3 * modmap->max_keypermod;
-  while (i < map_size)
-    {
-      /* get the key code at this point in the map,
-       * see if its keysym is one we're interested in
-       */
-      int keycode = modmap->modifiermap[i];
-
-      if (keycode >= keys->min_keycode &&
-          keycode <= keys->max_keycode)
-        {
-          int j = 0;
-          KeySym *syms = keys->keymap +
-            (keycode - keys->min_keycode) * keys->keysyms_per_keycode;
-
-          while (j < keys->keysyms_per_keycode)
-            {
-              if (syms[j] != 0)
-                {
-                  meta_topic (META_DEBUG_KEYBINDINGS,
-                              "Keysym %s bound to modifier 0x%x\n",
-                              keysym_name (syms[j]),
-                              (1 << ( i / modmap->max_keypermod)));
-                }
-
-              if (syms[j] == XKB_KEY_Scroll_Lock)
-                {
-                  scroll_lock_mask |= (1 << ( i / modmap->max_keypermod));
-                }
-              else if (syms[j] == XKB_KEY_Super_L ||
-                       syms[j] == XKB_KEY_Super_R)
-                {
-                  keys->super_mask |= (1 << ( i / modmap->max_keypermod));
-                }
-              else if (syms[j] == XKB_KEY_Hyper_L ||
-                       syms[j] == XKB_KEY_Hyper_R)
-                {
-                  keys->hyper_mask |= (1 << ( i / modmap->max_keypermod));
-                }
-              else if (syms[j] == XKB_KEY_Meta_L ||
-                       syms[j] == XKB_KEY_Meta_R)
-                {
-                  keys->meta_mask |= (1 << ( i / modmap->max_keypermod));
-                }
-
-              ++j;
-            }
-        }
-
-      ++i;
+  MetaBackend *backend = meta_get_backend ();
+  struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
+  xkb_mod_mask_t scroll_lock_mask;
+
+  /* Modifiers to find. */
+  struct {
+    char *name;
+    xkb_mod_mask_t *mask_p;
+  } mods[] = {
+    { "ScrollLock", &scroll_lock_mask },
+    { "Meta",       &keys->meta_mask },
+    { "Hyper",      &keys->hyper_mask },
+    { "Super",      &keys->super_mask },
+  };
+
+  gsize i;
+  for (i = 0; i < G_N_ELEMENTS (mods); i++)
+    {
+      xkb_mod_mask_t *mask_p = mods[i].mask_p;
+      xkb_mod_index_t idx = xkb_keymap_mod_get_index (keymap, mods[i].name);
+
+      if (idx != XKB_MOD_INVALID)
+        *mask_p = my_xkb_keymap_mod_get_mask (keymap, idx);
+      else
+        *mask_p = 0;
     }
 
   keys->ignored_modifier_mask = (scroll_lock_mask | Mod2Mask | LockMask);
@@ -279,8 +236,6 @@ reload_modmap (MetaKeyBindingManager *keys)
               keys->hyper_mask,
               keys->super_mask,
               keys->meta_mask);
-
-  XFreeModifiermap (modmap);
 }
 
 /* Original code from gdk_x11_keymap_get_entries_for_keyval() in
diff --git a/src/core/xkbcommon-hacks.c b/src/core/xkbcommon-hacks.c
new file mode 100644
index 0000000..330f0f7
--- /dev/null
+++ b/src/core/xkbcommon-hacks.c
@@ -0,0 +1,112 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2014 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+
+#include "xkbcommon-hacks.h"
+
+/* Terrible, gross hackery to provide an implementation for xkb_keymap_mod_get_mask.
+ * Delete when https://github.com/xkbcommon/libxkbcommon/pull/10 is pushed. */
+
+/* The structures here have been pulled from libxkbcommon. */
+
+enum xkb_action_controls {
+    CONTROL_REPEAT = (1 << 0),
+    CONTROL_SLOW = (1 << 1),
+    CONTROL_DEBOUNCE = (1 << 2),
+    CONTROL_STICKY = (1 << 3),
+    CONTROL_MOUSEKEYS = (1 << 4),
+    CONTROL_MOUSEKEYS_ACCEL = (1 << 5),
+    CONTROL_AX = (1 << 6),
+    CONTROL_AX_TIMEOUT = (1 << 7),
+    CONTROL_AX_FEEDBACK = (1 << 8),
+    CONTROL_BELL = (1 << 9),
+    CONTROL_IGNORE_GROUP_LOCK = (1 << 10),
+    CONTROL_ALL = \
+        (CONTROL_REPEAT | CONTROL_SLOW | CONTROL_DEBOUNCE | CONTROL_STICKY | \
+         CONTROL_MOUSEKEYS | CONTROL_MOUSEKEYS_ACCEL | CONTROL_AX | \
+         CONTROL_AX_TIMEOUT | CONTROL_AX_FEEDBACK | CONTROL_BELL | \
+         CONTROL_IGNORE_GROUP_LOCK)
+};
+
+typedef uint32_t xkb_atom_t;
+
+/* Don't allow more modifiers than we can hold in xkb_mod_mask_t. */
+#define XKB_MAX_MODS ((xkb_mod_index_t) (sizeof(xkb_mod_mask_t) * 8))
+
+/* These should all go away. */
+enum mod_type {
+    MOD_REAL = (1 << 0),
+    MOD_VIRT = (1 << 1),
+    MOD_BOTH = (MOD_REAL | MOD_VIRT),
+};
+
+struct xkb_mod {
+    xkb_atom_t name;
+    enum mod_type type;
+    xkb_mod_mask_t mapping; /* vmod -> real mod mapping */
+};
+
+struct xkb_mod_set {
+    struct xkb_mod mods[XKB_MAX_MODS];
+    unsigned int num_mods;
+};
+
+/* Common keyboard description structure */
+struct xkb_keymap_real {
+    struct xkb_context *ctx;
+
+    int refcnt;
+    enum xkb_keymap_compile_flags flags;
+    enum xkb_keymap_format format;
+
+    enum xkb_action_controls enabled_ctrls;
+
+    xkb_keycode_t min_key_code;
+    xkb_keycode_t max_key_code;
+    void *keys;
+
+    /* aliases in no particular order */
+    unsigned int num_key_aliases;
+    void *key_aliases;
+
+    void *types;
+    unsigned int num_types;
+
+    unsigned int num_sym_interprets;
+    void *sym_interprets;
+
+    struct xkb_mod_set mods;
+};
+
+xkb_mod_mask_t
+my_xkb_keymap_mod_get_mask(struct xkb_keymap *_keymap, xkb_mod_index_t idx)
+{
+    struct xkb_keymap_real *keymap = (struct xkb_keymap_real *) _keymap;
+
+    if (idx >= keymap->mods.num_mods)
+        return 0;
+
+    return keymap->mods.mods[idx].mapping;
+}
diff --git a/src/core/xkbcommon-hacks.h b/src/core/xkbcommon-hacks.h
new file mode 100644
index 0000000..9b64118
--- /dev/null
+++ b/src/core/xkbcommon-hacks.h
@@ -0,0 +1,34 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2014 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+
+#ifndef XKBCOMMON_HACKS_H
+#define XKBCOMMON_HACKS_H
+
+#include <xkbcommon/xkbcommon.h>
+
+xkb_mod_mask_t
+my_xkb_keymap_mod_get_mask(struct xkb_keymap *keymap, xkb_mod_index_t idx);
+
+#endif /* XKBCOMMON_HACKS_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]