mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 13:24:09 +00:00
clutter/evdev: implement slow keys support
Delay emitting clutter key press events when slow key is enabled. https://bugzilla.gnome.org/show_bug.cgi?id=788564
This commit is contained in:
parent
76b064cffc
commit
fa28481736
@ -54,6 +54,16 @@ enum {
|
|||||||
|
|
||||||
static GParamSpec *obj_props[N_PROPS] = { 0 };
|
static GParamSpec *obj_props[N_PROPS] = { 0 };
|
||||||
|
|
||||||
|
typedef struct _SlowKeysEventPending
|
||||||
|
{
|
||||||
|
ClutterInputDeviceEvdev *device;
|
||||||
|
ClutterEvent *event;
|
||||||
|
ClutterEmitInputDeviceEvent emit_event_func;
|
||||||
|
guint timer;
|
||||||
|
} SlowKeysEventPending;
|
||||||
|
|
||||||
|
static void clear_slow_keys (ClutterInputDeviceEvdev *device);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_input_device_evdev_finalize (GObject *object)
|
clutter_input_device_evdev_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@ -67,6 +77,8 @@ clutter_input_device_evdev_finalize (GObject *object)
|
|||||||
|
|
||||||
_clutter_device_manager_evdev_release_device_id (manager_evdev, device);
|
_clutter_device_manager_evdev_release_device_id (manager_evdev, device);
|
||||||
|
|
||||||
|
clear_slow_keys (device_evdev);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object);
|
G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +221,130 @@ clutter_input_device_evdev_is_grouped (ClutterInputDevice *device,
|
|||||||
libinput_device_get_device_group (other_libinput_device);
|
libinput_device_get_device_group (other_libinput_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_evdev_bell_notify (void)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend;
|
||||||
|
|
||||||
|
backend = clutter_get_default_backend ();
|
||||||
|
clutter_backend_bell_notify (backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_device_evdev_free_pending_slow_key (gpointer data)
|
||||||
|
{
|
||||||
|
SlowKeysEventPending *slow_keys_event = data;
|
||||||
|
|
||||||
|
clutter_event_free (slow_keys_event->event);
|
||||||
|
if (slow_keys_event->timer)
|
||||||
|
g_source_remove (slow_keys_event->timer);
|
||||||
|
g_free (slow_keys_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_slow_keys (ClutterInputDeviceEvdev *device)
|
||||||
|
{
|
||||||
|
g_list_free_full (device->slow_keys_list, clutter_input_device_evdev_free_pending_slow_key);
|
||||||
|
g_list_free (device->slow_keys_list);
|
||||||
|
device->slow_keys_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
get_slow_keys_delay (ClutterInputDevice *device)
|
||||||
|
{
|
||||||
|
ClutterKbdA11ySettings a11y_settings;
|
||||||
|
|
||||||
|
clutter_device_manager_get_kbd_a11y_settings (device->device_manager,
|
||||||
|
&a11y_settings);
|
||||||
|
/* Settings use int, we use uint, make sure we dont go negative */
|
||||||
|
return MAX (0, a11y_settings.slowkeys_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
trigger_slow_keys (gpointer data)
|
||||||
|
{
|
||||||
|
SlowKeysEventPending *slow_keys_event = data;
|
||||||
|
ClutterInputDeviceEvdev *device = slow_keys_event->device;
|
||||||
|
ClutterKeyEvent *key_event = (ClutterKeyEvent *) slow_keys_event->event;
|
||||||
|
|
||||||
|
/* Alter timestamp and emit the event */
|
||||||
|
key_event->time = us2ms (g_get_monotonic_time ());
|
||||||
|
slow_keys_event->emit_event_func (slow_keys_event->event,
|
||||||
|
CLUTTER_INPUT_DEVICE (device));
|
||||||
|
|
||||||
|
/* Then remote the pending event */
|
||||||
|
device->slow_keys_list = g_list_remove (device->slow_keys_list, slow_keys_event);
|
||||||
|
clutter_input_device_evdev_free_pending_slow_key (slow_keys_event);
|
||||||
|
|
||||||
|
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT)
|
||||||
|
clutter_input_device_evdev_bell_notify ();
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
find_pending_event_by_keycode (gconstpointer a,
|
||||||
|
gconstpointer b)
|
||||||
|
{
|
||||||
|
const SlowKeysEventPending *pa = a;
|
||||||
|
const ClutterKeyEvent *ka = (ClutterKeyEvent *) pa->event;
|
||||||
|
const ClutterKeyEvent *kb = b;
|
||||||
|
|
||||||
|
return kb->hardware_keycode - ka->hardware_keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_slow_keys (ClutterEvent *event,
|
||||||
|
ClutterInputDeviceEvdev *device,
|
||||||
|
ClutterEmitInputDeviceEvent emit_event_func)
|
||||||
|
{
|
||||||
|
SlowKeysEventPending *slow_keys_event;
|
||||||
|
ClutterKeyEvent *key_event = (ClutterKeyEvent *) event;
|
||||||
|
|
||||||
|
/* Synthetic key events are for autorepeat, ignore those... */
|
||||||
|
if (key_event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
slow_keys_event = g_new0 (SlowKeysEventPending, 1);
|
||||||
|
slow_keys_event->device = device;
|
||||||
|
slow_keys_event->event = clutter_event_copy (event);
|
||||||
|
slow_keys_event->emit_event_func = emit_event_func;
|
||||||
|
slow_keys_event->timer =
|
||||||
|
clutter_threads_add_timeout (get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)),
|
||||||
|
trigger_slow_keys,
|
||||||
|
slow_keys_event);
|
||||||
|
device->slow_keys_list = g_list_append (device->slow_keys_list, slow_keys_event);
|
||||||
|
|
||||||
|
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS)
|
||||||
|
clutter_input_device_evdev_bell_notify ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stop_slow_keys (ClutterEvent *event,
|
||||||
|
ClutterInputDeviceEvdev *device,
|
||||||
|
ClutterEmitInputDeviceEvent emit_event_func)
|
||||||
|
{
|
||||||
|
GList *item;
|
||||||
|
|
||||||
|
/* Check if we have a slow key event queued for this key event */
|
||||||
|
item = g_list_find_custom (device->slow_keys_list, event, find_pending_event_by_keycode);
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
SlowKeysEventPending *slow_keys_event = item->data;
|
||||||
|
|
||||||
|
device->slow_keys_list = g_list_delete_link (device->slow_keys_list, item);
|
||||||
|
clutter_input_device_evdev_free_pending_slow_key (slow_keys_event);
|
||||||
|
|
||||||
|
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT)
|
||||||
|
clutter_input_device_evdev_bell_notify ();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no key press event was pending, just emit the key release as-is */
|
||||||
|
emit_event_func (event, CLUTTER_INPUT_DEVICE (device));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent *event,
|
clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent *event,
|
||||||
ClutterInputDevice *device,
|
ClutterInputDevice *device,
|
||||||
@ -219,6 +355,17 @@ clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent *e
|
|||||||
if (!device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
|
if (!device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
|
||||||
goto emit_event;
|
goto emit_event;
|
||||||
|
|
||||||
|
if ((device_evdev->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_ENABLED) &&
|
||||||
|
(get_slow_keys_delay (device) != 0))
|
||||||
|
{
|
||||||
|
if (event->type == CLUTTER_KEY_PRESS)
|
||||||
|
start_slow_keys (event, device_evdev, emit_event_func);
|
||||||
|
else if (event->type == CLUTTER_KEY_RELEASE)
|
||||||
|
stop_slow_keys (event, device_evdev, emit_event_func);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit_event:
|
emit_event:
|
||||||
emit_event_func (event, device);
|
emit_event_func (event, device);
|
||||||
}
|
}
|
||||||
@ -227,6 +374,11 @@ void
|
|||||||
clutter_input_device_evdev_apply_kbd_a11y_settings (ClutterInputDeviceEvdev *device,
|
clutter_input_device_evdev_apply_kbd_a11y_settings (ClutterInputDeviceEvdev *device,
|
||||||
ClutterKbdA11ySettings *settings)
|
ClutterKbdA11ySettings *settings)
|
||||||
{
|
{
|
||||||
|
ClutterKeyboardA11yFlags changed_flags = (device->a11y_flags ^ settings->controls);
|
||||||
|
|
||||||
|
if (changed_flags & (CLUTTER_A11Y_KEYBOARD_ENABLED | CLUTTER_A11Y_SLOW_KEYS_ENABLED))
|
||||||
|
clear_slow_keys (device);
|
||||||
|
|
||||||
/* Keep our own copy of keyboard a11y features flags to see what changes */
|
/* Keep our own copy of keyboard a11y features flags to see what changes */
|
||||||
device->a11y_flags = settings->controls;
|
device->a11y_flags = settings->controls;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ struct _ClutterInputDeviceEvdev
|
|||||||
|
|
||||||
/* Keyboard a11y */
|
/* Keyboard a11y */
|
||||||
ClutterKeyboardA11yFlags a11y_flags;
|
ClutterKeyboardA11yFlags a11y_flags;
|
||||||
|
GList *slow_keys_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;
|
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user