mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
conf: bindings: allow several mappings for the same action
If the bindings has different pipe command associated with them, treat them as different actions.
This commit is contained in:
parent
062b0eb7ab
commit
1541531765
4 changed files with 166 additions and 87 deletions
203
config.c
203
config.c
|
|
@ -485,21 +485,19 @@ parse_section_csd(const char *key, const char *value, struct config *conf,
|
|||
}
|
||||
|
||||
static bool
|
||||
verify_key_combo(const struct config *conf, const char *combo, const char *path,
|
||||
unsigned lineno)
|
||||
verify_key_combo(const struct config *conf, enum bind_action_normal action,
|
||||
const char *combo, const char *path, unsigned lineno)
|
||||
{
|
||||
for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) {
|
||||
if (conf->bindings.key[action] == NULL)
|
||||
continue;
|
||||
|
||||
char *copy = strdup(conf->bindings.key[action]);
|
||||
tll_foreach(conf->bindings.key, it) {
|
||||
char *copy = strdup(it->item.key);
|
||||
|
||||
for (char *save = NULL, *collision = strtok_r(copy, " ", &save);
|
||||
collision != NULL;
|
||||
collision = strtok_r(NULL, " ", &save))
|
||||
{
|
||||
if (strcmp(combo, collision) == 0) {
|
||||
LOG_ERR("%s:%d: %s already mapped to %s", path, lineno, combo, binding_action_map[action]);
|
||||
LOG_ERR("%s:%d: %s already mapped to %s", path, lineno, combo,
|
||||
binding_action_map[it->item.action]);
|
||||
free(copy);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -530,11 +528,11 @@ parse_section_key_bindings(
|
|||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
{
|
||||
const char *spawn = strchr(key, ':');
|
||||
if (spawn != NULL)
|
||||
spawn++;
|
||||
const char *pipe_cmd = strchr(key, ':');
|
||||
if (pipe_cmd != NULL)
|
||||
pipe_cmd++;
|
||||
|
||||
const size_t key_len = spawn != NULL ? spawn - key - 1: strlen(key);
|
||||
const size_t key_len = pipe_cmd != NULL ? pipe_cmd - key - 1: strlen(key);
|
||||
|
||||
for (enum bind_action_normal action = 0;
|
||||
action < BIND_ACTION_COUNT;
|
||||
|
|
@ -547,19 +545,46 @@ parse_section_key_bindings(
|
|||
continue;
|
||||
|
||||
if (strcasecmp(value, "none") == 0) {
|
||||
free(conf->bindings.key[action]);
|
||||
conf->bindings.key[action] = NULL;
|
||||
tll_foreach(conf->bindings.key, it) {
|
||||
if (it->item.action == action) {
|
||||
free(it->item.key);
|
||||
free(it->item.pipe_cmd);
|
||||
tll_remove(conf->bindings.key, it);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!verify_key_combo(conf, value, path, lineno)) {
|
||||
if (!verify_key_combo(conf, action, value, path, lineno)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
free(conf->bindings.key[action]);
|
||||
free(conf->bindings.spawn[action]);
|
||||
conf->bindings.key[action] = strdup(value);
|
||||
conf->bindings.spawn[action] = spawn != NULL ? strdup(spawn) : NULL;
|
||||
bool already_added = false;
|
||||
tll_foreach(conf->bindings.key, it) {
|
||||
if (it->item.action == action &&
|
||||
((it->item.pipe_cmd == NULL && pipe_cmd == NULL) ||
|
||||
(it->item.pipe_cmd != NULL && pipe_cmd != NULL &&
|
||||
strcmp(it->item.pipe_cmd, pipe_cmd) == 0)))
|
||||
{
|
||||
|
||||
free(it->item.key);
|
||||
free(it->item.pipe_cmd);
|
||||
|
||||
it->item.key = strdup(value);
|
||||
it->item.pipe_cmd = pipe_cmd != NULL ? strdup(pipe_cmd) : NULL;
|
||||
already_added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!already_added) {
|
||||
struct config_key_binding_normal binding = {
|
||||
.action = action,
|
||||
.key = strdup(value),
|
||||
.pipe_cmd = pipe_cmd != NULL ? strdup(pipe_cmd) : NULL,
|
||||
};
|
||||
tll_push_back(conf->bindings.key, binding);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -581,7 +606,12 @@ parse_section_mouse_bindings(
|
|||
continue;
|
||||
|
||||
if (strcmp(value, "NONE") == 0) {
|
||||
conf->bindings.mouse[action] = (struct mouse_binding){0, 0, BIND_ACTION_NONE};
|
||||
tll_foreach(conf->bindings.mouse, it) {
|
||||
if (it->item.action == action) {
|
||||
tll_remove(conf->bindings.mouse, it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -603,16 +633,32 @@ parse_section_mouse_bindings(
|
|||
const int count = 1;
|
||||
|
||||
/* Make sure button isn't already mapped to another action */
|
||||
for (enum bind_action_normal j = 0; j < BIND_ACTION_COUNT; j++) {
|
||||
const struct mouse_binding *collision = &conf->bindings.mouse[j];
|
||||
if (collision->button == i && collision->count == count) {
|
||||
tll_foreach(conf->bindings.mouse, it) {
|
||||
if (it->item.button == i && it->item.count == count) {
|
||||
LOG_ERR("%s:%d: %s already mapped to %s", path, lineno,
|
||||
value, binding_action_map[collision->action]);
|
||||
value, binding_action_map[it->item.action]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
conf->bindings.mouse[action] = (struct mouse_binding){i, count, action};
|
||||
bool already_added = false;
|
||||
tll_foreach(conf->bindings.mouse, it) {
|
||||
if (it->item.action == action) {
|
||||
it->item.button = i;
|
||||
it->item.count = count;
|
||||
already_added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!already_added) {
|
||||
struct mouse_binding binding = {
|
||||
.action = action,
|
||||
.button = i,
|
||||
.count = count,
|
||||
};
|
||||
tll_push_back(conf->bindings.mouse, binding);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -896,42 +942,6 @@ config_load(struct config *conf, const char *conf_path)
|
|||
.cursor = 0,
|
||||
},
|
||||
},
|
||||
|
||||
.bindings = {
|
||||
.key = {
|
||||
[BIND_ACTION_SCROLLBACK_UP] = strdup("Shift+Page_Up"),
|
||||
[BIND_ACTION_SCROLLBACK_DOWN] = strdup("Shift+Page_Down"),
|
||||
[BIND_ACTION_CLIPBOARD_COPY] = strdup("Control+Shift+C"),
|
||||
[BIND_ACTION_CLIPBOARD_PASTE] = strdup("Control+Shift+V"),
|
||||
[BIND_ACTION_SEARCH_START] = strdup("Control+Shift+R"),
|
||||
[BIND_ACTION_FONT_SIZE_UP] = strdup("Control+plus Control+equal Control+KP_Add"),
|
||||
[BIND_ACTION_FONT_SIZE_DOWN] = strdup("Control+minus Control+KP_Subtract"),
|
||||
[BIND_ACTION_FONT_SIZE_RESET] = strdup("Control+0 Control+KP_0"),
|
||||
[BIND_ACTION_SPAWN_TERMINAL] = strdup("Control+Shift+N"),
|
||||
},
|
||||
.mouse = {
|
||||
[BIND_ACTION_PRIMARY_PASTE] = {BTN_MIDDLE, 1, BIND_ACTION_PRIMARY_PASTE},
|
||||
},
|
||||
.search = {
|
||||
[BIND_ACTION_SEARCH_CANCEL] = strdup("Control+g Escape"),
|
||||
[BIND_ACTION_SEARCH_COMMIT] = strdup("Return"),
|
||||
[BIND_ACTION_SEARCH_FIND_PREV] = strdup("Control+r"),
|
||||
[BIND_ACTION_SEARCH_FIND_NEXT] = strdup("Control+s"),
|
||||
[BIND_ACTION_SEARCH_EDIT_LEFT] = strdup("Left Control+b"),
|
||||
[BIND_ACTION_SEARCH_EDIT_LEFT_WORD] = strdup("Control+Left Mod1+b"),
|
||||
[BIND_ACTION_SEARCH_EDIT_RIGHT] = strdup("Right Control+f"),
|
||||
[BIND_ACTION_SEARCH_EDIT_RIGHT_WORD] = strdup("Control+Right Mod1+f"),
|
||||
[BIND_ACTION_SEARCH_EDIT_HOME] = strdup("Home Control+a"),
|
||||
[BIND_ACTION_SEARCH_EDIT_END] = strdup("End Control+e"),
|
||||
[BIND_ACTION_SEARCH_DELETE_PREV] = strdup("BackSpace"),
|
||||
[BIND_ACTION_SEARCH_DELETE_PREV_WORD] = strdup("Mod1+BackSpace Control+BackSpace"),
|
||||
[BIND_ACTION_SEARCH_DELETE_NEXT] = strdup("Delete "),
|
||||
[BIND_ACTION_SEARCH_DELETE_NEXT_WORD] = strdup("Mod1+d Control+Delete"),
|
||||
[BIND_ACTION_SEARCH_EXTEND_WORD] = strdup("Control+w"),
|
||||
[BIND_ACTION_SEARCH_EXTEND_WORD_WS] = strdup("Control+Shift+W"),
|
||||
},
|
||||
},
|
||||
|
||||
.csd = {
|
||||
.preferred = CONF_CSD_PREFER_SERVER,
|
||||
.title_height = 26,
|
||||
|
|
@ -951,6 +961,63 @@ config_load(struct config *conf, const char *conf_path)
|
|||
},
|
||||
};
|
||||
|
||||
struct config_key_binding_normal scrollback_up = {BIND_ACTION_SCROLLBACK_UP, strdup("Shift+Page_Up")};
|
||||
struct config_key_binding_normal scrollback_down = {BIND_ACTION_SCROLLBACK_DOWN, strdup("Shift+Page_Down")};
|
||||
struct config_key_binding_normal clipboard_copy = {BIND_ACTION_CLIPBOARD_COPY, strdup("Control+Shift+C")};
|
||||
struct config_key_binding_normal clipboard_paste = {BIND_ACTION_CLIPBOARD_PASTE, strdup("Control+Shift+V")};
|
||||
struct config_key_binding_normal search_start = {BIND_ACTION_SEARCH_START, strdup("Control+Shift+R")};
|
||||
struct config_key_binding_normal font_size_up = {BIND_ACTION_FONT_SIZE_UP, strdup("Control+plus Control+equal Control+KP_Add")};
|
||||
struct config_key_binding_normal font_size_down = {BIND_ACTION_FONT_SIZE_DOWN, strdup("Control+minus Control+KP_Subtract")};
|
||||
struct config_key_binding_normal font_size_reset = {BIND_ACTION_FONT_SIZE_RESET, strdup("Control+0 Control+KP_0")};
|
||||
struct config_key_binding_normal spawn_terminal = {BIND_ACTION_SPAWN_TERMINAL, strdup("Control+Shift+N")};
|
||||
|
||||
tll_push_back(conf->bindings.key, scrollback_up);
|
||||
tll_push_back(conf->bindings.key, scrollback_down);
|
||||
tll_push_back(conf->bindings.key, clipboard_copy);
|
||||
tll_push_back(conf->bindings.key, clipboard_paste);
|
||||
tll_push_back(conf->bindings.key, search_start);
|
||||
tll_push_back(conf->bindings.key, font_size_up);
|
||||
tll_push_back(conf->bindings.key, font_size_down);
|
||||
tll_push_back(conf->bindings.key, font_size_reset);
|
||||
tll_push_back(conf->bindings.key, spawn_terminal);
|
||||
|
||||
struct mouse_binding primary_paste = {BIND_ACTION_PRIMARY_PASTE, BTN_MIDDLE, 1};
|
||||
tll_push_back(conf->bindings.mouse, primary_paste);
|
||||
|
||||
struct config_key_binding_search search_cancel = {BIND_ACTION_SEARCH_CANCEL, strdup("Control+g Escape")};
|
||||
struct config_key_binding_search search_commit = {BIND_ACTION_SEARCH_COMMIT, strdup("Return")};
|
||||
struct config_key_binding_search search_find_prev = {BIND_ACTION_SEARCH_FIND_PREV, strdup("Control+r")};
|
||||
struct config_key_binding_search search_find_next = {BIND_ACTION_SEARCH_FIND_NEXT, strdup("Control+s")};
|
||||
struct config_key_binding_search search_edit_left = {BIND_ACTION_SEARCH_EDIT_LEFT, strdup("Left Control+b")};
|
||||
struct config_key_binding_search search_edit_left_word = {BIND_ACTION_SEARCH_EDIT_LEFT_WORD, strdup("Control+Left Mod1+b")};
|
||||
struct config_key_binding_search search_edit_right = {BIND_ACTION_SEARCH_EDIT_RIGHT, strdup("Right Control+f")};
|
||||
struct config_key_binding_search search_edit_right_word = {BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, strdup("Control+Right Mod1+f")};
|
||||
struct config_key_binding_search search_edit_home = {BIND_ACTION_SEARCH_EDIT_HOME, strdup("Home Control+a")};
|
||||
struct config_key_binding_search search_edit_end = {BIND_ACTION_SEARCH_EDIT_END, strdup("End Control+e")};
|
||||
struct config_key_binding_search search_del_prev = {BIND_ACTION_SEARCH_DELETE_PREV, strdup("BackSpace")};
|
||||
struct config_key_binding_search search_del_prev_word = {BIND_ACTION_SEARCH_DELETE_PREV_WORD, strdup("Mod1+BackSpace Control+BackSpace")};
|
||||
struct config_key_binding_search search_del_next = {BIND_ACTION_SEARCH_DELETE_NEXT, strdup("Delete")};
|
||||
struct config_key_binding_search search_del_next_word = {BIND_ACTION_SEARCH_DELETE_NEXT_WORD, strdup("Mod1+d Control+Delete")};
|
||||
struct config_key_binding_search search_ext_word = {BIND_ACTION_SEARCH_EXTEND_WORD, strdup("Control+w")};
|
||||
struct config_key_binding_search search_ext_word_ws = {BIND_ACTION_SEARCH_EXTEND_WORD_WS, strdup("Control+Shift+W")};
|
||||
|
||||
tll_push_back(conf->bindings.search, search_cancel);
|
||||
tll_push_back(conf->bindings.search, search_commit);
|
||||
tll_push_back(conf->bindings.search, search_find_prev);
|
||||
tll_push_back(conf->bindings.search, search_find_next);
|
||||
tll_push_back(conf->bindings.search, search_edit_left);
|
||||
tll_push_back(conf->bindings.search, search_edit_left_word);
|
||||
tll_push_back(conf->bindings.search, search_edit_right);
|
||||
tll_push_back(conf->bindings.search, search_edit_right_word);
|
||||
tll_push_back(conf->bindings.search, search_edit_home);
|
||||
tll_push_back(conf->bindings.search, search_edit_end);
|
||||
tll_push_back(conf->bindings.search, search_del_prev);
|
||||
tll_push_back(conf->bindings.search, search_del_prev_word);
|
||||
tll_push_back(conf->bindings.search, search_del_next);
|
||||
tll_push_back(conf->bindings.search, search_del_next_word);
|
||||
tll_push_back(conf->bindings.search, search_ext_word);
|
||||
tll_push_back(conf->bindings.search, search_ext_word_ws);
|
||||
|
||||
char *default_path = NULL;
|
||||
if (conf_path == NULL) {
|
||||
if ((default_path = get_config_path()) == NULL) {
|
||||
|
|
@ -995,12 +1062,16 @@ config_free(struct config conf)
|
|||
tll_free(conf.fonts);
|
||||
free(conf.server_socket_path);
|
||||
|
||||
for (enum bind_action_normal i = 0; i < BIND_ACTION_COUNT; i++) {
|
||||
free(conf.bindings.key[i]);
|
||||
free(conf.bindings.spawn[i]);
|
||||
tll_foreach(conf.bindings.key, it) {
|
||||
free(it->item.key);
|
||||
free(it->item.pipe_cmd);
|
||||
}
|
||||
for (enum bind_action_search i = 0; i < BIND_ACTION_SEARCH_COUNT; i++)
|
||||
free(conf.bindings.search[i]);
|
||||
tll_foreach(conf.bindings.search, it)
|
||||
free(it->item.key);
|
||||
|
||||
tll_free(conf.bindings.key);
|
||||
tll_free(conf.bindings.mouse);
|
||||
tll_free(conf.bindings.search);
|
||||
}
|
||||
|
||||
struct config_font
|
||||
|
|
|
|||
20
config.h
20
config.h
|
|
@ -6,6 +6,7 @@
|
|||
#include <tllist.h>
|
||||
|
||||
#include "terminal.h"
|
||||
#include "wayland.h"
|
||||
|
||||
struct config_font {
|
||||
char *pattern;
|
||||
|
|
@ -13,6 +14,17 @@ struct config_font {
|
|||
int px_size;
|
||||
};
|
||||
|
||||
struct config_key_binding_normal {
|
||||
enum bind_action_normal action;
|
||||
char *key;
|
||||
char *pipe_cmd;
|
||||
};
|
||||
|
||||
struct config_key_binding_search {
|
||||
enum bind_action_search action;
|
||||
char *key;
|
||||
};
|
||||
|
||||
struct config {
|
||||
char *term;
|
||||
char *shell;
|
||||
|
|
@ -48,10 +60,8 @@ struct config {
|
|||
|
||||
struct {
|
||||
/* Bindings for "normal" mode */
|
||||
char *key[BIND_ACTION_COUNT];
|
||||
char *spawn[BIND_ACTION_COUNT];
|
||||
|
||||
struct mouse_binding mouse[BIND_ACTION_COUNT];
|
||||
tll(struct config_key_binding_normal) key;
|
||||
tll(struct mouse_binding) mouse;
|
||||
|
||||
/*
|
||||
* Special modes
|
||||
|
|
@ -59,7 +69,7 @@ struct config {
|
|||
|
||||
/* While searching (not - action to *start* a search is in the
|
||||
* 'key' bindings above */
|
||||
char *search[BIND_ACTION_SEARCH_COUNT];
|
||||
tll(struct config_key_binding_search) search;
|
||||
} bindings;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
28
input.c
28
input.c
|
|
@ -398,34 +398,33 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
|||
munmap(map_str, size);
|
||||
close(fd);
|
||||
|
||||
for (enum bind_action_normal i = 0; i < BIND_ACTION_COUNT; i++) {
|
||||
tll_foreach(wayl->conf->bindings.key, it) {
|
||||
key_binding_list_t bindings = tll_init();
|
||||
input_parse_key_binding(
|
||||
seat->kbd.xkb_keymap, wayl->conf->bindings.key[i], &bindings);
|
||||
seat->kbd.xkb_keymap, it->item.key, &bindings);
|
||||
|
||||
tll_foreach(bindings, it) {
|
||||
tll_foreach(bindings, it2) {
|
||||
tll_push_back(
|
||||
seat->kbd.bindings.key,
|
||||
((struct key_binding_normal){
|
||||
.bind = it->item,
|
||||
.action = i,
|
||||
.pipe_cmd = wayl->conf->bindings.spawn[i]}));
|
||||
.bind = it2->item,
|
||||
.action = it->item.action,
|
||||
.pipe_cmd = it->item.pipe_cmd}));
|
||||
}
|
||||
|
||||
tll_free(bindings);
|
||||
}
|
||||
|
||||
for (enum bind_action_search i = 0; i < BIND_ACTION_SEARCH_COUNT; i++) {
|
||||
tll_foreach(wayl->conf->bindings.search, it) {
|
||||
key_binding_list_t bindings = tll_init();
|
||||
input_parse_key_binding(
|
||||
seat->kbd.xkb_keymap, wayl->conf->bindings.search[i], &bindings);
|
||||
seat->kbd.xkb_keymap, it->item.key, &bindings);
|
||||
|
||||
tll_foreach(bindings, it) {
|
||||
tll_foreach(bindings, it2) {
|
||||
tll_push_back(
|
||||
seat->kbd.bindings.search,
|
||||
((struct key_binding_search){.bind = it->item, .action = i}));
|
||||
((struct key_binding_search){
|
||||
.bind = it2->item, .action = it->item.action}));
|
||||
}
|
||||
|
||||
tll_free(bindings);
|
||||
}
|
||||
}
|
||||
|
|
@ -1370,9 +1369,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
}
|
||||
|
||||
else {
|
||||
for (size_t i = 0; i < ALEN(wayl->conf->bindings.mouse); i++) {
|
||||
const struct mouse_binding *binding =
|
||||
&wayl->conf->bindings.mouse[i];
|
||||
tll_foreach(wayl->conf->bindings.mouse, it) {
|
||||
const struct mouse_binding *binding = &it->item;
|
||||
|
||||
if (binding->button != button) {
|
||||
/* Wrong button */
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ struct key_binding_normal {
|
|||
};
|
||||
|
||||
struct mouse_binding {
|
||||
enum bind_action_normal action;
|
||||
uint32_t button;
|
||||
int count;
|
||||
enum bind_action_normal action;
|
||||
};
|
||||
|
||||
enum bind_action_search {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue