From c58f9a9ef93fd3fd2be711906b8214a53665e45f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 12 Mar 2020 10:46:27 +0100 Subject: [PATCH] config: mouse-bindings: verify button isn't already mapped A button may only be mapped to a single action. Detect when the user tried to map the same button to multiple actions and error out. To clear a binding (for example, to free up a button from the default bindings), one can set the action it is bound to to `NONE` (e.g. `primary-paste=NONE`). --- config.c | 26 +++++++++++++++++++++++++- doc/foot.5.scd | 14 ++++++++++---- input.c | 4 ++++ wayland.h | 1 + 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/config.c b/config.c index 7e1f8939..ba216348 100644 --- a/config.c +++ b/config.c @@ -49,6 +49,7 @@ static const uint32_t default_bright[] = { }; static const char *binding_action_map[] = { + [BIND_ACTION_NONE] = NULL, [BIND_ACTION_SCROLLBACK_UP] = "scrollback-up", [BIND_ACTION_SCROLLBACK_DOWN] = "scrollback-down", [BIND_ACTION_CLIPBOARD_COPY] = "clipboard-copy", @@ -454,6 +455,9 @@ parse_section_key_bindings( const char *path, unsigned lineno) { for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) { + if (binding_action_map[action] == NULL) + continue; + if (strcmp(key, binding_action_map[action]) != 0) continue; @@ -488,9 +492,17 @@ parse_section_mouse_bindings( const char *path, unsigned lineno) { for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) { + if (binding_action_map[action] == NULL) + continue; + if (strcmp(key, binding_action_map[action]) != 0) continue; + if (strcmp(value, "NONE") == 0) { + conf->bindings.mouse[action] = (struct mouse_binding){0, 0, BIND_ACTION_NONE}; + return true; + } + const char *map[] = { [BTN_LEFT] = "BTN_LEFT", [BTN_RIGHT] = "BTN_RIGHT", @@ -506,7 +518,19 @@ parse_section_mouse_bindings( if (map[i] == NULL || strcmp(map[i], value) != 0) continue; - conf->bindings.mouse[action] = (struct mouse_binding){i, 1, action}; + const int count = 1; + + /* Make sure button isn't already mapped to another action */ + for (enum binding_action j = 0; j < BIND_ACTION_COUNT; j++) { + const struct mouse_binding *collision = &conf->bindings.mouse[j]; + if (collision->button == i && collision->count == count) { + LOG_ERR("%s:%d: %s already mapped to %s", path, lineno, + value, binding_action_map[collision->action]); + return false; + } + } + + conf->bindings.mouse[action] = (struct mouse_binding){i, count, action}; return true; } diff --git a/doc/foot.5.scd b/doc/foot.5.scd index dbbcc52d..457d053b 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -151,15 +151,15 @@ component. This section lets you override the default key bindings. -The general format is *action*=*combo1*...*comboN*. That is, each +The general format is _action_=_combo1_..._comboN_. That is, each action may have one or more key combinations, space separated. Each -combination is on the form *mod1*+*mod2*+*key*. The names of the +combination is on the form _mod1_+_mod2_+_key_. The names of the modifiers and the key *must* be a valid XKB key name. Note that if *Shift* is one of the modifiers, the _key_ *must* be in upper case. -Note that _Alt_ is usually called *Mod1*. +Note that *Alt* is usually called *Mod1*. *scrollback-up* Scrolls up/back in history. Default: _Shift+Page_Up_. @@ -207,10 +207,16 @@ Note that _Alt_ is usually called *Mod1*. This section lets you override the default mouse bindings. -The general format is *action*=*BTN\_*, where *BTN\_* is +The general format is _action_=_BTN\__, where _BTN\__ is the name of the event code (e.g. *BTN\_LEFT*, *BTN\_RIGHT*). You can find the event names using *libinput debug-events*. +A button can only be mapped to *one* action. Lets say you want to bind +*BTN\_MIDDLE* to *fullscreen*. Since *BTN\_MIDDLE* is the default +binding for *primary-paste*, you first need to unmap the default +binding. This can be done by setting _action_=*NONE*; +e.g. *primary-paste*=*NONE*. + *primary-paste* Pastes from the _primary selection_. Default: _BTN_MIDDLE_. diff --git a/input.c b/input.c index 8fbb02cd..1c80dd8b 100644 --- a/input.c +++ b/input.c @@ -38,6 +38,9 @@ input_execute_binding(struct terminal *term, enum binding_action action, uint32_t serial) { switch (action) { + case BIND_ACTION_NONE: + break; + case BIND_ACTION_SCROLLBACK_UP: cmd_scrollback_up(term, term->rows); break; @@ -1168,6 +1171,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } input_execute_binding(term, binding->action, serial); + break; } selection_cancel(term); } diff --git a/wayland.h b/wayland.h index 2ddfdf87..b8b91c00 100644 --- a/wayland.h +++ b/wayland.h @@ -42,6 +42,7 @@ struct monitor { }; enum binding_action { + BIND_ACTION_NONE, BIND_ACTION_SCROLLBACK_UP, BIND_ACTION_SCROLLBACK_DOWN, BIND_ACTION_CLIPBOARD_COPY,