From 8c358f18b1be3a10430be6abb164494cf1591ed0 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Fri, 9 Aug 2013 17:06:39 +0200 Subject: [PATCH] evdev: allow hooking directly into libxkbcommon A wayland compositor needs to have more keyboard state than ClutterModifierState exposes, so it makes sense for it to use xkb_state directly. Also, it makes sense for it to provide it's own keymap, to ensure a consistent view between the compositor and the wayland clients. https://bugzilla.gnome.org/show_bug.cgi?id=705710 --- clutter/evdev/clutter-device-manager-evdev.c | 74 ++++++++++++++++++++ clutter/evdev/clutter-evdev.h | 5 ++ 2 files changed, 79 insertions(+) diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c index 48b34e982..0e7f7c24e 100644 --- a/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/evdev/clutter-device-manager-evdev.c @@ -75,6 +75,7 @@ struct _ClutterDeviceManagerEvdevPrivate guint stage_added_handler; guint stage_removed_handler; + GArray *keys; struct xkb_state *xkb; /* XKB state object */ uint32_t button_state; }; @@ -157,6 +158,29 @@ queue_event (ClutterEvent *event) _clutter_event_push (event, FALSE); } +static void +add_key (GArray *keys, + guint32 key) +{ + g_array_append_val (keys, key); +} + +static void +remove_key (GArray *keys, + guint32 key) +{ + unsigned int i; + + for (i = 0; i < keys->len; i++) + { + if (g_array_index (keys, guint32, i) == key) + { + g_array_remove_index_fast (keys, i); + return; + } + } +} + static void notify_key (ClutterEventSource *source, guint32 time_, @@ -188,6 +212,11 @@ notify_key (ClutterEventSource *source, time_, key, state); xkb_state_update_key (manager_evdev->priv->xkb, event->key.hardware_keycode, state ? XKB_KEY_DOWN : XKB_KEY_UP); + if (state) + add_key (manager_evdev->priv->keys, event->key.hardware_keycode); + else + remove_key (manager_evdev->priv->keys, event->key.hardware_keycode); + queue_event (event); } } @@ -874,6 +903,7 @@ clutter_device_manager_evdev_constructed (GObject *gobject) _clutter_device_manager_add_device (CLUTTER_DEVICE_MANAGER (manager_evdev), device); priv->core_keyboard = device; + priv->keys = g_array_new (FALSE, FALSE, sizeof (guint32)); priv->xkb = _clutter_xkb_state_new (NULL, option_xkb_layout, option_xkb_variant, @@ -1186,3 +1216,47 @@ clutter_evdev_set_open_callback (ClutterOpenDeviceCallback callback, open_callback = callback; open_callback_data = user_data; } + +/** + * clutter_evdev_get_keyboard_state: (skip) + * @evdev: the #ClutterDeviceManager created by the evdev backend + * + * Returns the xkb state tracking object for keyboard devices. + * The object must be treated as read only, and should be used only + * for reading out the detailed group and modifier state. + */ +struct xkb_state * +clutter_evdev_get_keyboard_state (ClutterDeviceManager *evdev) +{ + g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev), NULL); + + return (CLUTTER_DEVICE_MANAGER_EVDEV (evdev))->priv->xkb; +} + +/** + * clutter_evdev_set_keyboard_map: (skip) + * @evdev: the #ClutterDeviceManager created by the evdev backend + * @keymap: the new keymap + * + * Instructs @evdev to use the speficied keyboard map. This will cause + * the backend to drop the state and create a new one with the new map. + */ +void +clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev, + struct xkb_keymap *keymap) +{ + ClutterDeviceManagerEvdev *manager_evdev; + ClutterDeviceManagerEvdevPrivate *priv; + unsigned int i; + + g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER_EVDEV (evdev)); + + manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (evdev); + priv = manager_evdev->priv; + + xkb_state_unref (priv->xkb); + priv->xkb = xkb_state_new (keymap); + + for (i = 0; i < priv->keys->len; i++) + xkb_state_update_key (priv->xkb, g_array_index (priv->keys, guint32, i), XKB_KEY_DOWN); +} diff --git a/clutter/evdev/clutter-evdev.h b/clutter/evdev/clutter-evdev.h index 2b72951cb..fea26cb27 100644 --- a/clutter/evdev/clutter-evdev.h +++ b/clutter/evdev/clutter-evdev.h @@ -26,6 +26,7 @@ #include #include +#include #include G_BEGIN_DECLS @@ -50,6 +51,10 @@ void clutter_evdev_set_open_callback (ClutterOpenDeviceCallback callback, void clutter_evdev_release_devices (void); void clutter_evdev_reclaim_devices (void); +struct xkb_state * clutter_evdev_get_keyboard_state (ClutterDeviceManager *evdev); +void clutter_evdev_set_keyboard_map (ClutterDeviceManager *evdev, + struct xkb_keymap *keymap); + G_END_DECLS #endif /* __CLUTTER_EVDEV_H__ */