summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2016-06-22 17:56:44 +0800
committerCarlos Garnacho <carlosg@gnome.org>2016-07-26 18:45:25 +0200
commitc2ce0e67956f2308912253d9cd897804331f6f13 (patch)
treeba15ede56dfc4a8d81716556cac1482da434d21d
parentadbd566f8387f551fcccc461f9211ab001597316 (diff)
downloadmutter-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.c145
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 =