mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-07 08:21:02 -04:00
config: wip: add support for modifiers in mouse bindings
Mouse bindings can now include modifiers. They are specified in pretty much the same way as in keyboard bindings: Control+BTN_LEFT
This commit is contained in:
parent
823a7c0318
commit
544c1b1976
6 changed files with 207 additions and 31 deletions
102
config.c
102
config.c
|
|
@ -657,7 +657,7 @@ verify_key_combo(struct config *conf, const char *combo, const char *path, unsig
|
||||||
{
|
{
|
||||||
/* Check regular key bindings */
|
/* Check regular key bindings */
|
||||||
tll_foreach(conf->bindings.key, it) {
|
tll_foreach(conf->bindings.key, it) {
|
||||||
char *copy = xstrdup(it->item.key);
|
char *copy = xstrdup(it->item.combos);
|
||||||
|
|
||||||
for (char *save = NULL, *collision = strtok_r(copy, " ", &save);
|
for (char *save = NULL, *collision = strtok_r(copy, " ", &save);
|
||||||
collision != NULL;
|
collision != NULL;
|
||||||
|
|
@ -680,7 +680,7 @@ verify_key_combo(struct config *conf, const char *combo, const char *path, unsig
|
||||||
|
|
||||||
/* Check scrollback search bindings */
|
/* Check scrollback search bindings */
|
||||||
tll_foreach(conf->bindings.search, it) {
|
tll_foreach(conf->bindings.search, it) {
|
||||||
char *copy = xstrdup(it->item.key);
|
char *copy = xstrdup(it->item.combos);
|
||||||
|
|
||||||
for (char *save = NULL, *collision = strtok_r(copy, " ", &save);
|
for (char *save = NULL, *collision = strtok_r(copy, " ", &save);
|
||||||
collision != NULL;
|
collision != NULL;
|
||||||
|
|
@ -714,6 +714,46 @@ verify_key_combo(struct config *conf, const char *combo, const char *path, unsig
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
verify_mouse_combo(struct config *conf,
|
||||||
|
const char *combo, enum bind_action_normal action,
|
||||||
|
const char *path, unsigned lineno)
|
||||||
|
{
|
||||||
|
tll_foreach(conf->bindings.mouse, it) {
|
||||||
|
char *copy = xstrdup(it->item.combos);
|
||||||
|
for (char *save = NULL, *collision = strtok_r(copy, " ", &save);
|
||||||
|
collision != NULL;
|
||||||
|
collision = strtok_r(NULL, " ", &save))
|
||||||
|
{
|
||||||
|
if (strcmp(combo, collision) == 0) {
|
||||||
|
LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s'", path, lineno, combo,
|
||||||
|
binding_action_map[it->item.action]);
|
||||||
|
free(copy);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
struct xkb_keymap *keymap = xkb_keymap_new_from_names(
|
||||||
|
ctx, &(struct xkb_rule_names){}, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
bool valid_combo = input_parse_mouse_binding(keymap, combo, action, NULL);
|
||||||
|
|
||||||
|
xkb_keymap_unref(keymap);
|
||||||
|
xkb_context_unref(ctx);
|
||||||
|
|
||||||
|
if (!valid_combo) {
|
||||||
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid mouse binding: %s",
|
||||||
|
path, lineno, combo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
argv_compare(char *const *argv1, char *const *argv2)
|
argv_compare(char *const *argv1, char *const *argv2)
|
||||||
{
|
{
|
||||||
|
|
@ -780,7 +820,7 @@ parse_section_key_bindings(
|
||||||
if (strcasecmp(value, "none") == 0) {
|
if (strcasecmp(value, "none") == 0) {
|
||||||
tll_foreach(conf->bindings.key, it) {
|
tll_foreach(conf->bindings.key, it) {
|
||||||
if (it->item.action == action) {
|
if (it->item.action == action) {
|
||||||
free(it->item.key);
|
free(it->item.combos);
|
||||||
free(it->item.pipe.cmd);
|
free(it->item.pipe.cmd);
|
||||||
free(it->item.pipe.argv);
|
free(it->item.pipe.argv);
|
||||||
tll_remove(conf->bindings.key, it);
|
tll_remove(conf->bindings.key, it);
|
||||||
|
|
@ -805,11 +845,11 @@ parse_section_key_bindings(
|
||||||
argv_compare(it->item.pipe.argv, pipe_argv) == 0)))
|
argv_compare(it->item.pipe.argv, pipe_argv) == 0)))
|
||||||
{
|
{
|
||||||
|
|
||||||
free(it->item.key);
|
free(it->item.combos);
|
||||||
free(it->item.pipe.cmd);
|
free(it->item.pipe.cmd);
|
||||||
free(it->item.pipe.argv);
|
free(it->item.pipe.argv);
|
||||||
|
|
||||||
it->item.key = xstrdup(value);
|
it->item.combos = xstrdup(value);
|
||||||
it->item.pipe.cmd = pipe_cmd;
|
it->item.pipe.cmd = pipe_cmd;
|
||||||
it->item.pipe.argv = pipe_argv;
|
it->item.pipe.argv = pipe_argv;
|
||||||
already_added = true;
|
already_added = true;
|
||||||
|
|
@ -820,7 +860,7 @@ parse_section_key_bindings(
|
||||||
if (!already_added) {
|
if (!already_added) {
|
||||||
struct config_key_binding_normal binding = {
|
struct config_key_binding_normal binding = {
|
||||||
.action = action,
|
.action = action,
|
||||||
.key = xstrdup(value),
|
.combos = xstrdup(value),
|
||||||
.pipe = {
|
.pipe = {
|
||||||
.cmd = pipe_cmd,
|
.cmd = pipe_cmd,
|
||||||
.argv = pipe_argv,
|
.argv = pipe_argv,
|
||||||
|
|
@ -854,24 +894,21 @@ parse_section_search_bindings(
|
||||||
if (strcasecmp(value, "none") == 0) {
|
if (strcasecmp(value, "none") == 0) {
|
||||||
tll_foreach(conf->bindings.search, it) {
|
tll_foreach(conf->bindings.search, it) {
|
||||||
if (it->item.action == action) {
|
if (it->item.action == action) {
|
||||||
free(it->item.key);
|
free(it->item.combos);
|
||||||
tll_remove(conf->bindings.search, it);
|
tll_remove(conf->bindings.search, it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verify_key_combo(conf, value, path, lineno)) {
|
if (!verify_key_combo(conf, value, path, lineno))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
bool already_added = false;
|
bool already_added = false;
|
||||||
tll_foreach(conf->bindings.search, it) {
|
tll_foreach(conf->bindings.search, it) {
|
||||||
if (it->item.action == action) {
|
if (it->item.action == action) {
|
||||||
|
free(it->item.combos);
|
||||||
free(it->item.key);
|
it->item.combos = xstrdup(value);
|
||||||
|
|
||||||
it->item.key = xstrdup(value);
|
|
||||||
already_added = true;
|
already_added = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -880,7 +917,7 @@ parse_section_search_bindings(
|
||||||
if (!already_added) {
|
if (!already_added) {
|
||||||
struct config_key_binding_search binding = {
|
struct config_key_binding_search binding = {
|
||||||
.action = action,
|
.action = action,
|
||||||
.key = xstrdup(value),
|
.combos = xstrdup(value),
|
||||||
};
|
};
|
||||||
tll_push_back(conf->bindings.search, binding);
|
tll_push_back(conf->bindings.search, binding);
|
||||||
}
|
}
|
||||||
|
|
@ -907,6 +944,7 @@ parse_section_mouse_bindings(
|
||||||
if (strcmp(value, "NONE") == 0) {
|
if (strcmp(value, "NONE") == 0) {
|
||||||
tll_foreach(conf->bindings.mouse, it) {
|
tll_foreach(conf->bindings.mouse, it) {
|
||||||
if (it->item.action == action) {
|
if (it->item.action == action) {
|
||||||
|
free(it->item.combos);
|
||||||
tll_remove(conf->bindings.mouse, it);
|
tll_remove(conf->bindings.mouse, it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -914,6 +952,29 @@ parse_section_mouse_bindings(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!verify_mouse_combo(conf, value, action, path, lineno))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool already_added = false;
|
||||||
|
tll_foreach(conf->bindings.mouse, it) {
|
||||||
|
if (it->item.action == action) {
|
||||||
|
free(it->item.combos);
|
||||||
|
it->item.combos = xstrdup(value);
|
||||||
|
already_added = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!already_added) {
|
||||||
|
struct config_mouse_binding binding = {
|
||||||
|
.action = action,
|
||||||
|
.combos = xstrdup(value),
|
||||||
|
};
|
||||||
|
tll_push_back(conf->bindings.mouse, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#if 0
|
||||||
const char *map[] = {
|
const char *map[] = {
|
||||||
[BTN_LEFT] = "BTN_LEFT",
|
[BTN_LEFT] = "BTN_LEFT",
|
||||||
[BTN_RIGHT] = "BTN_RIGHT",
|
[BTN_RIGHT] = "BTN_RIGHT",
|
||||||
|
|
@ -951,8 +1012,9 @@ parse_section_mouse_bindings(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!already_added) {
|
if (!already_added) {
|
||||||
struct mouse_binding binding = {
|
struct config_mouse_binding binding = {
|
||||||
.action = action,
|
.action = action,
|
||||||
|
.mods = xstrdup(""),
|
||||||
.button = i,
|
.button = i,
|
||||||
.count = count,
|
.count = count,
|
||||||
};
|
};
|
||||||
|
|
@ -963,7 +1025,7 @@ parse_section_mouse_bindings(
|
||||||
|
|
||||||
LOG_AND_NOTIFY_ERR("%s:%d: invalid mouse button: %s", path, lineno, value);
|
LOG_AND_NOTIFY_ERR("%s:%d: invalid mouse button: %s", path, lineno, value);
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_AND_NOTIFY_ERR("%s:%u: [mouse-bindings]: %s: invalid key", path, lineno, key);
|
LOG_AND_NOTIFY_ERR("%s:%u: [mouse-bindings]: %s: invalid key", path, lineno, key);
|
||||||
|
|
@ -1340,7 +1402,7 @@ config_load(struct config *conf, const char *conf_path, bool errors_are_fatal)
|
||||||
tll_push_back(conf->bindings.key, font_size_reset);
|
tll_push_back(conf->bindings.key, font_size_reset);
|
||||||
tll_push_back(conf->bindings.key, spawn_terminal);
|
tll_push_back(conf->bindings.key, spawn_terminal);
|
||||||
|
|
||||||
struct mouse_binding primary_paste = {BIND_ACTION_PRIMARY_PASTE, BTN_MIDDLE, 1};
|
struct config_mouse_binding primary_paste = {BIND_ACTION_PRIMARY_PASTE, xstrdup("BTN_MIDDLE")};
|
||||||
tll_push_back(conf->bindings.mouse, primary_paste);
|
tll_push_back(conf->bindings.mouse, primary_paste);
|
||||||
|
|
||||||
struct config_key_binding_search search_cancel = {BIND_ACTION_SEARCH_CANCEL, xstrdup("Control+g Escape")};
|
struct config_key_binding_search search_cancel = {BIND_ACTION_SEARCH_CANCEL, xstrdup("Control+g Escape")};
|
||||||
|
|
@ -1428,12 +1490,14 @@ config_free(struct config conf)
|
||||||
free(conf.server_socket_path);
|
free(conf.server_socket_path);
|
||||||
|
|
||||||
tll_foreach(conf.bindings.key, it) {
|
tll_foreach(conf.bindings.key, it) {
|
||||||
free(it->item.key);
|
free(it->item.combos);
|
||||||
free(it->item.pipe.cmd);
|
free(it->item.pipe.cmd);
|
||||||
free(it->item.pipe.argv);
|
free(it->item.pipe.argv);
|
||||||
}
|
}
|
||||||
|
tll_foreach(conf.bindings.mouse, it)
|
||||||
|
free(it->item.combos);
|
||||||
tll_foreach(conf.bindings.search, it)
|
tll_foreach(conf.bindings.search, it)
|
||||||
free(it->item.key);
|
free(it->item.combos);
|
||||||
|
|
||||||
tll_free(conf.bindings.key);
|
tll_free(conf.bindings.key);
|
||||||
tll_free(conf.bindings.mouse);
|
tll_free(conf.bindings.mouse);
|
||||||
|
|
|
||||||
11
config.h
11
config.h
|
|
@ -17,16 +17,21 @@ struct config_font {
|
||||||
|
|
||||||
struct config_key_binding_normal {
|
struct config_key_binding_normal {
|
||||||
enum bind_action_normal action;
|
enum bind_action_normal action;
|
||||||
char *key;
|
char *combos;
|
||||||
struct {
|
struct {
|
||||||
char *cmd;
|
char *cmd;
|
||||||
char **argv;
|
char **argv;
|
||||||
} pipe;
|
} pipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct config_mouse_binding {
|
||||||
|
enum bind_action_normal action;
|
||||||
|
char *combos;
|
||||||
|
};
|
||||||
|
|
||||||
struct config_key_binding_search {
|
struct config_key_binding_search {
|
||||||
enum bind_action_search action;
|
enum bind_action_search action;
|
||||||
char *key;
|
char *combos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config {
|
struct config {
|
||||||
|
|
@ -91,7 +96,7 @@ struct config {
|
||||||
struct {
|
struct {
|
||||||
/* Bindings for "normal" mode */
|
/* Bindings for "normal" mode */
|
||||||
tll(struct config_key_binding_normal) key;
|
tll(struct config_key_binding_normal) key;
|
||||||
tll(struct mouse_binding) mouse;
|
tll(struct config_mouse_binding) mouse;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special modes
|
* Special modes
|
||||||
|
|
|
||||||
113
input.c
113
input.c
|
|
@ -303,7 +303,8 @@ input_parse_key_binding(struct xkb_keymap *keymap, const char *combos,
|
||||||
if (sym == XKB_KEY_NoSymbol) {
|
if (sym == XKB_KEY_NoSymbol) {
|
||||||
LOG_ERR("%s: key binding is not a valid XKB symbol name",
|
LOG_ERR("%s: key binding is not a valid XKB symbol name",
|
||||||
key);
|
key);
|
||||||
break;
|
free(copy);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -353,6 +354,90 @@ input_parse_key_binding(struct xkb_keymap *keymap, const char *combos,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
input_parse_mouse_binding(struct xkb_keymap *keymap, const char *combos,
|
||||||
|
enum bind_action_normal action,
|
||||||
|
mouse_binding_list_t *bindings)
|
||||||
|
{
|
||||||
|
if (combos == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
char *copy = xstrdup(combos);
|
||||||
|
for (char *save1 = NULL, *combo = strtok_r(copy, " ", &save1);
|
||||||
|
combo != NULL;
|
||||||
|
combo = strtok_r(NULL, " ", &save1))
|
||||||
|
{
|
||||||
|
xkb_mod_mask_t mod_mask = 0;
|
||||||
|
int button = 0;
|
||||||
|
|
||||||
|
for (char *save2 = NULL, *key = strtok_r(combo, "+", &save2),
|
||||||
|
*next_key = strtok_r(NULL, "+", &save2);
|
||||||
|
key != NULL;
|
||||||
|
key = next_key, next_key = strtok_r(NULL, "+", &save2))
|
||||||
|
{
|
||||||
|
if (next_key != NULL) {
|
||||||
|
/* Modifier */
|
||||||
|
xkb_mod_index_t mod = xkb_keymap_mod_get_index(keymap, key);
|
||||||
|
|
||||||
|
if (mod == -1) {
|
||||||
|
LOG_ERR("%s: not a valid modifier name", key);
|
||||||
|
free(copy);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_mask |= 1 << mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
/* Button */
|
||||||
|
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},
|
||||||
|
};
|
||||||
|
|
||||||
|
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_ERR("%s: invalid mouse button name", key);
|
||||||
|
free(copy);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bindings != NULL) {
|
||||||
|
const struct mouse_binding binding = {
|
||||||
|
.action = action,
|
||||||
|
.mods = mod_mask,
|
||||||
|
.button = button,
|
||||||
|
.count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
tll_push_back(*bindings, binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(copy);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
uint32_t format, int32_t fd, uint32_t size)
|
uint32_t format, int32_t fd, uint32_t size)
|
||||||
|
|
@ -402,6 +487,8 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
tll_free(it->item.bind.key_codes);
|
tll_free(it->item.bind.key_codes);
|
||||||
tll_free(seat->kbd.bindings.search);
|
tll_free(seat->kbd.bindings.search);
|
||||||
|
|
||||||
|
tll_free(seat->mouse.bindings);
|
||||||
|
|
||||||
seat->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
seat->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
seat->kbd.xkb_keymap = xkb_keymap_new_from_buffer(
|
seat->kbd.xkb_keymap = xkb_keymap_new_from_buffer(
|
||||||
seat->kbd.xkb, map_str, size, XKB_KEYMAP_FORMAT_TEXT_V1,
|
seat->kbd.xkb, map_str, size, XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
|
|
@ -427,7 +514,7 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
tll_foreach(wayl->conf->bindings.key, it) {
|
tll_foreach(wayl->conf->bindings.key, it) {
|
||||||
key_binding_list_t bindings = tll_init();
|
key_binding_list_t bindings = tll_init();
|
||||||
input_parse_key_binding(
|
input_parse_key_binding(
|
||||||
seat->kbd.xkb_keymap, it->item.key, &bindings);
|
seat->kbd.xkb_keymap, it->item.combos, &bindings);
|
||||||
|
|
||||||
tll_foreach(bindings, it2) {
|
tll_foreach(bindings, it2) {
|
||||||
tll_push_back(
|
tll_push_back(
|
||||||
|
|
@ -443,7 +530,7 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
tll_foreach(wayl->conf->bindings.search, it) {
|
tll_foreach(wayl->conf->bindings.search, it) {
|
||||||
key_binding_list_t bindings = tll_init();
|
key_binding_list_t bindings = tll_init();
|
||||||
input_parse_key_binding(
|
input_parse_key_binding(
|
||||||
seat->kbd.xkb_keymap, it->item.key, &bindings);
|
seat->kbd.xkb_keymap, it->item.combos, &bindings);
|
||||||
|
|
||||||
tll_foreach(bindings, it2) {
|
tll_foreach(bindings, it2) {
|
||||||
tll_push_back(
|
tll_push_back(
|
||||||
|
|
@ -453,6 +540,12 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
}
|
}
|
||||||
tll_free(bindings);
|
tll_free(bindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tll_foreach(wayl->conf->bindings.mouse, it) {
|
||||||
|
input_parse_mouse_binding(
|
||||||
|
seat->kbd.xkb_keymap, it->item.combos, it->item.action,
|
||||||
|
&seat->mouse.bindings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1440,9 +1533,12 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
|
|
||||||
bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
|
bool cursor_is_on_grid = seat->mouse.col >= 0 && seat->mouse.row >= 0;
|
||||||
|
|
||||||
|
xkb_mod_mask_t mods = xkb_state_serialize_mods(
|
||||||
|
seat->kbd.xkb_state, XKB_STATE_MODS_DEPRESSED);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case WL_POINTER_BUTTON_STATE_PRESSED: {
|
case WL_POINTER_BUTTON_STATE_PRESSED: {
|
||||||
if (button == BTN_LEFT && seat->mouse.count <= 3) {
|
if (button == BTN_LEFT && seat->mouse.count <= 3 && mods == 0) {
|
||||||
selection_cancel(term);
|
selection_cancel(term);
|
||||||
|
|
||||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||||
|
|
@ -1466,7 +1562,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (button == BTN_RIGHT && seat->mouse.count == 1) {
|
else if (button == BTN_RIGHT && seat->mouse.count == 1 && mods == 0) {
|
||||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||||
selection_extend(
|
selection_extend(
|
||||||
seat, term, seat->mouse.col, seat->mouse.row, serial);
|
seat, term, seat->mouse.col, seat->mouse.row, serial);
|
||||||
|
|
@ -1474,7 +1570,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
tll_foreach(wayl->conf->bindings.mouse, it) {
|
tll_foreach(seat->mouse.bindings, it) {
|
||||||
const struct mouse_binding *binding = &it->item;
|
const struct mouse_binding *binding = &it->item;
|
||||||
|
|
||||||
if (binding->button != button) {
|
if (binding->button != button) {
|
||||||
|
|
@ -1482,6 +1578,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (binding->mods != mods) {
|
||||||
|
/* Modifier mismatch */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (binding->count != seat->mouse.count) {
|
if (binding->count != seat->mouse.count) {
|
||||||
/* Not correct click count */
|
/* Not correct click count */
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
3
input.h
3
input.h
|
|
@ -12,3 +12,6 @@ void input_repeat(struct seat *seat, uint32_t key);
|
||||||
|
|
||||||
bool input_parse_key_binding(struct xkb_keymap *keymap, const char *combos,
|
bool input_parse_key_binding(struct xkb_keymap *keymap, const char *combos,
|
||||||
key_binding_list_t *bindings);
|
key_binding_list_t *bindings);
|
||||||
|
bool input_parse_mouse_binding(struct xkb_keymap *keymap, const char *combos,
|
||||||
|
enum bind_action_normal action,
|
||||||
|
mouse_binding_list_t *bindings);
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,8 @@ seat_destroy(struct seat *seat)
|
||||||
tll_free(it->item.bind.key_codes);
|
tll_free(it->item.bind.key_codes);
|
||||||
tll_free(seat->kbd.bindings.search);
|
tll_free(seat->kbd.bindings.search);
|
||||||
|
|
||||||
|
tll_free(seat->mouse.bindings);
|
||||||
|
|
||||||
if (seat->kbd.xkb_compose_state != NULL)
|
if (seat->kbd.xkb_compose_state != NULL)
|
||||||
xkb_compose_state_unref(seat->kbd.xkb_compose_state);
|
xkb_compose_state_unref(seat->kbd.xkb_compose_state);
|
||||||
if (seat->kbd.xkb_compose_table != NULL)
|
if (seat->kbd.xkb_compose_table != NULL)
|
||||||
|
|
@ -762,9 +764,6 @@ handle_global(void *data, struct wl_registry *registry,
|
||||||
struct wl_seat *wl_seat = wl_registry_bind(
|
struct wl_seat *wl_seat = wl_registry_bind(
|
||||||
wayl->registry, name, &wl_seat_interface, required);
|
wayl->registry, name, &wl_seat_interface, required);
|
||||||
|
|
||||||
/* Clipboard */
|
|
||||||
/* Primary selection */
|
|
||||||
|
|
||||||
tll_push_back(wayl->seats, ((struct seat){
|
tll_push_back(wayl->seats, ((struct seat){
|
||||||
.wayl = wayl,
|
.wayl = wayl,
|
||||||
.wl_seat = wl_seat,
|
.wl_seat = wl_seat,
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,11 @@ struct key_binding_normal {
|
||||||
|
|
||||||
struct mouse_binding {
|
struct mouse_binding {
|
||||||
enum bind_action_normal action;
|
enum bind_action_normal action;
|
||||||
|
xkb_mod_mask_t mods;
|
||||||
uint32_t button;
|
uint32_t button;
|
||||||
int count;
|
int count;
|
||||||
};
|
};
|
||||||
|
typedef tll(struct mouse_binding) mouse_binding_list_t;
|
||||||
|
|
||||||
enum bind_action_search {
|
enum bind_action_search {
|
||||||
BIND_ACTION_SEARCH_NONE,
|
BIND_ACTION_SEARCH_NONE,
|
||||||
|
|
@ -173,6 +175,8 @@ struct seat {
|
||||||
/* We used a discrete axis event in the current pointer frame */
|
/* We used a discrete axis event in the current pointer frame */
|
||||||
double axis_aggregated;
|
double axis_aggregated;
|
||||||
bool have_discrete;
|
bool have_discrete;
|
||||||
|
|
||||||
|
mouse_binding_list_t bindings;
|
||||||
} mouse;
|
} mouse;
|
||||||
|
|
||||||
/* Clipboard */
|
/* Clipboard */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue