Re: [hackers] [dwm][PATCH] ratpoison-like prefix key

From: Hiltjo Posthuma <hiltjo_AT_codemadness.org>
Date: Sat, 11 May 2019 11:12:23 +0200

On Wed, May 08, 2019 at 10:21:09PM +0200, Philip Linde wrote:
> - Run "prefix" to enter prefix mode.
> - Prefix mode is indicated by a flag in the tag bar.
> - While prefix mode is enabled, MODKEY is ignored in all bindings.
> - Executing prefix while in prefix mode will send the keysym/mod
> combination of its argument to the active window.
> - Executing any key-bound command while in prefix mode will exit prefix
> mode.
> ---
> config.def.h | 2 ++
> dwm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 50 insertions(+), 3 deletions(-)
>
> diff --git a/config.def.h b/config.def.h
> index 1c0b587..b14b678 100644
> --- a/config.def.h
> +++ b/config.def.h
> _AT_@ -94,6 +94,8 @@ static Key keys[] = {
> TAGKEYS( XK_8, 7)
> TAGKEYS( XK_9, 8)
> { MODKEY|ShiftMask, XK_q, quit, {0} },
> + { ControlMask, XK_t, prefix, {.c = { ControlMask, XK_t } } },
> + { MODKEY, XK_Escape, noop, {0} },
> };
>
> /* button definitions */
> diff --git a/dwm.c b/dwm.c
> index 4465af1..43714ae 100644
> --- a/dwm.c
> +++ b/dwm.c
> _AT_@ -67,11 +67,17 @@ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms *
> enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
> ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
>
> +typedef struct {
> + unsigned int mod;
> + KeySym keysym;
> +} Combo;
> +
> typedef union {
> int i;
> unsigned int ui;
> float f;
> const void *v;
> + Combo c;
> } Arg;
>
> typedef struct {
> _AT_@ -233,6 +239,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
> static int xerrordummy(Display *dpy, XErrorEvent *ee);
> static int xerrorstart(Display *dpy, XErrorEvent *ee);
> static void zoom(const Arg *arg);
> +static void prefix(const Arg *arg);
> +static void noop(const Arg *arg);
>
> /* variables */
> static const char broken[] = "broken";
> _AT_@ -243,6 +251,7 @@ 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 numlockmask = 0;
> +static unsigned int prefixmask = ~0;
> static void (*handler[LASTEvent]) (XEvent *) = {
> [ButtonPress] = buttonpress,
> [ClientMessage] = clientmessage,
> _AT_@ -699,6 +708,7 @@ drawbar(Monitor *m)
> int boxs = drw->fonts->h / 9;
> int boxw = drw->fonts->h / 6 + 2;
> unsigned int i, occ = 0, urg = 0;
> + char *prefixmode;
> Client *c;
>
> /* draw status first so it can be overdrawn by tags later */
> _AT_@ -728,6 +738,9 @@ drawbar(Monitor *m)
> drw_setscheme(drw, scheme[SchemeNorm]);
> x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
>
> + prefixmode = prefixmask == ~MODKEY ? "⚑" : " ";
> + x = drw_text(drw, x, 0, TEXTW(prefixmode), bh, lrpad / 2, prefixmode, 0);
> +
> if ((w = m->ww - sw - x) > bh) {
> if (m->sel) {
> drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
> _AT_@ -958,8 +971,8 @@ grabkeys(void)
> for (i = 0; i < LENGTH(keys); i++)
> if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
> for (j = 0; j < LENGTH(modifiers); j++)
> - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
> - True, GrabModeAsync, GrabModeAsync);
> + XGrabKey(dpy, code, (keys[i].mod & prefixmask) | modifiers[j],
> + root, True, GrabModeAsync, GrabModeAsync);
> }
> }
>
> _AT_@ -988,14 +1001,23 @@ keypress(XEvent *e)
> unsigned int i;
> KeySym keysym;
> XKeyEvent *ev;
> + unsigned int prevmask;
>
> + prevmask = prefixmask;
> ev = &e->xkey;
> keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
> for (i = 0; i < LENGTH(keys); i++)
> if (keysym == keys[i].keysym
> - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
> + && CLEANMASK(keys[i].mod & prefixmask) == CLEANMASK(ev->state)
> && keys[i].func)
> keys[i].func(&(keys[i].arg));
> +
> + if (prevmask == prefixmask)
> + prefixmask = ~0;
> + if (prevmask != prefixmask) {
> + drawbar(selmon);
> + grabkeys();
> + }
> }
>
> void
> _AT_@ -2124,6 +2146,29 @@ zoom(const Arg *arg)
> pop(c);
> }
>
> +void
> +prefix(const Arg *arg)
> +{
> + unsigned int keycode;
> + XEvent fwd = {0};
> +
> + keycode = XKeysymToKeycode(dpy, arg->c.keysym);
> + if (selmon->sel && prefixmask == ~MODKEY) {
> + fwd.xkey.type = KeyPress;
> + fwd.xkey.display = dpy;
> + fwd.xkey.window = selmon->sel->win;
> + fwd.xkey.state = arg->c.mod;
> + fwd.xkey.time = CurrentTime;
> + fwd.xkey.keycode = keycode;
> + XSendEvent(dpy, selmon->sel->win, False, KeyPressMask, &fwd);
> + } else {
> + prefixmask = ~MODKEY;
> + }
> +}
> +
> +void
> +noop(const Arg *arg) { }
> +
> int
> main(int argc, char *argv[])
> {
> --
> 2.21.0
>
>

Hi,

Patches which you think are useful to others can be uploaded to the wiki
(public repository "sites" on git.suckless.org).

See also: https://suckless.org/hacking/

-- 
Kind regards,
Hiltjo
Received on Sat May 11 2019 - 11:12:23 CEST

This archive was generated by hypermail 2.3.0 : Sat May 11 2019 - 11:12:32 CEST