dwm-keychord-20211210-a786211.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dwm-keychord-20211210-a786211.diff (9244B)
       ---
            1 From e61a957ff8b7e14219b5fbaab9da794b722e7874 Mon Sep 17 00:00:00 2001
            2 From: Hai Nguyen <hhai2105@gmail.com>
            3 Date: Fri, 10 Dec 2021 21:45:00 -0500
            4 Subject: [PATCH] add Keychord struct, change keypress() and grabkeys() to be
            5  able to grab a sequence of keystroke
            6 
            7 ---
            8  config.def.h | 67 ++++++++++++++++++++++++++------------------------
            9  dwm.c        | 69 ++++++++++++++++++++++++++++++++++++++++------------
           10  2 files changed, 88 insertions(+), 48 deletions(-)
           11 
           12 diff --git a/config.def.h b/config.def.h
           13 index a2ac963..15a3e05 100644
           14 --- a/config.def.h
           15 +++ b/config.def.h
           16 @@ -46,11 +46,12 @@ static const Layout layouts[] = {
           17  
           18  /* key definitions */
           19  #define MODKEY Mod1Mask
           20 -#define TAGKEYS(KEY,TAG) \
           21 -        { MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \
           22 -        { MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \
           23 -        { MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \
           24 -        { MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} },
           25 +
           26 +#define TAGKEYS(KEY,TAG)                                                                                                \
           27 +        {1, {{MODKEY, KEY}},                                                                view,           {.ui = 1 << TAG} },        \
           28 +        {1, {{MODKEY|ControlMask, KEY}},                                        toggleview,     {.ui = 1 << TAG} }, \
           29 +        {1, {{MODKEY|ShiftMask, KEY}},                                                tag,            {.ui = 1 << TAG} }, \
           30 +        {1, {{MODKEY|ControlMask|ShiftMask, KEY}},                        toggletag,      {.ui = 1 << TAG} },
           31  
           32  /* helper for spawning shell commands in the pre dwm-5.0 fashion */
           33  #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
           34 @@ -59,32 +60,34 @@ static const Layout layouts[] = {
           35  static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
           36  static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
           37  static const char *termcmd[]  = { "st", NULL };
           38 +static const char *emacs[]  = { "emacs", NULL };
           39  
           40 -static Key keys[] = {
           41 -        /* modifier                     key        function        argument */
           42 -        { MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
           43 -        { MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
           44 -        { MODKEY,                       XK_b,      togglebar,      {0} },
           45 -        { MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
           46 -        { MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
           47 -        { MODKEY,                       XK_i,      incnmaster,     {.i = +1 } },
           48 -        { MODKEY,                       XK_d,      incnmaster,     {.i = -1 } },
           49 -        { MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
           50 -        { MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
           51 -        { MODKEY,                       XK_Return, zoom,           {0} },
           52 -        { MODKEY,                       XK_Tab,    view,           {0} },
           53 -        { MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
           54 -        { MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} },
           55 -        { MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} },
           56 -        { MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} },
           57 -        { MODKEY,                       XK_space,  setlayout,      {0} },
           58 -        { MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
           59 -        { MODKEY,                       XK_0,      view,           {.ui = ~0 } },
           60 -        { MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
           61 -        { MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
           62 -        { MODKEY,                       XK_period, focusmon,       {.i = +1 } },
           63 -        { MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
           64 -        { MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
           65 +static Keychord keychords[] = {
           66 +        /* Keys        function        argument */
           67 +        {1, {{MODKEY, XK_p}},                                                        spawn,          {.v = dmenucmd } },
           68 +        {1, {{MODKEY|ShiftMask, XK_Return}},                        spawn,          {.v = termcmd } },
           69 +        {2, {{MODKEY, XK_e}, {MODKEY, XK_e}},                        spawn,          {.v = termcmd } },
           70 +        {1, {{MODKEY, XK_b}},                                                        togglebar,      {0} },
           71 +        {1, {{MODKEY, XK_j}},                                                        focusstack,     {.i = +1 } },
           72 +        {1, {{MODKEY, XK_k}},                                                        focusstack,     {.i = -1 } },
           73 +        {1, {{MODKEY, XK_i}},                                                        incnmaster,     {.i = +1 } },
           74 +        {1, {{MODKEY, XK_d}},                                                        incnmaster,     {.i = -1 } },
           75 +        {1, {{MODKEY, XK_h}},                                                        setmfact,       {.f = -0.05} },
           76 +        {1, {{MODKEY, XK_l}},                                                        setmfact,       {.f = +0.05} },
           77 +        {1, {{MODKEY, XK_Return}},                                                zoom,           {0} },
           78 +        {1, {{MODKEY, XK_Tab}},                                                        view,           {0} },
           79 +        {1, {{MODKEY|ShiftMask, XK_c}},                                        killclient,     {0} },
           80 +        {1, {{MODKEY, XK_t}},                                                        setlayout,      {.v = &layouts[0]} },
           81 +        {1, {{MODKEY, XK_f}},                                                        setlayout,      {.v = &layouts[1]} },
           82 +        {1, {{MODKEY, XK_m}},                                                        setlayout,      {.v = &layouts[2]} },
           83 +        {1, {{MODKEY, XK_space}},                                                setlayout,      {0} },
           84 +        {1, {{MODKEY|ShiftMask, XK_space}},                                togglefloating, {0} },
           85 +        {1, {{MODKEY, XK_0}},                                                        view,           {.ui = ~0 } },
           86 +        {1, {{MODKEY|ShiftMask, XK_0}},                                        tag,            {.ui = ~0 } },
           87 +        {1, {{MODKEY, XK_comma}},                                                focusmon,       {.i = -1 } },
           88 +        {1, {{MODKEY, XK_period}},                                                focusmon,       {.i = +1 } },
           89 +        {1, {{MODKEY|ShiftMask, XK_comma}},                                tagmon,         {.i = -1 } },
           90 +        {1, {{MODKEY|ShiftMask, XK_period}},                        tagmon,         {.i = +1 } },
           91          TAGKEYS(                        XK_1,                      0)
           92          TAGKEYS(                        XK_2,                      1)
           93          TAGKEYS(                        XK_3,                      2)
           94 @@ -92,9 +95,9 @@ static Key keys[] = {
           95          TAGKEYS(                        XK_5,                      4)
           96          TAGKEYS(                        XK_6,                      5)
           97          TAGKEYS(                        XK_7,                      6)
           98 -        TAGKEYS(                        XK_8,                      7)
           99 +         TAGKEYS(                        XK_8,                      7)
          100          TAGKEYS(                        XK_9,                      8)
          101 -        { MODKEY|ShiftMask,             XK_q,      quit,           {0} },
          102 +        {1, {{MODKEY|ShiftMask, XK_q}},                                        quit,           {0} },
          103  };
          104  
          105  /* button definitions */
          106 diff --git a/dwm.c b/dwm.c
          107 index 5e4d494..56c4661 100644
          108 --- a/dwm.c
          109 +++ b/dwm.c
          110 @@ -102,9 +102,14 @@ struct Client {
          111  typedef struct {
          112          unsigned int mod;
          113          KeySym keysym;
          114 +} Key;
          115 +
          116 +typedef struct {
          117 +        unsigned int n;
          118 +        const Key keys[5];
          119          void (*func)(const Arg *);
          120          const Arg arg;
          121 -} Key;
          122 +} Keychord;
          123  
          124  typedef struct {
          125          const char *symbol;
          126 @@ -268,6 +273,7 @@ static Display *dpy;
          127  static Drw *drw;
          128  static Monitor *mons, *selmon;
          129  static Window root, wmcheckwin;
          130 +unsigned int currentkey = 0;
          131  
          132  /* configuration, allows nested code to access above variables */
          133  #include "config.h"
          134 @@ -951,16 +957,16 @@ grabkeys(void)
          135  {
          136          updatenumlockmask();
          137          {
          138 -                unsigned int i, j;
          139 +                unsigned int i, k;
          140                  unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
          141                  KeyCode code;
          142  
          143                  XUngrabKey(dpy, AnyKey, AnyModifier, root);
          144 -                for (i = 0; i < LENGTH(keys); i++)
          145 -                        if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
          146 -                                for (j = 0; j < LENGTH(modifiers); j++)
          147 -                                        XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
          148 -                                                True, GrabModeAsync, GrabModeAsync);
          149 +                for (i = 0; i < LENGTH(keychords); i++)
          150 +                        if ((code = XKeysymToKeycode(dpy, keychords[i].keys[currentkey].keysym)))
          151 +                                for (k = 0; k < LENGTH(modifiers); k++)
          152 +                                        XGrabKey(dpy, code, keychords[i].keys[currentkey].mod | modifiers[k], root,
          153 +                                                         True, GrabModeAsync, GrabModeAsync);
          154          }
          155  }
          156  
          157 @@ -986,17 +992,48 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
          158  void
          159  keypress(XEvent *e)
          160  {
          161 -        unsigned int i;
          162 +        XEvent event = *e;
          163 +        Keychord *keychord;
          164 +        unsigned int ran = 0;
          165          KeySym keysym;
          166          XKeyEvent *ev;
          167 -
          168 -        ev = &e->xkey;
          169 -        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
          170 -        for (i = 0; i < LENGTH(keys); i++)
          171 -                if (keysym == keys[i].keysym
          172 -                && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
          173 -                && keys[i].func)
          174 -                        keys[i].func(&(keys[i].arg));
          175 +        Keychord *newoptions;
          176 +        Keychord *oldoptions = (Keychord *)malloc(sizeof(keychords));
          177 +
          178 +        memcpy(oldoptions, keychords, sizeof(keychords));
          179 +        size_t numoption = 0;
          180 +        while(!ran){
          181 +                ev = &event.xkey;
          182 +                keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
          183 +                newoptions = (Keychord *)malloc(0);
          184 +                numoption = 0;
          185 +                for (keychord = oldoptions; keychord->n != 0 && currentkey < 5; keychord = (Keychord *)((char *)keychord + sizeof(Keychord))){
          186 +                        if(keysym == keychord->keys[currentkey].keysym
          187 +                           && CLEANMASK(keychord->keys[currentkey].mod) == CLEANMASK(ev->state)
          188 +                           && keychord->func){
          189 +                                if(keychord->n == currentkey +1){
          190 +                                        keychord->func(&(keychord->arg));
          191 +                                        ran = 1;
          192 +                                }else{
          193 +                                        numoption++;
          194 +                                        newoptions = (Keychord *)realloc(newoptions, numoption * sizeof(Keychord));
          195 +                                        memcpy((char *)newoptions + (numoption -1) * sizeof(Keychord),keychord, sizeof(Keychord));
          196 +                                }
          197 +                        }
          198 +                }
          199 +                currentkey++;
          200 +                if(numoption == 0)
          201 +                        break;
          202 +                grabkeys();
          203 +                while (running && !XNextEvent(dpy, &event) && !ran)
          204 +                        if(event.type == KeyPress)
          205 +                                break;
          206 +                free(oldoptions);
          207 +                oldoptions = newoptions;
          208 +        }
          209 +        free(newoptions);
          210 +        currentkey = 0;
          211 +        grabkeys();
          212  }
          213  
          214  void
          215 -- 
          216 2.34.1
          217