From 0992b5c53e182ace6e61de3d6450c9aca124bfa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 22 Jun 2016 17:56:44 +0800 Subject: [PATCH] ClutterVirtualInputDeviceEvdev: Forward button and key presses https://bugzilla.gnome.org/show_bug.cgi?id=765009 --- .../clutter-virtual-input-device-evdev.c | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c index d6517d5c4..2f1100d57 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 +#include #include "clutter-private.h" #include "clutter-virtual-input-device.h" @@ -50,12 +51,102 @@ 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 + 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++) + { + if (virtual_evdev->button_count[code] == 0) + continue; + + 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 +185,31 @@ 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 < 0 || button_count > 1) + { + g_warning ("Received multiple virtual 0x%x button %s (ignoring)", button, + button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases"); + update_button_count (virtual_evdev, button, 1 - button_state); + return; + } + + clutter_seat_evdev_notify_button (virtual_evdev->seat, + virtual_evdev->device, + time_us, + button, + button_state); } static void @@ -102,6 +218,31 @@ 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 < 0 || key_count > 1) + { + g_warning ("Received multiple virtual 0x%x key %s (ignoring)", key, + key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases"); + update_button_count (virtual_evdev, key, 1 - key_state); + return; + } + + clutter_seat_evdev_notify_key (virtual_evdev->seat, + virtual_evdev->device, + time_us, + key, + key_state, + TRUE); } static void @@ -176,6 +317,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 =