update globalkey

This commit is contained in:
korei999 2025-03-14 20:22:46 +02:00
parent 9356baf802
commit dd4dfcb71e
2 changed files with 36 additions and 27 deletions

View File

@ -6,13 +6,13 @@ This might deal with Wayland's lack of global shortcuts.
Example: Example:
``` ```
static const PassKeypressRule pass_rules[] = { static const PassKeypressRule pass_rules[] = {
ADDPASSRULE("com.obsproject.Studio", MODKEY, XKB_KEY_Home), ADDPASSRULE("com.obsproject.Studio", XKB_KEY_Home),
ADDPASSRULE("discord", 0, XKB_KEY_n), ADDPASSRULE("WebCord", XKB_KEY_n),
/* xkb key is case-insensitive */ /* xkb key is case-insensitive */
}; };
``` ```
This will pass the `MODKEY + Home` keys to OBS regardless of what client is currently focused, if any. This will pass the `Home` key (alongside with mods) to OBS regardless of what client is currently focused, if any.
The string "com.obsproject.Studio" should match the exact appid of the client. The string "com.obsproject.Studio" should match the exact appid of the client.
To get the appid use [dwlmsg](https://codeberg.org/notchoc/dwlmsg) or run stock dwl from a terminal then launch the needed application inside, dwl will print all the info to the stdout. To get the appid use [dwlmsg](https://codeberg.org/notchoc/dwlmsg) or run stock dwl from a terminal then launch the needed application inside, dwl will print all the info to the stdout.
@ -20,6 +20,12 @@ To get the appid use [dwlmsg](https://codeberg.org/notchoc/dwlmsg) or run stock
Note that if a popup (like [fuzzel](https://codeberg.org/dnkl/fuzzel)) is focused, no keys will be globally passed. Note that if a popup (like [fuzzel](https://codeberg.org/dnkl/fuzzel)) is focused, no keys will be globally passed.
This is done so these menus don't get closed after hitting some of the global keys. This is done so these menus don't get closed after hitting some of the global keys.
## Warning
This patch is a stupid hack, it doesn't work all the time.
Examples: obs needs to be clicked on once before applying global hotkeys.
Electron (discord/webcord/chromium) with wayland backend ignores the very first press.
Other programs might not work at all.
### Download ### Download
- [git branch](https://codeberg.org/korei999/dwl/src/branch/globalkey) - [git branch](https://codeberg.org/korei999/dwl/src/branch/globalkey)
- [2024-06-08](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/globalkey/globalkey.patch) - [2024-06-08](https://codeberg.org/dwl/dwl-patches/src/branch/main/patches/globalkey/globalkey.patch)

View File

@ -1,51 +1,50 @@
From 65e2466212beb3040241e3b6ca8e730e6b96fd66 Mon Sep 17 00:00:00 2001 From f36e3f134c9f14a9821783d9908471ed0bdca0ed Mon Sep 17 00:00:00 2001
From: korei999 <ju7t1xe@gmail.com> From: korei999 <ju7t1xe@gmail.com>
Date: Thu, 21 Nov 2024 02:24:32 +0200 Date: Fri, 14 Mar 2025 20:05:45 +0200
Subject: [PATCH] implement globalkey patch Subject: [PATCH] implement globalkey patch
--- ---
config.def.h | 8 ++++++++ config.def.h | 8 +++++++
dwl.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ dwl.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+) 2 files changed, 69 insertions(+)
diff --git a/config.def.h b/config.def.h diff --git a/config.def.h b/config.def.h
index 22d2171..2bf1c68 100644 index 22d2171..25486c8 100644
--- a/config.def.h --- a/config.def.h
+++ b/config.def.h +++ b/config.def.h
@@ -122,6 +122,14 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA @@ -122,6 +122,14 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
static const char *termcmd[] = { "foot", NULL }; static const char *termcmd[] = { "foot", NULL };
static const char *menucmd[] = { "wmenu-run", NULL }; static const char *menucmd[] = { "wmenu-run", NULL };
+#define ADDPASSRULE(S, M, K) {.appid = S, .len = LENGTH(S), .key = K} +#define ADDPASSRULE(S, K) {.appid = S, .len = LENGTH(S), .key = K}
+static const PassKeypressRule pass_rules[] = { +static const PassKeypressRule pass_rules[] = {
+ ADDPASSRULE("com.obsproject.Studio", MODKEY, XKB_KEY_Home), + ADDPASSRULE("com.obsproject.Studio", XKB_KEY_Home),
+ ADDPASSRULE("com.obsproject.Studio", MODKEY, XKB_KEY_End), + ADDPASSRULE("com.obsproject.Studio", XKB_KEY_End),
+ ADDPASSRULE("com.obsproject.Studio", MODKEY, XKB_KEY_F12), + ADDPASSRULE("com.obsproject.Studio", XKB_KEY_F12),
+ ADDPASSRULE("discord", 0, XKB_KEY_n), + ADDPASSRULE("WebCord", XKB_KEY_n),
+}; +};
+ +
static const Key keys[] = { static const Key keys[] = {
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */ /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
/* modifier key function argument */ /* modifier key function argument */
diff --git a/dwl.c b/dwl.c diff --git a/dwl.c b/dwl.c
index 9acb898..a0d632a 100644 index 4816159..9ad64dd 100644
--- a/dwl.c --- a/dwl.c
+++ b/dwl.c +++ b/dwl.c
@@ -221,6 +221,13 @@ typedef struct { @@ -217,6 +217,12 @@ typedef struct {
int x, y; int x, y;
} MonitorRule; } MonitorRule;
+typedef struct { +typedef struct {
+ const char* appid; + const char* appid;
+ size_t len; + size_t len;
+ uint32_t mod;
+ uint32_t key; + uint32_t key;
+} PassKeypressRule; +} PassKeypressRule;
+ +
typedef struct { typedef struct {
struct wlr_pointer_constraint_v1 *constraint; struct wlr_pointer_constraint_v1 *constraint;
struct wl_listener destroy; struct wl_listener destroy;
@@ -297,6 +304,7 @@ static void incnmaster(const Arg *arg); @@ -293,6 +299,7 @@ static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data); static void inputdevice(struct wl_listener *listener, void *data);
static int keybinding(uint32_t mods, xkb_keysym_t sym); static int keybinding(uint32_t mods, xkb_keysym_t sym);
static void keypress(struct wl_listener *listener, void *data); static void keypress(struct wl_listener *listener, void *data);
@ -53,7 +52,7 @@ index 9acb898..a0d632a 100644
static void keypressmod(struct wl_listener *listener, void *data); static void keypressmod(struct wl_listener *listener, void *data);
static int keyrepeat(void *data); static int keyrepeat(void *data);
static void killclient(const Arg *arg); static void killclient(const Arg *arg);
@@ -1575,6 +1583,12 @@ keypress(struct wl_listener *listener, void *data) @@ -1628,6 +1635,12 @@ keypress(struct wl_listener *listener, void *data)
/* This event is raised when a key is pressed or released. */ /* This event is raised when a key is pressed or released. */
KeyboardGroup *group = wl_container_of(listener, group, key); KeyboardGroup *group = wl_container_of(listener, group, key);
struct wlr_keyboard_key_event *event = data; struct wlr_keyboard_key_event *event = data;
@ -66,7 +65,7 @@ index 9acb898..a0d632a 100644
/* Translate libinput keycode -> xkbcommon */ /* Translate libinput keycode -> xkbcommon */
uint32_t keycode = event->keycode + 8; uint32_t keycode = event->keycode + 8;
@@ -1609,12 +1623,56 @@ keypress(struct wl_listener *listener, void *data) @@ -1662,12 +1675,60 @@ keypress(struct wl_listener *listener, void *data)
if (handled) if (handled)
return; return;
@ -78,8 +77,10 @@ index 9acb898..a0d632a 100644
+#endif +#endif
+ ; + ;
+ /* passed keys don't get repeated */ + /* passed keys don't get repeated */
+ if (pass && syms) + if (!locked && pass) {
+ keypressglobal(last_surface, &group->wlr_group->keyboard, event, mods, syms[0]); + for (i = 0; i < nsyms; ++i)
+ keypressglobal(last_surface, &group->wlr_group->keyboard, event, mods, syms[i]);
+ }
+ +
wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard); wlr_seat_set_keyboard(seat, &group->wlr_group->keyboard);
/* Pass unhandled keycodes along to the client. */ /* Pass unhandled keycodes along to the client. */
@ -91,13 +92,13 @@ index 9acb898..a0d632a 100644
+keypressglobal(struct wlr_surface *last_surface, struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event, uint32_t mods, xkb_keysym_t keysym) +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); + Client *c = NULL, *lastc = focustop(selmon);
+ uint32_t keycodes[32] = {0};
+ int reset = false; + int reset = false;
+ const char *appid = NULL; + const char *appid = NULL;
+ +
+ for (size_t r = 0; r < LENGTH(pass_rules); r++) { + for (size_t r = 0; r < LENGTH(pass_rules); r++) {
+ uint32_t rcode = xkb_keysym_to_upper(pass_rules[r].key); + uint32_t rcode = xkb_keysym_to_upper(pass_rules[r].key);
+ uint32_t pcode = xkb_keysym_to_upper(keysym); + uint32_t pcode = xkb_keysym_to_upper(keysym);
+
+ /* match key only (case insensitive) ignoring mods */ + /* match key only (case insensitive) ignoring mods */
+ if (rcode == pcode) { + if (rcode == pcode) {
+ wl_list_for_each(c, &clients, link) { + wl_list_for_each(c, &clients, link) {
@ -105,7 +106,9 @@ index 9acb898..a0d632a 100644
+ appid = client_get_appid(c); + appid = client_get_appid(c);
+ if (appid && strncmp(appid, pass_rules[r].appid, pass_rules[r].len) == 0) { + if (appid && strncmp(appid, pass_rules[r].appid, pass_rules[r].len) == 0) {
+ reset = true; + reset = true;
+ wlr_seat_keyboard_enter(seat, client_surface(c), keycodes, 0, &keyboard->modifiers); +
+ client_notify_enter(client_surface(c), keyboard);
+ client_activate_surface(client_surface(c), 1);
+ wlr_seat_keyboard_send_key(seat, event->time_msec, event->keycode, event->state); + wlr_seat_keyboard_send_key(seat, event->time_msec, event->keycode, event->state);
+ +
+ goto done; + goto done;
@ -116,13 +119,13 @@ index 9acb898..a0d632a 100644
+ } + }
+ +
+done: +done:
+ if (reset) + if (reset && last_surface)
+ wlr_seat_keyboard_enter(seat, last_surface, keycodes, 0, &keyboard->modifiers); + client_notify_enter(last_surface, keyboard);
+} +}
+ +
void void
keypressmod(struct wl_listener *listener, void *data) keypressmod(struct wl_listener *listener, void *data)
{ {
-- --
2.47.0 2.48.1