[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