commit cdb32fa277fcfe79fea6b85038e0ce0fb3ec1d01
parent b15a0b78132b2df5e6b10651a236ee8091dd26c9
Author: Michael Hendricks <michael@ndrix.org>
Date: Fri, 22 Apr 2022 14:45:31 -0600
[dwm][patch][keymodes] rebase onto master
Diffstat:
2 files changed, 321 insertions(+), 0 deletions(-)
diff --git a/dwm.suckless.org/patches/keymodes/dwm-keymodes-20220422.diff b/dwm.suckless.org/patches/keymodes/dwm-keymodes-20220422.diff
@@ -0,0 +1,320 @@
+diff --git a/config.def.h b/config.def.h
+index a2ac963..3bde49d 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -47,10 +47,10 @@ static const Layout layouts[] = {
+ /* key definitions */
+ #define MODKEY Mod1Mask
+ #define TAGKEYS(KEY,TAG) \
+- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
+- { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
+- { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
+- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
++ { {0,0,0,0}, {KEY,0,0,0}, view, {.ui = 1 << TAG} }, \
++ { {ControlMask,0,0,0}, {KEY,0,0,0}, toggleview, {.ui = 1 << TAG} }, \
++ { {ShiftMask,0,0,0}, {KEY,0,0,0}, tag, {.ui = 1 << TAG} }, \
++ { {ControlMask|ShiftMask,0,0,0}, {KEY,0,0,0}, toggletag, {.ui = 1 << TAG} },
+
+ /* helper for spawning shell commands in the pre dwm-5.0 fashion */
+ #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
+@@ -62,39 +62,50 @@ static const char *termcmd[] = { "st", NULL };
+
+ static Key keys[] = {
+ /* modifier key function argument */
+- { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
+- { MODKEY, XK_b, togglebar, {0} },
+- { MODKEY, XK_j, focusstack, {.i = +1 } },
+- { MODKEY, XK_k, focusstack, {.i = -1 } },
+- { MODKEY, XK_i, incnmaster, {.i = +1 } },
+- { MODKEY, XK_d, incnmaster, {.i = -1 } },
+- { MODKEY, XK_h, setmfact, {.f = -0.05} },
+- { MODKEY, XK_l, setmfact, {.f = +0.05} },
+- { MODKEY, XK_Return, zoom, {0} },
+- { MODKEY, XK_Tab, view, {0} },
+- { MODKEY|ShiftMask, XK_c, killclient, {0} },
+- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
+- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
+- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+- { MODKEY, XK_space, setlayout, {0} },
+- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+- { MODKEY, XK_0, view, {.ui = ~0 } },
+- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
+- { MODKEY, XK_comma, focusmon, {.i = -1 } },
+- { MODKEY, XK_period, focusmon, {.i = +1 } },
+- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
+- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+- TAGKEYS( XK_1, 0)
+- TAGKEYS( XK_2, 1)
+- TAGKEYS( XK_3, 2)
+- TAGKEYS( XK_4, 3)
+- TAGKEYS( XK_5, 4)
+- TAGKEYS( XK_6, 5)
+- TAGKEYS( XK_7, 6)
+- TAGKEYS( XK_8, 7)
+- TAGKEYS( XK_9, 8)
+- { MODKEY|ShiftMask, XK_q, quit, {0} },
++ { MODKEY, XK_Escape, setkeymode, {.ui = ModeCommand} },
++};
++
++static Key cmdkeys[] = {
++ /* modifier keys function argument */
++ { 0, XK_Escape, clearcmd, {0} },
++ { ControlMask, XK_g, clearcmd, {0} },
++ { 0, XK_i, setkeymode, {.ui = ModeInsert} },
++};
++static Command commands[] = {
++ /* modifier (4 keys) keysyms (4 keys) function argument */
++ { {0, 0, 0, 0}, { XK_p, 0, 0, 0}, spawn, {.v = dmenucmd } },
++ { {ShiftMask, 0, 0, 0}, { XK_Return, 0, 0, 0}, spawn, {.v = termcmd } },
++ { {0, 0, 0, 0}, { XK_b, 0, 0, 0}, togglebar, {0} },
++ { {0, 0, 0, 0}, { XK_j, 0, 0, 0}, focusstack, {.i = +1 } },
++ { {0, 0, 0, 0}, { XK_k, 0, 0, 0}, focusstack, {.i = -1 } },
++ { {0, 0, 0, 0}, { XK_i, 0, 0, 0}, incnmaster, {.i = +1 } },
++ { {0, 0, 0, 0}, { XK_d, 0, 0, 0}, incnmaster, {.i = -1 } },
++ { {0, 0, 0, 0}, { XK_h, 0, 0, 0}, setmfact, {.f = -0.05} },
++ { {0, 0, 0, 0}, { XK_l, 0, 0, 0}, setmfact, {.f = +0.05} },
++ { {0, 0, 0, 0}, { XK_Return, 0, 0, 0}, zoom, {0} },
++ { {ControlMask, 0, 0, 0}, { XK_i, 0, 0, 0}, view, {0} },
++ { {ShiftMask, 0, 0, 0}, { XK_k, 0, 0, 0}, killclient, {0} },
++ { {0, 0, 0, 0}, { XK_t, 0, 0, 0}, setlayout, {.v = &layouts[0]} },
++ { {0, 0, 0, 0}, { XK_f, 0, 0, 0}, setlayout, {.v = &layouts[1]} },
++ { {0, 0, 0, 0}, { XK_m, 0, 0, 0}, setlayout, {.v = &layouts[2]} },
++ { {0, 0, 0, 0}, { XK_space, 0, 0, 0}, setlayout, {0} },
++ { {ShiftMask, 0, 0, 0}, { XK_space, 0, 0, 0}, togglefloating, {0} },
++ { {0, 0, 0, 0}, { XK_0, 0, 0, 0}, view, {.ui = ~0 } },
++ { {ShiftMask, 0, 0, 0}, { XK_0, 0, 0, 0}, tag, {.ui = ~0 } },
++ { {0, 0, 0, 0}, { XK_comma, 0, 0, 0}, focusmon, {.i = -1 } },
++ { {0, 0, 0, 0}, { XK_period, 0, 0, 0}, focusmon, {.i = +1 } },
++ { {ShiftMask, 0, 0, 0}, { XK_comma, 0, 0, 0}, tagmon, {.i = -1 } },
++ { {ShiftMask, 0, 0, 0}, { XK_period, 0, 0, 0}, tagmon, {.i = +1 } },
++ TAGKEYS(XK_1, 0)
++ TAGKEYS(XK_2, 1)
++ TAGKEYS(XK_3, 2)
++ TAGKEYS(XK_4, 3)
++ TAGKEYS(XK_5, 4)
++ TAGKEYS(XK_6, 5)
++ TAGKEYS(XK_7, 6)
++ TAGKEYS(XK_8, 7)
++ TAGKEYS(XK_9, 8)
++ { {ShiftMask, 0, 0, 0}, { XK_q, 0, 0, 0}, quit, {0} },
+ };
+
+ /* button definitions */
+@@ -113,4 +124,3 @@ static Button buttons[] = {
+ { ClkTagBar, MODKEY, Button1, tag, {0} },
+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+ };
+-
+diff --git a/config.mk b/config.mk
+index b6eb7e0..c9334e2 100644
+--- a/config.mk
++++ b/config.mk
+@@ -18,7 +18,7 @@ XINERAMAFLAGS = -DXINERAMA
+ FREETYPELIBS = -lfontconfig -lXft
+ FREETYPEINC = /usr/include/freetype2
+ # OpenBSD (uncomment)
+-#FREETYPEINC = ${X11INC}/freetype2
++FREETYPEINC = ${X11INC}/freetype2
+
+ # includes and libs
+ INCS = -I${X11INC} -I${FREETYPEINC}
+diff --git a/dwm.c b/dwm.c
+index 0fc328a..487484e 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -60,6 +60,7 @@
+ /* enums */
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+ enum { SchemeNorm, SchemeSel }; /* color schemes */
++enum { ModeCommand, ModeInsert };
+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+@@ -99,6 +100,13 @@ struct Client {
+ Window win;
+ };
+
++typedef struct {
++ unsigned int mod[4];
++ KeySym keysym[4];
++ void (*func)(const Arg *);
++ const Arg arg;
++} Command;
++
+ typedef struct {
+ unsigned int mod;
+ KeySym keysym;
+@@ -152,6 +160,7 @@ static void buttonpress(XEvent *e);
+ static void checkotherwm(void);
+ static void cleanup(void);
+ static void cleanupmon(Monitor *mon);
++static void clearcmd(const Arg *arg);
+ static void clientmessage(XEvent *e);
+ static void configure(Client *c);
+ static void configurenotify(XEvent *e);
+@@ -177,6 +186,7 @@ static void grabbuttons(Client *c, int focused);
+ static void grabkeys(void);
+ static void incnmaster(const Arg *arg);
+ static void keypress(XEvent *e);
++static void keypresscmd(XEvent *e);
+ static void killclient(const Arg *arg);
+ static void manage(Window w, XWindowAttributes *wa);
+ static void mappingnotify(XEvent *e);
+@@ -200,6 +210,8 @@ static void sendmon(Client *c, Monitor *m);
+ static void setclientstate(Client *c, long state);
+ static void setfocus(Client *c);
+ static void setfullscreen(Client *c, int fullscreen);
++static void setinsertmode(void);
++static void setkeymode(const Arg *arg);
+ static void setlayout(const Arg *arg);
+ static void setmfact(const Arg *arg);
+ static void setup(void);
+@@ -243,6 +255,8 @@ static int sw, sh; /* X display screen geometry width, height */
+ static int bh, blw = 0; /* bar geometry */
+ static int lrpad; /* sum of left and right padding for text */
+ static int (*xerrorxlib)(Display *, XErrorEvent *);
++static unsigned int cmdmod[4];
++static unsigned int keymode = ModeCommand;
+ static unsigned int numlockmask = 0;
+ static void (*handler[LASTEvent]) (XEvent *) = {
+ [ButtonPress] = buttonpress,
+@@ -266,6 +280,7 @@ static Cur *cursor[CurLast];
+ static Clr **scheme;
+ static Display *dpy;
+ static Drw *drw;
++static KeySym cmdkeysym[4];
+ static Monitor *mons, *selmon;
+ static Window root, wmcheckwin;
+
+@@ -513,6 +528,17 @@ cleanupmon(Monitor *mon)
+ free(mon);
+ }
+
++void
++clearcmd(const Arg *arg)
++{
++ unsigned int i;
++
++ for (i = 0; i < LENGTH(cmdkeysym); i++) {
++ cmdkeysym[i] = 0;
++ cmdmod[i] = 0;
++ }
++}
++
+ void
+ clientmessage(XEvent *e)
+ {
+@@ -955,6 +981,13 @@ grabbuttons(Client *c, int focused)
+ void
+ grabkeys(void)
+ {
++ if (keymode == ModeCommand) {
++ XUngrabKey(dpy, AnyKey, AnyModifier, root);
++ XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
++ return;
++ }
++
++ XUngrabKeyboard(dpy, CurrentTime);
+ updatenumlockmask();
+ {
+ unsigned int i, j;
+@@ -996,6 +1029,11 @@ keypress(XEvent *e)
+ KeySym keysym;
+ XKeyEvent *ev;
+
++ if (keymode == ModeCommand) {
++ keypresscmd(e);
++ return;
++ }
++
+ ev = &e->xkey;
+ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+ for (i = 0; i < LENGTH(keys); i++)
+@@ -1005,6 +1043,53 @@ keypress(XEvent *e)
+ keys[i].func(&(keys[i].arg));
+ }
+
++void
++keypresscmd(XEvent *e) {
++ unsigned int i, j;
++ int matches = 0;
++ KeySym keysym;
++ XKeyEvent *ev;
++
++ ev = &e->xkey;
++ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
++ if (XK_Shift_L <= keysym && keysym <= XK_Hyper_R) {
++ return;
++ }
++
++ for (i = 0; i < LENGTH(cmdkeys); i++) {
++ if (keysym == cmdkeys[i].keysym
++ && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state)
++ && cmdkeys[i].func) {
++ cmdkeys[i].func(&(cmdkeys[i].arg));
++ return;
++ }
++ }
++
++ for (j = 0; j < LENGTH(cmdkeysym); j++) {
++ if (cmdkeysym[j] == 0) {
++ cmdkeysym[j] = keysym;
++ cmdmod[j] = ev->state;
++ break;
++ }
++ }
++
++ for (i = 0; i < LENGTH(commands); i++) {
++ matches = 0;
++ for (j = 0; j < LENGTH(cmdkeysym); j++) {
++ if (cmdkeysym[j] == commands[i].keysym[j]
++ && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j]))
++ matches++;
++ }
++ if (matches == LENGTH(cmdkeysym)) {
++ if (commands[i].func)
++ commands[i].func(&(commands[i].arg));
++ clearcmd(NULL);
++ return;
++ }
++ }
++}
++
++
+ void
+ killclient(const Arg *arg)
+ {
+@@ -1438,6 +1523,24 @@ setclientstate(Client *c, long state)
+ PropModeReplace, (unsigned char *)data, 2);
+ }
+
++void
++setinsertmode()
++{
++ keymode = ModeInsert;
++ clearcmd(NULL);
++ grabkeys();
++}
++
++void
++setkeymode(const Arg *arg)
++{
++ if(!arg)
++ return;
++ keymode = arg->ui;
++ clearcmd(NULL);
++ grabkeys();
++}
++
+ int
+ sendevent(Client *c, Atom proto)
+ {
+@@ -1645,6 +1748,7 @@ sigchld(int unused)
+ void
+ spawn(const Arg *arg)
+ {
++ setinsertmode();
+ if (arg->v == dmenucmd)
+ dmenumon[0] = '0' + selmon->num;
+ if (fork() == 0) {
diff --git a/dwm.suckless.org/patches/keymodes/index.md b/dwm.suckless.org/patches/keymodes/index.md
@@ -65,3 +65,4 @@ Download
--------
* [dwm-keymodes-5.8.2.diff](dwm-keymodes-5.8.2.diff) (20100611, joten (at) freenet (dot) de)
* [dwm-keymodes-vim-5.8.2.diff](dwm-keymodes-vim-5.8.2.diff) (20100611, joten (at) freenet (dot) de)
+* [dwm-keymodes-20220422.diff](dwm-keymodes-20220422.diff) (michael@ndrix.org)