key-binding: new API, for handling sets of key bindings

Up until now, our Wayland seats have been tracking key bindings. This
makes sense, since the seat’s keymap determines how the key bindings
are resolved.

However, tying bindings to the seat/keymap alone isn’t enough, since
we also depend on the current configuration (i.e. user settings) when
resolving a key binding.

This means configurations that doesn’t match the wayland object’s
configuration, currently don’t resolve key bindings correctly. This
applies to footclients where the user has overridden key bindings on
the command line (e.g. --override key-bindings.foo=bar).

Thus, to correctly resolve key bindings, each set of key bindings must
be tied *both* to a seat/keymap, *and* a configuration.

This patch introduces a key-binding manager, with an API to
add/remove/lookup, and load/unload keymaps from sets of key bindings.

In the API, sets are tied to a seat and terminal instance, since this
makes the most sense (we need to instantiate, or incref a set whenever
a new terminal instance is created). Internally, the set is tied to a
seat and the terminal’s configuration.

Sets are *added* when a new seat is added, and when a new terminal
instance is created. Since there can only be one instance of each
seat, sets are always removed when a seat is removed.

Terminals on the other hand can re-use the same configuration (and
typically do). Thus, sets ref-count the configuration. In other words,
when instantiating a new terminal, we may not have to instantiate a
new set of key bindings, but can often be incref:ed instead.

Whenever the keymap changes on a seat, all key bindings sets
associated with that seat reloads (re-resolves) their key bindings.

Closes #931
This commit is contained in:
Daniel Eklöf 2022-04-17 15:39:51 +02:00
parent e95bc9283e
commit 90a2ca966f
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
15 changed files with 732 additions and 381 deletions

143
key-binding.h Normal file
View file

@ -0,0 +1,143 @@
#pragma once
#include <stdint.h>
#include <xkbcommon/xkbcommon.h>
#include <tllist.h>
#include "config.h"
enum bind_action_normal {
BIND_ACTION_NONE,
BIND_ACTION_NOOP,
BIND_ACTION_SCROLLBACK_UP_PAGE,
BIND_ACTION_SCROLLBACK_UP_HALF_PAGE,
BIND_ACTION_SCROLLBACK_UP_LINE,
BIND_ACTION_SCROLLBACK_DOWN_PAGE,
BIND_ACTION_SCROLLBACK_DOWN_HALF_PAGE,
BIND_ACTION_SCROLLBACK_DOWN_LINE,
BIND_ACTION_SCROLLBACK_HOME,
BIND_ACTION_SCROLLBACK_END,
BIND_ACTION_CLIPBOARD_COPY,
BIND_ACTION_CLIPBOARD_PASTE,
BIND_ACTION_PRIMARY_PASTE,
BIND_ACTION_SEARCH_START,
BIND_ACTION_FONT_SIZE_UP,
BIND_ACTION_FONT_SIZE_DOWN,
BIND_ACTION_FONT_SIZE_RESET,
BIND_ACTION_SPAWN_TERMINAL,
BIND_ACTION_MINIMIZE,
BIND_ACTION_MAXIMIZE,
BIND_ACTION_FULLSCREEN,
BIND_ACTION_PIPE_SCROLLBACK,
BIND_ACTION_PIPE_VIEW,
BIND_ACTION_PIPE_SELECTED,
BIND_ACTION_SHOW_URLS_COPY,
BIND_ACTION_SHOW_URLS_LAUNCH,
BIND_ACTION_SHOW_URLS_PERSISTENT,
BIND_ACTION_TEXT_BINDING,
/* Mouse specific actions - i.e. they require a mouse coordinate */
BIND_ACTION_SELECT_BEGIN,
BIND_ACTION_SELECT_BEGIN_BLOCK,
BIND_ACTION_SELECT_EXTEND,
BIND_ACTION_SELECT_EXTEND_CHAR_WISE,
BIND_ACTION_SELECT_WORD,
BIND_ACTION_SELECT_WORD_WS,
BIND_ACTION_SELECT_ROW,
BIND_ACTION_KEY_COUNT = BIND_ACTION_TEXT_BINDING + 1,
BIND_ACTION_COUNT = BIND_ACTION_SELECT_ROW + 1,
};
enum bind_action_search {
BIND_ACTION_SEARCH_NONE,
BIND_ACTION_SEARCH_CANCEL,
BIND_ACTION_SEARCH_COMMIT,
BIND_ACTION_SEARCH_FIND_PREV,
BIND_ACTION_SEARCH_FIND_NEXT,
BIND_ACTION_SEARCH_EDIT_LEFT,
BIND_ACTION_SEARCH_EDIT_LEFT_WORD,
BIND_ACTION_SEARCH_EDIT_RIGHT,
BIND_ACTION_SEARCH_EDIT_RIGHT_WORD,
BIND_ACTION_SEARCH_EDIT_HOME,
BIND_ACTION_SEARCH_EDIT_END,
BIND_ACTION_SEARCH_DELETE_PREV,
BIND_ACTION_SEARCH_DELETE_PREV_WORD,
BIND_ACTION_SEARCH_DELETE_NEXT,
BIND_ACTION_SEARCH_DELETE_NEXT_WORD,
BIND_ACTION_SEARCH_EXTEND_WORD,
BIND_ACTION_SEARCH_EXTEND_WORD_WS,
BIND_ACTION_SEARCH_CLIPBOARD_PASTE,
BIND_ACTION_SEARCH_PRIMARY_PASTE,
BIND_ACTION_SEARCH_COUNT,
};
enum bind_action_url {
BIND_ACTION_URL_NONE,
BIND_ACTION_URL_CANCEL,
BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL,
BIND_ACTION_URL_COUNT,
};
typedef tll(xkb_keycode_t) xkb_keycode_list_t;
struct key_binding {
enum key_binding_type type;
int action; /* enum bind_action_* */
xkb_mod_mask_t mods;
union {
struct {
xkb_keysym_t sym;
xkb_keycode_list_t key_codes;
} k;
struct {
uint32_t button;
int count;
} m;
};
const struct binding_aux *aux;
};
typedef tll(struct key_binding) key_binding_list_t;
struct terminal;
struct seat;
struct key_binding_set {
key_binding_list_t key;
key_binding_list_t search;
key_binding_list_t url;
key_binding_list_t mouse;
};
struct key_binding_manager;
struct key_binding_manager *key_binding_manager_new(void);
void key_binding_manager_destroy(struct key_binding_manager *mgr);
void key_binding_new_for_seat(
struct key_binding_manager *mgr, const struct seat *seat);
void key_binding_new_for_term(
struct key_binding_manager *mgr, const struct terminal *term);
/* Returns the set of key bindings associated with this seat/term pair */
struct key_binding_set *key_binding_for(
struct key_binding_manager *mgr, const struct terminal *term,
const struct seat *seat);
/* Remove all key bindings tied to the specified seat */
void key_binding_remove_seat(
struct key_binding_manager *mgr, const struct seat *seat);
void key_binding_unref_term(
struct key_binding_manager *mgr, const struct terminal *term);
void key_binding_load_keymap(
struct key_binding_manager *mgr, const struct seat *seat);
void key_binding_unload_keymap(
struct key_binding_manager *mgr, const struct seat *seat);