From bb32cba795c7ab11e3b4844d21f0b2ae2f1fdc2d Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Sat, 19 Mar 2016 13:42:32 +0100 Subject: [PATCH] Make key handling less strict Sway has been very strict when it comes to key handling. Only on an exact match would a bindsym be triggered. This patch makes it less strict by for instance allowing the key combo `$mod+1+2` to act as `$mod+2` if 2 was the last pressed key and `$mod+1` if 1 was the last pressed key. The new key handling uses the following algorithm: 1. List of bindings sorted by number of keys in binding (already the default) 2. Find all bindings covered by the current keyboard state and list them by same order as in 1. 3. Select the first binding from the list where the last pressed key is part of the binding. Addresses #452 --- sway/handlers.c | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index d992a7b6..cec63192 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -405,7 +405,28 @@ static void handle_binding_command(struct sway_binding *binding) { free_cmd_results(res); } -static bool handle_bindsym(struct sway_binding *binding) { +static bool handle_bindsym(struct sway_binding *binding, uint32_t keysym, uint32_t keycode) { + int i; + for (i = 0; i < binding->keys->length; ++i) { + if (binding->bindcode) { + xkb_keycode_t *key = binding->keys->items[i]; + if (keycode == *key) { + handle_binding_command(binding); + return true; + } + } else { + xkb_keysym_t *key = binding->keys->items[i]; + if (keysym == *key) { + handle_binding_command(binding); + return true; + } + } + } + + return false; +} + +static bool valid_bindsym(struct sway_binding *binding) { bool match = false; int i; for (i = 0; i < binding->keys->length; ++i) { @@ -422,12 +443,7 @@ static bool handle_bindsym(struct sway_binding *binding) { } } - if (match) { - handle_binding_command(binding); - return true; - } - - return false; + return match; } static bool handle_bindsym_release(struct sway_binding *binding) { @@ -489,18 +505,19 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier modifiers_state_update(modifiers->mods); // handle bindings + list_t *candidates = create_list(); for (i = 0; i < mode->bindings->length; ++i) { struct sway_binding *binding = mode->bindings->items[i]; if ((modifiers->mods ^ binding->modifiers) == 0) { switch (state) { case WLC_KEY_STATE_PRESSED: { - if (!binding->release && handle_bindsym(binding)) { - return EVENT_HANDLED; + if (!binding->release && valid_bindsym(binding)) { + list_add(candidates, binding); } - break; } case WLC_KEY_STATE_RELEASED: if (binding->release && handle_bindsym_release(binding)) { + list_free(candidates); return EVENT_HANDLED; } break; @@ -508,6 +525,17 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier } } + for (i = 0; i < candidates->length; ++i) { + struct sway_binding *binding = candidates->items[i]; + if (state == WLC_KEY_STATE_PRESSED) { + if (!binding->release && handle_bindsym(binding, sym, key)) { + list_free(candidates); + return EVENT_HANDLED; + } + } + } + + list_free(candidates); return EVENT_PASSTHROUGH; }