Skip to content

Commit 6236adb

Browse files
feat: allow-none-key-name
Fixed none keybind trigger involving an additional modifier bug Fixed mouse click behaviour bug
1 parent 722f9f6 commit 6236adb

2 files changed

Lines changed: 89 additions & 1 deletion

File tree

src/config/parse_config.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
enum { NUM_TYPE_MINUS, NUM_TYPE_PLUS, NUM_TYPE_DEFAULT };
2222

23-
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
23+
enum { KEY_TYPE_CODE, KEY_TYPE_SYM, KEY_TYPE_NONE };
2424

2525
typedef struct {
2626
uint32_t keycode1;
@@ -768,6 +768,22 @@ void create_config_keymap(void) {
768768
KeySymCode parse_key(const char *key_str, bool isbindsym) {
769769
KeySymCode kc = {0}; // 初始化为0
770770

771+
// Handle "none" key for modifier-only bindings
772+
{
773+
char lower_key[10];
774+
int32_t ki = 0;
775+
while (key_str[ki] && ki < 9) {
776+
lower_key[ki] = tolower(key_str[ki]);
777+
ki++;
778+
}
779+
lower_key[ki] = '\0';
780+
if (strcmp(lower_key, "none") == 0) {
781+
kc.type = KEY_TYPE_NONE;
782+
kc.keysym = XKB_KEY_NoSymbol;
783+
return kc;
784+
}
785+
}
786+
771787
if (config.keymap == NULL || config.ctx == NULL) {
772788
// 处理错误
773789
kc.type = KEY_TYPE_SYM;
@@ -2315,6 +2331,18 @@ bool parse_option(Config *config, char *key, char *value) {
23152331
binding->func =
23162332
parse_func_name(func_name, &binding->arg, arg_value, arg_value2,
23172333
arg_value3, arg_value4, arg_value5);
2334+
2335+
/* KEY_TYPE_NONE bindings must use the release flag (bindr) */
2336+
if (binding->keysymcode.type == KEY_TYPE_NONE) {
2337+
if (!binding->isreleaseapply) {
2338+
fprintf(stderr,
2339+
"\033[1m\033[33m[WARN]:\033[0m "
2340+
"\"none\" key only works with bindr "
2341+
"(release bind), forcing release mode\n");
2342+
binding->isreleaseapply = true;
2343+
}
2344+
}
2345+
23182346
if (!binding->func || binding->mod == UINT32_MAX ||
23192347
(binding->keysymcode.type == KEY_TYPE_SYM &&
23202348
binding->keysymcode.keysym == XKB_KEY_NoSymbol)) {

src/mango.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,8 @@ struct dvec2 *baked_points_opafadeout;
887887
static struct wl_event_source *hide_source;
888888
static bool cursor_hidden = false;
889889
static bool tag_combo = false;
890+
static bool mod_key_used = false;
891+
static uint32_t prev_mods = 0;
890892
static const char *cli_config_path = NULL;
891893
static KeyMode keymode = {
892894
.mode = {'d', 'e', 'f', 'a', 'u', 'l', 't', '\0'},
@@ -1989,6 +1991,9 @@ buttonpress(struct wl_listener *listener, void *data) {
19891991
if (locked)
19901992
break;
19911993

1994+
/* Invalidate modifier-only bindings on mouse click */
1995+
mod_key_used = true;
1996+
19921997
xytonode(cursor->x, cursor->y, &surface, NULL, NULL, NULL, NULL);
19931998
if (toplevel_from_wlr_surface(surface, &c, &l) >= 0) {
19941999
if (c && c->scene->node.enabled &&
@@ -3596,6 +3601,10 @@ keybinding(uint32_t state, bool locked, uint32_t mods, xkb_keysym_t sym,
35963601
state != WL_KEYBOARD_KEY_STATE_RELEASED)
35973602
continue;
35983603

3604+
/* Skip KEY_TYPE_NONE bindings here; they are handled in keypressmod */
3605+
if (config.key_bindings[ji].keysymcode.type == KEY_TYPE_NONE)
3606+
continue;
3607+
35993608
k = &config.key_bindings[ji];
36003609
if ((k->iscommonmode || (k->isdefaultmode && keymode.isdefault) ||
36013610
(strcmp(keymode.mode, k->mode) == 0)) &&
@@ -3726,6 +3735,16 @@ void keypress(struct wl_listener *listener, void *data) {
37263735
}
37273736
}
37283737

3738+
/* Track non-modifier key presses to invalidate modifier-only bindings.
3739+
* Modifier keycodes: 133,134=Super, 37,105=Ctrl, 50,62=Shift, 64,108=Alt */
3740+
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED &&
3741+
keycode != 133 && keycode != 134 && /* Super_L, Super_R */
3742+
keycode != 37 && keycode != 105 && /* Control_L, Control_R */
3743+
keycode != 50 && keycode != 62 && /* Shift_L, Shift_R */
3744+
keycode != 64 && keycode != 108) { /* Alt_L, Alt_R */
3745+
mod_key_used = true;
3746+
}
3747+
37293748
/* On _press_ if there is no active screen locker,
37303749
* attempt to process a compositor keybinding. */
37313750
for (i = 0; i < nsyms; i++)
@@ -3782,6 +3801,47 @@ void keypressmod(struct wl_listener *listener, void *data) {
37823801
* pressed. We simply communicate this to the client. */
37833802
KeyboardGroup *group = wl_container_of(listener, group, modifiers);
37843803

3804+
uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
3805+
3806+
/* Handle modifier-only keybindings (KEY_TYPE_NONE).
3807+
* Fire when a modifier is released without any non-modifier key having
3808+
* been pressed during the hold. We detect release by checking if a
3809+
* modifier bit was set in prev_mods but is now cleared.
3810+
* The (prev_mods & ~mods) check ensures a modifier was actually
3811+
* released (bits cleared), not just a new modifier added. */
3812+
if (!locked && group == kb_group && !mod_key_used && prev_mods != 0 &&
3813+
mods != prev_mods && (prev_mods & ~mods) != 0) {
3814+
/* A modifier was released — check if the previously held modifier
3815+
* combination matches any KEY_TYPE_NONE bindings */
3816+
for (int32_t ji = 0; ji < config.key_bindings_count; ji++) {
3817+
const KeyBinding *k = &config.key_bindings[ji];
3818+
if (k->keysymcode.type != KEY_TYPE_NONE)
3819+
continue;
3820+
if (!k->func)
3821+
continue;
3822+
if (!(k->iscommonmode ||
3823+
(k->isdefaultmode && keymode.isdefault) ||
3824+
(strcmp(keymode.mode, k->mode) == 0)))
3825+
continue;
3826+
/* The binding's mod should match the modifiers that were held
3827+
* before this release */
3828+
if (CLEANMASK(prev_mods) == CLEANMASK(k->mod)) {
3829+
k->func(&k->arg);
3830+
/* Mark as used so we don't fire again during
3831+
* subsequent releases of the same combo */
3832+
mod_key_used = true;
3833+
break;
3834+
}
3835+
}
3836+
}
3837+
3838+
/* Reset tracking when all modifiers are released */
3839+
if (mods == 0) {
3840+
mod_key_used = false;
3841+
}
3842+
3843+
prev_mods = mods;
3844+
37853845
if (!dwl_im_keyboard_grab_forward_modifiers(group)) {
37863846

37873847
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);

0 commit comments

Comments
 (0)