x11: Use XKB to track the Locks state
authorEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 13 Jul 2010 08:15:21 +0000 (09:15 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 13 Jul 2010 08:15:21 +0000 (09:15 +0100)
For Caps Lock and Num Lock. Store the state of both in the
platform-specific per-event data structure. No accessors, yet.

clutter/x11/clutter-event-x11.c
clutter/x11/clutter-keymap-x11.c
clutter/x11/clutter-keymap-x11.h

index 42f6034..267aa52 100644 (file)
@@ -94,6 +94,9 @@ struct _ClutterEventX11
 {
   /* additional fields for Key events */
   gint key_group;
+
+  guint num_lock_set  : 1;
+  guint caps_lock_set : 1;
 };
 
 ClutterEventX11 *
@@ -328,7 +331,7 @@ convert_xdevicekey_to_xkey (XDeviceKeyEvent *xkev,
 }
 #endif /* HAVE_XINPUT */
 
-static void
+static inline void
 translate_key_event (ClutterBackendX11 *backend_x11,
                      ClutterEvent      *event,
                      XEvent            *xevent)
@@ -336,9 +339,6 @@ translate_key_event (ClutterBackendX11 *backend_x11,
   ClutterEventX11 *event_x11;
   char buffer[256 + 1];
   int n;
-  
-  CLUTTER_NOTE (EVENT, "Translating key %s event",
-                xevent->xany.type == KeyPress ? "press" : "release");
 
   /* KeyEvents have platform specific data associated to them */
   event_x11 = _clutter_event_x11_new ();
@@ -357,6 +357,10 @@ translate_key_event (ClutterBackendX11 *backend_x11,
   event_x11->key_group =
     _clutter_keymap_x11_get_key_group (backend_x11->keymap,
                                        event->key.modifier_state);
+  event_x11->num_lock_set =
+    _clutter_keymap_x11_get_num_lock_state (backend_x11->keymap);
+  event_x11->caps_lock_set =
+    _clutter_keymap_x11_get_caps_lock_state (backend_x11->keymap);
 
   /* unicode_value is the printable representation */
   n = XLookupString (&xevent->xkey, buffer, sizeof (buffer) - 1, NULL, NULL);
@@ -366,10 +370,13 @@ translate_key_event (ClutterBackendX11 *backend_x11,
       event->key.unicode_value = g_utf8_get_char_validated (buffer, n);
       if ((event->key.unicode_value != -1) &&
           (event->key.unicode_value != -2))
-        return;
+        goto out;
     }
   else
     event->key.unicode_value = (gunichar)'\0';
+
+out:
+  return;
 }
 
 static gboolean
index fcf0f38..9957e8a 100644 (file)
@@ -59,6 +59,9 @@ struct _ClutterKeymapX11
 #ifdef HAVE_XKB
   XkbDescPtr xkb_desc;
 #endif
+
+  guint caps_lock_state : 1;
+  guint num_lock_state  : 1;
 };
 
 struct _ClutterKeymapX11Class
@@ -156,6 +159,65 @@ get_xkb (ClutterKeymapX11 *keymap_x11)
 }
 #endif /* HAVE_XKB */
 
+#ifdef HAVE_XKB
+static void
+update_locked_mods (ClutterKeymapX11 *keymap_x11,
+                    gint              locked_mods)
+{
+  gboolean old_caps_lock_state, old_num_lock_state;
+
+  old_caps_lock_state = keymap_x11->caps_lock_state;
+  old_num_lock_state  = keymap_x11->num_lock_state;
+
+  keymap_x11->caps_lock_state = (locked_mods & CLUTTER_LOCK_MASK) != 0;
+  keymap_x11->num_lock_state  = (locked_mods & keymap_x11->num_lock_mask) != 0;
+
+  CLUTTER_NOTE (BACKEND, "Locks state changed - Num: %s, Caps: %s",
+                keymap_x11->num_lock_state ? "set" : "unset",
+                keymap_x11->caps_lock_state ? "set" : "unset");
+#if 0
+  /* Add signal to ClutterBackend? */
+  if ((keymap_x11->caps_lock_state != old_caps_lock_state) ||
+      (keymap_x11->num_lock_state != old_num_lock_state))
+    g_signal_emit_by_name (keymap_x11->backend, "key-lock-changed");
+#endif
+}
+
+static ClutterX11FilterReturn
+xkb_filter (XEvent       *xevent,
+            ClutterEvent *event,
+            gpointer      data)
+{
+  ClutterBackendX11 *backend_x11 = data;
+  ClutterKeymapX11 *keymap_x11 = backend_x11->keymap;
+
+  g_assert (keymap_x11 != NULL);
+
+  if (!backend_x11->use_xkb)
+    return CLUTTER_X11_FILTER_CONTINUE;
+
+  if (xevent->type == backend_x11->xkb_event_base)
+    {
+      XkbEvent *xkb_event = (XkbEvent *) xevent;
+
+      CLUTTER_NOTE (BACKEND, "Received XKB event [%d]",
+                    xkb_event->any.xkb_type);
+
+      switch (xkb_event->any.xkb_type)
+        {
+        case XkbStateNotify:
+          update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  return CLUTTER_X11_FILTER_CONTINUE;
+}
+#endif /* HAVE_XKB */
+
 static void
 clutter_keymap_x11_constructed (GObject *gobject)
 {
@@ -183,8 +245,6 @@ clutter_keymap_x11_constructed (GObject *gobject)
 
             backend_x11->use_xkb = TRUE;
 
-#if 0
-            /* XXX - enable when we handle keymap-related events */
             XkbSelectEvents (backend_x11->xdpy,
                              XkbUseCoreKbd,
                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
@@ -194,7 +254,8 @@ clutter_keymap_x11_constructed (GObject *gobject)
                                    XkbUseCoreKbd, XkbStateNotify,
                                    XkbAllStateComponentsMask,
                                    XkbGroupLockMask|XkbModifierLockMask);
-#endif
+
+            clutter_x11_add_filter (xkb_filter, backend_x11);
 
             /* enable XKB autorepeat */
             XkbSetDetectableAutoRepeat (backend_x11->xdpy,
@@ -274,3 +335,19 @@ _clutter_keymap_x11_get_key_group (ClutterKeymapX11    *keymap,
   return 0;
 #endif /* HAVE_XKB */
 }
+
+gboolean
+_clutter_keymap_x11_get_num_lock_state (ClutterKeymapX11 *keymap)
+{
+  g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE);
+
+  return keymap->num_lock_state;
+}
+
+gboolean
+_clutter_keymap_x11_get_caps_lock_state (ClutterKeymapX11 *keymap)
+{
+  g_return_val_if_fail (CLUTTER_IS_KEYMAP_X11 (keymap), FALSE);
+
+  return keymap->caps_lock_state;
+}
index e0d0fb6..f228c6f 100644 (file)
@@ -37,8 +37,10 @@ typedef struct _ClutterKeymapX11        ClutterKeymapX11;
 
 GType clutter_keymap_x11_get_type (void) G_GNUC_CONST;
 
-gint _clutter_keymap_x11_get_key_group (ClutterKeymapX11    *keymap,
-                                        ClutterModifierType  state);
+gint     _clutter_keymap_x11_get_key_group       (ClutterKeymapX11    *keymap,
+                                                  ClutterModifierType  state);
+gboolean _clutter_keymap_x11_get_num_lock_state  (ClutterKeymapX11    *keymap);
+gboolean _clutter_keymap_x11_get_caps_lock_state (ClutterKeymapX11    *keymap);
 
 G_END_DECLS