feat:add global shortcut pass

This commit is contained in:
DreamMaoMao 2025-03-14 12:54:44 +08:00
parent 16fa2cad95
commit b1b5a6d57a
5 changed files with 114 additions and 8 deletions

View file

@ -49,6 +49,7 @@ See below for more features.
- height : type-num(0-9999)
- isterm : type-num(0 or 1) it will be swallowed by the sub window
- noswallow: type-num(0 or 1) don't swallow the isterm window
- globalkeybinding: type-string(for example-- alt-l or alt+super-l)
# some special feature
- hycov like overview

View file

@ -103,6 +103,7 @@ tags=id:9,layout_name:tile
# height : type-num(0-9999)
# isterm : type-num (0 or 1) -- when new window open, will replace it, and will restore after the sub window exit
# nnoswallow : type-num(0 or 1) -- if enable, this window wll not replace isterm window when it was open by isterm window
# globalkeybinding: type-string(for example-- alt-l or alt+super-l)
# example
# windowrule=isfloating:1,appid:yesplaymusic
@ -113,6 +114,9 @@ tags=id:9,layout_name:tile
# windowrule=isfloating:1,appid:wofi
# windowrule=isnoborder:1,appid:wofi
# windowrule=animation_type_open:zoom,appid:wofi
# windowrule=globalkeybinding:ctrl+alt-o,appid:com.obsproject.Studio
# windowrule=globalkeybinding:ctrl+alt-n,appid:com.obsproject.Studio
# open in specific tag
# windowrule=tags:4,appid:Google-chrome
@ -122,6 +126,18 @@ tags=id:9,layout_name:tile
# windowrule=tags:6,appid:obs
# Monitor Rules
# name|mfact|nmaster|scale|layout|(rotate or reflect)|x|y
# rotate or reflect:
# 0:no transform
# 1:90 degrees counter-clockwise
# 2:180 degrees counter-clockwise
# 3:270 degrees counter-clockwise
# 4:180 degree flip around a vertical axis
# 5:flip and rotate 90 degrees counter-clockwise
# 6:flip and rotate 180 degrees counter-clockwise
# 7:flip and rotate 270 degrees counter-clockwise
# example
# monitorrule=eDP-1,0.55,1,tile,0,1,0,0
# monitorrule=HDMI-A-1,0.55,1,tile,0,1,1920,0

View file

@ -480,6 +480,7 @@ static void inputdevice(struct wl_listener *listener, void *data);
static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data);
static void keypressmod(struct wl_listener *listener, void *data);
static bool keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event, uint32_t mods, xkb_keysym_t keysym);
static void locksession(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
@ -3381,6 +3382,62 @@ keybinding(uint32_t mods, xkb_keysym_t sym) {
return handled;
}
bool
keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event, uint32_t mods, xkb_keysym_t keysym)
{
Client *c = NULL, *lastc = focustop(selmon);
uint32_t keycodes[32] = {0};
int reset = false;
const char *appid = NULL;
const char *title = NULL;
int appid_len,title_len,ji;
const ConfigWinRule *r;
for (ji = 0; ji < config.window_rules_count; ji++) {
if (config.window_rules_count < 1)
break;
r = &config.window_rules[ji];
if(!r->globalkeybinding.mod || !r->globalkeybinding.keysym )
continue;
/* match key only (case insensitive) ignoring mods */
if (r->globalkeybinding.keysym == keysym && r->globalkeybinding.mod == mods) {
wl_list_for_each(c, &clients, link) {
if (c && c != lastc) {
appid = client_get_appid(c);
title = client_get_title(c);
if (appid && r->id) {
appid_len = strlen(appid);
if(strncmp(appid, r->id, appid_len) == 0) {
reset = true;
wlr_seat_keyboard_enter(seat, client_surface(c), keycodes, 0, &keyboard->modifiers);
wlr_seat_keyboard_send_key(seat, event->time_msec, event->keycode, event->state);
goto done;
}
}
if (title && r->title) {
title_len = strlen(title);
if(strncmp(title, r->title, title_len) == 0) {
reset = true;
wlr_seat_keyboard_enter(seat, client_surface(c), keycodes, 0, &keyboard->modifiers);
wlr_seat_keyboard_send_key(seat, event->time_msec, event->keycode, event->state);
goto done;
}
}
}
}
}
}
done:
if (reset)
wlr_seat_keyboard_enter(seat, last_surface, keycodes, 0, &keyboard->modifiers);
return reset;
}
void
keypress(struct wl_listener *listener, void *data)
{
@ -3389,6 +3446,14 @@ keypress(struct wl_listener *listener, void *data)
KeyboardGroup *group = wl_container_of(listener, group, key);
struct wlr_keyboard_key_event *event = data;
struct wlr_surface *last_surface = seat->keyboard_state.focused_surface;
struct wlr_xdg_surface *xdg_surface = last_surface ? wlr_xdg_surface_try_from_wlr_surface(last_surface) : NULL;
int pass = 0;
bool hit_global = false;
#ifdef XWAYLAND
struct wlr_xwayland_surface *xsurface = last_surface ? wlr_xwayland_surface_try_from_wlr_surface(last_surface) : NULL;
#endif
/* Translate libinput keycode -> xkbcommon */
uint32_t keycode = event->keycode + 8;
/* Get a list of keysyms based on the keymap for this keyboard */
@ -3443,6 +3508,21 @@ keypress(struct wl_listener *listener, void *data)
if (handled)
return;
/* don't pass when popup is focused
* this is better than having popups (like fuzzel or wmenu) closing while typing in a passed keybind */
pass = (xdg_surface && xdg_surface->role != WLR_XDG_SURFACE_ROLE_POPUP) || !last_surface
#ifdef XWAYLAND
|| xsurface
#endif
;
/* passed keys don't get repeated */
if (pass && syms)
hit_global = keypressglobal(last_surface, &group->wlr_group->keyboard, event, mods, syms[0]);
if(hit_global) {
return;
}
#ifdef IM
/* if there is a keyboard grab, we send the key there */
struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(group);

View file

@ -7,6 +7,13 @@
#define SYSCONFDIR "/etc"
#endif
typedef struct {
uint32_t mod;
xkb_keysym_t keysym;
void (*func)(const Arg *);
Arg arg;
} KeyBinding;
typedef struct {
const char *id;
const char *title;
@ -22,6 +29,9 @@ typedef struct {
int height;
int isterm;
int noswallow;
uint32_t passmod;
xkb_keysym_t keysym;
KeyBinding globalkeybinding;
} ConfigWinRule;
typedef struct {
@ -36,13 +46,6 @@ typedef struct {
int noswallow;
} ConfigMonitorRule;
typedef struct {
uint32_t mod;
xkb_keysym_t keysym;
void (*func)(const Arg *);
Arg arg;
} KeyBinding;
// 定义一个宏来简化默认按键绑定的添加
#define CHVT(n) \
{ \
@ -802,6 +805,7 @@ void parse_config_line(Config *config, const char *line) {
rule->id = NULL;
rule->title = NULL;
rule->tags = 0;
rule->globalkeybinding = (KeyBinding){0};
char *token = strtok(value, ",");
while (token != NULL) {
@ -839,6 +843,11 @@ void parse_config_line(Config *config, const char *line) {
rule->scroller_proportion = atof(val);
} else if (strcmp(key, "isfullscreen") == 0) {
rule->isfullscreen = atoi(val);
} else if (strcmp(key, "globalkeybinding") == 0) {
char mod_str[256], keysym_str[256];
sscanf(val, "%[^-]-%[a-zA-Z]", mod_str, keysym_str);
rule->globalkeybinding.mod = parse_mod(mod_str);
rule->globalkeybinding.keysym = parse_keysym(keysym_str);
}
}
token = strtok(NULL, ",");

View file

@ -31,7 +31,7 @@ unsigned int default_nmaster = 1; // 默认master数量
/* logging */
int log_level = WLR_ERROR;
unsigned int numlockon = 1; // 是否打开右边小键盘
unsigned int capslock = 0; // 是否打开大写锁定
unsigned int capslock = 0; // 是否启用快捷键
unsigned int ov_tab_mode = 0; // alt tab切换模式
unsigned int hotarea_size = 10; // 热区大小,10x10