diff options
author | Jonas Ã…dahl <jadahl@gmail.com> | 2016-06-22 17:56:44 +0800 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2016-07-26 18:45:25 +0200 |
commit | c2ce0e67956f2308912253d9cd897804331f6f13 (patch) | |
tree | ba15ede56dfc4a8d81716556cac1482da434d21d | |
parent | adbd566f8387f551fcccc461f9211ab001597316 (diff) | |
download | mutter-c2ce0e67956f2308912253d9cd897804331f6f13.tar.gz |
ClutterVirtualInputDeviceEvdev: Forward button and key presses
https://bugzilla.gnome.org/show_bug.cgi?id=765009
-rw-r--r-- | clutter/clutter/evdev/clutter-virtual-input-device-evdev.c | 145 |
1 files changed, 145 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 d6517d5c4..b4925e12e 100644 --- a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c +++ b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c @@ -26,6 +26,7 @@ #endif #include <glib-object.h> +#include <linux/input.h> #include "clutter-private.h" #include "clutter-virtual-input-device.h" @@ -50,12 +51,107 @@ struct _ClutterVirtualInputDeviceEvdev ClutterInputDevice *device; ClutterSeatEvdev *seat; + int button_count[KEY_CNT]; }; G_DEFINE_TYPE (ClutterVirtualInputDeviceEvdev, clutter_virtual_input_device_evdev, CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) +typedef enum _EvdevButtonType +{ + EVDEV_BUTTON_TYPE_NONE, + EVDEV_BUTTON_TYPE_KEY, + EVDEV_BUTTON_TYPE_BUTTON, +} EvdevButtonType; + +static int +update_button_count (ClutterVirtualInputDeviceEvdev *virtual_evdev, + uint32_t button, + uint32_t state) +{ + if (state) + { + return ++virtual_evdev->button_count[button]; + } + else + { + /* Handle cases where we newer saw the initial pressed event. */ + if (virtual_evdev->button_count[button] == 0) + return 0; + + return --virtual_evdev->button_count[button]; + } +} + +static EvdevButtonType +get_button_type (uint16_t code) +{ + switch (code) + { + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + case BTN_TOOL_QUINTTAP: + case BTN_TOOL_DOUBLETAP: + case BTN_TOOL_TRIPLETAP: + case BTN_TOOL_QUADTAP: + case BTN_TOOL_FINGER: + case BTN_TOUCH: + return EVDEV_BUTTON_TYPE_NONE; + } + + if (code >= KEY_ESC && code <= KEY_MICMUTE) + return EVDEV_BUTTON_TYPE_KEY; + if (code >= BTN_MISC && code <= BTN_GEAR_UP) + return EVDEV_BUTTON_TYPE_BUTTON; + if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE) + return EVDEV_BUTTON_TYPE_KEY; + if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT) + return EVDEV_BUTTON_TYPE_BUTTON; + if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL) + return EVDEV_BUTTON_TYPE_KEY; + if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40) + return EVDEV_BUTTON_TYPE_BUTTON; + return EVDEV_BUTTON_TYPE_NONE; +} + +static void +release_pressed_buttons (ClutterVirtualInputDevice *virtual_device) +{ + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int code; + uint64_t time_us; + + time_us = g_get_monotonic_time (); + + for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++) + { + switch (get_button_type (code)) + { + case EVDEV_BUTTON_TYPE_KEY: + clutter_virtual_input_device_notify_key (virtual_device, + time_us, + code, + CLUTTER_KEY_STATE_RELEASED); + break; + case EVDEV_BUTTON_TYPE_BUTTON: + clutter_virtual_input_device_notify_button (virtual_device, + time_us, + code, + CLUTTER_BUTTON_STATE_RELEASED); + break; + case EVDEV_BUTTON_TYPE_NONE: + g_assert_not_reached (); + } + } +} + static void clutter_virtual_input_device_evdev_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, uint64_t time_us, @@ -94,6 +190,30 @@ clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *vir uint32_t button, ClutterButtonState button_state) { + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int button_count; + + if (get_button_type (button) != EVDEV_BUTTON_TYPE_BUTTON) + { + g_warning ("Unknown/invalid virtual device button 0x%x pressed", + button); + return; + } + + button_count = update_button_count (virtual_evdev, button, button_state); + if (button_count > 1) + { + g_warning ("Received multiple virtual 0x%x button presses (ignoring)", + button); + return; + } + + clutter_seat_evdev_notify_button (virtual_evdev->seat, + virtual_evdev->device, + time_us, + button, + button_state); } static void @@ -102,6 +222,30 @@ clutter_virtual_input_device_evdev_notify_key (ClutterVirtualInputDevice *virtua uint32_t key, ClutterKeyState key_state) { + ClutterVirtualInputDeviceEvdev *virtual_evdev = + CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device); + int key_count; + + if (get_button_type (key) != EVDEV_BUTTON_TYPE_KEY) + { + g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", key); + return; + } + + key_count = update_button_count (virtual_evdev, key, key_state); + if (key_count > 1) + { + g_warning ("Received multiple virtual 0x%x key presses (ignoring)", + key); + return; + } + + clutter_seat_evdev_notify_key (virtual_evdev->seat, + virtual_evdev->device, + time_us, + key, + key_state, + TRUE); } static void @@ -176,6 +320,7 @@ clutter_virtual_input_device_evdev_finalize (GObject *object) CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object); GObjectClass *object_class; + release_pressed_buttons (virtual_device); g_clear_object (&virtual_evdev->device); object_class = |