sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-keychord-6.2.diff (9320B)


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