dwm-keymodes-20220422.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-keymodes-20220422.diff (11577B)
---
1 diff --git a/config.def.h b/config.def.h
2 index a2ac963..3bde49d 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -47,10 +47,10 @@ static const Layout layouts[] = {
6 /* key definitions */
7 #define MODKEY Mod1Mask
8 #define TAGKEYS(KEY,TAG) \
9 - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
10 - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
11 - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
12 - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
13 + { {0,0,0,0}, {KEY,0,0,0}, view, {.ui = 1 << TAG} }, \
14 + { {ControlMask,0,0,0}, {KEY,0,0,0}, toggleview, {.ui = 1 << TAG} }, \
15 + { {ShiftMask,0,0,0}, {KEY,0,0,0}, tag, {.ui = 1 << TAG} }, \
16 + { {ControlMask|ShiftMask,0,0,0}, {KEY,0,0,0}, toggletag, {.ui = 1 << TAG} },
17
18 /* helper for spawning shell commands in the pre dwm-5.0 fashion */
19 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
20 @@ -62,39 +62,50 @@ static const char *termcmd[] = { "st", NULL };
21
22 static Key keys[] = {
23 /* modifier key function argument */
24 - { MODKEY, XK_p, spawn, {.v = dmenucmd } },
25 - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
26 - { MODKEY, XK_b, togglebar, {0} },
27 - { MODKEY, XK_j, focusstack, {.i = +1 } },
28 - { MODKEY, XK_k, focusstack, {.i = -1 } },
29 - { MODKEY, XK_i, incnmaster, {.i = +1 } },
30 - { MODKEY, XK_d, incnmaster, {.i = -1 } },
31 - { MODKEY, XK_h, setmfact, {.f = -0.05} },
32 - { MODKEY, XK_l, setmfact, {.f = +0.05} },
33 - { MODKEY, XK_Return, zoom, {0} },
34 - { MODKEY, XK_Tab, view, {0} },
35 - { MODKEY|ShiftMask, XK_c, killclient, {0} },
36 - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
37 - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
38 - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
39 - { MODKEY, XK_space, setlayout, {0} },
40 - { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
41 - { MODKEY, XK_0, view, {.ui = ~0 } },
42 - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
43 - { MODKEY, XK_comma, focusmon, {.i = -1 } },
44 - { MODKEY, XK_period, focusmon, {.i = +1 } },
45 - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
46 - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
47 - TAGKEYS( XK_1, 0)
48 - TAGKEYS( XK_2, 1)
49 - TAGKEYS( XK_3, 2)
50 - TAGKEYS( XK_4, 3)
51 - TAGKEYS( XK_5, 4)
52 - TAGKEYS( XK_6, 5)
53 - TAGKEYS( XK_7, 6)
54 - TAGKEYS( XK_8, 7)
55 - TAGKEYS( XK_9, 8)
56 - { MODKEY|ShiftMask, XK_q, quit, {0} },
57 + { MODKEY, XK_Escape, setkeymode, {.ui = ModeCommand} },
58 +};
59 +
60 +static Key cmdkeys[] = {
61 + /* modifier keys function argument */
62 + { 0, XK_Escape, clearcmd, {0} },
63 + { ControlMask, XK_g, clearcmd, {0} },
64 + { 0, XK_i, setkeymode, {.ui = ModeInsert} },
65 +};
66 +static Command commands[] = {
67 + /* modifier (4 keys) keysyms (4 keys) function argument */
68 + { {0, 0, 0, 0}, { XK_p, 0, 0, 0}, spawn, {.v = dmenucmd } },
69 + { {ShiftMask, 0, 0, 0}, { XK_Return, 0, 0, 0}, spawn, {.v = termcmd } },
70 + { {0, 0, 0, 0}, { XK_b, 0, 0, 0}, togglebar, {0} },
71 + { {0, 0, 0, 0}, { XK_j, 0, 0, 0}, focusstack, {.i = +1 } },
72 + { {0, 0, 0, 0}, { XK_k, 0, 0, 0}, focusstack, {.i = -1 } },
73 + { {0, 0, 0, 0}, { XK_i, 0, 0, 0}, incnmaster, {.i = +1 } },
74 + { {0, 0, 0, 0}, { XK_d, 0, 0, 0}, incnmaster, {.i = -1 } },
75 + { {0, 0, 0, 0}, { XK_h, 0, 0, 0}, setmfact, {.f = -0.05} },
76 + { {0, 0, 0, 0}, { XK_l, 0, 0, 0}, setmfact, {.f = +0.05} },
77 + { {0, 0, 0, 0}, { XK_Return, 0, 0, 0}, zoom, {0} },
78 + { {ControlMask, 0, 0, 0}, { XK_i, 0, 0, 0}, view, {0} },
79 + { {ShiftMask, 0, 0, 0}, { XK_k, 0, 0, 0}, killclient, {0} },
80 + { {0, 0, 0, 0}, { XK_t, 0, 0, 0}, setlayout, {.v = &layouts[0]} },
81 + { {0, 0, 0, 0}, { XK_f, 0, 0, 0}, setlayout, {.v = &layouts[1]} },
82 + { {0, 0, 0, 0}, { XK_m, 0, 0, 0}, setlayout, {.v = &layouts[2]} },
83 + { {0, 0, 0, 0}, { XK_space, 0, 0, 0}, setlayout, {0} },
84 + { {ShiftMask, 0, 0, 0}, { XK_space, 0, 0, 0}, togglefloating, {0} },
85 + { {0, 0, 0, 0}, { XK_0, 0, 0, 0}, view, {.ui = ~0 } },
86 + { {ShiftMask, 0, 0, 0}, { XK_0, 0, 0, 0}, tag, {.ui = ~0 } },
87 + { {0, 0, 0, 0}, { XK_comma, 0, 0, 0}, focusmon, {.i = -1 } },
88 + { {0, 0, 0, 0}, { XK_period, 0, 0, 0}, focusmon, {.i = +1 } },
89 + { {ShiftMask, 0, 0, 0}, { XK_comma, 0, 0, 0}, tagmon, {.i = -1 } },
90 + { {ShiftMask, 0, 0, 0}, { XK_period, 0, 0, 0}, tagmon, {.i = +1 } },
91 + TAGKEYS(XK_1, 0)
92 + TAGKEYS(XK_2, 1)
93 + TAGKEYS(XK_3, 2)
94 + TAGKEYS(XK_4, 3)
95 + TAGKEYS(XK_5, 4)
96 + TAGKEYS(XK_6, 5)
97 + TAGKEYS(XK_7, 6)
98 + TAGKEYS(XK_8, 7)
99 + TAGKEYS(XK_9, 8)
100 + { {ShiftMask, 0, 0, 0}, { XK_q, 0, 0, 0}, quit, {0} },
101 };
102
103 /* button definitions */
104 @@ -113,4 +124,3 @@ static Button buttons[] = {
105 { ClkTagBar, MODKEY, Button1, tag, {0} },
106 { ClkTagBar, MODKEY, Button3, toggletag, {0} },
107 };
108 -
109 diff --git a/dwm.c b/dwm.c
110 index 0fc328a..487484e 100644
111 --- a/dwm.c
112 +++ b/dwm.c
113 @@ -60,6 +60,7 @@
114 /* enums */
115 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
116 enum { SchemeNorm, SchemeSel }; /* color schemes */
117 +enum { ModeCommand, ModeInsert };
118 enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
119 NetWMFullscreen, NetActiveWindow, NetWMWindowType,
120 NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
121 @@ -99,6 +100,13 @@ struct Client {
122 Window win;
123 };
124
125 +typedef struct {
126 + unsigned int mod[4];
127 + KeySym keysym[4];
128 + void (*func)(const Arg *);
129 + const Arg arg;
130 +} Command;
131 +
132 typedef struct {
133 unsigned int mod;
134 KeySym keysym;
135 @@ -152,6 +160,7 @@ static void buttonpress(XEvent *e);
136 static void checkotherwm(void);
137 static void cleanup(void);
138 static void cleanupmon(Monitor *mon);
139 +static void clearcmd(const Arg *arg);
140 static void clientmessage(XEvent *e);
141 static void configure(Client *c);
142 static void configurenotify(XEvent *e);
143 @@ -177,6 +186,7 @@ static void grabbuttons(Client *c, int focused);
144 static void grabkeys(void);
145 static void incnmaster(const Arg *arg);
146 static void keypress(XEvent *e);
147 +static void keypresscmd(XEvent *e);
148 static void killclient(const Arg *arg);
149 static void manage(Window w, XWindowAttributes *wa);
150 static void mappingnotify(XEvent *e);
151 @@ -200,6 +210,8 @@ static void sendmon(Client *c, Monitor *m);
152 static void setclientstate(Client *c, long state);
153 static void setfocus(Client *c);
154 static void setfullscreen(Client *c, int fullscreen);
155 +static void setinsertmode(void);
156 +static void setkeymode(const Arg *arg);
157 static void setlayout(const Arg *arg);
158 static void setmfact(const Arg *arg);
159 static void setup(void);
160 @@ -243,6 +255,8 @@ static int sw, sh; /* X display screen geometry width, height */
161 static int bh, blw = 0; /* bar geometry */
162 static int lrpad; /* sum of left and right padding for text */
163 static int (*xerrorxlib)(Display *, XErrorEvent *);
164 +static unsigned int cmdmod[4];
165 +static unsigned int keymode = ModeCommand;
166 static unsigned int numlockmask = 0;
167 static void (*handler[LASTEvent]) (XEvent *) = {
168 [ButtonPress] = buttonpress,
169 @@ -266,6 +280,7 @@ static Cur *cursor[CurLast];
170 static Clr **scheme;
171 static Display *dpy;
172 static Drw *drw;
173 +static KeySym cmdkeysym[4];
174 static Monitor *mons, *selmon;
175 static Window root, wmcheckwin;
176
177 @@ -513,6 +528,17 @@ cleanupmon(Monitor *mon)
178 free(mon);
179 }
180
181 +void
182 +clearcmd(const Arg *arg)
183 +{
184 + unsigned int i;
185 +
186 + for (i = 0; i < LENGTH(cmdkeysym); i++) {
187 + cmdkeysym[i] = 0;
188 + cmdmod[i] = 0;
189 + }
190 +}
191 +
192 void
193 clientmessage(XEvent *e)
194 {
195 @@ -955,6 +981,13 @@ grabbuttons(Client *c, int focused)
196 void
197 grabkeys(void)
198 {
199 + if (keymode == ModeCommand) {
200 + XUngrabKey(dpy, AnyKey, AnyModifier, root);
201 + XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
202 + return;
203 + }
204 +
205 + XUngrabKeyboard(dpy, CurrentTime);
206 updatenumlockmask();
207 {
208 unsigned int i, j;
209 @@ -996,6 +1029,11 @@ keypress(XEvent *e)
210 KeySym keysym;
211 XKeyEvent *ev;
212
213 + if (keymode == ModeCommand) {
214 + keypresscmd(e);
215 + return;
216 + }
217 +
218 ev = &e->xkey;
219 keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
220 for (i = 0; i < LENGTH(keys); i++)
221 @@ -1005,6 +1043,53 @@ keypress(XEvent *e)
222 keys[i].func(&(keys[i].arg));
223 }
224
225 +void
226 +keypresscmd(XEvent *e) {
227 + unsigned int i, j;
228 + int matches = 0;
229 + KeySym keysym;
230 + XKeyEvent *ev;
231 +
232 + ev = &e->xkey;
233 + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
234 + if (XK_Shift_L <= keysym && keysym <= XK_Hyper_R) {
235 + return;
236 + }
237 +
238 + for (i = 0; i < LENGTH(cmdkeys); i++) {
239 + if (keysym == cmdkeys[i].keysym
240 + && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state)
241 + && cmdkeys[i].func) {
242 + cmdkeys[i].func(&(cmdkeys[i].arg));
243 + return;
244 + }
245 + }
246 +
247 + for (j = 0; j < LENGTH(cmdkeysym); j++) {
248 + if (cmdkeysym[j] == 0) {
249 + cmdkeysym[j] = keysym;
250 + cmdmod[j] = ev->state;
251 + break;
252 + }
253 + }
254 +
255 + for (i = 0; i < LENGTH(commands); i++) {
256 + matches = 0;
257 + for (j = 0; j < LENGTH(cmdkeysym); j++) {
258 + if (cmdkeysym[j] == commands[i].keysym[j]
259 + && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j]))
260 + matches++;
261 + }
262 + if (matches == LENGTH(cmdkeysym)) {
263 + if (commands[i].func)
264 + commands[i].func(&(commands[i].arg));
265 + clearcmd(NULL);
266 + return;
267 + }
268 + }
269 +}
270 +
271 +
272 void
273 killclient(const Arg *arg)
274 {
275 @@ -1438,6 +1523,24 @@ setclientstate(Client *c, long state)
276 PropModeReplace, (unsigned char *)data, 2);
277 }
278
279 +void
280 +setinsertmode()
281 +{
282 + keymode = ModeInsert;
283 + clearcmd(NULL);
284 + grabkeys();
285 +}
286 +
287 +void
288 +setkeymode(const Arg *arg)
289 +{
290 + if(!arg)
291 + return;
292 + keymode = arg->ui;
293 + clearcmd(NULL);
294 + grabkeys();
295 +}
296 +
297 int
298 sendevent(Client *c, Atom proto)
299 {
300 @@ -1645,6 +1748,7 @@ sigchld(int unused)
301 void
302 spawn(const Arg *arg)
303 {
304 + setinsertmode();
305 if (arg->v == dmenucmd)
306 dmenumon[0] = '0' + selmon->num;
307 if (fork() == 0) {