[RFC] compositor: Simple key repeat implementation.
Scott Moreau
oreaus at gmail.com
Wed Mar 7 14:21:11 PST 2012
There's nothing fancy about this, we just set a timer and simulate
events using states 2 and 3 for repeat-up and repeat-down events.
---
src/compositor.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/compositor.h | 5 +++
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c
index 0e33971..8d4ec55 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1438,6 +1438,19 @@ idle_handler(void *data)
return 1;
}
+static int
+key_repeat_handler(void *data)
+{
+ struct weston_input_device *device = data;
+ int repeat_speed = 100;
+
+ notify_key(&device->input_device, weston_compositor_get_time(), device->key_repeat.key, 2);
+ notify_key(&device->input_device, weston_compositor_get_time(), device->key_repeat.key, 3);
+ wl_event_source_timer_update(device->key_repeat.source, repeat_speed);
+
+ return 1;
+}
+
static void
weston_input_update_drag_surface(struct wl_input_device *input_device,
int dx, int dy);
@@ -1580,14 +1593,68 @@ update_modifier_state(struct weston_input_device *device,
device->modifier_state &= ~modifier;
}
+static int
+is_repeat_key (uint32_t key)
+{
+ /* Return 0 for keys that should not auto-repeat */
+
+ if (key >= KEY_FN && key <= KEY_FN_B)
+ return 0;
+
+ switch (key) {
+ case KEY_LEFTCTRL:
+ case KEY_RIGHTCTRL:
+ case KEY_LEFTALT:
+ case KEY_RIGHTALT:
+ case KEY_LEFTMETA:
+ case KEY_RIGHTMETA:
+ case KEY_LEFTSHIFT:
+ case KEY_RIGHTSHIFT:
+ case KEY_NUMLOCK:
+ case KEY_SCROLLLOCK:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
WL_EXPORT void
notify_key(struct wl_input_device *device,
uint32_t time, uint32_t key, uint32_t state)
{
struct weston_input_device *wd = (struct weston_input_device *) device;
struct weston_compositor *compositor = wd->compositor;
+ struct wl_event_loop *loop;
+ int repeat_delay = 500;
uint32_t *k, *end;
+ /* FIXME: do this properly when we have xkb map in the compositor */
+ /* For key repeat, use states 2 and 3 for simulated
+ * repeat events to distinguish between real events */
+ if (state != 2 && state != 3 && is_repeat_key(key)) {
+ if (wd->key_repeat.active && key == wd->key_repeat.key && !state) {
+ wl_event_source_remove(wd->key_repeat.source);
+ wd->key_repeat.key = 0;
+ wd->key_repeat.active = 0;
+ }
+ if (state) {
+ if (!wd->key_repeat.active) {
+ loop = wl_display_get_event_loop(compositor->wl_display);
+ wd->key_repeat.source =
+ wl_event_loop_add_timer(loop, key_repeat_handler, wd);
+ }
+
+ wd->key_repeat.key = key;
+ wd->key_repeat.active = 1;
+ wl_event_source_timer_update(wd->key_repeat.source, repeat_delay);
+ }
+ }
+
+ if (state == 2)
+ state = 0;
+ if (state == 3)
+ state = 1;
+
if (state) {
weston_compositor_idle_inhibit(compositor);
device->grab_key = key;
@@ -1909,6 +1976,8 @@ weston_input_device_init(struct weston_input_device *device,
device->hotspot_y = 16;
device->modifier_state = 0;
device->num_tp = 0;
+ device->key_repeat.key = 0;
+ device->key_repeat.active = 0;
device->drag_surface_destroy_listener.func = handle_drag_surface_destroy;
@@ -1924,6 +1993,9 @@ weston_input_device_release(struct weston_input_device *device)
if (device->sprite)
destroy_surface(&device->sprite->surface.resource);
+ if (device->key_repeat.active)
+ wl_event_source_remove(device->key_repeat.source);
+
wl_input_device_release(&device->input_device);
}
diff --git a/src/compositor.h b/src/compositor.h
index b94731b..5ad9943 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -108,6 +108,11 @@ struct weston_input_device {
struct weston_surface *sprite;
struct weston_surface *drag_surface;
struct wl_listener drag_surface_destroy_listener;
+ struct {
+ struct wl_event_source *source;
+ uint32_t key;
+ int active;
+ } key_repeat;
int32_t hotspot_x, hotspot_y;
struct wl_list link;
uint32_t modifier_state;
--
1.7.4.1
More information about the wayland-devel
mailing list