Introduction
Introduction Statistics Contact Development Disclaimer Help
[dwm][patch][keysequence] Add new patch - sites - public wiki contents of suckl…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
commit d166954782572f6ca3c36136c31b9e9e6e5efb2e
parent 648d2edf20bb3fb153660f48a27a03adfd121dea
Author: TUVIMEN <[email protected]>
Date: Fri, 6 Jun 2025 09:18:30 +0200
[dwm][patch][keysequence] Add new patch
Add patch that allows for defining sequential key bindings
Diffstat:
A dwm.suckless.org/patches/keysequen… | 50 +++++++++++++++++++++++++++…
A dwm.suckless.org/patches/keysequen… | 158 +++++++++++++++++++++++++++…
2 files changed, 208 insertions(+), 0 deletions(-)
---
diff --git a/dwm.suckless.org/patches/keysequence/index.md b/dwm.suckless.org/p…
@@ -0,0 +1,50 @@
+keysequence
+===========
+
+Description
+-----------
+
+This patch allows for defining sequential keybindings, for example `MOD+A W`.
+This is done not through the `XGrabKey()` which is used for root bindings,
+but by the `XGrabKeyboard()` so any key presses that are not defined will
+stop the matching without passing them to programs. This behaviour is
+less confusing.
+
+It defines new bindable function `keypress_other()` that as argument takes
+a pointer to array of bindings.
+
+ static Key keyseq_a[] = {
+ { 0, XK_t, setlayout, {.v = &layouts[…
+ { ShiftMask, XK_t, setlayout, {.v = &layouts[…
+ { MODKEY, XK_y, setlayout, {.v = &lay…
+ {0}
+ }
+
+ static Key keys[] = {
+ { MODKEY, XK_a, keypress_other, {.v = keyseq_a}},
+ {0}
+ }
+
+This assigns `MOD+a t`, `MOD+a T`, `MOD+a MOD+y` to changing layout, you can
+nest bindings endlessly.
+
+Notice that now keybinding arrays are ended by `{0}` empty element,
+this is necessary because `Arg` structure can take only pointer
+sized elements, there's no place to specify size so it has to be
+calculated while running.
+
+While typing sequence all events are ignored other than key presses
+and mouse, moving mouse exits sequence.
+
+Save your hands! Don't make long sequences, stick to simple, easy to
+access binding and use plain letters, realistically speaking you'll
+use it for dmenu scripts, layout bindings, and other rarely used
+commands.
+
+Download
+--------
+* [keysequence-20250606-0d6af14.diff](keysequence-20250606-0d6af14.diff)
+
+Author
+------
+* TUVIMEN <[email protected]>
diff --git a/dwm.suckless.org/patches/keysequence/keysequence-20250606-0d6af14.…
@@ -0,0 +1,158 @@
+From 0d6af14efa1250631b081ad9d1f3aa0263221fd8 Mon Sep 17 00:00:00 2001
+From: TUVIMEN <[email protected]>
+Date: Fri, 6 Jun 2025 09:08:40 +0200
+Subject: [PATCH] [PATCH] 6.5 keysequence patch
+
+---
+ config.def.h | 1 +
+ dwm.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 80 insertions(+), 7 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 9efa774..6104343 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -95,6 +95,7 @@ static const Key keys[] = {
+ TAGKEYS( XK_8, 7)
+ TAGKEYS( XK_9, 8)
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
++ {0}
+ };
+
+ /* button definitions */
+diff --git a/dwm.c b/dwm.c
+index f1d86b2..89a4bc5 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -28,6 +28,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <time.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <X11/cursorfont.h>
+@@ -177,6 +178,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 keypress_other(const Arg *arg);
+ static void killclient(const Arg *arg);
+ static void manage(Window w, XWindowAttributes *wa);
+ static void mappingnotify(XEvent *e);
+@@ -949,6 +951,13 @@ grabbuttons(Client *c, int focused)
+ }
+ }
+
++static char
++key_not_empty(const Key *key)
++{
++ static const Key empty = {0};
++ return memcmp(key, &empty, sizeof(Key)) != 0;
++}
++
+ void
+ grabkeys(void)
+ {
+@@ -965,7 +974,7 @@ grabkeys(void)
+ if (!syms)
+ return;
+ for (k = start; k <= end; k++)
+- for (i = 0; i < LENGTH(keys); i++)
++ for (i = 0; key_not_empty(keys+i); i++)
+ /* skip modifier codes, we do that ourselves …
+ if (keys[i].keysym == syms[(k - start) * skip…
+ for (j = 0; j < LENGTH(modifiers); j+…
+@@ -996,8 +1005,8 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, Xinera…
+ }
+ #endif /* XINERAMA */
+
+-void
+-keypress(XEvent *e)
++static void
++keypress_r(XEvent *e, const Key *keys)
+ {
+ unsigned int i;
+ KeySym keysym;
+@@ -1005,11 +1014,74 @@ keypress(XEvent *e)
+
+ ev = &e->xkey;
+ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+- for (i = 0; i < LENGTH(keys); i++)
++ for (i = 0; key_not_empty(keys+i); i++)
+ if (keysym == keys[i].keysym
+- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
+- && keys[i].func)
+- keys[i].func(&(keys[i].arg));
++ && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
++ && keys[i].func)
++ keys[i].func(&(keys[i].arg));
++}
++
++static char
++grabkeyboard(void) //taken from dmenu
++{
++ struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
++
++ /* try to grab keyboard, we may have to wait for another process to u…
++ for (int i = 0; i < 1000; i++) {
++ if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabMode…
++ GrabModeAsync, CurrentTime) == GrabSuccess)
++ return 0;
++ nanosleep(&ts, NULL);
++ }
++ return 1; //failed
++}
++
++static char
++keysym_is_modifier(KeySym s)
++{
++ return (s == XK_Shift_L ||
++ s == XK_Shift_R ||
++ s == XK_Control_L ||
++ s == XK_Control_R ||
++ s == XK_Caps_Lock ||
++ s == XK_Shift_Lock ||
++ s == XK_Meta_L ||
++ s == XK_Meta_R ||
++ s == XK_Alt_L ||
++ s == XK_Alt_R ||
++ s == XK_Super_L ||
++ s == XK_Super_R ||
++ s == XK_Hyper_L ||
++ s == XK_Hyper_R);
++}
++
++void
++keypress_other(const Arg *arg)
++{
++ if (grabkeyboard())
++ return;
++
++ XEvent ev;
++ while (!XNextEvent(dpy, &ev)) {
++ if (ev.type == ButtonPress)
++ break;
++ if (ev.type == KeyPress) {
++ KeySym keysym = XKeycodeToKeysym(dpy, (KeyCode)ev.xkey.keycode, 0…
++ if (keysym_is_modifier(keysym))
++ continue;
++ keypress_r(&ev, (Key*)arg->v);
++ break;
++ }
++ }
++
++ XUngrabKeyboard(dpy, CurrentTime);
++ grabkeys();
++}
++
++void
++keypress(XEvent *e)
++{
++ keypress_r(e,keys);
+ }
+
+ void
+--
+2.49.0
+
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.