[mutter/wip/garnacho/virtual-input-device: 106/107] clutter/evdev: Implement ClutterVirtualInputDevice::notify_keyval
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/garnacho/virtual-input-device: 106/107] clutter/evdev: Implement ClutterVirtualInputDevice::notify_keyval
- Date: Tue, 26 Jul 2016 17:23:04 +0000 (UTC)
commit 5f91d34f88daa51563973aa032addfbe7c4b9335
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Jul 20 18:03:44 2016 +0200
clutter/evdev: Implement ClutterVirtualInputDevice::notify_keyval
This is somewhat gross at the moment, because we're after all mimicking
real keyboard events, we can only lookup keycodes that are available
in the current map, and the control of levels is rather limited.
Eventually, we want to implement the text_input protocol, handle these
events separately to MetaWaylandKeyboard, so event->key.keyval is
is guaranteed to be the final result. Until then, this is the farthest
we can get.
https://bugzilla.gnome.org/show_bug.cgi?id=765009
.../evdev/clutter-virtual-input-device-evdev.c | 137 ++++++++++++++++++++
1 files changed, 137 insertions(+), 0 deletions(-)
---
diff --git a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c
b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c
index ceda3c6..dd0dd22 100644
--- a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c
+++ b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c
@@ -248,6 +248,142 @@ clutter_virtual_input_device_evdev_notify_key (ClutterVirtualInputDevice *virtua
TRUE);
}
+static gboolean
+pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_device,
+ guint keyval,
+ guint *keycode_out,
+ guint *level_out)
+{
+ ClutterVirtualInputDeviceEvdev *virtual_evdev =
+ CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
+ ClutterDeviceManager *manager;
+ struct xkb_keymap *xkb_keymap;
+ struct xkb_state *state;
+ guint keycode, layout;
+ xkb_keycode_t min_keycode, max_keycode;
+
+ manager = clutter_virtual_input_device_get_manager (virtual_device);
+ xkb_keymap = _clutter_device_manager_evdev_get_keymap (CLUTTER_DEVICE_MANAGER_EVDEV (manager));
+ state = virtual_evdev->seat->xkb;
+
+ layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE);
+ min_keycode = xkb_keymap_min_keycode (xkb_keymap);
+ max_keycode = xkb_keymap_max_keycode (xkb_keymap);
+ for (keycode = min_keycode; keycode < max_keycode; keycode++)
+ {
+ gint num_levels, level;
+ num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
+ for (level = 0; level < num_levels; level++)
+ {
+ const xkb_keysym_t *syms;
+ gint num_syms, sym;
+ num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
+ for (sym = 0; sym < num_syms; sym++)
+ {
+ if (syms[sym] == keyval)
+ {
+ *keycode_out = keycode;
+ if (level_out)
+ *level_out = level;
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
+ uint64_t time_us,
+ uint32_t level,
+ uint32_t key_state)
+{
+ ClutterVirtualInputDeviceEvdev *virtual_evdev =
+ CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
+ guint keysym, keycode, evcode;
+
+ if (level == 0)
+ return;
+
+ if (level == 1)
+ {
+ keysym = XKB_KEY_Shift_L;
+ }
+ else if (level == 2)
+ {
+ keysym = XKB_KEY_ISO_Level3_Shift;
+ }
+ else
+ {
+ g_warning ("Unhandled level: %d\n", level);
+ return;
+ }
+
+ if (!pick_keycode_for_keyval_in_current_group (virtual_device, keysym,
+ &keycode, NULL))
+ return;
+
+ clutter_input_device_keycode_to_evdev (virtual_evdev->device,
+ keycode, &evcode);
+ clutter_seat_evdev_notify_key (virtual_evdev->seat,
+ virtual_evdev->device,
+ time_us,
+ evcode,
+ key_state,
+ TRUE);
+}
+
+static void
+clutter_virtual_input_device_evdev_notify_keyval (ClutterVirtualInputDevice *virtual_device,
+ uint64_t time_us,
+ uint32_t keyval,
+ ClutterKeyState key_state)
+{
+ ClutterVirtualInputDeviceEvdev *virtual_evdev =
+ CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
+ int key_count;
+ guint keycode = 0, level = 0, evcode = 0;
+
+ if (!pick_keycode_for_keyval_in_current_group (virtual_device,
+ keyval, &keycode, &level))
+ {
+ g_warning ("No keycode found for keyval %x in current group", keyval);
+ return;
+ }
+
+ clutter_input_device_keycode_to_evdev (virtual_evdev->device,
+ keycode, &evcode);
+
+ if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
+ {
+ g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", evcode);
+ return;
+ }
+
+ key_count = update_button_count (virtual_evdev, evcode, key_state);
+ if (key_count > 1)
+ {
+ g_warning ("Received multiple virtual 0x%x key presses (ignoring)",
+ keycode);
+ return;
+ }
+
+ if (key_state)
+ apply_level_modifiers (virtual_device, time_us, level, key_state);
+
+ clutter_seat_evdev_notify_key (virtual_evdev->seat,
+ virtual_evdev->device,
+ time_us,
+ evcode,
+ key_state,
+ TRUE);
+
+ if (!key_state)
+ apply_level_modifiers (virtual_device, time_us, level, key_state);
+}
+
static void
clutter_virtual_input_device_evdev_get_property (GObject *object,
guint prop_id,
@@ -350,6 +486,7 @@ clutter_virtual_input_device_evdev_class_init (ClutterVirtualInputDeviceEvdevCla
virtual_input_device_class->notify_absolute_motion =
clutter_virtual_input_device_evdev_notify_absolute_motion;
virtual_input_device_class->notify_button = clutter_virtual_input_device_evdev_notify_button;
virtual_input_device_class->notify_key = clutter_virtual_input_device_evdev_notify_key;
+ virtual_input_device_class->notify_keyval = clutter_virtual_input_device_evdev_notify_keyval;
obj_props[PROP_SEAT] = g_param_spec_pointer ("seat",
P_("ClutterSeatEvdev"),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]