dwm-keychord-20211210-a786211.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-keychord-20211210-a786211.diff (9244B)
---
1 From e61a957ff8b7e14219b5fbaab9da794b722e7874 Mon Sep 17 00:00:00 2001
2 From: Hai Nguyen <hhai2105@gmail.com>
3 Date: Fri, 10 Dec 2021 21:45:00 -0500
4 Subject: [PATCH] add Keychord struct, change keypress() and grabkeys() to be
5 able to grab a sequence of keystroke
6
7 ---
8 config.def.h | 67 ++++++++++++++++++++++++++------------------------
9 dwm.c | 69 ++++++++++++++++++++++++++++++++++++++++------------
10 2 files changed, 88 insertions(+), 48 deletions(-)
11
12 diff --git a/config.def.h b/config.def.h
13 index a2ac963..15a3e05 100644
14 --- a/config.def.h
15 +++ b/config.def.h
16 @@ -46,11 +46,12 @@ static const Layout layouts[] = {
17
18 /* key definitions */
19 #define MODKEY Mod1Mask
20 -#define TAGKEYS(KEY,TAG) \
21 - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
22 - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
23 - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
24 - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
25 +
26 +#define TAGKEYS(KEY,TAG) \
27 + {1, {{MODKEY, KEY}}, view, {.ui = 1 << TAG} }, \
28 + {1, {{MODKEY|ControlMask, KEY}}, toggleview, {.ui = 1 << TAG} }, \
29 + {1, {{MODKEY|ShiftMask, KEY}}, tag, {.ui = 1 << TAG} }, \
30 + {1, {{MODKEY|ControlMask|ShiftMask, KEY}}, toggletag, {.ui = 1 << TAG} },
31
32 /* helper for spawning shell commands in the pre dwm-5.0 fashion */
33 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
34 @@ -59,32 +60,34 @@ static const Layout layouts[] = {
35 static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
36 static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
37 static const char *termcmd[] = { "st", NULL };
38 +static const char *emacs[] = { "emacs", NULL };
39
40 -static Key keys[] = {
41 - /* modifier key function argument */
42 - { MODKEY, XK_p, spawn, {.v = dmenucmd } },
43 - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
44 - { MODKEY, XK_b, togglebar, {0} },
45 - { MODKEY, XK_j, focusstack, {.i = +1 } },
46 - { MODKEY, XK_k, focusstack, {.i = -1 } },
47 - { MODKEY, XK_i, incnmaster, {.i = +1 } },
48 - { MODKEY, XK_d, incnmaster, {.i = -1 } },
49 - { MODKEY, XK_h, setmfact, {.f = -0.05} },
50 - { MODKEY, XK_l, setmfact, {.f = +0.05} },
51 - { MODKEY, XK_Return, zoom, {0} },
52 - { MODKEY, XK_Tab, view, {0} },
53 - { MODKEY|ShiftMask, XK_c, killclient, {0} },
54 - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
55 - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
56 - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
57 - { MODKEY, XK_space, setlayout, {0} },
58 - { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
59 - { MODKEY, XK_0, view, {.ui = ~0 } },
60 - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
61 - { MODKEY, XK_comma, focusmon, {.i = -1 } },
62 - { MODKEY, XK_period, focusmon, {.i = +1 } },
63 - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
64 - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
65 +static Keychord keychords[] = {
66 + /* Keys function argument */
67 + {1, {{MODKEY, XK_p}}, spawn, {.v = dmenucmd } },
68 + {1, {{MODKEY|ShiftMask, XK_Return}}, spawn, {.v = termcmd } },
69 + {2, {{MODKEY, XK_e}, {MODKEY, XK_e}}, spawn, {.v = termcmd } },
70 + {1, {{MODKEY, XK_b}}, togglebar, {0} },
71 + {1, {{MODKEY, XK_j}}, focusstack, {.i = +1 } },
72 + {1, {{MODKEY, XK_k}}, focusstack, {.i = -1 } },
73 + {1, {{MODKEY, XK_i}}, incnmaster, {.i = +1 } },
74 + {1, {{MODKEY, XK_d}}, incnmaster, {.i = -1 } },
75 + {1, {{MODKEY, XK_h}}, setmfact, {.f = -0.05} },
76 + {1, {{MODKEY, XK_l}}, setmfact, {.f = +0.05} },
77 + {1, {{MODKEY, XK_Return}}, zoom, {0} },
78 + {1, {{MODKEY, XK_Tab}}, view, {0} },
79 + {1, {{MODKEY|ShiftMask, XK_c}}, killclient, {0} },
80 + {1, {{MODKEY, XK_t}}, setlayout, {.v = &layouts[0]} },
81 + {1, {{MODKEY, XK_f}}, setlayout, {.v = &layouts[1]} },
82 + {1, {{MODKEY, XK_m}}, setlayout, {.v = &layouts[2]} },
83 + {1, {{MODKEY, XK_space}}, setlayout, {0} },
84 + {1, {{MODKEY|ShiftMask, XK_space}}, togglefloating, {0} },
85 + {1, {{MODKEY, XK_0}}, view, {.ui = ~0 } },
86 + {1, {{MODKEY|ShiftMask, XK_0}}, tag, {.ui = ~0 } },
87 + {1, {{MODKEY, XK_comma}}, focusmon, {.i = -1 } },
88 + {1, {{MODKEY, XK_period}}, focusmon, {.i = +1 } },
89 + {1, {{MODKEY|ShiftMask, XK_comma}}, tagmon, {.i = -1 } },
90 + {1, {{MODKEY|ShiftMask, XK_period}}, tagmon, {.i = +1 } },
91 TAGKEYS( XK_1, 0)
92 TAGKEYS( XK_2, 1)
93 TAGKEYS( XK_3, 2)
94 @@ -92,9 +95,9 @@ static Key keys[] = {
95 TAGKEYS( XK_5, 4)
96 TAGKEYS( XK_6, 5)
97 TAGKEYS( XK_7, 6)
98 - TAGKEYS( XK_8, 7)
99 + TAGKEYS( XK_8, 7)
100 TAGKEYS( XK_9, 8)
101 - { MODKEY|ShiftMask, XK_q, quit, {0} },
102 + {1, {{MODKEY|ShiftMask, XK_q}}, quit, {0} },
103 };
104
105 /* button definitions */
106 diff --git a/dwm.c b/dwm.c
107 index 5e4d494..56c4661 100644
108 --- a/dwm.c
109 +++ b/dwm.c
110 @@ -102,9 +102,14 @@ struct Client {
111 typedef struct {
112 unsigned int mod;
113 KeySym keysym;
114 +} Key;
115 +
116 +typedef struct {
117 + unsigned int n;
118 + const Key keys[5];
119 void (*func)(const Arg *);
120 const Arg arg;
121 -} Key;
122 +} Keychord;
123
124 typedef struct {
125 const char *symbol;
126 @@ -268,6 +273,7 @@ static Display *dpy;
127 static Drw *drw;
128 static Monitor *mons, *selmon;
129 static Window root, wmcheckwin;
130 +unsigned int currentkey = 0;
131
132 /* configuration, allows nested code to access above variables */
133 #include "config.h"
134 @@ -951,16 +957,16 @@ grabkeys(void)
135 {
136 updatenumlockmask();
137 {
138 - unsigned int i, j;
139 + unsigned int i, k;
140 unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
141 KeyCode code;
142
143 XUngrabKey(dpy, AnyKey, AnyModifier, root);
144 - for (i = 0; i < LENGTH(keys); i++)
145 - if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
146 - for (j = 0; j < LENGTH(modifiers); j++)
147 - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
148 - True, GrabModeAsync, GrabModeAsync);
149 + for (i = 0; i < LENGTH(keychords); i++)
150 + if ((code = XKeysymToKeycode(dpy, keychords[i].keys[currentkey].keysym)))
151 + for (k = 0; k < LENGTH(modifiers); k++)
152 + XGrabKey(dpy, code, keychords[i].keys[currentkey].mod | modifiers[k], root,
153 + True, GrabModeAsync, GrabModeAsync);
154 }
155 }
156
157 @@ -986,17 +992,48 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
158 void
159 keypress(XEvent *e)
160 {
161 - unsigned int i;
162 + XEvent event = *e;
163 + Keychord *keychord;
164 + unsigned int ran = 0;
165 KeySym keysym;
166 XKeyEvent *ev;
167 -
168 - ev = &e->xkey;
169 - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
170 - for (i = 0; i < LENGTH(keys); i++)
171 - if (keysym == keys[i].keysym
172 - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
173 - && keys[i].func)
174 - keys[i].func(&(keys[i].arg));
175 + Keychord *newoptions;
176 + Keychord *oldoptions = (Keychord *)malloc(sizeof(keychords));
177 +
178 + memcpy(oldoptions, keychords, sizeof(keychords));
179 + size_t numoption = 0;
180 + while(!ran){
181 + ev = &event.xkey;
182 + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
183 + newoptions = (Keychord *)malloc(0);
184 + numoption = 0;
185 + for (keychord = oldoptions; keychord->n != 0 && currentkey < 5; keychord = (Keychord *)((char *)keychord + sizeof(Keychord))){
186 + if(keysym == keychord->keys[currentkey].keysym
187 + && CLEANMASK(keychord->keys[currentkey].mod) == CLEANMASK(ev->state)
188 + && keychord->func){
189 + if(keychord->n == currentkey +1){
190 + keychord->func(&(keychord->arg));
191 + ran = 1;
192 + }else{
193 + numoption++;
194 + newoptions = (Keychord *)realloc(newoptions, numoption * sizeof(Keychord));
195 + memcpy((char *)newoptions + (numoption -1) * sizeof(Keychord),keychord, sizeof(Keychord));
196 + }
197 + }
198 + }
199 + currentkey++;
200 + if(numoption == 0)
201 + break;
202 + grabkeys();
203 + while (running && !XNextEvent(dpy, &event) && !ran)
204 + if(event.type == KeyPress)
205 + break;
206 + free(oldoptions);
207 + oldoptions = newoptions;
208 + }
209 + free(newoptions);
210 + currentkey = 0;
211 + grabkeys();
212 }
213
214 void
215 --
216 2.34.1
217