mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-07-05 00:06:20 -04:00
feat: add bindm (modifier-only exclusive keybind)
This commit is contained in:
parent
cabafb2393
commit
01a7bf5a8d
2 changed files with 132 additions and 0 deletions
|
|
@ -45,6 +45,7 @@ typedef struct {
|
|||
bool islockapply;
|
||||
bool isreleaseapply;
|
||||
bool ispassapply;
|
||||
bool ismodonly;
|
||||
} KeyBinding;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -2436,6 +2437,92 @@ bool parse_option(Config *config, char *key, char *value) {
|
|||
config->key_bindings_count++;
|
||||
}
|
||||
|
||||
} else if (regex_match("^bindm[lp]*$", key)) {
|
||||
/* bindm: fire on modifier release if no other bind used the hold
|
||||
* format: bindm[flags]=MODIFIERS,,COMMAND,PARAMS */
|
||||
config->key_bindings =
|
||||
realloc(config->key_bindings,
|
||||
(config->key_bindings_count + 1) * sizeof(KeyBinding));
|
||||
if (!config->key_bindings) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Failed to allocate "
|
||||
"memory for key bindings (bindm)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyBinding *binding = &config->key_bindings[config->key_bindings_count];
|
||||
memset(binding, 0, sizeof(KeyBinding));
|
||||
|
||||
char mod_str[256], func_name[256],
|
||||
arg_value[256] = "0\0", arg_value2[256] = "0\0",
|
||||
arg_value3[256] = "0\0", arg_value4[256] = "0\0",
|
||||
arg_value5[256] = "0\0";
|
||||
|
||||
if (sscanf(value,
|
||||
"%255[^,],,%255[^,],%255[^,],%255[^,],%255[^,],%255[^\n]",
|
||||
mod_str, func_name, arg_value, arg_value2,
|
||||
arg_value3, arg_value4) < 2) {
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Invalid bindm format "
|
||||
"(expected MODIFIERS,,COMMAND,...): "
|
||||
"\033[1m\033[31m%s\n",
|
||||
value);
|
||||
return false;
|
||||
}
|
||||
trim_whitespace(mod_str);
|
||||
trim_whitespace(func_name);
|
||||
trim_whitespace(arg_value);
|
||||
trim_whitespace(arg_value2);
|
||||
trim_whitespace(arg_value3);
|
||||
trim_whitespace(arg_value4);
|
||||
trim_whitespace(arg_value5);
|
||||
|
||||
strcpy(binding->mode, config->keymode);
|
||||
if (strcmp(binding->mode, "common") == 0) {
|
||||
binding->iscommonmode = true;
|
||||
binding->isdefaultmode = false;
|
||||
} else if (strcmp(binding->mode, "default") == 0) {
|
||||
binding->isdefaultmode = true;
|
||||
binding->iscommonmode = false;
|
||||
} else {
|
||||
binding->isdefaultmode = false;
|
||||
binding->iscommonmode = false;
|
||||
}
|
||||
|
||||
for (const char *f = key + 5; *f != '\0'; f++) {
|
||||
if (*f == 'l') binding->islockapply = true;
|
||||
if (*f == 'p') binding->ispassapply = true;
|
||||
}
|
||||
|
||||
binding->mod = parse_mod(mod_str);
|
||||
binding->ismodonly = true;
|
||||
|
||||
binding->func =
|
||||
parse_func_name(func_name, &binding->arg, arg_value, arg_value2,
|
||||
arg_value3, arg_value4, arg_value5);
|
||||
if (!binding->func || binding->mod == UINT32_MAX) {
|
||||
if (binding->arg.v) {
|
||||
free(binding->arg.v);
|
||||
binding->arg.v = NULL;
|
||||
}
|
||||
if (binding->arg.v2) {
|
||||
free(binding->arg.v2);
|
||||
binding->arg.v2 = NULL;
|
||||
}
|
||||
if (binding->arg.v3) {
|
||||
free(binding->arg.v3);
|
||||
binding->arg.v3 = NULL;
|
||||
}
|
||||
if (!binding->func)
|
||||
fprintf(stderr,
|
||||
"\033[1m\033[31m[ERROR]:\033[33m Unknown dispatch in "
|
||||
"bindm: \033[1m\033[31m%s\n",
|
||||
func_name);
|
||||
return false;
|
||||
} else {
|
||||
config->key_bindings_count++;
|
||||
}
|
||||
|
||||
} else if (strncmp(key, "mousebind", 9) == 0) {
|
||||
config->mouse_bindings =
|
||||
realloc(config->mouse_bindings,
|
||||
|
|
|
|||
45
src/mango.c
45
src/mango.c
|
|
@ -922,6 +922,10 @@ static struct wl_event_source *hide_cursor_source;
|
|||
static struct wl_event_source *keep_idle_inhibit_source;
|
||||
static bool cursor_hidden = false;
|
||||
static bool tag_combo = false;
|
||||
|
||||
/* set when a bind fires while modifiers held; cleared on modifier press */
|
||||
static bool mod_used_for_bind = false;
|
||||
|
||||
static const char *cli_config_path = NULL;
|
||||
static bool cli_debug_log = false;
|
||||
static KeyMode keymode = {
|
||||
|
|
@ -2332,6 +2336,7 @@ buttonpress(struct wl_listener *listener, void *data) {
|
|||
event->button == m->button && m->func &&
|
||||
(CLEANMASK(m->mod) != 0 ||
|
||||
(event->button != BTN_LEFT && event->button != BTN_RIGHT))) {
|
||||
mod_used_for_bind = true;
|
||||
m->func(&m->arg);
|
||||
return;
|
||||
}
|
||||
|
|
@ -3996,6 +4001,9 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym,
|
|||
state != WL_KEYBOARD_KEY_STATE_RELEASED)
|
||||
continue;
|
||||
|
||||
if (config.key_bindings[ji].ismodonly)
|
||||
continue;
|
||||
|
||||
k = &config.key_bindings[ji];
|
||||
if ((k->iscommonmode || (k->isdefaultmode && keymode.isdefault) ||
|
||||
(strcmp(keymode.mode, k->mode) == 0)) &&
|
||||
|
|
@ -4014,6 +4022,9 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym,
|
|||
else
|
||||
handled = 0;
|
||||
|
||||
if (!k->ispassapply)
|
||||
mod_used_for_bind = true;
|
||||
|
||||
isbreak = k->func(&k->arg);
|
||||
|
||||
if (isbreak)
|
||||
|
|
@ -4115,6 +4126,15 @@ void keypress(struct wl_listener *listener, void *data) {
|
|||
|
||||
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
||||
|
||||
bool is_modifier_key =
|
||||
(keycode == 133 || keycode == 134 ||
|
||||
keycode == 37 || keycode == 105 ||
|
||||
keycode == 64 || keycode == 108 ||
|
||||
keycode == 50 || keycode == 62);
|
||||
|
||||
if (is_modifier_key && event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
mod_used_for_bind = false;
|
||||
|
||||
// ov tab mode detect moe key release
|
||||
if (config.ov_tab_mode && !locked && group == kb_group &&
|
||||
event->state == WL_KEYBOARD_KEY_STATE_RELEASED &&
|
||||
|
|
@ -4132,6 +4152,31 @@ void keypress(struct wl_listener *listener, void *data) {
|
|||
handled =
|
||||
keybinding(event->state, locked, mods, syms[i], keycode) || handled;
|
||||
|
||||
/* bindm: fire mod-only binds on release if no combo fired */
|
||||
if (is_modifier_key && event->state == WL_KEYBOARD_KEY_STATE_RELEASED &&
|
||||
!mod_used_for_bind) {
|
||||
int32_t ji;
|
||||
for (ji = 0; ji < config.key_bindings_count; ji++) {
|
||||
const KeyBinding *k = &config.key_bindings[ji];
|
||||
|
||||
if (!k->ismodonly)
|
||||
continue;
|
||||
if (locked && !k->islockapply)
|
||||
continue;
|
||||
if (!(k->iscommonmode ||
|
||||
(k->isdefaultmode && keymode.isdefault) ||
|
||||
(strcmp(keymode.mode, k->mode) == 0)))
|
||||
continue;
|
||||
if (CLEANMASK(mods) != CLEANMASK(k->mod))
|
||||
continue;
|
||||
if (!k->func)
|
||||
continue;
|
||||
|
||||
handled = 1;
|
||||
k->func(&k->arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
tag_combo = false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue