evdev: Factor out the xkbcommon code from the wayland client backend
authorDamien Lespiau <damien.lespiau@intel.com>
Thu, 4 Nov 2010 10:59:22 +0000 (06:59 -0400)
committerDamien Lespiau <damien.lespiau@intel.com>
Tue, 30 Nov 2010 14:40:37 +0000 (14:40 +0000)
The wayland client code has support for translating raw linux input
device key codes coming from the wayland compositor into key symbols
thanks to libxkbcommon.

A backend directly listening to linux input devices (called evdev, just
like the Xorg one) could use exactly the same code for the translation,
so abstract it a bit in a separate file.

clutter/Makefile.am
clutter/evdev/clutter-xkb-utils.c [new file with mode: 0644]
clutter/evdev/clutter-xkb-utils.h [new file with mode: 0644]
clutter/wayland/clutter-input-device-wayland.c

index fc153b6..813ca61 100644 (file)
@@ -22,6 +22,7 @@ INCLUDES = \
        -I$(top_srcdir)/clutter/$(CLUTTER_WINSYS)       \
        -I$(top_srcdir)/clutter/$(CLUTTER_WINSYS_BASE)  \
        -I$(top_srcdir)/clutter/cally                   \
+       -I$(top_srcdir)/clutter/evdev                   \
        -I$(top_builddir)                               \
        -I$(top_builddir)/clutter                       \
        -I$(top_builddir)/clutter/cogl                  \
@@ -513,13 +514,15 @@ backend_source_h += \
        $(srcdir)/wayland/clutter-wayland.h
 
 backend_source_h_priv += \
-       $(srcdir)/wayland/clutter-backend-wayland.h \
+       $(srcdir)/evdev/clutter-xkb-utils.h             \
+       $(srcdir)/wayland/clutter-backend-wayland.h     \
        $(srcdir)/wayland/clutter-stage-wayland.h
 
 backend_source_c += \
-       $(srcdir)/wayland/clutter-backend-wayland.c \
-       $(srcdir)/wayland/clutter-stage-wayland.c \
-       $(srcdir)/wayland/clutter-event-wayland.c \
+       $(srcdir)/evdev/clutter-xkb-utils.c             \
+       $(srcdir)/wayland/clutter-backend-wayland.c     \
+       $(srcdir)/wayland/clutter-stage-wayland.c       \
+       $(srcdir)/wayland/clutter-event-wayland.c       \
        $(srcdir)/wayland/clutter-input-device-wayland.c
 
 clutterwayland_includedir = $(clutter_includedir)/wayland
diff --git a/clutter/evdev/clutter-xkb-utils.c b/clutter/evdev/clutter-xkb-utils.c
new file mode 100644 (file)
index 0000000..f0c3b58
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010  Intel Corporation.
+ *
+ * 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/>.
+
+ * Authors:
+ *  Kristian Høgsberg
+ */
+
+#include "clutter-keysyms.h"
+#include "clutter-xkb-utils.h"
+
+/*
+ * _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent
+ * @device: a ClutterInputDevice
+ * @stage: the stage the event should be delivered to
+ * @xkb: XKB rules to translate the event
+ * @_time: timestamp of the event
+ * @key: a key code coming from a Linux input device
+ * @state: TRUE if a press event, FALSE if a release event
+ * @modifer_state: in/out
+ *
+ * Translate @key to a #ClutterKeyEvent using rules from xbbcommon.
+ *
+ * Return value: the new #ClutterEvent
+ */
+ClutterEvent *
+_clutter_key_event_new_from_evdev (ClutterInputDevice *device,
+                                   ClutterStage       *stage,
+                                   struct xkb_desc    *xkb,
+                                   uint32_t            _time,
+                                   uint32_t            key,
+                                   uint32_t            state,
+                                   uint32_t           *modifier_state)
+{
+  ClutterEvent *event;
+  uint32_t code, sym, level;
+  char buffer[128];
+  int n;
+
+  if (state)
+    event = clutter_event_new (CLUTTER_KEY_PRESS);
+  else
+    event = clutter_event_new (CLUTTER_KEY_RELEASE);
+
+  code = key + xkb->min_key_code;
+  level = 0;
+
+  if (*modifier_state & CLUTTER_SHIFT_MASK &&
+      XkbKeyGroupWidth (xkb, code, 0) > 1)
+    level = 1;
+
+  sym = XkbKeySymEntry (xkb, code, level, 0);
+  if (state)
+    *modifier_state |= xkb->map->modmap[code];
+  else
+    *modifier_state &= ~xkb->map->modmap[code];
+
+  event->key.device = device;
+  event->key.stage = stage;
+  event->key.time = _time;
+  event->key.modifier_state = *modifier_state;
+  event->key.hardware_keycode = key;
+  event->key.keyval = sym;
+  event->key.unicode_value = sym;
+
+  return event;
+}
+
+/*
+ * _clutter_xkb_desc_new:
+ *
+ * Create a new xkbcommon keymap.
+ *
+ * FIXME: We need a way to override the layout here, a fixed or runtime
+ * detected layout is provided by the backend calling _clutter_xkb_desc_new();
+ */
+struct xkb_desc *
+_clutter_xkb_desc_new (const gchar *model,
+                       const gchar *layout,
+                       const gchar *variant,
+                       const gchar *options)
+{
+  struct xkb_rule_names names;
+
+  names.rules = "evdev";
+  if (model)
+    names.model = model;
+  else
+    names.model = "pc105";
+  names.layout = layout;
+  names.variant = variant;
+  names.options = options;
+
+  return xkb_compile_keymap_from_rules (&names);
+}
diff --git a/clutter/evdev/clutter-xkb-utils.h b/clutter/evdev/clutter-xkb-utils.h
new file mode 100644 (file)
index 0000000..34e65c6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010  Intel Corporation.
+ *
+ * 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/>.
+
+ * Authors:
+ *  Damien Lespiau <damien.lespiau@intel.com>
+ */
+
+#include <X11/extensions/XKBcommon.h>
+
+#include "clutter-stage.h"
+#include "clutter-event.h"
+#include "clutter-input-device.h"
+
+ClutterEvent *    _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
+                                                     ClutterStage       *stage,
+                                                     struct xkb_desc    *xkb,
+                                                     uint32_t            _time,
+                                                     uint32_t            key,
+                                                     uint32_t            state,
+                                                     uint32_t           *modifier_state);
+struct xkb_desc * _clutter_xkb_desc_new             (const gchar *model,
+                                                     const gchar *layout,
+                                                     const gchar *variant,
+                                                     const gchar *options);
index 81c1dbc..2e62403 100644 (file)
 #include <wayland-util.h>
 #include <wayland-client.h>
 
-#include <X11/extensions/XKBcommon.h>
-
 #include "clutter-debug.h"
 #include "clutter-device-manager-private.h"
 #include "clutter-private.h"
 #include "clutter-keysyms.h"
+#include "clutter-xkb-utils.h"
 
 #include "clutter-stage-wayland.h"
 
@@ -147,33 +146,12 @@ clutter_backend_wayland_handle_key (void *data,
   ClutterStageWayland       *stage_wayland = device->keyboard_focus;
   ClutterMainContext        *clutter_context;
   ClutterEvent              *event;
-  uint32_t                   code, sym, level;
-
-  if (state)
-    event = clutter_event_new (CLUTTER_KEY_PRESS);
-  else
-    event = clutter_event_new (CLUTTER_KEY_RELEASE);
-
-  code = key + device->xkb->min_key_code;
-  level = 0;
 
-  if (device->modifier_state & CLUTTER_SHIFT_MASK &&
-      XkbKeyGroupWidth (device->xkb, code, 0) > 1)
-    level = 1;
-
-  sym = XkbKeySymEntry (device->xkb, code, level, 0);
-  if (state)
-    device->modifier_state |= device->xkb->map->modmap[code];
-  else
-    device->modifier_state &= ~device->xkb->map->modmap[code];
-
-  event->key.device = CLUTTER_INPUT_DEVICE (device);
-  event->key.stage = stage_wayland->wrapper;
-  event->key.time = _time;
-  event->key.modifier_state = device->modifier_state;
-  event->key.hardware_keycode = key;
-  event->key.keyval = sym;
-  event->key.unicode_value = sym;
+  event = _clutter_key_event_new_from_evdev ((ClutterInputDevice *) device,
+                                             stage_wayland->wrapper,
+                                             device->xkb,
+                                             _time, key, state
+                                             &device->modifier_state);
 
   clutter_context = _clutter_context_get_default ();
   g_queue_push_head (clutter_context->events_queue, event);
@@ -315,7 +293,6 @@ _clutter_backend_add_input_device (ClutterBackendWayland *backend_wayland,
                                   uint32_t id)
 {
   ClutterInputDeviceWayland *device;
-  struct xkb_rule_names names;
 
   device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_WAYLAND,
                         "id", id,
@@ -329,13 +306,10 @@ _clutter_backend_add_input_device (ClutterBackendWayland *backend_wayland,
                                &input_device_listener, device);
   wl_input_device_set_user_data (device->input_device, device);
 
-  names.rules = "evdev";
-  names.model = "pc105";
-  names.layout = option_xkb_layout;
-  names.variant = option_xkb_variant;
-  names.options = option_xkb_options;
-
-  device->xkb = xkb_compile_keymap_from_rules (&names);
+  device->xkb = _clutter_xkb_desc_new (NULL,
+                                       option_xkb_layout,
+                                       option_xkb_variant,
+                                       option_xkb_options);
   if (!device->xkb)
     CLUTTER_NOTE (BACKEND, "Failed to compile keymap");
 }