[PATCH 2/9] Add modifier-only binding

Emilio Pozuelo Monfort pochu27 at gmail.com
Fri Nov 15 08:53:31 PST 2013


From: Daniel Stone <daniel at fooishbar.org>

Add the ability to bind to modifiers; the binding is armed when a key
which sets the requested modifier is pressed, and triggered if the key
is released with no other keys having been pressed in the meantime, as
well as mouse buttons or scroll axes.

This only works for direct modifiers (e.g. Shift and Alt), not modifiers
which latch or lock.

[pochu: rebased]
---
 src/bindings.c   | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/compositor.c |  1 +
 src/compositor.h | 16 ++++++++++++++++
 src/input.c      | 38 +++++++++++++++++++++++++++++++++++++
 4 files changed, 113 insertions(+)

diff --git a/src/bindings.c b/src/bindings.c
index 7cbded9..fb758d1 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -76,6 +76,24 @@ weston_compositor_add_key_binding(struct weston_compositor *compositor,
 }
 
 WL_EXPORT struct weston_binding *
+weston_compositor_add_modifier_binding(struct weston_compositor *compositor,
+				       uint32_t modifier,
+				       weston_modifier_binding_handler_t handler,
+				       void *data)
+{
+	struct weston_binding *binding;
+
+	binding = weston_compositor_add_binding(compositor, 0, 0, 0,
+						modifier, handler, data);
+	if (binding == NULL)
+		return NULL;
+
+	wl_list_insert(compositor->modifier_binding_list.prev, &binding->link);
+
+	return binding;
+}
+
+WL_EXPORT struct weston_binding *
 weston_compositor_add_button_binding(struct weston_compositor *compositor,
 				     uint32_t button, uint32_t modifier,
 				     weston_button_binding_handler_t handler,
@@ -248,6 +266,10 @@ weston_compositor_run_key_binding(struct weston_compositor *compositor,
 	if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
 		return;
 
+	/* Invalidate all active modifier bindings. */
+	wl_list_for_each(b, &compositor->modifier_binding_list, link)
+		b->key = key;
+
 	wl_list_for_each(b, &compositor->key_binding_list, link) {
 		if (b->key == key && b->modifier == seat->modifier_state) {
 			weston_key_binding_handler_t handler = b->handler;
@@ -264,6 +286,34 @@ weston_compositor_run_key_binding(struct weston_compositor *compositor,
 }
 
 WL_EXPORT void
+weston_compositor_run_modifier_binding(struct weston_compositor *compositor,
+				       struct weston_seat *seat,
+				       enum weston_keyboard_modifier modifier,
+				       enum wl_keyboard_key_state state)
+{
+	struct weston_binding *b;
+
+	wl_list_for_each(b, &compositor->modifier_binding_list, link) {
+		weston_modifier_binding_handler_t handler = b->handler;
+
+		if (b->modifier != modifier)
+			continue;
+
+		/* Prime the modifier binding. */
+		if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
+			b->key = 0;
+			continue;
+		}
+		/* Ignore the binding if a key was pressed in between. */
+		else if (b->key != 0) {
+			return;
+		}
+
+		handler(seat, modifier, b->data);
+	}
+}
+
+WL_EXPORT void
 weston_compositor_run_button_binding(struct weston_compositor *compositor,
 				     struct weston_seat *seat,
 				     uint32_t time, uint32_t button,
@@ -274,6 +324,10 @@ weston_compositor_run_button_binding(struct weston_compositor *compositor,
 	if (state == WL_POINTER_BUTTON_STATE_RELEASED)
 		return;
 
+	/* Invalidate all active modifier bindings. */
+	wl_list_for_each(b, &compositor->modifier_binding_list, link)
+		b->key = button;
+
 	wl_list_for_each(b, &compositor->button_binding_list, link) {
 		if (b->button == button && b->modifier == seat->modifier_state) {
 			weston_button_binding_handler_t handler = b->handler;
@@ -308,6 +362,10 @@ weston_compositor_run_axis_binding(struct weston_compositor *compositor,
 {
 	struct weston_binding *b;
 
+	/* Invalidate all active modifier bindings. */
+	wl_list_for_each(b, &compositor->modifier_binding_list, link)
+		b->key = axis;
+
 	wl_list_for_each(b, &compositor->axis_binding_list, link) {
 		if (b->axis == axis && b->modifier == seat->modifier_state) {
 			weston_axis_binding_handler_t handler = b->handler;
diff --git a/src/compositor.c b/src/compositor.c
index c6cf682..34c0551 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3332,6 +3332,7 @@ weston_compositor_init(struct weston_compositor *ec,
 	wl_list_init(&ec->seat_list);
 	wl_list_init(&ec->output_list);
 	wl_list_init(&ec->key_binding_list);
+	wl_list_init(&ec->modifier_binding_list);
 	wl_list_init(&ec->button_binding_list);
 	wl_list_init(&ec->touch_binding_list);
 	wl_list_init(&ec->axis_binding_list);
diff --git a/src/compositor.h b/src/compositor.h
index 841dd52..b67b993 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -570,6 +570,7 @@ struct weston_compositor {
 	struct wl_list view_list;
 	struct wl_list plane_list;
 	struct wl_list key_binding_list;
+	struct wl_list modifier_binding_list;
 	struct wl_list button_binding_list;
 	struct wl_list touch_binding_list;
 	struct wl_list axis_binding_list;
@@ -1004,6 +1005,15 @@ weston_compositor_add_key_binding(struct weston_compositor *compositor,
 				  weston_key_binding_handler_t binding,
 				  void *data);
 
+typedef void (*weston_modifier_binding_handler_t)(struct weston_seat *seat,
+					          enum weston_keyboard_modifier modifier,
+					          void *data);
+struct weston_binding *
+weston_compositor_add_modifier_binding(struct weston_compositor *compositor,
+				       enum weston_keyboard_modifier modifier,
+				       weston_modifier_binding_handler_t binding,
+				       void *data);
+
 typedef void (*weston_button_binding_handler_t)(struct weston_seat *seat,
 						uint32_t time, uint32_t button,
 						void *data);
@@ -1048,6 +1058,12 @@ weston_compositor_run_key_binding(struct weston_compositor *compositor,
 				  struct weston_seat *seat, uint32_t time,
 				  uint32_t key,
 				  enum wl_keyboard_key_state state);
+
+void
+weston_compositor_run_modifier_binding(struct weston_compositor *compositor,
+				       struct weston_seat *seat,
+				       enum weston_keyboard_modifier modifier,
+				       enum wl_keyboard_key_state state);
 void
 weston_compositor_run_button_binding(struct weston_compositor *compositor,
 				     struct weston_seat *seat, uint32_t time,
diff --git a/src/input.c b/src/input.c
index 153bcb6..ed3e06f 100644
--- a/src/input.c
+++ b/src/input.c
@@ -753,6 +753,41 @@ notify_motion(struct weston_seat *seat,
 	pointer->grab->interface->motion(pointer->grab, time);
 }
 
+static void
+run_modifier_bindings(struct weston_seat *seat, uint32_t old, uint32_t new)
+{
+	struct weston_compositor *compositor = seat->compositor;
+	uint32_t diff;
+	unsigned int i;
+	struct {
+		uint32_t xkb;
+		enum weston_keyboard_modifier weston;
+	} mods[] = {
+		{ seat->xkb_info->ctrl_mod, MODIFIER_CTRL },
+		{ seat->xkb_info->alt_mod, MODIFIER_ALT },
+		{ seat->xkb_info->super_mod, MODIFIER_SUPER },
+		{ seat->xkb_info->shift_mod, MODIFIER_SHIFT },
+	};
+
+	diff = new & ~old;
+	for (i = 0; i < ARRAY_LENGTH(mods); i++) {
+		if (diff & (1 << mods[i].xkb))
+			weston_compositor_run_modifier_binding(compositor,
+			                                       seat,
+			                                       mods[i].weston,
+			                                       WL_KEYBOARD_KEY_STATE_PRESSED);
+	}
+
+	diff = old & ~new;
+	for (i = 0; i < ARRAY_LENGTH(mods); i++) {
+		if (diff & (1 << mods[i].xkb))
+			weston_compositor_run_modifier_binding(compositor,
+			                                       seat,
+			                                       mods[i].weston,
+			                                       WL_KEYBOARD_KEY_STATE_RELEASED);
+	}
+}
+
 WL_EXPORT void
 notify_motion_absolute(struct weston_seat *seat,
 		       uint32_t time, wl_fixed_t x, wl_fixed_t y)
@@ -876,6 +911,9 @@ notify_modifiers(struct weston_seat *seat, uint32_t serial)
 	    group != seat->keyboard->modifiers.group)
 		changed = 1;
 
+	run_modifier_bindings(seat, seat->keyboard->modifiers.mods_depressed,
+	                      mods_depressed);
+
 	seat->keyboard->modifiers.mods_depressed = mods_depressed;
 	seat->keyboard->modifiers.mods_latched = mods_latched;
 	seat->keyboard->modifiers.mods_locked = mods_locked;
-- 
1.8.4.rc3



More information about the wayland-devel mailing list