mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
config, input: allow configuring select-override modifiers
This commit is contained in:
parent
281127cae1
commit
a4d53bdf88
6 changed files with 100 additions and 19 deletions
86
config.c
86
config.c
|
|
@ -1333,6 +1333,10 @@ parse_section_cursor(struct context *ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_modifiers(struct context *ctx, const char *text, size_t len,
|
||||
struct config_key_modifiers *modifiers);
|
||||
|
||||
static bool
|
||||
parse_section_mouse(struct context *ctx)
|
||||
{
|
||||
|
|
@ -1345,6 +1349,13 @@ parse_section_mouse(struct context *ctx)
|
|||
else if (strcmp(key, "alternate-scroll-mode") == 0)
|
||||
return value_to_bool(ctx, &conf->mouse.alternate_scroll_mode);
|
||||
|
||||
else if (strcmp(key, "selection-override-modifiers") == 0) {
|
||||
if (!parse_modifiers(ctx, ctx->value, strlen(ctx->value), &conf->mouse.selection_override_modifiers)) {
|
||||
LOG_CONTEXTUAL_ERR("%s: invalid modifiers '%s'", key, ctx->value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
LOG_CONTEXTUAL_ERR("not a valid option: %s", key);
|
||||
return false;
|
||||
|
|
@ -1971,10 +1982,6 @@ value_to_mouse_combos(struct context *ctx, struct key_combo_list *key_combos)
|
|||
*key = '\0';
|
||||
if (!parse_modifiers(ctx, combo, key - combo, &modifiers))
|
||||
goto err;
|
||||
if (modifiers.shift) {
|
||||
LOG_CONTEXTUAL_ERR("Shift cannot be used in mouse bindings");
|
||||
goto err;
|
||||
}
|
||||
key++; /* Skip past the '+' */
|
||||
}
|
||||
|
||||
|
|
@ -2054,6 +2061,62 @@ err:
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
modifiers_equal(const struct config_key_modifiers *mods1,
|
||||
const struct config_key_modifiers *mods2)
|
||||
{
|
||||
bool shift = mods1->shift == mods2->shift;
|
||||
bool alt = mods1->alt == mods2->alt;
|
||||
bool ctrl = mods1->ctrl == mods2->ctrl;
|
||||
bool meta = mods1->meta == mods2->meta;
|
||||
return shift && alt && ctrl && meta;
|
||||
}
|
||||
|
||||
static bool
|
||||
modifiers_disjoint(const struct config_key_modifiers *mods1,
|
||||
const struct config_key_modifiers *mods2)
|
||||
{
|
||||
bool shift = mods1->shift && mods2->shift;
|
||||
bool alt = mods1->alt && mods2->alt;
|
||||
bool ctrl = mods1->ctrl && mods2->ctrl;
|
||||
bool meta = mods1->meta && mods2->meta;
|
||||
return !(shift || alt || ctrl || meta);
|
||||
}
|
||||
|
||||
static char *
|
||||
modifiers_to_str(const struct config_key_modifiers *mods)
|
||||
{
|
||||
char *ret = xasprintf("%s%s%s%s",
|
||||
mods->ctrl ? "Control+" : "",
|
||||
mods->alt ? "Alt+": "",
|
||||
mods->meta ? "Meta+": "",
|
||||
mods->shift ? "Shift+": "");
|
||||
ret[strlen(ret) - 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
selection_override_interferes_with_mouse_binding(struct context *ctx,
|
||||
const struct key_combo_list *key_combos)
|
||||
{
|
||||
struct config *conf = ctx->conf;
|
||||
|
||||
const struct config_key_modifiers *override_mods = &conf->mouse.selection_override_modifiers;
|
||||
for (size_t i = 0; i < key_combos->count; i++) {
|
||||
const struct key_combo *combo = &key_combos->combos[i];
|
||||
if (!modifiers_disjoint(&combo->modifiers, override_mods)) {
|
||||
char *modifiers_str = modifiers_to_str(override_mods);
|
||||
LOG_CONTEXTUAL_ERR(
|
||||
"Selection override modifiers (%s) cannot be used in mouse bindings",
|
||||
modifiers_str);
|
||||
free (modifiers_str);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_mouse_binding_collisions(struct context *ctx,
|
||||
const struct key_combo_list *key_combos)
|
||||
|
|
@ -2071,14 +2134,10 @@ has_mouse_binding_collisions(struct context *ctx,
|
|||
const struct config_key_modifiers *mods1 = &combo1->modifiers;
|
||||
const struct config_key_modifiers *mods2 = &combo2->modifiers;
|
||||
|
||||
bool shift = mods1->shift == mods2->shift;
|
||||
bool alt = mods1->alt == mods2->alt;
|
||||
bool ctrl = mods1->ctrl == mods2->ctrl;
|
||||
bool meta = mods1->meta == mods2->meta;
|
||||
bool button = combo1->button == combo2->m.button;
|
||||
bool count = combo1->count == combo2->m.count;
|
||||
|
||||
if (shift && alt && ctrl && meta && button && count) {
|
||||
if (modifiers_equal(mods1, mods2) && button && count) {
|
||||
bool has_pipe = combo1->pipe.argv.args != NULL;
|
||||
LOG_CONTEXTUAL_ERR("%s already mapped to '%s%s%s%s'",
|
||||
combo2->text,
|
||||
|
|
@ -2136,7 +2195,8 @@ parse_section_mouse_bindings(struct context *ctx)
|
|||
|
||||
struct key_combo_list key_combos = {0};
|
||||
if (!value_to_mouse_combos(ctx, &key_combos) ||
|
||||
has_mouse_binding_collisions(ctx, &key_combos))
|
||||
has_mouse_binding_collisions(ctx, &key_combos) ||
|
||||
selection_override_interferes_with_mouse_binding(ctx, &key_combos))
|
||||
{
|
||||
free_argv(&pipe_argv);
|
||||
free_key_combo_list(&key_combos);
|
||||
|
|
@ -2780,6 +2840,12 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.mouse = {
|
||||
.hide_when_typing = false,
|
||||
.alternate_scroll_mode = true,
|
||||
.selection_override_modifiers = {
|
||||
.shift = true,
|
||||
.alt = false,
|
||||
.ctrl = false,
|
||||
.meta = false,
|
||||
},
|
||||
},
|
||||
.csd = {
|
||||
.preferred = CONF_CSD_PREFER_SERVER,
|
||||
|
|
|
|||
1
config.h
1
config.h
|
|
@ -193,6 +193,7 @@ struct config {
|
|||
struct {
|
||||
bool hide_when_typing;
|
||||
bool alternate_scroll_mode;
|
||||
struct config_key_modifiers selection_override_modifiers;
|
||||
} mouse;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
14
input.c
14
input.c
|
|
@ -701,6 +701,11 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
|||
seat->kbd.key_arrow_down = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "DOWN");
|
||||
}
|
||||
|
||||
/* Set selection-override modmask from configured mods and seat's mod indices */
|
||||
const struct config_key_modifiers* override_mods =
|
||||
&wayl->conf->mouse.selection_override_modifiers;
|
||||
seat->kbd.selection_override_modmask = conf_modifiers_to_mask(seat, override_mods);
|
||||
|
||||
munmap(map_str, size);
|
||||
close(fd);
|
||||
|
||||
|
|
@ -983,7 +988,7 @@ UNITTEST
|
|||
xassert(strcmp(info->seq, "\033[27;3;13~") == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
get_current_modifiers(const struct seat *seat,
|
||||
xkb_mod_mask_t *effective,
|
||||
xkb_mod_mask_t *consumed, uint32_t key)
|
||||
|
|
@ -2372,11 +2377,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
|
|||
get_current_modifiers(seat, &mods, NULL, 0);
|
||||
mods &= seat->kbd.bind_significant;
|
||||
|
||||
/* Ignore Shift when matching modifiers, since it is
|
||||
* used to enable selection in mouse grabbing client
|
||||
* applications */
|
||||
if (seat->kbd.mod_shift != XKB_MOD_INVALID)
|
||||
mods &= ~(1 << seat->kbd.mod_shift);
|
||||
/* Ignore selection override modifiers when matching modifiers */
|
||||
mods &= ~seat->kbd.selection_override_modmask;
|
||||
|
||||
const struct mouse_binding *match = NULL;
|
||||
|
||||
|
|
|
|||
5
input.h
5
input.h
|
|
@ -27,4 +27,9 @@ extern const struct wl_pointer_listener pointer_listener;
|
|||
|
||||
void input_repeat(struct seat *seat, uint32_t key);
|
||||
|
||||
void get_current_modifiers(const struct seat *seat,
|
||||
xkb_mod_mask_t *effective,
|
||||
xkb_mod_mask_t *consumed,
|
||||
uint32_t key);
|
||||
|
||||
const char *xcursor_for_csd_border(struct terminal *term, int x, int y);
|
||||
|
|
|
|||
11
terminal.c
11
terminal.c
|
|
@ -2826,10 +2826,15 @@ term_mouse_grabbed(const struct terminal *term, struct seat *seat)
|
|||
/*
|
||||
* Mouse is grabbed by us, regardless of whether mouse tracking has been enabled or not.
|
||||
*/
|
||||
|
||||
xkb_mod_mask_t mods;
|
||||
get_current_modifiers(seat, &mods, NULL, 0);
|
||||
|
||||
const xkb_mod_mask_t override_modmask = seat->kbd.selection_override_modmask;
|
||||
bool override_mods_pressed = (mods & override_modmask) == override_modmask;
|
||||
|
||||
return term->mouse_tracking == MOUSE_NONE ||
|
||||
(seat->kbd_focus == term &&
|
||||
seat->kbd.shift &&
|
||||
!seat->kbd.alt && /*!seat->kbd.ctrl &&*/ !seat->kbd.super);
|
||||
(seat->kbd_focus == term && override_mods_pressed);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -201,6 +201,8 @@ struct seat {
|
|||
xkb_mod_mask_t bind_significant;
|
||||
xkb_mod_mask_t kitty_significant;
|
||||
|
||||
xkb_mod_mask_t selection_override_modmask;
|
||||
|
||||
xkb_keycode_t key_arrow_up;
|
||||
xkb_keycode_t key_arrow_down;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue