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
This commit is contained in:
Mikkel Oscar Lyderik 2016-03-19 13:42:32 +01:00
parent 8c7bdfc004
commit bb32cba795

View file

@ -405,7 +405,28 @@ static void handle_binding_command(struct sway_binding *binding) {
free_cmd_results(res); 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; bool match = false;
int i; int i;
for (i = 0; i < binding->keys->length; ++i) { for (i = 0; i < binding->keys->length; ++i) {
@ -422,12 +443,7 @@ static bool handle_bindsym(struct sway_binding *binding) {
} }
} }
if (match) { return match;
handle_binding_command(binding);
return true;
}
return false;
} }
static bool handle_bindsym_release(struct sway_binding *binding) { 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); modifiers_state_update(modifiers->mods);
// handle bindings // handle bindings
list_t *candidates = create_list();
for (i = 0; i < mode->bindings->length; ++i) { for (i = 0; i < mode->bindings->length; ++i) {
struct sway_binding *binding = mode->bindings->items[i]; struct sway_binding *binding = mode->bindings->items[i];
if ((modifiers->mods ^ binding->modifiers) == 0) { if ((modifiers->mods ^ binding->modifiers) == 0) {
switch (state) { switch (state) {
case WLC_KEY_STATE_PRESSED: { case WLC_KEY_STATE_PRESSED: {
if (!binding->release && handle_bindsym(binding)) { if (!binding->release && valid_bindsym(binding)) {
return EVENT_HANDLED; list_add(candidates, binding);
} }
break;
} }
case WLC_KEY_STATE_RELEASED: case WLC_KEY_STATE_RELEASED:
if (binding->release && handle_bindsym_release(binding)) { if (binding->release && handle_bindsym_release(binding)) {
list_free(candidates);
return EVENT_HANDLED; return EVENT_HANDLED;
} }
break; 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; return EVENT_PASSTHROUGH;
} }