summaryrefslogtreecommitdiffstats
path: root/dwl-patches/patches/globalkey/globalkey.patch
blob: 07d3856ce3d7756019311bb795f5b07f5f0eb3ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From f36e3f134c9f14a9821783d9908471ed0bdca0ed Mon Sep 17 00:00:00 2001
From: korei999 <ju7t1xe@gmail.com>
Date: Fri, 14 Mar 2025 20:05:45 +0200
Subject: [PATCH] implement globalkey patch

---
 config.def.h |  8 +++++++
 dwl.c        | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/config.def.h b/config.def.h
index 22d2171..25486c8 100644
--- a/config.def.h
+++ b/config.def.h
@@ -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 *menucmd[] = { "wmenu-run", NULL };
 
+#define ADDPASSRULE(S, K) {.appid = S, .len = LENGTH(S), .key = K}
+static const PassKeypressRule pass_rules[] = {
+	ADDPASSRULE("com.obsproject.Studio", XKB_KEY_Home),
+	ADDPASSRULE("com.obsproject.Studio", XKB_KEY_End),
+	ADDPASSRULE("com.obsproject.Studio", XKB_KEY_F12),
+	ADDPASSRULE("WebCord", XKB_KEY_n),
+};
+
 static const Key keys[] = {
 	/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
 	/* modifier                  key                 function        argument */
diff --git a/dwl.c b/dwl.c
index 4816159..9ad64dd 100644
--- a/dwl.c
+++ b/dwl.c
@@ -217,6 +217,12 @@ typedef struct {
 	int x, y;
 } MonitorRule;
 
+typedef struct {
+	const char* appid;
+	size_t len;
+	uint32_t key;
+} PassKeypressRule;
+
 typedef struct {
 	struct wlr_pointer_constraint_v1 *constraint;
 	struct wl_listener destroy;
@@ -293,6 +299,7 @@ static void incnmaster(const Arg *arg);
 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 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 keypressmod(struct wl_listener *listener, void *data);
 static int keyrepeat(void *data);
 static void killclient(const Arg *arg);
@@ -1628,6 +1635,12 @@ keypress(struct wl_listener *listener, void *data)
 	/* This event is raised when a key is pressed or released. */
 	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;
+#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;
@@ -1662,12 +1675,60 @@ 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 (!locked && pass) {
+		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);
 	/* Pass unhandled keycodes along to the client. */
 	wlr_seat_keyboard_notify_key(seat, event->time_msec,
 			event->keycode, event->state);
 }
 
+void
+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);
+	int reset = false;
+	const char *appid = NULL;
+
+	for (size_t r = 0; r < LENGTH(pass_rules); r++) {
+		uint32_t rcode = xkb_keysym_to_upper(pass_rules[r].key);
+		uint32_t pcode = xkb_keysym_to_upper(keysym);
+
+		/* match key only (case insensitive) ignoring mods */
+		if (rcode == pcode) {
+			wl_list_for_each(c, &clients, link) {
+				if (c && c != lastc) {
+					appid = client_get_appid(c);
+					if (appid && strncmp(appid, pass_rules[r].appid, pass_rules[r].len) == 0) {
+						reset = true;
+
+						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);
+
+						goto done;
+					}
+				}
+			}
+		}
+	}
+
+done:
+	if (reset && last_surface)
+		client_notify_enter(last_surface, keyboard);
+}
+
 void
 keypressmod(struct wl_listener *listener, void *data)
 {
-- 
2.48.1