dwm-keymodes-20220422.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
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 … | |
10 - { MODKEY|ControlMask, KEY, toggleview, {.ui … | |
11 - { MODKEY|ShiftMask, KEY, tag, {.ui … | |
12 - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui … | |
13 + { {0,0,0,0}, {KEY,0,0,0}, view, … | |
14 + { {ControlMask,0,0,0}, {KEY,0,0,0}, toggleview, … | |
15 + { {ShiftMask,0,0,0}, {KEY,0,0,0}, tag, … | |
16 + { {ControlMask|ShiftMask,0,0,0}, {KEY,0,0,0}, toggletag, … | |
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 argu… | |
24 - { MODKEY, XK_p, spawn, {.v … | |
25 - { MODKEY|ShiftMask, XK_Return, spawn, {.v … | |
26 - { MODKEY, XK_b, togglebar, {0} … | |
27 - { MODKEY, XK_j, focusstack, {.i … | |
28 - { MODKEY, XK_k, focusstack, {.i … | |
29 - { MODKEY, XK_i, incnmaster, {.i … | |
30 - { MODKEY, XK_d, incnmaster, {.i … | |
31 - { MODKEY, XK_h, setmfact, {.f … | |
32 - { MODKEY, XK_l, setmfact, {.f … | |
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 … | |
37 - { MODKEY, XK_f, setlayout, {.v … | |
38 - { MODKEY, XK_m, setlayout, {.v … | |
39 - { MODKEY, XK_space, setlayout, {0} … | |
40 - { MODKEY|ShiftMask, XK_space, togglefloating, {0} … | |
41 - { MODKEY, XK_0, view, {.ui… | |
42 - { MODKEY|ShiftMask, XK_0, tag, {.ui… | |
43 - { MODKEY, XK_comma, focusmon, {.i … | |
44 - { MODKEY, XK_period, focusmon, {.i … | |
45 - { MODKEY|ShiftMask, XK_comma, tagmon, {.i … | |
46 - { MODKEY|ShiftMask, XK_period, tagmon, {.i … | |
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… | |
58 +}; | |
59 + | |
60 +static Key cmdkeys[] = { | |
61 + /* modifier keys functio… | |
62 + { 0, XK_Escape, clearcm… | |
63 + { ControlMask, XK_g, clearcm… | |
64 + { 0, XK_i, setkeym… | |
65 +}; | |
66 +static Command commands[] = { | |
67 + /* modifier (4 keys) keysyms (4 keys) function … | |
68 + { {0, 0, 0, 0}, { XK_p, 0, 0, 0}, spawn, … | |
69 + { {ShiftMask, 0, 0, 0}, { XK_Return, 0, 0, 0}, spawn, … | |
70 + { {0, 0, 0, 0}, { XK_b, 0, 0, 0}, togglebar… | |
71 + { {0, 0, 0, 0}, { XK_j, 0, 0, 0}, focusstac… | |
72 + { {0, 0, 0, 0}, { XK_k, 0, 0, 0}, focusstac… | |
73 + { {0, 0, 0, 0}, { XK_i, 0, 0, 0}, incnmaste… | |
74 + { {0, 0, 0, 0}, { XK_d, 0, 0, 0}, incnmaste… | |
75 + { {0, 0, 0, 0}, { XK_h, 0, 0, 0}, setmfact,… | |
76 + { {0, 0, 0, 0}, { XK_l, 0, 0, 0}, setmfact,… | |
77 + { {0, 0, 0, 0}, { XK_Return, 0, 0, 0}, zoom, … | |
78 + { {ControlMask, 0, 0, 0}, { XK_i, 0, 0, 0}, view, … | |
79 + { {ShiftMask, 0, 0, 0}, { XK_k, 0, 0, 0}, killclien… | |
80 + { {0, 0, 0, 0}, { XK_t, 0, 0, 0}, setlayout… | |
81 + { {0, 0, 0, 0}, { XK_f, 0, 0, 0}, setlayout… | |
82 + { {0, 0, 0, 0}, { XK_m, 0, 0, 0}, setlayout… | |
83 + { {0, 0, 0, 0}, { XK_space, 0, 0, 0}, setlayout… | |
84 + { {ShiftMask, 0, 0, 0}, { XK_space, 0, 0, 0}, toggleflo… | |
85 + { {0, 0, 0, 0}, { XK_0, 0, 0, 0}, view, … | |
86 + { {ShiftMask, 0, 0, 0}, { XK_0, 0, 0, 0}, tag, … | |
87 + { {0, 0, 0, 0}, { XK_comma, 0, 0, 0}, focusmon,… | |
88 + { {0, 0, 0, 0}, { XK_period, 0, 0, 0}, focusmon,… | |
89 + { {ShiftMask, 0, 0, 0}, { XK_comma, 0, 0, 0}, tagmon, … | |
90 + { {ShiftMask, 0, 0, 0}, { XK_period, 0, 0, 0}, tagmon, … | |
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, … | |
101 }; | |
102 | |
103 /* button definitions */ | |
104 @@ -113,4 +124,3 @@ static Button buttons[] = { | |
105 { ClkTagBar, MODKEY, Button1, tag, … | |
106 { ClkTagBar, MODKEY, Button3, togglet… | |
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 geo… | |
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, GrabModeA… | |
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… | |
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) { |