2019-07-16 11:52:22 +02:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdbool.h>
|
2019-07-17 10:12:14 +02:00
|
|
|
#include <ctype.h>
|
2019-07-16 11:52:22 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <pwd.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
2020-03-12 10:20:05 +01:00
|
|
|
#include <linux/input-event-codes.h>
|
2020-03-09 20:03:04 +01:00
|
|
|
#include <xkbcommon/xkbcommon.h>
|
2020-07-07 10:44:55 +02:00
|
|
|
#include <fontconfig/fontconfig.h>
|
2020-03-09 20:03:04 +01:00
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
#define LOG_MODULE "config"
|
|
|
|
|
#define LOG_ENABLE_DBG 0
|
|
|
|
|
#include "log.h"
|
2020-03-09 20:03:04 +01:00
|
|
|
#include "input.h"
|
2020-08-07 20:42:34 +01:00
|
|
|
#include "macros.h"
|
2020-07-30 18:53:51 +02:00
|
|
|
#include "tokenize.h"
|
2020-05-01 11:46:24 +02:00
|
|
|
#include "util.h"
|
2020-03-09 20:03:04 +01:00
|
|
|
#include "wayland.h"
|
2020-08-04 23:28:16 +01:00
|
|
|
#include "xmalloc.h"
|
2020-03-09 20:03:04 +01:00
|
|
|
|
2019-07-21 11:06:28 +02:00
|
|
|
static const uint32_t default_foreground = 0xdcdccc;
|
|
|
|
|
static const uint32_t default_background = 0x111111;
|
|
|
|
|
|
|
|
|
|
static const uint32_t default_regular[] = {
|
2019-09-21 12:01:29 +02:00
|
|
|
0x222222,
|
2019-07-21 11:06:28 +02:00
|
|
|
0xcc9393,
|
|
|
|
|
0x7f9f7f,
|
|
|
|
|
0xd0bf8f,
|
|
|
|
|
0x6ca0a3,
|
|
|
|
|
0xdc8cc3,
|
|
|
|
|
0x93e0e3,
|
|
|
|
|
0xdcdccc,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const uint32_t default_bright[] = {
|
2019-08-23 19:42:14 +02:00
|
|
|
0x666666,
|
2019-07-21 11:06:28 +02:00
|
|
|
0xdca3a3,
|
|
|
|
|
0xbfebbf,
|
|
|
|
|
0xf0dfaf,
|
|
|
|
|
0x8cd0d3,
|
2019-09-21 12:09:50 +02:00
|
|
|
0xfcace3,
|
|
|
|
|
0xb3ffff,
|
2019-07-21 11:06:28 +02:00
|
|
|
0xffffff,
|
|
|
|
|
};
|
|
|
|
|
|
2020-07-29 17:27:01 +02:00
|
|
|
static const char *const binding_action_map[] = {
|
2020-03-12 10:46:27 +01:00
|
|
|
[BIND_ACTION_NONE] = NULL,
|
2020-03-09 20:03:04 +01:00
|
|
|
[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",
|
2020-03-12 09:34:09 +01:00
|
|
|
[BIND_ACTION_MINIMIZE] = "minimize",
|
|
|
|
|
[BIND_ACTION_MAXIMIZE] = "maximize",
|
|
|
|
|
[BIND_ACTION_FULLSCREEN] = "fullscreen",
|
2020-07-15 09:46:13 +02:00
|
|
|
[BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback",
|
|
|
|
|
[BIND_ACTION_PIPE_VIEW] = "pipe-visible",
|
2020-07-31 17:02:53 +02:00
|
|
|
[BIND_ACTION_PIPE_SELECTED] = "pipe-selected",
|
2020-08-11 09:55:33 +02:00
|
|
|
|
|
|
|
|
/* Mouse-specific actions */
|
|
|
|
|
[BIND_ACTION_SELECT_BEGIN] = "select-begin",
|
2020-08-11 10:17:19 +02:00
|
|
|
[BIND_ACTION_SELECT_BEGIN_BLOCK] = "select-begin-block",
|
|
|
|
|
[BIND_ACTION_SELECT_EXTEND] = "select-extend",
|
2020-08-11 09:55:33 +02:00
|
|
|
[BIND_ACTION_SELECT_WORD] = "select-word",
|
|
|
|
|
[BIND_ACTION_SELECT_WORD_WS] = "select-word-whitespace",
|
2020-08-11 10:17:19 +02:00
|
|
|
[BIND_ACTION_SELECT_ROW] = "select-row",
|
2020-03-09 20:03:04 +01:00
|
|
|
};
|
|
|
|
|
|
2020-03-12 09:34:09 +01:00
|
|
|
static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT,
|
|
|
|
|
"binding action map size mismatch");
|
|
|
|
|
|
2020-07-29 17:27:01 +02:00
|
|
|
static const char *const search_binding_action_map[] = {
|
|
|
|
|
[BIND_ACTION_SEARCH_NONE] = NULL,
|
|
|
|
|
[BIND_ACTION_SEARCH_CANCEL] = "cancel",
|
|
|
|
|
[BIND_ACTION_SEARCH_COMMIT] = "commit",
|
|
|
|
|
[BIND_ACTION_SEARCH_FIND_PREV] = "find-prev",
|
|
|
|
|
[BIND_ACTION_SEARCH_FIND_NEXT] = "find-next",
|
|
|
|
|
[BIND_ACTION_SEARCH_EDIT_LEFT] = "cursor-left",
|
|
|
|
|
[BIND_ACTION_SEARCH_EDIT_LEFT_WORD] = "cursor-left-word",
|
|
|
|
|
[BIND_ACTION_SEARCH_EDIT_RIGHT] = "cursor-right",
|
|
|
|
|
[BIND_ACTION_SEARCH_EDIT_RIGHT_WORD] = "cursor-right-word",
|
|
|
|
|
[BIND_ACTION_SEARCH_EDIT_HOME] = "cursor-home",
|
|
|
|
|
[BIND_ACTION_SEARCH_EDIT_END] = "cursor-end",
|
|
|
|
|
[BIND_ACTION_SEARCH_DELETE_PREV] = "delete-prev",
|
|
|
|
|
[BIND_ACTION_SEARCH_DELETE_PREV_WORD] = "delete-prev-word",
|
|
|
|
|
[BIND_ACTION_SEARCH_DELETE_NEXT] = "delete-next",
|
|
|
|
|
[BIND_ACTION_SEARCH_DELETE_NEXT_WORD] = "delete-next-word",
|
|
|
|
|
[BIND_ACTION_SEARCH_EXTEND_WORD] = "extend-to-word-boundary",
|
|
|
|
|
[BIND_ACTION_SEARCH_EXTEND_WORD_WS] = "extend-to-next-whitespace",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static_assert(ALEN(search_binding_action_map) == BIND_ACTION_SEARCH_COUNT,
|
|
|
|
|
"search binding action map size mismatch");
|
|
|
|
|
|
2020-08-10 19:38:53 +02:00
|
|
|
#define LOG_AND_NOTIFY_ERR(fmt, ...) \
|
|
|
|
|
do { \
|
|
|
|
|
LOG_ERR(fmt, ## __VA_ARGS__); \
|
|
|
|
|
char *text = xasprintf(fmt, ## __VA_ARGS__); \
|
|
|
|
|
struct user_notification notif = { \
|
|
|
|
|
.kind = USER_NOTIFICATION_ERROR, \
|
|
|
|
|
.text = text, \
|
|
|
|
|
}; \
|
|
|
|
|
tll_push_back(conf->notifications, notif); \
|
|
|
|
|
} while (0)
|
2020-07-31 17:07:14 +02:00
|
|
|
|
|
|
|
|
#define LOG_AND_NOTIFY_WARN(fmt, ...) \
|
2020-08-10 19:38:53 +02:00
|
|
|
do { \
|
|
|
|
|
LOG_WARN(fmt, ## __VA_ARGS__); \
|
2020-08-04 23:28:16 +01:00
|
|
|
char *text = xasprintf(fmt, ## __VA_ARGS__); \
|
2020-07-31 17:07:14 +02:00
|
|
|
struct user_notification notif = { \
|
|
|
|
|
.kind = USER_NOTIFICATION_WARNING, \
|
|
|
|
|
.text = text, \
|
|
|
|
|
}; \
|
|
|
|
|
tll_push_back(conf->notifications, notif); \
|
2020-08-10 19:38:53 +02:00
|
|
|
} while (0)
|
2020-07-31 17:07:14 +02:00
|
|
|
|
|
|
|
|
#define LOG_AND_NOTIFY_ERRNO(fmt, ...) \
|
2020-08-10 19:38:53 +02:00
|
|
|
do { \
|
2020-07-31 17:07:14 +02:00
|
|
|
int _errno = errno; \
|
|
|
|
|
LOG_ERRNO(fmt, ## __VA_ARGS__); \
|
2020-08-10 19:38:53 +02:00
|
|
|
int len = snprintf(NULL, 0, fmt, ## __VA_ARGS__); \
|
|
|
|
|
int errno_len = snprintf(NULL, 0, ": %s", strerror(_errno)); \
|
|
|
|
|
char *text = xmalloc(len + errno_len + 1); \
|
|
|
|
|
snprintf(text, len + errno_len + 1, fmt, ## __VA_ARGS__); \
|
|
|
|
|
snprintf(&text[len], errno_len + 1, ": %s", strerror(_errno)); \
|
|
|
|
|
struct user_notification notif = { \
|
|
|
|
|
.kind = USER_NOTIFICATION_ERROR, \
|
|
|
|
|
.text = text, \
|
|
|
|
|
}; \
|
|
|
|
|
tll_push_back(conf->notifications, notif); \
|
|
|
|
|
} while(0)
|
2020-07-31 17:07:14 +02:00
|
|
|
|
2019-07-17 09:29:56 +02:00
|
|
|
static char *
|
|
|
|
|
get_shell(void)
|
|
|
|
|
{
|
2020-03-02 18:45:38 +01:00
|
|
|
const char *shell = getenv("SHELL");
|
|
|
|
|
|
|
|
|
|
if (shell == NULL) {
|
|
|
|
|
struct passwd *passwd = getpwuid(getuid());
|
|
|
|
|
if (passwd == NULL) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_ERRNO("failed to lookup user: falling back to 'sh'");
|
|
|
|
|
shell = "sh";
|
|
|
|
|
} else
|
|
|
|
|
shell = passwd->pw_shell;
|
2019-07-17 09:29:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG_DBG("user's shell: %s", shell);
|
2020-08-04 23:28:16 +01:00
|
|
|
return xstrdup(shell);
|
2019-07-17 09:29:56 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
static char *
|
|
|
|
|
get_config_path_user_config(void)
|
|
|
|
|
{
|
|
|
|
|
struct passwd *passwd = getpwuid(getuid());
|
|
|
|
|
if (passwd == NULL) {
|
|
|
|
|
LOG_ERRNO("failed to lookup user");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *home_dir = passwd->pw_dir;
|
|
|
|
|
LOG_DBG("user's home directory: %s", home_dir);
|
|
|
|
|
|
2020-08-04 23:28:16 +01:00
|
|
|
char *path = xasprintf("%s/.config/footrc", home_dir);
|
2019-07-16 11:52:22 +02:00
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
get_config_path_xdg(void)
|
|
|
|
|
{
|
|
|
|
|
const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
|
|
|
|
|
if (xdg_config_home == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2020-08-04 23:28:16 +01:00
|
|
|
char *path = xasprintf("%s/footrc", xdg_config_home);
|
2019-07-16 11:52:22 +02:00
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
get_config_path(void)
|
|
|
|
|
{
|
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
|
|
char *config = get_config_path_xdg();
|
|
|
|
|
if (config != NULL && stat(config, &st) == 0 && S_ISREG(st.st_mode))
|
|
|
|
|
return config;
|
|
|
|
|
free(config);
|
|
|
|
|
|
|
|
|
|
/* 'Default' XDG_CONFIG_HOME */
|
|
|
|
|
config = get_config_path_user_config();
|
|
|
|
|
if (config != NULL && stat(config, &st) == 0 && S_ISREG(st.st_mode))
|
|
|
|
|
return config;
|
|
|
|
|
free(config);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-11 16:10:14 +01:00
|
|
|
static bool
|
|
|
|
|
str_to_bool(const char *s)
|
|
|
|
|
{
|
|
|
|
|
return strcasecmp(s, "on") == 0 ||
|
|
|
|
|
strcasecmp(s, "true") == 0 ||
|
|
|
|
|
strcasecmp(s, "yes") == 0 ||
|
|
|
|
|
strtoul(s, NULL, 0) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-23 18:54:58 +02:00
|
|
|
static bool
|
2019-07-29 20:13:26 +02:00
|
|
|
str_to_ulong(const char *s, int base, unsigned long *res)
|
2019-07-23 18:54:58 +02:00
|
|
|
{
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
char *end = NULL;
|
|
|
|
|
|
2019-07-29 20:13:26 +02:00
|
|
|
*res = strtoul(s, &end, base);
|
|
|
|
|
return errno == 0 && *end == '\0';
|
|
|
|
|
}
|
2019-07-23 18:54:58 +02:00
|
|
|
|
2019-08-15 18:15:43 +02:00
|
|
|
static bool
|
|
|
|
|
str_to_double(const char *s, double *res)
|
|
|
|
|
{
|
|
|
|
|
if (s == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
char *end = NULL;
|
|
|
|
|
|
|
|
|
|
*res = strtod(s, &end);
|
|
|
|
|
return errno == 0 && *end == '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-29 20:13:26 +02:00
|
|
|
static bool
|
2020-07-31 17:07:14 +02:00
|
|
|
str_to_color(const char *s, uint32_t *color, bool allow_alpha, const char *path, int lineno,
|
|
|
|
|
const char *section, const char *key)
|
2019-07-29 20:13:26 +02:00
|
|
|
{
|
|
|
|
|
unsigned long value;
|
|
|
|
|
if (!str_to_ulong(s, 16, &value)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_ERRNO("%s:%d: [%s]: %s: invalid color: %s", path, lineno, section, key, s);
|
2019-07-23 18:54:58 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 18:42:49 +01:00
|
|
|
if (!allow_alpha && (value & 0xff000000) != 0) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_ERR("%s:%d: [%s]: %s: color value must not have an alpha component: %s",
|
|
|
|
|
path, lineno, section, key, s);
|
2020-03-02 18:42:49 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*color = value;
|
2019-07-23 18:54:58 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
static bool
|
2019-07-17 10:12:14 +02:00
|
|
|
parse_section_main(const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
2019-07-16 11:52:22 +02:00
|
|
|
{
|
2019-07-18 14:29:40 +02:00
|
|
|
if (strcmp(key, "term") == 0) {
|
|
|
|
|
free(conf->term);
|
2020-08-04 23:28:16 +01:00
|
|
|
conf->term = xstrdup(value);
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-17 09:40:58 +02:00
|
|
|
else if (strcmp(key, "shell") == 0) {
|
|
|
|
|
free(conf->shell);
|
2020-08-04 23:28:16 +01:00
|
|
|
conf->shell = xstrdup(value);
|
2019-07-17 09:40:58 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-20 18:35:10 +01:00
|
|
|
else if (strcmp(key, "login-shell") == 0) {
|
2020-03-11 16:10:14 +01:00
|
|
|
conf->login_shell = str_to_bool(value);
|
2020-02-20 18:35:10 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-01 19:59:47 +02:00
|
|
|
else if (strcmp(key, "title") == 0) {
|
|
|
|
|
free(conf->title);
|
2020-08-04 23:28:16 +01:00
|
|
|
conf->title = xstrdup(value);
|
2020-04-01 19:59:47 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-01 18:40:51 +02:00
|
|
|
else if (strcmp(key, "app-id") == 0) {
|
|
|
|
|
free(conf->app_id);
|
2020-08-04 23:28:16 +01:00
|
|
|
conf->app_id = xstrdup(value);
|
2020-04-01 18:40:51 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-23 17:26:41 +02:00
|
|
|
else if (strcmp(key, "geometry") == 0) {
|
|
|
|
|
unsigned width, height;
|
|
|
|
|
if (sscanf(value, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s: %d: [default]: geometry: expected WIDTHxHEIGHT, "
|
|
|
|
|
"where both are positive integers, got '%s'",
|
2019-08-23 17:26:41 +02:00
|
|
|
path, lineno, value);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->width = width;
|
|
|
|
|
conf->height = height;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-15 19:00:56 +01:00
|
|
|
else if (strcmp(key, "pad") == 0) {
|
|
|
|
|
unsigned x, y;
|
|
|
|
|
if (sscanf(value, "%ux%u", &x, &y) != 2) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s:%d: [default]: pad: expected PAD_XxPAD_Y, "
|
|
|
|
|
"where both are positive integers, got '%s'",
|
2020-02-15 19:00:56 +01:00
|
|
|
path, lineno, value);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->pad_x = x;
|
|
|
|
|
conf->pad_y = y;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-28 12:04:00 +01:00
|
|
|
else if (strcmp(key, "initial-window-mode") == 0) {
|
2020-03-26 19:39:12 +01:00
|
|
|
if (strcmp(value, "windowed") == 0)
|
|
|
|
|
conf->startup_mode = STARTUP_WINDOWED;
|
|
|
|
|
else if (strcmp(value, "maximized") == 0)
|
|
|
|
|
conf->startup_mode = STARTUP_MAXIMIZED;
|
|
|
|
|
else if (strcmp(value, "fullscreen") == 0)
|
|
|
|
|
conf->startup_mode = STARTUP_FULLSCREEN;
|
|
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s:%d: [default]: initial-window-mode: expected either "
|
|
|
|
|
"'windowed', 'maximized' or 'fullscreen'",
|
2020-03-26 19:39:12 +01:00
|
|
|
path, lineno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-18 14:29:40 +02:00
|
|
|
else if (strcmp(key, "font") == 0) {
|
2020-08-04 23:28:16 +01:00
|
|
|
char *copy = xstrdup(value);
|
2019-12-05 19:33:54 +01:00
|
|
|
for (const char *font = strtok(copy, ","); font != NULL; font = strtok(NULL, ",")) {
|
|
|
|
|
/* Trim spaces, strictly speaking not necessary, but looks nice :) */
|
|
|
|
|
while (*font != '\0' && isspace(*font))
|
|
|
|
|
font++;
|
|
|
|
|
if (*font != '\0')
|
2020-07-07 10:44:55 +02:00
|
|
|
tll_push_back(conf->fonts, config_font_parse(font));
|
2019-12-05 19:33:54 +01:00
|
|
|
}
|
2019-07-30 18:04:28 +02:00
|
|
|
free(copy);
|
2019-07-18 14:29:40 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-29 20:13:26 +02:00
|
|
|
else if (strcmp(key, "workers") == 0) {
|
|
|
|
|
unsigned long count;
|
|
|
|
|
if (!str_to_ulong(value, 10, &count)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s:%d: [default]: workers: expected an integer, got '%s'",
|
|
|
|
|
path, lineno, value);
|
2019-07-29 20:13:26 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
conf->render_worker_count = count;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-01 19:28:14 +02:00
|
|
|
else if (strcmp(key, "scrollback") == 0) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_WARN("deprecated: [default]: scrollback: use 'scrollback.lines' instead'");
|
2020-07-29 17:41:24 +02:00
|
|
|
|
2020-08-02 23:54:04 +01:00
|
|
|
const char *fmt = "%s:%d: \033[1mdefault.scrollback\033[21m, use \033[1mscrollback.lines\033[21m instead";
|
2020-08-04 23:28:16 +01:00
|
|
|
char *text = xasprintf(fmt, path, lineno);
|
2020-07-29 19:43:11 +02:00
|
|
|
|
2020-07-30 18:57:21 +02:00
|
|
|
struct user_notification deprecation = {
|
|
|
|
|
.kind = USER_NOTIFICATION_DEPRECATED,
|
2020-07-29 19:43:11 +02:00
|
|
|
.text = text,
|
|
|
|
|
};
|
2020-07-30 18:57:21 +02:00
|
|
|
tll_push_back(conf->notifications, deprecation);
|
2020-07-29 19:43:11 +02:00
|
|
|
|
2020-07-29 17:41:24 +02:00
|
|
|
unsigned long lines;
|
|
|
|
|
if (!str_to_ulong(value, 10, &lines)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s:%d: [default]: scrollback: expected an integer, got '%s'",
|
|
|
|
|
path, lineno, value);
|
2020-07-29 17:41:24 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
conf->scrollback.lines = lines;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [default]: %s: invalid key", path, lineno, key);
|
2020-07-29 17:41:24 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
parse_section_scrollback(const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(key, "lines") == 0) {
|
2019-08-01 19:28:14 +02:00
|
|
|
unsigned long lines;
|
|
|
|
|
if (!str_to_ulong(value, 10, &lines)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: [scrollback]: lines: expected an integer, got '%s'", path, lineno, value);
|
2019-08-01 19:28:14 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2020-07-25 14:31:45 +02:00
|
|
|
conf->scrollback.lines = lines;
|
2019-08-01 19:28:14 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 17:41:24 +02:00
|
|
|
else if (strcmp(key, "indicator-position") == 0) {
|
2020-07-25 14:31:45 +02:00
|
|
|
if (strcmp(value, "none") == 0)
|
2020-07-27 20:02:51 +02:00
|
|
|
conf->scrollback.indicator.position = SCROLLBACK_INDICATOR_POSITION_NONE;
|
2020-07-25 14:40:46 +02:00
|
|
|
else if (strcmp(value, "fixed") == 0)
|
2020-07-27 20:02:51 +02:00
|
|
|
conf->scrollback.indicator.position = SCROLLBACK_INDICATOR_POSITION_FIXED;
|
2020-07-25 14:40:46 +02:00
|
|
|
else if (strcmp(value, "relative") == 0)
|
2020-07-27 20:02:51 +02:00
|
|
|
conf->scrollback.indicator.position = SCROLLBACK_INDICATOR_POSITION_RELATIVE;
|
2020-07-25 14:31:45 +02:00
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: [scrollback]: indicator-position must be one of "
|
2020-07-26 09:44:16 +02:00
|
|
|
"'none', 'fixed' or 'moving'",
|
2020-07-25 14:31:45 +02:00
|
|
|
path, lineno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-24 18:20:26 +02:00
|
|
|
|
2020-07-29 17:41:24 +02:00
|
|
|
else if (strcmp(key, "indicator-format") == 0) {
|
2020-07-28 19:57:26 +02:00
|
|
|
if (strcmp(value, "percentage") == 0) {
|
2020-07-26 11:39:02 +02:00
|
|
|
conf->scrollback.indicator.format
|
|
|
|
|
= SCROLLBACK_INDICATOR_FORMAT_PERCENTAGE;
|
|
|
|
|
} else if (strcmp(value, "line") == 0) {
|
|
|
|
|
conf->scrollback.indicator.format
|
|
|
|
|
= SCROLLBACK_INDICATOR_FORMAT_LINENO;
|
|
|
|
|
} else {
|
2020-07-28 19:56:53 +02:00
|
|
|
free(conf->scrollback.indicator.text);
|
|
|
|
|
conf->scrollback.indicator.text = NULL;
|
|
|
|
|
|
2020-08-22 10:56:53 +02:00
|
|
|
size_t len = mbstowcs(NULL, value, 0);
|
2020-07-28 19:56:53 +02:00
|
|
|
if (len < 0) {
|
2020-08-22 10:56:53 +02:00
|
|
|
LOG_AND_NOTIFY_ERRNO(
|
|
|
|
|
"%s:%d: [scrollback]: indicator-format: "
|
|
|
|
|
"invalid value: %s", path, lineno, value);
|
2020-07-28 19:56:53 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-04 23:28:16 +01:00
|
|
|
conf->scrollback.indicator.text = xcalloc(len + 1, sizeof(wchar_t));
|
2020-07-28 19:56:53 +02:00
|
|
|
mbstowcs(conf->scrollback.indicator.text, value, len);
|
2020-07-24 18:34:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 19:43:06 +02:00
|
|
|
else if (strcmp(key, "multiplier") == 0) {
|
|
|
|
|
double multiplier;
|
|
|
|
|
if (!str_to_double(value, &multiplier)) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: [scrollback]: multiplier: "
|
|
|
|
|
"invalid value: %s", path, lineno, value);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->scrollback.multiplier = multiplier;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [scrollback]: %s: invalid key", path, lineno, key);
|
2019-07-16 11:52:22 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-21 11:31:16 +02:00
|
|
|
static bool
|
|
|
|
|
parse_section_colors(const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
uint32_t *color = NULL;
|
|
|
|
|
|
|
|
|
|
if (strcmp(key, "foreground") == 0) color = &conf->colors.fg;
|
|
|
|
|
else if (strcmp(key, "background") == 0) color = &conf->colors.bg;
|
|
|
|
|
else if (strcmp(key, "regular0") == 0) color = &conf->colors.regular[0];
|
|
|
|
|
else if (strcmp(key, "regular1") == 0) color = &conf->colors.regular[1];
|
|
|
|
|
else if (strcmp(key, "regular2") == 0) color = &conf->colors.regular[2];
|
|
|
|
|
else if (strcmp(key, "regular3") == 0) color = &conf->colors.regular[3];
|
|
|
|
|
else if (strcmp(key, "regular4") == 0) color = &conf->colors.regular[4];
|
|
|
|
|
else if (strcmp(key, "regular5") == 0) color = &conf->colors.regular[5];
|
|
|
|
|
else if (strcmp(key, "regular6") == 0) color = &conf->colors.regular[6];
|
|
|
|
|
else if (strcmp(key, "regular7") == 0) color = &conf->colors.regular[7];
|
|
|
|
|
else if (strcmp(key, "bright0") == 0) color = &conf->colors.bright[0];
|
|
|
|
|
else if (strcmp(key, "bright1") == 0) color = &conf->colors.bright[1];
|
|
|
|
|
else if (strcmp(key, "bright2") == 0) color = &conf->colors.bright[2];
|
|
|
|
|
else if (strcmp(key, "bright3") == 0) color = &conf->colors.bright[3];
|
|
|
|
|
else if (strcmp(key, "bright4") == 0) color = &conf->colors.bright[4];
|
|
|
|
|
else if (strcmp(key, "bright5") == 0) color = &conf->colors.bright[5];
|
|
|
|
|
else if (strcmp(key, "bright6") == 0) color = &conf->colors.bright[6];
|
|
|
|
|
else if (strcmp(key, "bright7") == 0) color = &conf->colors.bright[7];
|
2020-08-12 18:53:32 +02:00
|
|
|
else if (strcmp(key, "selection-foreground") == 0) color = &conf->colors.selection_fg;
|
|
|
|
|
else if (strcmp(key, "selection-background") == 0) color = &conf->colors.selection_bg;
|
2019-08-15 18:15:43 +02:00
|
|
|
else if (strcmp(key, "alpha") == 0) {
|
|
|
|
|
double alpha;
|
|
|
|
|
if (!str_to_double(value, &alpha) || alpha < 0. || alpha > 1.) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s: %d: [colors]: alpha: expected a value in the range 0.0-1.0",
|
2019-08-15 18:15:43 +02:00
|
|
|
path, lineno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-16 22:06:06 +02:00
|
|
|
conf->colors.alpha = alpha * 65535.;
|
2019-08-15 18:15:43 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-07-21 11:31:16 +02:00
|
|
|
|
|
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: [colors]: %s: invalid key", path, lineno, key);
|
2019-07-21 11:31:16 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-23 18:54:58 +02:00
|
|
|
uint32_t color_value;
|
2020-07-31 17:07:14 +02:00
|
|
|
if (!str_to_color(value, &color_value, false, path, lineno, "colors", key))
|
2019-07-21 11:31:16 +02:00
|
|
|
return false;
|
|
|
|
|
|
2019-07-23 18:54:58 +02:00
|
|
|
*color = color_value;
|
2019-07-21 11:31:16 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-22 20:15:14 +02:00
|
|
|
static bool
|
|
|
|
|
parse_section_cursor(const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(key, "style") == 0) {
|
|
|
|
|
if (strcmp(value, "block") == 0)
|
|
|
|
|
conf->cursor.style = CURSOR_BLOCK;
|
|
|
|
|
else if (strcmp(value, "bar") == 0)
|
|
|
|
|
conf->cursor.style = CURSOR_BAR;
|
|
|
|
|
else if (strcmp(value, "underline") == 0)
|
|
|
|
|
conf->cursor.style = CURSOR_UNDERLINE;
|
|
|
|
|
|
|
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid 'style': %s", path, lineno, value);
|
2019-07-22 20:15:14 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-30 17:45:34 +02:00
|
|
|
else if (strcmp(key, "blink") == 0)
|
|
|
|
|
conf->cursor.blink = str_to_bool(value);
|
|
|
|
|
|
2019-07-23 18:54:58 +02:00
|
|
|
else if (strcmp(key, "color") == 0) {
|
2020-08-04 23:28:16 +01:00
|
|
|
char *value_copy = xstrdup(value);
|
2019-07-23 18:54:58 +02:00
|
|
|
const char *text = strtok(value_copy, " ");
|
|
|
|
|
const char *cursor = strtok(NULL, " ");
|
|
|
|
|
|
|
|
|
|
uint32_t text_color, cursor_color;
|
|
|
|
|
if (text == NULL || cursor == NULL ||
|
2020-07-31 17:07:14 +02:00
|
|
|
!str_to_color(text, &text_color, false, path, lineno, "cursor", "color") ||
|
|
|
|
|
!str_to_color(cursor, &cursor_color, false, path, lineno, "cursor", "color"))
|
2019-07-23 18:54:58 +02:00
|
|
|
{
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid cursor colors: %s", path, lineno, value);
|
2019-07-23 18:54:58 +02:00
|
|
|
free(value_copy);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-09 13:35:02 +02:00
|
|
|
conf->cursor.color.text = 1u << 31 | text_color;
|
|
|
|
|
conf->cursor.color.cursor = 1u << 31 | cursor_color;
|
2019-07-23 18:54:58 +02:00
|
|
|
free(value_copy);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-22 20:15:14 +02:00
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: [cursor]: %s: invalid key", path, lineno, key);
|
2019-07-22 20:15:14 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-04 07:33:15 +02:00
|
|
|
static bool
|
|
|
|
|
parse_section_mouse(const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(key, "hide-when-typing") == 0)
|
|
|
|
|
conf->mouse.hide_when_typing = str_to_bool(value);
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: [mouse]: %s: invalid key", path, lineno, key);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 18:42:49 +01:00
|
|
|
static bool
|
|
|
|
|
parse_section_csd(const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(key, "preferred") == 0) {
|
|
|
|
|
if (strcmp(value, "server") == 0)
|
|
|
|
|
conf->csd.preferred = CONF_CSD_PREFER_SERVER;
|
|
|
|
|
else if (strcmp(value, "client") == 0)
|
|
|
|
|
conf->csd.preferred = CONF_CSD_PREFER_CLIENT;
|
|
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: csd.preferred: expected either 'server' or 'client'", path, lineno);
|
2020-03-02 18:42:49 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-03 18:18:59 +01:00
|
|
|
else if (strcmp(key, "color") == 0) {
|
2020-03-02 18:42:49 +01:00
|
|
|
uint32_t color;
|
2020-07-31 17:07:14 +02:00
|
|
|
if (!str_to_color(value, &color, true, path, lineno, "csd", "color")) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid titlebar-color: %s", path, lineno, value);
|
2020-03-02 18:42:49 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->csd.color.title_set = true;
|
|
|
|
|
conf->csd.color.title = color;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-03 18:18:59 +01:00
|
|
|
else if (strcmp(key, "size") == 0) {
|
2020-03-02 18:42:49 +01:00
|
|
|
unsigned long pixels;
|
|
|
|
|
if (!str_to_ulong(value, 10, &pixels)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: expected an integer, got '%s'", path, lineno, value);
|
2020-03-02 18:42:49 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->csd.title_height = pixels;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 20:29:28 +01:00
|
|
|
else if (strcmp(key, "button-width") == 0) {
|
|
|
|
|
unsigned long pixels;
|
|
|
|
|
if (!str_to_ulong(value, 10, &pixels)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: expected an integer, got '%s'", path, lineno, value);
|
2020-03-02 20:29:28 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->csd.button_width = pixels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (strcmp(key, "button-minimize-color") == 0) {
|
|
|
|
|
uint32_t color;
|
2020-07-31 17:07:14 +02:00
|
|
|
if (!str_to_color(value, &color, true, path, lineno, "csd", "button-minimize-color")) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid button-minimize-color: %s", path, lineno, value);
|
2020-03-02 20:29:28 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->csd.color.minimize_set = true;
|
|
|
|
|
conf->csd.color.minimize = color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (strcmp(key, "button-maximize-color") == 0) {
|
|
|
|
|
uint32_t color;
|
2020-07-31 17:07:14 +02:00
|
|
|
if (!str_to_color(value, &color, true, path, lineno, "csd", "button-maximize-color")) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid button-maximize-color: %s", path, lineno, value);
|
2020-03-02 20:29:28 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->csd.color.maximize_set = true;
|
|
|
|
|
conf->csd.color.maximize = color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (strcmp(key, "button-close-color") == 0) {
|
|
|
|
|
uint32_t color;
|
2020-07-31 17:07:14 +02:00
|
|
|
if (!str_to_color(value, &color, true, path, lineno, "csd", "button-close-color")) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid button-close-color: %s", path, lineno, value);
|
2020-03-02 20:29:28 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->csd.color.close_set = true;
|
|
|
|
|
conf->csd.color.close = color;
|
|
|
|
|
}
|
2020-03-08 14:08:48 +01:00
|
|
|
|
|
|
|
|
else {
|
2020-08-11 09:55:33 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [csd]: %s: invalid action",
|
|
|
|
|
path, lineno, key);
|
2020-03-08 14:08:48 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 18:42:49 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Struct that holds temporary key/mouse binding parsed data */
|
|
|
|
|
struct key_combo {
|
|
|
|
|
char *text; /* Raw text, e.g. "Control+Shift+V" */
|
|
|
|
|
struct config_key_modifiers modifiers;
|
|
|
|
|
union {
|
|
|
|
|
xkb_keysym_t sym; /* Key converted to an XKB symbol, e.g. XKB_KEY_V */
|
|
|
|
|
struct {
|
|
|
|
|
int button;
|
|
|
|
|
int count;
|
|
|
|
|
} m;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
typedef tll(struct key_combo) key_combo_list_t;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_key_combo_list(key_combo_list_t *key_combos)
|
|
|
|
|
{
|
|
|
|
|
tll_foreach(*key_combos, it)
|
|
|
|
|
free(it->item.text);
|
|
|
|
|
tll_free(*key_combos);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 17:16:35 +01:00
|
|
|
static bool
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
parse_modifiers(struct config *conf, const char *text, size_t len,
|
|
|
|
|
struct config_key_modifiers *modifiers, const char *path, unsigned lineno)
|
2020-03-12 17:16:35 +01:00
|
|
|
{
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
bool ret = false;
|
2020-03-12 17:16:35 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
*modifiers = (struct config_key_modifiers){};
|
|
|
|
|
char *copy = xstrndup(text, len);
|
2020-07-30 18:57:21 +02:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
for (char *tok_ctx = NULL, *key = strtok_r(copy, "+", &tok_ctx);
|
|
|
|
|
key != NULL;
|
|
|
|
|
key = strtok_r(NULL, "+", &tok_ctx))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(key, XKB_MOD_NAME_SHIFT) == 0)
|
|
|
|
|
modifiers->shift = true;
|
|
|
|
|
else if (strcmp(key, XKB_MOD_NAME_CTRL) == 0)
|
|
|
|
|
modifiers->ctrl = true;
|
|
|
|
|
else if (strcmp(key, XKB_MOD_NAME_ALT) == 0)
|
|
|
|
|
modifiers->alt = true;
|
|
|
|
|
else if (strcmp(key, XKB_MOD_NAME_LOGO) == 0)
|
|
|
|
|
modifiers->meta = true;
|
|
|
|
|
else {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: %s: not a valid modifier name",
|
|
|
|
|
path, lineno, key);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2020-07-30 18:57:21 +02:00
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
ret = true;
|
2020-07-30 18:57:21 +02:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
out:
|
|
|
|
|
free(copy);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2020-03-12 17:16:35 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
static bool
|
|
|
|
|
parse_key_combos(struct config *conf, const char *combos, key_combo_list_t *key_combos,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
assert(tll_length(*key_combos) == 0);
|
2020-03-12 17:16:35 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
char *copy = xstrdup(combos);
|
2020-03-12 17:16:35 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
for (char *tok_ctx = NULL, *combo = strtok_r(copy, " ", &tok_ctx);
|
|
|
|
|
combo != NULL;
|
|
|
|
|
combo = strtok_r(NULL, " ", &tok_ctx))
|
|
|
|
|
{
|
|
|
|
|
struct config_key_modifiers modifiers = {};
|
|
|
|
|
const char *key = strrchr(combo, '+');
|
2020-03-12 17:16:35 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (key == NULL) {
|
|
|
|
|
/* No modifiers */
|
|
|
|
|
key = combo;
|
|
|
|
|
} else {
|
|
|
|
|
if (!parse_modifiers(conf, combo, key - combo, &modifiers, path, lineno))
|
|
|
|
|
goto err;
|
|
|
|
|
key++; /* Skip past the '+' */
|
|
|
|
|
}
|
2020-03-12 17:16:35 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Translate key name to symbol */
|
|
|
|
|
xkb_keysym_t sym = xkb_keysym_from_name(key, 0);
|
|
|
|
|
if (sym == XKB_KEY_NoSymbol) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: %s: key is not a valid XKB key name",
|
|
|
|
|
path, lineno, key);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tll_push_back(
|
|
|
|
|
*key_combos,
|
|
|
|
|
((struct key_combo){.text = xstrdup(combo), .modifiers = modifiers, .sym = sym}));
|
2020-03-12 17:16:35 +01:00
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
free(copy);
|
2020-03-12 17:16:35 +01:00
|
|
|
return true;
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
tll_foreach(*key_combos, it)
|
|
|
|
|
free(it->item.text);
|
|
|
|
|
tll_free(*key_combos);
|
|
|
|
|
free(copy);
|
|
|
|
|
return false;
|
2020-03-12 17:16:35 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-09 22:40:53 +02:00
|
|
|
static bool
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
has_key_binding_collisions(struct config *conf, const key_combo_list_t *key_combos,
|
|
|
|
|
const char *path, unsigned lineno)
|
2020-08-09 22:40:53 +02:00
|
|
|
{
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
tll_foreach(conf->bindings.key, it) {
|
|
|
|
|
tll_foreach(*key_combos, it2) {
|
|
|
|
|
const struct config_key_modifiers *mods1 = &it->item.modifiers;
|
|
|
|
|
const struct config_key_modifiers *mods2 = &it2->item.modifiers;
|
|
|
|
|
|
|
|
|
|
if (memcmp(mods1, mods2, sizeof(*mods1)) == 0 &&
|
|
|
|
|
it->item.sym == it2->item.sym)
|
|
|
|
|
{
|
|
|
|
|
bool has_pipe = it->item.pipe.cmd != NULL;
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s%s%s%s'",
|
|
|
|
|
path, lineno, it2->item.text,
|
|
|
|
|
binding_action_map[it->item.action],
|
|
|
|
|
has_pipe ? " [" : "",
|
|
|
|
|
has_pipe ? it->item.pipe.cmd : "",
|
|
|
|
|
has_pipe ? "]" : "");
|
|
|
|
|
return true;
|
2020-08-09 22:40:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2020-08-09 22:40:53 +02:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
static bool
|
|
|
|
|
has_search_binding_collisions(struct config *conf, const key_combo_list_t *key_combos,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
tll_foreach(conf->bindings.search, it) {
|
|
|
|
|
tll_foreach(*key_combos, it2) {
|
|
|
|
|
const struct config_key_modifiers *mods1 = &it->item.modifiers;
|
|
|
|
|
const struct config_key_modifiers *mods2 = &it2->item.modifiers;
|
2020-08-09 22:40:53 +02:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (memcmp(mods1, mods2, sizeof(*mods1)) == 0 &&
|
|
|
|
|
it->item.sym == it2->item.sym)
|
|
|
|
|
{
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s'",
|
|
|
|
|
path, lineno, it2->item.text,
|
|
|
|
|
search_binding_action_map[it->item.action]);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-09 22:40:53 +02:00
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
return false;
|
2020-08-09 22:40:53 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-30 18:57:21 +02:00
|
|
|
static int
|
|
|
|
|
argv_compare(char *const *argv1, char *const *argv2)
|
|
|
|
|
{
|
|
|
|
|
assert(argv1 != NULL);
|
|
|
|
|
assert(argv2 != NULL);
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; ; i++) {
|
|
|
|
|
if (argv1[i] == NULL && argv2[i] == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (argv1[i] == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
if (argv2[i] == NULL)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
int ret = strcmp(argv1[i], argv2[i]);
|
|
|
|
|
if (ret != 0)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(false);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-09 20:03:04 +01:00
|
|
|
static bool
|
2020-03-12 10:20:05 +01:00
|
|
|
parse_section_key_bindings(
|
|
|
|
|
const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
2020-03-09 20:03:04 +01:00
|
|
|
{
|
2020-07-30 18:53:51 +02:00
|
|
|
char *pipe_cmd = NULL;
|
|
|
|
|
char **pipe_argv = NULL;
|
2020-07-15 17:28:09 +02:00
|
|
|
size_t pipe_len = 0;
|
2020-07-15 13:32:31 +02:00
|
|
|
|
2020-07-15 17:28:09 +02:00
|
|
|
if (value[0] == '[') {
|
|
|
|
|
const char *pipe_cmd_end = strrchr(value, ']');
|
|
|
|
|
if (pipe_cmd_end == NULL) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: unclosed '['", path, lineno);
|
2020-07-15 17:28:09 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-31 17:10:12 +02:00
|
|
|
pipe_len = pipe_cmd_end - value - 1;
|
2020-08-08 20:34:30 +01:00
|
|
|
pipe_cmd = xstrndup(&value[1], pipe_len);
|
2020-07-30 18:53:51 +02:00
|
|
|
|
|
|
|
|
if (!tokenize_cmdline(pipe_cmd, &pipe_argv)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: syntax error in command line", path, lineno);
|
2020-07-30 18:53:51 +02:00
|
|
|
free(pipe_cmd);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-07-15 17:28:09 +02:00
|
|
|
|
|
|
|
|
value = pipe_cmd_end + 1;
|
2020-07-30 18:53:51 +02:00
|
|
|
while (isspace(*value))
|
|
|
|
|
value++;
|
2020-07-15 17:28:09 +02:00
|
|
|
}
|
2020-07-15 13:32:31 +02:00
|
|
|
|
|
|
|
|
for (enum bind_action_normal action = 0;
|
2020-08-11 09:55:33 +02:00
|
|
|
action < BIND_ACTION_KEY_COUNT;
|
2020-07-15 13:32:31 +02:00
|
|
|
action++)
|
|
|
|
|
{
|
2020-03-12 10:46:27 +01:00
|
|
|
if (binding_action_map[action] == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
2020-07-15 17:28:09 +02:00
|
|
|
if (strcmp(key, binding_action_map[action]) != 0)
|
2020-03-09 20:03:04 +01:00
|
|
|
continue;
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Unset binding */
|
2020-03-18 14:52:04 +01:00
|
|
|
if (strcasecmp(value, "none") == 0) {
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_foreach(conf->bindings.key, it) {
|
|
|
|
|
if (it->item.action == action) {
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (it->item.pipe.master_copy) {
|
|
|
|
|
free(it->item.pipe.cmd);
|
|
|
|
|
free(it->item.pipe.argv);
|
|
|
|
|
}
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_remove(conf->bindings.key, it);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-30 18:53:51 +02:00
|
|
|
free(pipe_argv);
|
|
|
|
|
free(pipe_cmd);
|
2020-03-12 17:16:35 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
2020-03-09 20:03:04 +01:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
key_combo_list_t key_combos = tll_init();
|
|
|
|
|
if (!parse_key_combos(conf, value, &key_combos, path, lineno) ||
|
|
|
|
|
has_key_binding_collisions(conf, &key_combos, path, lineno))
|
|
|
|
|
{
|
2020-07-30 18:53:51 +02:00
|
|
|
free(pipe_argv);
|
|
|
|
|
free(pipe_cmd);
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
free_key_combo_list(&key_combos);
|
2020-03-09 20:03:04 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Remove existing bindings for this action+pipe */
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_foreach(conf->bindings.key, it) {
|
|
|
|
|
if (it->item.action == action &&
|
2020-07-30 18:53:51 +02:00
|
|
|
((it->item.pipe.argv == NULL && pipe_argv == NULL) ||
|
|
|
|
|
(it->item.pipe.argv != NULL && pipe_argv != NULL &&
|
|
|
|
|
argv_compare(it->item.pipe.argv, pipe_argv) == 0)))
|
2020-07-15 16:39:07 +02:00
|
|
|
{
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (it->item.pipe.master_copy) {
|
|
|
|
|
free(it->item.pipe.cmd);
|
|
|
|
|
free(it->item.pipe.argv);
|
|
|
|
|
}
|
|
|
|
|
tll_remove(conf->bindings.key, it);
|
2020-07-15 16:39:07 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Emit key bindings */
|
|
|
|
|
bool first = true;
|
|
|
|
|
tll_foreach(key_combos, it) {
|
2020-07-15 16:39:07 +02:00
|
|
|
struct config_key_binding_normal binding = {
|
|
|
|
|
.action = action,
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
.modifiers = it->item.modifiers,
|
|
|
|
|
.sym = it->item.sym,
|
2020-07-30 18:53:51 +02:00
|
|
|
.pipe = {
|
|
|
|
|
.cmd = pipe_cmd,
|
|
|
|
|
.argv = pipe_argv,
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
.master_copy = first,
|
2020-07-30 18:53:51 +02:00
|
|
|
},
|
2020-07-15 16:39:07 +02:00
|
|
|
};
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_push_back(conf->bindings.key, binding);
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
first = false;
|
2020-07-15 16:39:07 +02:00
|
|
|
}
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
|
|
|
|
free_key_combo_list(&key_combos);
|
2020-03-09 20:03:04 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-11 09:55:33 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [key-bindings]: %s: invalid action",
|
|
|
|
|
path, lineno, key);
|
2020-03-09 20:03:04 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 17:27:01 +02:00
|
|
|
static bool
|
|
|
|
|
parse_section_search_bindings(
|
|
|
|
|
const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
for (enum bind_action_search action = 0;
|
|
|
|
|
action < BIND_ACTION_SEARCH_COUNT;
|
|
|
|
|
action++)
|
|
|
|
|
{
|
|
|
|
|
if (search_binding_action_map[action] == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (strcmp(key, search_binding_action_map[action]) != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Unset binding */
|
2020-07-29 17:27:01 +02:00
|
|
|
if (strcasecmp(value, "none") == 0) {
|
|
|
|
|
tll_foreach(conf->bindings.search, it) {
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (it->item.action == action)
|
2020-07-29 17:27:01 +02:00
|
|
|
tll_remove(conf->bindings.search, it);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
key_combo_list_t key_combos = tll_init();
|
|
|
|
|
if (!parse_key_combos(conf, value, &key_combos, path, lineno) ||
|
|
|
|
|
has_search_binding_collisions(conf, &key_combos, path, lineno))
|
|
|
|
|
{
|
|
|
|
|
free_key_combo_list(&key_combos);
|
2020-07-29 17:27:01 +02:00
|
|
|
return false;
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
}
|
2020-07-29 17:27:01 +02:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Remove existing bindings for this action */
|
2020-07-29 17:27:01 +02:00
|
|
|
tll_foreach(conf->bindings.search, it) {
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (it->item.action == action)
|
|
|
|
|
tll_remove(conf->bindings.search, it);
|
2020-07-29 17:27:01 +02:00
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Emit key bindings */
|
|
|
|
|
tll_foreach(key_combos, it) {
|
|
|
|
|
struct config_key_binding_normal binding = {
|
2020-07-29 17:27:01 +02:00
|
|
|
.action = action,
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
.modifiers = it->item.modifiers,
|
|
|
|
|
.sym = it->item.sym,
|
2020-07-29 17:27:01 +02:00
|
|
|
};
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
tll_push_back(conf->bindings.key, binding);
|
2020-07-29 17:27:01 +02:00
|
|
|
}
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
|
|
|
|
free_key_combo_list(&key_combos);
|
2020-07-29 17:27:01 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [search-bindings]: %s: invalid key", path, lineno, key);
|
2020-07-29 17:27:01 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
static bool
|
|
|
|
|
parse_mouse_combos(struct config *conf, const char *combos, key_combo_list_t *key_combos,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
assert(tll_length(*key_combos) == 0);
|
|
|
|
|
|
|
|
|
|
char *copy = xstrdup(combos);
|
|
|
|
|
|
|
|
|
|
for (char *tok_ctx = NULL, *combo = strtok_r(copy, " ", &tok_ctx);
|
|
|
|
|
combo != NULL;
|
|
|
|
|
combo = strtok_r(NULL, " ", &tok_ctx))
|
|
|
|
|
{
|
|
|
|
|
struct config_key_modifiers modifiers = {};
|
2020-08-10 19:39:37 +02:00
|
|
|
char *key = strrchr(combo, '+');
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
|
|
|
|
if (key == NULL) {
|
|
|
|
|
/* No modifiers */
|
|
|
|
|
key = combo;
|
|
|
|
|
} else {
|
2020-08-10 19:39:37 +02:00
|
|
|
*key = '\0';
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (!parse_modifiers(conf, combo, key - combo, &modifiers, path, lineno))
|
|
|
|
|
goto err;
|
2020-08-11 10:44:27 +02:00
|
|
|
if (modifiers.shift) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: Shift cannot be used in mosue bindings",
|
|
|
|
|
path, lineno);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
key++; /* Skip past the '+' */
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-10 19:39:37 +02:00
|
|
|
size_t count = 0;
|
|
|
|
|
{
|
|
|
|
|
char *_count = strrchr(key, '-');
|
|
|
|
|
if (_count != NULL) {
|
|
|
|
|
*_count = '\0';
|
|
|
|
|
_count++;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
char *end;
|
|
|
|
|
unsigned long value = strtoul(_count, &end, 10);
|
|
|
|
|
if (_count[0] == '\0' || *end != '\0' || errno != 0) {
|
|
|
|
|
if (errno != 0)
|
|
|
|
|
LOG_AND_NOTIFY_ERRNO(
|
|
|
|
|
"%s:%d: %s: invalid click count", path, lineno, _count);
|
|
|
|
|
else
|
|
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s:%d: %s: invalid click count", path, lineno, _count);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
count = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
static const struct {
|
|
|
|
|
const char *name;
|
|
|
|
|
int code;
|
|
|
|
|
} map[] = {
|
|
|
|
|
{"BTN_LEFT", BTN_LEFT},
|
|
|
|
|
{"BTN_RIGHT", BTN_RIGHT},
|
|
|
|
|
{"BTN_MIDDLE", BTN_MIDDLE},
|
|
|
|
|
{"BTN_SIDE", BTN_SIDE},
|
|
|
|
|
{"BTN_EXTRA", BTN_EXTRA},
|
|
|
|
|
{"BTN_FORWARD", BTN_FORWARD},
|
|
|
|
|
{"BTN_BACK", BTN_BACK},
|
|
|
|
|
{"BTN_TASK", BTN_TASK},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int button = 0;
|
|
|
|
|
for (size_t i = 0; i < ALEN(map); i++) {
|
|
|
|
|
if (strcmp(key, map[i].name) == 0) {
|
|
|
|
|
button = map[i].code;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (button == 0) {
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: %s: invalid mouse button name", path, lineno, key);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct key_combo new = {
|
|
|
|
|
.text = xstrdup(combo),
|
|
|
|
|
.modifiers = modifiers,
|
|
|
|
|
.m = {
|
|
|
|
|
.button = button,
|
2020-08-10 19:39:37 +02:00
|
|
|
.count = count,
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
tll_push_back(*key_combos, new);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(copy);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
tll_foreach(*key_combos, it)
|
|
|
|
|
free(it->item.text);
|
|
|
|
|
tll_free(*key_combos);
|
|
|
|
|
free(copy);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
has_mouse_binding_collisions(struct config *conf, const key_combo_list_t *key_combos,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
|
|
|
|
tll_foreach(conf->bindings.mouse, it) {
|
|
|
|
|
tll_foreach(*key_combos, it2) {
|
|
|
|
|
const struct config_key_modifiers *mods1 = &it->item.modifiers;
|
|
|
|
|
const struct config_key_modifiers *mods2 = &it2->item.modifiers;
|
|
|
|
|
|
|
|
|
|
if (memcmp(mods1, mods2, sizeof(*mods1)) == 0 &&
|
|
|
|
|
it->item.button == it2->item.m.button &&
|
|
|
|
|
it->item.count == it2->item.m.count)
|
|
|
|
|
{
|
|
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s'",
|
|
|
|
|
path, lineno, it2->item.text,
|
|
|
|
|
binding_action_map[it->item.action]);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-03-12 10:20:05 +01:00
|
|
|
static bool
|
|
|
|
|
parse_section_mouse_bindings(
|
|
|
|
|
const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
2020-08-11 09:55:33 +02:00
|
|
|
for (enum bind_action_normal action = 0;
|
|
|
|
|
action < BIND_ACTION_COUNT;
|
|
|
|
|
action++)
|
|
|
|
|
{
|
2020-03-12 10:46:27 +01:00
|
|
|
if (binding_action_map[action] == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
2020-03-12 10:20:05 +01:00
|
|
|
if (strcmp(key, binding_action_map[action]) != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Unset binding */
|
|
|
|
|
if (strcasecmp(value, "none") == 0) {
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_foreach(conf->bindings.mouse, it) {
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (it->item.action == action)
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_remove(conf->bindings.mouse, it);
|
|
|
|
|
}
|
2020-03-12 10:46:27 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
key_combo_list_t key_combos = tll_init();
|
|
|
|
|
if (!parse_mouse_combos(conf, value, &key_combos, path, lineno) ||
|
|
|
|
|
has_mouse_binding_collisions(conf, &key_combos, path, lineno))
|
|
|
|
|
{
|
|
|
|
|
free_key_combo_list(&key_combos);
|
2020-08-09 22:40:53 +02:00
|
|
|
return false;
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
}
|
2020-08-09 22:40:53 +02:00
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Remove existing bindings for this action */
|
2020-08-09 22:40:53 +02:00
|
|
|
tll_foreach(conf->bindings.mouse, it) {
|
|
|
|
|
if (it->item.action == action) {
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
tll_remove(conf->bindings.mouse, it);
|
2020-08-09 22:40:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
/* Emit mouse bindings */
|
|
|
|
|
tll_foreach(key_combos, it) {
|
2020-08-09 22:40:53 +02:00
|
|
|
struct config_mouse_binding binding = {
|
|
|
|
|
.action = action,
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
.modifiers = it->item.modifiers,
|
|
|
|
|
.button = it->item.m.button,
|
|
|
|
|
.count = it->item.m.count,
|
2020-08-09 22:40:53 +02:00
|
|
|
};
|
|
|
|
|
tll_push_back(conf->bindings.mouse, binding);
|
|
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
free_key_combo_list(&key_combos);
|
2020-08-09 22:40:53 +02:00
|
|
|
return true;
|
2020-03-12 10:20:05 +01:00
|
|
|
}
|
|
|
|
|
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [mouse-bindings]: %s: invalid key", path, lineno, key);
|
2020-03-12 10:20:05 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 16:46:54 +01:00
|
|
|
static bool
|
|
|
|
|
parse_section_tweak(
|
|
|
|
|
const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno)
|
|
|
|
|
{
|
2020-08-13 18:35:17 +02:00
|
|
|
if (strcmp(key, "render-timer") == 0) {
|
|
|
|
|
if (strcmp(value, "none") == 0) {
|
|
|
|
|
conf->tweak.render_timer_osd = false;
|
|
|
|
|
conf->tweak.render_timer_log = false;
|
|
|
|
|
} else if (strcmp(value, "osd") == 0) {
|
|
|
|
|
conf->tweak.render_timer_osd = true;
|
|
|
|
|
conf->tweak.render_timer_log = false;
|
|
|
|
|
} else if (strcmp(value, "log") == 0) {
|
|
|
|
|
conf->tweak.render_timer_osd = false;
|
|
|
|
|
conf->tweak.render_timer_log = true;
|
|
|
|
|
} else if (strcmp(value, "both") == 0) {
|
|
|
|
|
conf->tweak.render_timer_osd = true;
|
|
|
|
|
conf->tweak.render_timer_log = true;
|
|
|
|
|
} else {
|
|
|
|
|
LOG_AND_NOTIFY_ERR(
|
|
|
|
|
"%s:%d: [tweak]: %s: invalid 'render-timer' value, "
|
|
|
|
|
"expected one of 'none', 'osd', 'log' or 'both'",
|
|
|
|
|
path, lineno, value);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (strcmp(key, "delayed-render-lower") == 0) {
|
2020-03-17 16:46:54 +01:00
|
|
|
unsigned long ns;
|
|
|
|
|
if (!str_to_ulong(value, 10, &ns)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: expected an integer, got '%s'", path, lineno, value);
|
2020-03-17 16:46:54 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ns > 16666666) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: timeout must not exceed 16ms", path, lineno);
|
2020-03-17 16:46:54 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->tweak.delayed_render_lower_ns = ns;
|
|
|
|
|
LOG_WARN("tweak: delayed-render-lower=%lu", ns);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (strcmp(key, "delayed-render-upper") == 0) {
|
|
|
|
|
unsigned long ns;
|
|
|
|
|
if (!str_to_ulong(value, 10, &ns)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: expected an integer, got '%s'", path, lineno, value);
|
2020-03-17 16:46:54 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ns > 16666666) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: timeout must not exceed 16ms", path, lineno);
|
2020-03-17 16:46:54 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->tweak.delayed_render_upper_ns = ns;
|
|
|
|
|
LOG_WARN("tweak: delayed-render-upper=%lu", ns);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-25 20:48:02 +01:00
|
|
|
else if (strcmp(key, "max-shm-pool-size-mb") == 0) {
|
|
|
|
|
unsigned long mb;
|
|
|
|
|
if (!str_to_ulong(value, 10, &mb)) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: expected an integer, got '%s'", path, lineno, value);
|
2020-03-25 20:48:02 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf->tweak.max_shm_pool_size = min(mb * 1024 * 1024, INT32_MAX);
|
2020-08-06 23:20:46 +02:00
|
|
|
LOG_WARN("tweak: max-shm-pool-size=%lld bytes",
|
|
|
|
|
(long long)conf->tweak.max_shm_pool_size);
|
2020-03-25 20:48:02 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-17 16:46:54 +01:00
|
|
|
else {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%u: [tweak]: %s: invalid key", path, lineno, key);
|
2020-03-17 16:46:54 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
static bool
|
2020-07-31 17:07:14 +02:00
|
|
|
parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_are_fatal)
|
2019-07-16 11:52:22 +02:00
|
|
|
{
|
|
|
|
|
enum section {
|
|
|
|
|
SECTION_MAIN,
|
2020-07-29 17:41:24 +02:00
|
|
|
SECTION_SCROLLBACK,
|
2019-07-21 11:31:16 +02:00
|
|
|
SECTION_COLORS,
|
2019-07-22 20:15:14 +02:00
|
|
|
SECTION_CURSOR,
|
2020-08-04 07:33:15 +02:00
|
|
|
SECTION_MOUSE,
|
2020-03-02 18:42:49 +01:00
|
|
|
SECTION_CSD,
|
2020-03-09 20:03:04 +01:00
|
|
|
SECTION_KEY_BINDINGS,
|
2020-07-29 17:27:01 +02:00
|
|
|
SECTION_SEARCH_BINDINGS,
|
2020-03-12 10:20:05 +01:00
|
|
|
SECTION_MOUSE_BINDINGS,
|
2020-03-17 16:46:54 +01:00
|
|
|
SECTION_TWEAK,
|
2020-03-09 20:03:04 +01:00
|
|
|
SECTION_COUNT,
|
2019-07-16 11:52:22 +02:00
|
|
|
} section = SECTION_MAIN;
|
|
|
|
|
|
|
|
|
|
/* Function pointer, called for each key/value line */
|
|
|
|
|
typedef bool (*parser_fun_t)(
|
2019-07-17 10:12:14 +02:00
|
|
|
const char *key, const char *value, struct config *conf,
|
|
|
|
|
const char *path, unsigned lineno);
|
2019-07-16 11:52:22 +02:00
|
|
|
|
2020-03-09 20:03:04 +01:00
|
|
|
static const struct {
|
|
|
|
|
parser_fun_t fun;
|
|
|
|
|
const char *name;
|
|
|
|
|
} section_info[] = {
|
2020-07-29 17:27:01 +02:00
|
|
|
[SECTION_MAIN] = {&parse_section_main, "main"},
|
2020-07-29 17:41:24 +02:00
|
|
|
[SECTION_SCROLLBACK] = {&parse_section_scrollback, "scrollback"},
|
2020-07-29 17:27:01 +02:00
|
|
|
[SECTION_COLORS] = {&parse_section_colors, "colors"},
|
|
|
|
|
[SECTION_CURSOR] = {&parse_section_cursor, "cursor"},
|
2020-08-04 07:33:15 +02:00
|
|
|
[SECTION_MOUSE] = {&parse_section_mouse, "mouse"},
|
2020-07-29 17:27:01 +02:00
|
|
|
[SECTION_CSD] = {&parse_section_csd, "csd"},
|
|
|
|
|
[SECTION_KEY_BINDINGS] = {&parse_section_key_bindings, "key-bindings"},
|
|
|
|
|
[SECTION_SEARCH_BINDINGS] = {&parse_section_search_bindings, "search-bindings"},
|
|
|
|
|
[SECTION_MOUSE_BINDINGS] = {&parse_section_mouse_bindings, "mouse-bindings"},
|
|
|
|
|
[SECTION_TWEAK] = {&parse_section_tweak, "tweak"},
|
2019-07-16 11:52:22 +02:00
|
|
|
};
|
|
|
|
|
|
2020-03-09 20:03:04 +01:00
|
|
|
static_assert(ALEN(section_info) == SECTION_COUNT, "section info array size mismatch");
|
2019-07-17 10:12:14 +02:00
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
unsigned lineno = 0;
|
2020-03-02 18:48:29 +01:00
|
|
|
|
2019-07-21 11:46:46 +02:00
|
|
|
char *_line = NULL;
|
2020-03-02 18:48:29 +01:00
|
|
|
size_t count = 0;
|
2019-07-16 11:52:22 +02:00
|
|
|
|
2020-07-31 17:07:14 +02:00
|
|
|
#define error_or_continue() \
|
|
|
|
|
{ \
|
|
|
|
|
if (errors_are_fatal) \
|
|
|
|
|
goto err; \
|
|
|
|
|
else \
|
|
|
|
|
continue; \
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-16 11:52:22 +02:00
|
|
|
while (true) {
|
|
|
|
|
errno = 0;
|
|
|
|
|
lineno++;
|
|
|
|
|
|
2019-07-21 11:46:46 +02:00
|
|
|
ssize_t ret = getline(&_line, &count, f);
|
2019-07-16 11:52:22 +02:00
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
if (errno != 0) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERRNO("failed to read from configuration");
|
|
|
|
|
if (errors_are_fatal)
|
|
|
|
|
goto err;
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 19:55:09 +02:00
|
|
|
/* Strip leading whitespace */
|
2019-07-21 11:46:46 +02:00
|
|
|
char *line = _line;
|
|
|
|
|
{
|
|
|
|
|
while (isspace(*line))
|
|
|
|
|
line++;
|
|
|
|
|
if (line[0] != '\0') {
|
|
|
|
|
char *end = line + strlen(line) - 1;
|
|
|
|
|
while (isspace(*end))
|
|
|
|
|
end--;
|
|
|
|
|
*(end + 1) = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Empty line, or comment */
|
2020-03-02 18:48:29 +01:00
|
|
|
if (line[0] == '\0' || line[0] == '#')
|
2019-07-21 11:46:46 +02:00
|
|
|
continue;
|
|
|
|
|
|
2020-07-28 19:55:09 +02:00
|
|
|
/* Split up into key/value pair + trailing comment */
|
|
|
|
|
char *key_value = strtok(line, "#");
|
2020-08-07 20:42:34 +01:00
|
|
|
char UNUSED *comment = strtok(NULL, "\n");
|
2020-07-28 19:55:09 +02:00
|
|
|
|
2019-07-21 11:46:46 +02:00
|
|
|
/* Check for new section */
|
2020-07-28 19:55:09 +02:00
|
|
|
if (key_value[0] == '[') {
|
|
|
|
|
char *end = strchr(key_value, ']');
|
2019-07-21 11:31:16 +02:00
|
|
|
if (end == NULL) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: syntax error: %s", path, lineno, key_value);
|
|
|
|
|
error_or_continue();
|
2019-07-21 11:31:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*end = '\0';
|
|
|
|
|
|
2020-03-09 20:03:04 +01:00
|
|
|
section = SECTION_COUNT;
|
|
|
|
|
for (enum section i = 0; i < SECTION_COUNT; i++) {
|
2020-07-28 19:55:09 +02:00
|
|
|
if (strcmp(&key_value[1], section_info[i].name) == 0) {
|
2020-03-09 20:03:04 +01:00
|
|
|
section = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (section == SECTION_COUNT) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid section name: %s", path, lineno, &key_value[1]);
|
|
|
|
|
error_or_continue();
|
2019-07-21 11:31:16 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-09 20:03:04 +01:00
|
|
|
/* Process next line */
|
2019-07-21 11:31:16 +02:00
|
|
|
continue;
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-28 19:55:09 +02:00
|
|
|
char *key = strtok(key_value, "=");
|
|
|
|
|
if (key == NULL) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s:%d: syntax error: no key specified", path, lineno);
|
|
|
|
|
error_or_continue();
|
2020-07-28 19:55:09 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-17 10:12:14 +02:00
|
|
|
char *value = strtok(NULL, "\n");
|
2020-07-28 19:55:09 +02:00
|
|
|
if (value == NULL) {
|
|
|
|
|
/* Empty value, i.e. "key=" */
|
|
|
|
|
value = key + strlen(key);
|
|
|
|
|
}
|
2019-07-17 10:12:14 +02:00
|
|
|
|
2019-07-21 11:46:46 +02:00
|
|
|
/* Strip trailing whitespace from key (leading stripped earlier) */
|
2020-08-02 20:01:07 +02:00
|
|
|
{
|
2019-07-21 11:46:46 +02:00
|
|
|
assert(!isspace(*key));
|
|
|
|
|
|
2019-07-17 10:12:14 +02:00
|
|
|
char *end = key + strlen(key) - 1;
|
|
|
|
|
while (isspace(*end))
|
|
|
|
|
end--;
|
|
|
|
|
*(end + 1) = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 19:55:09 +02:00
|
|
|
/* Strip leading+trailing whitespace from value */
|
2019-07-17 10:12:14 +02:00
|
|
|
{
|
|
|
|
|
while (isspace(*value))
|
|
|
|
|
value++;
|
|
|
|
|
|
2020-07-28 19:55:09 +02:00
|
|
|
if (value[0] != '\0') {
|
|
|
|
|
char *end = value + strlen(value) - 1;
|
|
|
|
|
while (isspace(*end))
|
|
|
|
|
end--;
|
|
|
|
|
*(end + 1) = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-17 10:12:14 +02:00
|
|
|
|
2020-07-28 19:55:09 +02:00
|
|
|
LOG_DBG("section=%s, key='%s', value='%s', comment='%s'",
|
|
|
|
|
section_info[section].name, key, value, comment);
|
2019-07-17 10:12:14 +02:00
|
|
|
|
2020-03-09 20:03:04 +01:00
|
|
|
parser_fun_t section_parser = section_info[section].fun;
|
2019-07-16 11:52:22 +02:00
|
|
|
assert(section_parser != NULL);
|
|
|
|
|
|
2019-07-21 11:46:46 +02:00
|
|
|
if (!section_parser(key, value, conf, path, lineno))
|
2020-07-31 17:07:14 +02:00
|
|
|
error_or_continue();
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-02 18:48:29 +01:00
|
|
|
free(_line);
|
2019-07-16 11:52:22 +02:00
|
|
|
return true;
|
2019-07-21 11:46:46 +02:00
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
free(_line);
|
|
|
|
|
return false;
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-14 12:59:06 +01:00
|
|
|
static char *
|
|
|
|
|
get_server_socket_path(void)
|
|
|
|
|
{
|
|
|
|
|
const char *xdg_runtime = getenv("XDG_RUNTIME_DIR");
|
|
|
|
|
if (xdg_runtime == NULL)
|
2020-08-04 23:28:16 +01:00
|
|
|
return xstrdup("/tmp/foot.sock");
|
2019-12-14 12:59:06 +01:00
|
|
|
|
2020-08-02 13:10:31 +02:00
|
|
|
const char *wayland_display = getenv("WAYLAND_DISPLAY");
|
|
|
|
|
if (wayland_display == NULL) {
|
2020-08-04 23:28:16 +01:00
|
|
|
return xasprintf("%s/foot.sock", xdg_runtime);
|
2020-08-02 13:10:31 +02:00
|
|
|
}
|
2020-03-09 18:47:10 +01:00
|
|
|
|
2020-08-04 23:28:16 +01:00
|
|
|
return xasprintf("%s/foot-%s.sock", xdg_runtime, wayland_display);
|
2019-12-14 12:59:06 +01:00
|
|
|
}
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
static void
|
|
|
|
|
add_default_key_bindings(struct config *conf)
|
|
|
|
|
{
|
|
|
|
|
#define add_binding(action, mods, sym) \
|
|
|
|
|
do { \
|
|
|
|
|
tll_push_back( \
|
|
|
|
|
conf->bindings.key, \
|
|
|
|
|
((struct config_key_binding_normal){action, mods, sym})); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
const struct config_key_modifiers shift = {.shift = true};
|
|
|
|
|
const struct config_key_modifiers ctrl = {.ctrl = true};
|
|
|
|
|
const struct config_key_modifiers ctrl_shift = {.ctrl = true, .shift = true};
|
|
|
|
|
|
|
|
|
|
add_binding(BIND_ACTION_SCROLLBACK_UP, shift, XKB_KEY_Page_Up);
|
|
|
|
|
add_binding(BIND_ACTION_SCROLLBACK_DOWN, shift, XKB_KEY_Page_Down);
|
|
|
|
|
add_binding(BIND_ACTION_CLIPBOARD_COPY, ctrl_shift, XKB_KEY_C);
|
|
|
|
|
add_binding(BIND_ACTION_CLIPBOARD_PASTE, ctrl_shift, XKB_KEY_V);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_START, ctrl_shift, XKB_KEY_R);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_UP, ctrl, XKB_KEY_plus);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_UP, ctrl, XKB_KEY_equal);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_UP, ctrl, XKB_KEY_KP_Add);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_DOWN, ctrl, XKB_KEY_minus);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_DOWN, ctrl, XKB_KEY_KP_Subtract);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_RESET, ctrl, XKB_KEY_0);
|
|
|
|
|
add_binding(BIND_ACTION_FONT_SIZE_RESET, ctrl, XKB_KEY_KP_0);
|
|
|
|
|
add_binding(BIND_ACTION_SPAWN_TERMINAL, ctrl_shift, XKB_KEY_N);
|
|
|
|
|
|
|
|
|
|
#undef add_binding
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_default_search_bindings(struct config *conf)
|
|
|
|
|
{
|
|
|
|
|
#define add_binding(action, mods, sym) \
|
|
|
|
|
do { \
|
|
|
|
|
tll_push_back( \
|
|
|
|
|
conf->bindings.search, \
|
|
|
|
|
((struct config_key_binding_search){action, mods, sym})); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
const struct config_key_modifiers none = {};
|
|
|
|
|
const struct config_key_modifiers alt = {.alt = true};
|
|
|
|
|
const struct config_key_modifiers ctrl = {.ctrl = true};
|
|
|
|
|
const struct config_key_modifiers ctrl_shift = {.ctrl = true, .shift = true};
|
|
|
|
|
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_CANCEL, ctrl, XKB_KEY_g);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_CANCEL, none, XKB_KEY_Escape);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_COMMIT, none, XKB_KEY_Return);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_FIND_PREV, ctrl, XKB_KEY_r);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_FIND_NEXT, ctrl, XKB_KEY_s);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_LEFT, none, XKB_KEY_Left);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_LEFT, ctrl, XKB_KEY_b);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_LEFT_WORD, ctrl, XKB_KEY_Left);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_LEFT_WORD, alt, XKB_KEY_b);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_RIGHT, none, XKB_KEY_Right);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_RIGHT, ctrl, XKB_KEY_f);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, ctrl, XKB_KEY_Right);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, alt, XKB_KEY_f);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_HOME, none, XKB_KEY_Home);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_HOME, ctrl, XKB_KEY_a);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_END, none, XKB_KEY_End);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EDIT_END, ctrl, XKB_KEY_e);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_DELETE_PREV, none, XKB_KEY_BackSpace);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_DELETE_PREV_WORD, ctrl, XKB_KEY_BackSpace);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_DELETE_PREV_WORD, alt, XKB_KEY_BackSpace);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_DELETE_NEXT, none, XKB_KEY_Delete);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_DELETE_NEXT_WORD, ctrl, XKB_KEY_Delete);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_DELETE_NEXT_WORD, alt, XKB_KEY_d);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EXTEND_WORD, ctrl, XKB_KEY_w);
|
|
|
|
|
add_binding(BIND_ACTION_SEARCH_EXTEND_WORD_WS, ctrl_shift, XKB_KEY_W);
|
|
|
|
|
|
|
|
|
|
#undef add_binding
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_default_mouse_bindings(struct config *conf)
|
|
|
|
|
{
|
|
|
|
|
#define add_binding(action, mods, btn, count) \
|
|
|
|
|
do { \
|
|
|
|
|
tll_push_back( \
|
|
|
|
|
conf->bindings.mouse, \
|
|
|
|
|
((struct config_mouse_binding){action, mods, btn, count})); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
const struct config_key_modifiers none = {};
|
2020-08-11 09:55:33 +02:00
|
|
|
const struct config_key_modifiers ctrl = {.ctrl = true};
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
|
|
|
|
add_binding(BIND_ACTION_PRIMARY_PASTE, none, BTN_MIDDLE, 1);
|
2020-08-11 09:55:33 +02:00
|
|
|
add_binding(BIND_ACTION_SELECT_BEGIN, none, BTN_LEFT, 1);
|
2020-08-11 10:17:19 +02:00
|
|
|
add_binding(BIND_ACTION_SELECT_BEGIN_BLOCK, ctrl, BTN_LEFT, 1);
|
|
|
|
|
add_binding(BIND_ACTION_SELECT_EXTEND, none, BTN_RIGHT, 1);
|
2020-08-11 09:55:33 +02:00
|
|
|
add_binding(BIND_ACTION_SELECT_WORD, none, BTN_LEFT, 2);
|
|
|
|
|
add_binding(BIND_ACTION_SELECT_WORD_WS, ctrl, BTN_LEFT, 2);
|
2020-08-11 10:17:19 +02:00
|
|
|
add_binding(BIND_ACTION_SELECT_ROW, none, BTN_LEFT, 3);
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
|
|
|
|
|
#undef add_binding
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-17 10:12:14 +02:00
|
|
|
bool
|
2020-07-31 17:07:14 +02:00
|
|
|
config_load(struct config *conf, const char *conf_path, bool errors_are_fatal)
|
2019-07-16 11:52:22 +02:00
|
|
|
{
|
2019-07-17 10:12:14 +02:00
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
*conf = (struct config) {
|
2020-08-04 23:28:16 +01:00
|
|
|
.term = xstrdup("foot"),
|
2019-07-17 09:29:56 +02:00
|
|
|
.shell = get_shell(),
|
2020-08-04 23:28:16 +01:00
|
|
|
.title = xstrdup("foot"),
|
|
|
|
|
.app_id = xstrdup("foot"),
|
2020-02-29 11:01:23 +01:00
|
|
|
.width = 700,
|
|
|
|
|
.height = 500,
|
2020-02-15 19:00:56 +01:00
|
|
|
.pad_x = 2,
|
|
|
|
|
.pad_y = 2,
|
2020-03-26 19:39:12 +01:00
|
|
|
.startup_mode = STARTUP_WINDOWED,
|
2019-07-30 18:04:28 +02:00
|
|
|
.fonts = tll_init(),
|
2020-07-25 14:31:45 +02:00
|
|
|
.scrollback = {
|
|
|
|
|
.lines = 1000,
|
|
|
|
|
.indicator = {
|
2020-07-27 20:02:51 +02:00
|
|
|
.position = SCROLLBACK_INDICATOR_POSITION_RELATIVE,
|
2020-07-28 19:56:53 +02:00
|
|
|
.format = SCROLLBACK_INDICATOR_FORMAT_TEXT,
|
|
|
|
|
.text = wcsdup(L""),
|
2020-07-25 14:31:45 +02:00
|
|
|
},
|
2020-08-03 19:43:06 +02:00
|
|
|
.multiplier = 1.,
|
2020-07-25 14:31:45 +02:00
|
|
|
},
|
2019-07-21 11:06:28 +02:00
|
|
|
.colors = {
|
|
|
|
|
.fg = default_foreground,
|
|
|
|
|
.bg = default_background,
|
|
|
|
|
.regular = {
|
|
|
|
|
default_regular[0],
|
|
|
|
|
default_regular[1],
|
|
|
|
|
default_regular[2],
|
|
|
|
|
default_regular[3],
|
|
|
|
|
default_regular[4],
|
|
|
|
|
default_regular[5],
|
|
|
|
|
default_regular[6],
|
|
|
|
|
default_regular[7],
|
|
|
|
|
},
|
|
|
|
|
.bright = {
|
|
|
|
|
default_bright[0],
|
|
|
|
|
default_bright[1],
|
|
|
|
|
default_bright[2],
|
|
|
|
|
default_bright[3],
|
|
|
|
|
default_bright[4],
|
|
|
|
|
default_bright[5],
|
|
|
|
|
default_bright[6],
|
|
|
|
|
default_bright[7],
|
|
|
|
|
},
|
2019-08-16 22:06:06 +02:00
|
|
|
.alpha = 0xffff,
|
2020-08-12 18:53:32 +02:00
|
|
|
.selection_fg = 0x80000000, /* Use default bg */
|
|
|
|
|
.selection_bg = 0x80000000, /* Use default fg */
|
|
|
|
|
.selection_uses_custom_colors = false,
|
2019-07-21 11:06:28 +02:00
|
|
|
},
|
2019-07-22 20:15:14 +02:00
|
|
|
|
|
|
|
|
.cursor = {
|
|
|
|
|
.style = CURSOR_BLOCK,
|
2020-06-30 17:45:34 +02:00
|
|
|
.blink = false,
|
2019-07-23 18:54:58 +02:00
|
|
|
.color = {
|
|
|
|
|
.text = 0,
|
|
|
|
|
.cursor = 0,
|
|
|
|
|
},
|
2019-07-22 20:15:14 +02:00
|
|
|
},
|
2020-08-04 07:33:15 +02:00
|
|
|
.mouse = {
|
|
|
|
|
.hide_when_typing = false,
|
|
|
|
|
},
|
2020-03-02 18:42:49 +01:00
|
|
|
.csd = {
|
|
|
|
|
.preferred = CONF_CSD_PREFER_SERVER,
|
|
|
|
|
.title_height = 26,
|
|
|
|
|
.border_width = 5,
|
2020-03-06 19:11:31 +01:00
|
|
|
.button_width = 26,
|
2020-03-02 18:42:49 +01:00
|
|
|
},
|
|
|
|
|
|
2019-07-29 20:13:26 +02:00
|
|
|
.render_worker_count = sysconf(_SC_NPROCESSORS_ONLN),
|
2019-12-14 12:59:06 +01:00
|
|
|
.server_socket_path = get_server_socket_path(),
|
2020-02-03 19:58:32 +01:00
|
|
|
.presentation_timings = false,
|
|
|
|
|
.hold_at_exit = false,
|
2020-03-17 16:46:54 +01:00
|
|
|
|
|
|
|
|
.tweak = {
|
|
|
|
|
.delayed_render_lower_ns = 500000, /* 0.5ms */
|
|
|
|
|
.delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */
|
2020-03-25 20:48:02 +01:00
|
|
|
.max_shm_pool_size = 512 * 1024 * 1024,
|
2020-08-13 18:35:17 +02:00
|
|
|
.render_timer_osd = false,
|
|
|
|
|
.render_timer_log = false,
|
2020-03-17 16:46:54 +01:00
|
|
|
},
|
2020-07-29 19:42:12 +02:00
|
|
|
|
2020-07-30 18:57:21 +02:00
|
|
|
.notifications = tll_init(),
|
2019-07-16 11:52:22 +02:00
|
|
|
};
|
|
|
|
|
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
add_default_key_bindings(conf);
|
|
|
|
|
add_default_search_bindings(conf);
|
|
|
|
|
add_default_mouse_bindings(conf);
|
2020-07-15 16:39:07 +02:00
|
|
|
|
2019-12-17 19:08:43 +01:00
|
|
|
char *default_path = NULL;
|
|
|
|
|
if (conf_path == NULL) {
|
|
|
|
|
if ((default_path = get_config_path()) == NULL) {
|
|
|
|
|
/* Default conf */
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_WARN("no configuration found, using defaults");
|
|
|
|
|
ret = !errors_are_fatal;
|
2019-12-17 19:08:43 +01:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conf_path = default_path;
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-17 19:08:43 +01:00
|
|
|
assert(conf_path != NULL);
|
|
|
|
|
LOG_INFO("loading configuration from %s", conf_path);
|
2019-08-12 19:31:21 +02:00
|
|
|
|
2019-12-17 19:08:43 +01:00
|
|
|
FILE *f = fopen(conf_path, "r");
|
2019-07-16 11:52:22 +02:00
|
|
|
if (f == NULL) {
|
2020-07-31 17:07:14 +02:00
|
|
|
LOG_AND_NOTIFY_ERR("%s: failed to open", conf_path);
|
|
|
|
|
ret = !errors_are_fatal;
|
2019-07-16 11:52:22 +02:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-31 17:07:14 +02:00
|
|
|
ret = parse_config_file(f, conf, conf_path, errors_are_fatal);
|
2019-07-16 11:52:22 +02:00
|
|
|
fclose(f);
|
|
|
|
|
|
2020-08-12 18:53:32 +02:00
|
|
|
conf->colors.selection_uses_custom_colors =
|
|
|
|
|
conf->colors.selection_fg >> 24 == 0 &&
|
|
|
|
|
conf->colors.selection_bg >> 24 == 0;
|
|
|
|
|
|
2020-02-28 18:33:30 +01:00
|
|
|
out:
|
2019-12-17 19:08:43 +01:00
|
|
|
if (ret && tll_length(conf->fonts) == 0)
|
2020-07-07 10:44:55 +02:00
|
|
|
tll_push_back(conf->fonts, config_font_parse("monospace"));
|
2019-12-17 19:08:43 +01:00
|
|
|
|
|
|
|
|
free(default_path);
|
2019-07-17 10:12:14 +02:00
|
|
|
return ret;
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
config_free(struct config conf)
|
|
|
|
|
{
|
2019-07-21 11:46:46 +02:00
|
|
|
free(conf.term);
|
2019-07-17 09:29:56 +02:00
|
|
|
free(conf.shell);
|
2020-04-01 19:59:47 +02:00
|
|
|
free(conf.title);
|
2020-04-01 18:40:51 +02:00
|
|
|
free(conf.app_id);
|
2020-07-28 19:56:53 +02:00
|
|
|
free(conf.scrollback.indicator.text);
|
2020-07-07 10:44:55 +02:00
|
|
|
tll_foreach(conf.fonts, it)
|
|
|
|
|
config_font_destroy(&it->item);
|
|
|
|
|
tll_free(conf.fonts);
|
2019-12-14 12:59:06 +01:00
|
|
|
free(conf.server_socket_path);
|
2020-03-08 12:08:46 +01:00
|
|
|
|
2020-07-15 16:39:07 +02:00
|
|
|
tll_foreach(conf.bindings.key, it) {
|
config: key/mouse bindings: refactor: less parsing in keyboard_enter()
This simplifies the handling of mouse and keyboard bindings.
Before, the bindings where parsed *both* when loading the
configuration, and then on every keyboard enter event. This was done
since keys require a keymap to be decoded. Something we don't have at
configuration time. The idea was that at config time, we used a
default keymap just to verify the key combo strings were valid.
The following has changed:
* The bindings in the config struct is now *one* key combo per
entry. Previously, it was one *action* per entry, and each entry
had one or more key combos.
Doing it this way makes it easier when converting the binding in the
keyboard enter event (which previously had to expand the combos
anyway).
* The bindings in the config struct no longer contains any unparsed
strings.
A key binding contains a decoded 'modifier' struct (which specifies
whether e.g. ctrl, or shift, or ctrl+shift must be pressed for the
binding to be used).
It also contains a decoded XKB keysym.
* A mouse binding in the config struct is similar to a key binding,
except it contains the button, and click count instead of the XKB
key sym.
* The modifiers in the user-specified key combo is decoded at config
time, by using the pre-defined XKB constants
XKB_MOD_NAME_<modifier>.
The result is stored in a 'modifiers' struct, which is just a
collection of booleans; one for each supported modifier.
The supported modifiers are: shift, ctrl, alt and meta/super.
* The key sym is decoded at config time using
xkb_keysym_from_name(). This call does *not* depend on a keymap.
* The mouse button is decoded at config time using a hardcoded mapping
table (just like before).
* The click count is currently hard-coded to 1.
* In the keyboard enter event, all we need to do is pre-compute the
xkb_mod_mask_t variable for each key/mouse binding, and find all the
*key codes* that map to the (already decoded) symbol.
For mouse bindings, the modifiers are the *only* reason we convert
the mouse bindings at all.
In fact, on button events, we check if the seat has a keyboard. If
not, we use the mouse bindings from the configuration directly, and
simply filter out those with a non-empty set of modifiers.
2020-08-10 19:00:03 +02:00
|
|
|
if (it->item.pipe.master_copy) {
|
|
|
|
|
free(it->item.pipe.cmd);
|
|
|
|
|
free(it->item.pipe.argv);
|
|
|
|
|
}
|
2020-07-15 13:32:31 +02:00
|
|
|
}
|
2020-07-15 16:39:07 +02:00
|
|
|
|
|
|
|
|
tll_free(conf.bindings.key);
|
|
|
|
|
tll_free(conf.bindings.mouse);
|
|
|
|
|
tll_free(conf.bindings.search);
|
2020-07-29 19:42:12 +02:00
|
|
|
|
2020-07-30 18:57:21 +02:00
|
|
|
tll_foreach(conf.notifications, it)
|
2020-07-29 19:42:12 +02:00
|
|
|
free(it->item.text);
|
2020-07-30 18:57:21 +02:00
|
|
|
tll_free(conf.notifications);
|
2019-07-16 11:52:22 +02:00
|
|
|
}
|
2020-07-07 10:44:55 +02:00
|
|
|
|
|
|
|
|
struct config_font
|
|
|
|
|
config_font_parse(const char *pattern)
|
|
|
|
|
{
|
|
|
|
|
FcPattern *pat = FcNameParse((const FcChar8 *)pattern);
|
|
|
|
|
|
|
|
|
|
double pt_size = -1.0;
|
|
|
|
|
FcPatternGetDouble(pat, FC_SIZE, 0, &pt_size);
|
|
|
|
|
FcPatternRemove(pat, FC_SIZE, 0);
|
|
|
|
|
|
|
|
|
|
int px_size = -1;
|
|
|
|
|
FcPatternGetInteger(pat, FC_PIXEL_SIZE, 0, &px_size);
|
|
|
|
|
FcPatternRemove(pat, FC_PIXEL_SIZE, 0);
|
|
|
|
|
|
|
|
|
|
if (pt_size == -1. && px_size == -1)
|
|
|
|
|
pt_size = 8.0;
|
|
|
|
|
|
|
|
|
|
char *stripped_pattern = (char *)FcNameUnparse(pat);
|
|
|
|
|
FcPatternDestroy(pat);
|
|
|
|
|
|
|
|
|
|
return (struct config_font){
|
|
|
|
|
.pattern = stripped_pattern,
|
|
|
|
|
.pt_size = pt_size,
|
|
|
|
|
.px_size = px_size};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
config_font_destroy(struct config_font *font)
|
|
|
|
|
{
|
|
|
|
|
if (font == NULL)
|
|
|
|
|
return;
|
|
|
|
|
free(font->pattern);
|
|
|
|
|
}
|