mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-25 09:05:47 -04:00
config: load custom key bindings
This adds parsing of a new section - "key-bindings" - where the user can configure the key bindings on the form "action=combo1 .. comboN" The validity of the key combinations are checked with the default XKB keymap.
This commit is contained in:
parent
0c72128405
commit
048edc58f1
1 changed files with 74 additions and 22 deletions
96
config.c
96
config.c
|
|
@ -12,9 +12,15 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
#define LOG_MODULE "config"
|
#define LOG_MODULE "config"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "wayland.h"
|
||||||
|
|
||||||
|
#define ALEN(v) (sizeof(v) / sizeof(v[0]))
|
||||||
|
|
||||||
static const uint32_t default_foreground = 0xdcdccc;
|
static const uint32_t default_foreground = 0xdcdccc;
|
||||||
static const uint32_t default_background = 0x111111;
|
static const uint32_t default_background = 0x111111;
|
||||||
|
|
@ -41,6 +47,19 @@ static const uint32_t default_bright[] = {
|
||||||
0xffffff,
|
0xffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *binding_action_map[] = {
|
||||||
|
[BIND_ACTION_SCROLLBACK_UP] = "scrollback-up",
|
||||||
|
[BIND_ACTION_SCROLLBACK_DOWN] = "scrollback-down",
|
||||||
|
[BIND_ACTION_CLIPBOARD_COPY] = "clipboard-copy",
|
||||||
|
[BIND_ACTION_CLIPBOARD_PASTE] = "clipboard-paste",
|
||||||
|
[BIND_ACTION_PRIMARY_PASTE] = "primary-paste",
|
||||||
|
[BIND_ACTION_SEARCH_START] = "search-start",
|
||||||
|
[BIND_ACTION_FONT_SIZE_UP] = "font-increase",
|
||||||
|
[BIND_ACTION_FONT_SIZE_DOWN] = "font-decrease",
|
||||||
|
[BIND_ACTION_FONT_SIZE_RESET] = "font-reset",
|
||||||
|
[BIND_ACTION_SPAWN_TERMINAL] = "spawn-terminal",
|
||||||
|
};
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
get_shell(void)
|
get_shell(void)
|
||||||
{
|
{
|
||||||
|
|
@ -422,6 +441,39 @@ parse_section_csd(const char *key, const char *value, struct config *conf,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_section_key_bindings(const char *key, const char *value, struct config *conf,
|
||||||
|
const char *path, unsigned lineno)
|
||||||
|
{
|
||||||
|
for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) {
|
||||||
|
if (strcmp(key, binding_action_map[action]) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
struct xkb_keymap *keymap = xkb_keymap_new_from_names(
|
||||||
|
ctx, &(struct xkb_rule_names){0}, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
bool valid_combo = input_parse_key_binding_for_action(keymap, action, value, NULL);
|
||||||
|
|
||||||
|
xkb_keymap_unref(keymap);
|
||||||
|
xkb_context_unref(ctx);
|
||||||
|
|
||||||
|
if (!valid_combo) {
|
||||||
|
LOG_ERR("%s:%d: invalid key combination: %s", path, lineno, value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(conf->bindings.key[action]);
|
||||||
|
conf->bindings.key[action] = strdup(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOG_WARN("%s:%u: invalid key: %s", path, lineno, key);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
parse_config_file(FILE *f, struct config *conf, const char *path)
|
parse_config_file(FILE *f, struct config *conf, const char *path)
|
||||||
{
|
{
|
||||||
|
|
@ -430,6 +482,8 @@ parse_config_file(FILE *f, struct config *conf, const char *path)
|
||||||
SECTION_COLORS,
|
SECTION_COLORS,
|
||||||
SECTION_CURSOR,
|
SECTION_CURSOR,
|
||||||
SECTION_CSD,
|
SECTION_CSD,
|
||||||
|
SECTION_KEY_BINDINGS,
|
||||||
|
SECTION_COUNT,
|
||||||
} section = SECTION_MAIN;
|
} section = SECTION_MAIN;
|
||||||
|
|
||||||
/* Function pointer, called for each key/value line */
|
/* Function pointer, called for each key/value line */
|
||||||
|
|
@ -437,22 +491,18 @@ parse_config_file(FILE *f, struct config *conf, const char *path)
|
||||||
const char *key, const char *value, struct config *conf,
|
const char *key, const char *value, struct config *conf,
|
||||||
const char *path, unsigned lineno);
|
const char *path, unsigned lineno);
|
||||||
|
|
||||||
/* Maps sections to line parser functions */
|
static const struct {
|
||||||
static const parser_fun_t section_parser_map[] = {
|
parser_fun_t fun;
|
||||||
[SECTION_MAIN] = &parse_section_main,
|
const char *name;
|
||||||
[SECTION_COLORS] = &parse_section_colors,
|
} section_info[] = {
|
||||||
[SECTION_CURSOR] = &parse_section_cursor,
|
[SECTION_MAIN] = {&parse_section_main, "main"},
|
||||||
[SECTION_CSD] = &parse_section_csd,
|
[SECTION_COLORS] = {&parse_section_colors, "colors"},
|
||||||
|
[SECTION_CURSOR] = {&parse_section_cursor, "cursor"},
|
||||||
|
[SECTION_CSD] = {&parse_section_csd, "csd"},
|
||||||
|
[SECTION_KEY_BINDINGS] = {&parse_section_key_bindings, "key-bindings"},
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(_DEBUG) && defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
|
static_assert(ALEN(section_info) == SECTION_COUNT, "section info array size mismatch");
|
||||||
static const char *const section_names[] = {
|
|
||||||
[SECTION_MAIN] = "main",
|
|
||||||
[SECTION_COLORS] = "colors",
|
|
||||||
[SECTION_CURSOR] = "cursor",
|
|
||||||
[SECTION_CSD] = "csd",
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned lineno = 0;
|
unsigned lineno = 0;
|
||||||
|
|
||||||
|
|
@ -500,17 +550,19 @@ parse_config_file(FILE *f, struct config *conf, const char *path)
|
||||||
|
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
|
|
||||||
if (strcmp(&line[1], "colors") == 0)
|
section = SECTION_COUNT;
|
||||||
section = SECTION_COLORS;
|
for (enum section i = 0; i < SECTION_COUNT; i++) {
|
||||||
else if (strcmp(&line[1], "cursor") == 0)
|
if (strcmp(&line[1], section_info[i].name) == 0) {
|
||||||
section = SECTION_CURSOR;
|
section = i;
|
||||||
else if (strcmp(&line[1], "csd") == 0)
|
}
|
||||||
section = SECTION_CSD;
|
}
|
||||||
else {
|
|
||||||
|
if (section == SECTION_COUNT) {
|
||||||
LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &line[1]);
|
LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &line[1]);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Process next line */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -549,7 +601,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path)
|
||||||
LOG_DBG("section=%s, key='%s', value='%s'",
|
LOG_DBG("section=%s, key='%s', value='%s'",
|
||||||
section_names[section], key, value);
|
section_names[section], key, value);
|
||||||
|
|
||||||
parser_fun_t section_parser = section_parser_map[section];
|
parser_fun_t section_parser = section_info[section].fun;
|
||||||
assert(section_parser != NULL);
|
assert(section_parser != NULL);
|
||||||
|
|
||||||
if (!section_parser(key, value, conf, path, lineno))
|
if (!section_parser(key, value, conf, path, lineno))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue