Introduction
Introduction Statistics Contact Development Disclaimer Help
dwm-multikey-6.2.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
dwm-multikey-6.2.diff (13835B)
---
1 From b845451cde90c3b46f7863c27a184555b444e9af Mon Sep 17 00:00:00 2001
2 From: Miles Alan <[email protected]>
3 Date: Sat, 18 Apr 2020 19:25:29 -0500
4 Subject: [PATCH] Multikey: Run different actions for single keybinding b…
5 on # of keypresses
6
7 Changed keypress code to allow keybindings to be selectively dispatched …
8 tapped a specific # of times as specified by the new npresses field on t…
9 Key struct.
10
11 In the example added to the config.def.h, the tiling layout is set when
12 Mod+w is tapped once, float layout is set when Mod+w is tapped twice,
13 and monocole layout is set when Mod+w is tapped three times (or held dow…
14 ---
15 config.def.h | 84 ++++++++++++++++++++++------------------
16 config.mk | 2 +-
17 dwm.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++--
18 3 files changed, 150 insertions(+), 43 deletions(-)
19
20 diff --git a/config.def.h b/config.def.h
21 index 1c0b587..dc945b4 100644
22 --- a/config.def.h
23 +++ b/config.def.h
24 @@ -46,10 +46,10 @@ static const Layout layouts[] = {
25 /* key definitions */
26 #define MODKEY Mod1Mask
27 #define TAGKEYS(KEY,TAG) \
28 - { MODKEY, KEY, view, {.ui …
29 - { MODKEY|ControlMask, KEY, toggleview, {.ui …
30 - { MODKEY|ShiftMask, KEY, tag, {.ui …
31 - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui …
32 + { 0, MODKEY, KEY, view, {.…
33 + { 0, MODKEY|ControlMask, KEY, toggleview, {.…
34 + { 0, MODKEY|ShiftMask, KEY, tag, {.…
35 + { 0, MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.…
36
37 /* helper for spawning shell commands in the pre dwm-5.0 fashion */
38 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL }…
39 @@ -59,41 +59,49 @@ static char dmenumon[2] = "0"; /* component of dmenu…
40 static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", d…
41 static const char *termcmd[] = { "st", NULL };
42
43 +#define MULTIKEY_THRESHOLD_MS_PRESS 200
44 +#define MULTIKEY_THRESHOLD_MS_HOLD 700
45 +
46 static Key keys[] = {
47 - /* modifier key function argu…
48 - { MODKEY, XK_p, spawn, {.v …
49 - { MODKEY|ShiftMask, XK_Return, spawn, {.v …
50 - { MODKEY, XK_b, togglebar, {0} …
51 - { MODKEY, XK_j, focusstack, {.i …
52 - { MODKEY, XK_k, focusstack, {.i …
53 - { MODKEY, XK_i, incnmaster, {.i …
54 - { MODKEY, XK_d, incnmaster, {.i …
55 - { MODKEY, XK_h, setmfact, {.f …
56 - { MODKEY, XK_l, setmfact, {.f …
57 - { MODKEY, XK_Return, zoom, {0} …
58 - { MODKEY, XK_Tab, view, {0} …
59 - { MODKEY|ShiftMask, XK_c, killclient, {0} …
60 - { MODKEY, XK_t, setlayout, {.v …
61 - { MODKEY, XK_f, setlayout, {.v …
62 - { MODKEY, XK_m, setlayout, {.v …
63 - { MODKEY, XK_space, setlayout, {0} …
64 - { MODKEY|ShiftMask, XK_space, togglefloating, {0} …
65 - { MODKEY, XK_0, view, {.ui…
66 - { MODKEY|ShiftMask, XK_0, tag, {.ui…
67 - { MODKEY, XK_comma, focusmon, {.i …
68 - { MODKEY, XK_period, focusmon, {.i …
69 - { MODKEY|ShiftMask, XK_comma, tagmon, {.i …
70 - { MODKEY|ShiftMask, XK_period, tagmon, {.i …
71 - TAGKEYS( XK_1, 0)
72 - TAGKEYS( XK_2, 1)
73 - TAGKEYS( XK_3, 2)
74 - TAGKEYS( XK_4, 3)
75 - TAGKEYS( XK_5, 4)
76 - TAGKEYS( XK_6, 5)
77 - TAGKEYS( XK_7, 6)
78 - TAGKEYS( XK_8, 7)
79 - TAGKEYS( XK_9, 8)
80 - { MODKEY|ShiftMask, XK_q, quit, {0} …
81 + /* npresses, modifier key function…
82 + { 0, MODKEY, XK_p, spawn, …
83 + { 0, MODKEY|ShiftMask, XK_Return, spawn, …
84 + { 0, MODKEY, XK_b, toggleb…
85 + { 0, MODKEY, XK_j, focusst…
86 + { 0, MODKEY, XK_k, focusst…
87 + { 0, MODKEY, XK_i, incnmas…
88 + { 0, MODKEY, XK_d, incnmas…
89 + { 0, MODKEY, XK_h, setmfac…
90 + { 0, MODKEY, XK_l, setmfac…
91 + { 0, MODKEY, XK_Return, zoom, …
92 + { 0, MODKEY, XK_Tab, view, …
93 + { 0, MODKEY|ShiftMask, XK_c, killcli…
94 + { 0, MODKEY, XK_t, setlayo…
95 + { 0, MODKEY, XK_f, setlayo…
96 + { 0, MODKEY, XK_m, setlayo…
97 + { 0, MODKEY, XK_space, setlayo…
98 + { 0, MODKEY|ShiftMask, XK_space, togglef…
99 + { 0, MODKEY, XK_0, view, …
100 + { 0, MODKEY|ShiftMask, XK_0, tag, …
101 + { 0, MODKEY, XK_comma, focusmo…
102 + { 0, MODKEY, XK_period, focusmo…
103 + { 0, MODKEY|ShiftMask, XK_comma, tagmon,…
104 + { 0, MODKEY|ShiftMask, XK_period, tagmon,…
105 +
106 + { 1, MODKEY, XK_w, setlayo…
107 + { 2, MODKEY, XK_w, setlayo…
108 + { 3, MODKEY, XK_w, setlayo…
109 +
110 + TAGKEYS( XK_1, …
111 + TAGKEYS( XK_2, …
112 + TAGKEYS( XK_3, …
113 + TAGKEYS( XK_4, …
114 + TAGKEYS( XK_5, …
115 + TAGKEYS( XK_6, …
116 + TAGKEYS( XK_7, …
117 + TAGKEYS( XK_8, …
118 + TAGKEYS( XK_9, …
119 + { 0, MODKEY|ShiftMask, XK_q, quit, …
120 };
121
122 /* button definitions */
123 diff --git a/config.mk b/config.mk
124 index 6d36cb7..fe0a2ec 100644
125 --- a/config.mk
126 +++ b/config.mk
127 @@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
128
129 # includes and libs
130 INCS = -I${X11INC} -I${FREETYPEINC}
131 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
132 +LIBS = -L${X11LIB} -lrt -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
133
134 # flags
135 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSIO…
136 diff --git a/dwm.c b/dwm.c
137 index 4465af1..975956c 100644
138 --- a/dwm.c
139 +++ b/dwm.c
140 @@ -27,6 +27,7 @@
141 #include <stdio.h>
142 #include <stdlib.h>
143 #include <string.h>
144 +#include <time.h>
145 #include <unistd.h>
146 #include <sys/types.h>
147 #include <sys/wait.h>
148 @@ -40,6 +41,7 @@
149 #include <X11/extensions/Xinerama.h>
150 #endif /* XINERAMA */
151 #include <X11/Xft/Xft.h>
152 +#include <X11/XKBlib.h>
153
154 #include "drw.h"
155 #include "util.h"
156 @@ -100,6 +102,7 @@ struct Client {
157 };
158
159 typedef struct {
160 + unsigned int npresses;
161 unsigned int mod;
162 KeySym keysym;
163 void (*func)(const Arg *);
164 @@ -176,6 +179,10 @@ static void grabbuttons(Client *c, int focused);
165 static void grabkeys(void);
166 static void incnmaster(const Arg *arg);
167 static void keypress(XEvent *e);
168 +static void keypresstimerdispatch(int msduration, int data);
169 +static void keypresstimerdone(union sigval timer_data);
170 +static void keypresstimerdonesync(int idx);
171 +static void keyrelease(XEvent *e);
172 static void killclient(const Arg *arg);
173 static void manage(Window w, XWindowAttributes *wa);
174 static void mappingnotify(XEvent *e);
175 @@ -253,13 +260,14 @@ static void (*handler[LASTEvent]) (XEvent *) = {
176 [Expose] = expose,
177 [FocusIn] = focusin,
178 [KeyPress] = keypress,
179 + [KeyRelease] = keyrelease,
180 [MappingNotify] = mappingnotify,
181 [MapRequest] = maprequest,
182 [MotionNotify] = motionnotify,
183 [PropertyNotify] = propertynotify,
184 [UnmapNotify] = unmapnotify
185 };
186 -static Atom wmatom[WMLast], netatom[NetLast];
187 +static Atom timeratom, wmatom[WMLast], netatom[NetLast];
188 static int running = 1;
189 static Cur *cursor[CurLast];
190 static Clr **scheme;
191 @@ -268,6 +276,10 @@ static Drw *drw;
192 static Monitor *mons, *selmon;
193 static Window root, wmcheckwin;
194
195 +static int multikeypendingindex = -1;
196 +static timer_t multikeypendingtimer = NULL;
197 +static int multikeyup = 1;
198 +
199 /* configuration, allows nested code to access above variables */
200 #include "config.h"
201
202 @@ -515,6 +527,10 @@ clientmessage(XEvent *e)
203 XClientMessageEvent *cme = &e->xclient;
204 Client *c = wintoclient(cme->window);
205
206 + if (cme->message_type == timeratom) {
207 + keypresstimerdonesync(cme->data.s[0]);
208 + return;
209 + }
210 if (!c)
211 return;
212 if (cme->message_type == netatom[NetWMState]) {
213 @@ -991,11 +1007,92 @@ keypress(XEvent *e)
214
215 ev = &e->xkey;
216 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
217 - for (i = 0; i < LENGTH(keys); i++)
218 + for (i = 0; i < LENGTH(keys); i++) {
219 if (keysym == keys[i].keysym
220 && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
221 - && keys[i].func)
222 - keys[i].func(&(keys[i].arg));
223 + && keys[i].func) {
224 + // E.g. Normal functionality case - npresses 0 …
225 + if (keys[i].npresses == 0) {
226 + keys[i].func(&(keys[i].arg));
227 + break;
228 + }
229 +
230 + // Multikey functionality - find index of key, …
231 + if (
232 + (multikeypendingindex == -1 && multikeyup && …
233 + (multikeypendingindex != -1 && keys[multikeyp…
234 + ) {
235 + multikeyup = 0;
236 + multikeypendingindex = i;
237 + keypresstimerdispatch(MULTIKEY_THRESHOL…
238 + break;
239 + }
240 + }
241 + }
242 +}
243 +
244 +void
245 +keypresstimerdispatch(int msduration, int data)
246 +{
247 + struct sigevent timer_signal_event;
248 + struct itimerspec timer_period;
249 + static int multikeypendingtimer_created = 0;
250 + // Clear out the old timer if any set,and dispatch new timer
251 + if (multikeypendingtimer_created) {
252 + timer_delete(multikeypendingtimer);
253 + }
254 + timer_signal_event.sigev_notify = SIGEV_THREAD;
255 + timer_signal_event.sigev_notify_function = keypresstimerdone;
256 + timer_signal_event.sigev_value.sival_int = data;
257 + timer_signal_event.sigev_notify_attributes = NULL;
258 + timer_create(CLOCK_MONOTONIC, &timer_signal_event, &multikeypen…
259 + multikeypendingtimer_created = 1;
260 + timer_period.it_value.tv_sec = 0;
261 + timer_period.it_value.tv_nsec = msduration * 1000000;
262 + timer_period.it_interval.tv_sec = 0;
263 + timer_period.it_interval.tv_nsec = 0;
264 + timer_settime(multikeypendingtimer, 0, &timer_period, NULL);
265 +}
266 +
267 +void
268 +keypresstimerdone(union sigval timer_data)
269 +{
270 + XEvent ev;
271 + memset(&ev, 0, sizeof ev);
272 + ev.xclient.type = ClientMessage;
273 + ev.xclient.window = root;
274 + ev.xclient.message_type = timeratom;
275 + ev.xclient.format = 16;
276 + ev.xclient.data.s[0] = ((short) timer_data.sival_int);
277 + XSendEvent(dpy, root, False, SubstructureRedirectMask, &ev);
278 + XSync(dpy, False);
279 +}
280 +
281 +void
282 +keypresstimerdonesync(int idx)
283 +{
284 + int i, maxidx;
285 + if (keys[idx].npresses == 1 && !multikeyup) {
286 + // Dispatch hold key
287 + maxidx = -1;
288 + for (i = 0; i < LENGTH(keys); i++)
289 + if (keys[i].keysym == keys[idx].keysym) maxidx …
290 + if (maxidx != -1)
291 + keypresstimerdispatch(
292 + MULTIKEY_THRESHOLD_MS_HOLD - MULTIKEY_T…
293 + maxidx
294 + );
295 + } else if (keys[idx].func) {
296 + // Run the actual keys' fn
297 + keys[idx].func(&(keys[idx].arg));
298 + multikeypendingindex = -1;
299 + }
300 +}
301 +
302 +void
303 +keyrelease(XEvent *e)
304 +{
305 + multikeyup = 1;
306 }
307
308 void
309 @@ -2127,6 +2224,7 @@ zoom(const Arg *arg)
310 int
311 main(int argc, char *argv[])
312 {
313 + XInitThreads();
314 if (argc == 2 && !strcmp("-v", argv[1]))
315 die("dwm-"VERSION);
316 else if (argc != 1)
317 @@ -2135,6 +2233,7 @@ main(int argc, char *argv[])
318 fputs("warning: no locale support\n", stderr);
319 if (!(dpy = XOpenDisplay(NULL)))
320 die("dwm: cannot open display");
321 + XkbSetDetectableAutoRepeat(dpy, True, NULL);
322 checkotherwm();
323 setup();
324 #ifdef __OpenBSD__
325 --
326 2.30.1
327
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.