Index | Thread | Search

From:
Okan Demirmen <okan@demirmen.com>
Subject:
Re: New 'swap-mods' option patch for cwm to swap modifier keys
To:
ZenitDS <zenitds@proton.me>
Cc:
"tech@openbsd.org" <tech@openbsd.org>
Date:
Wed, 10 Apr 2024 15:55:31 -0400

Download raw body.

Thread
On Wed 2024.04.10 at 19:13 +0000, ZenitDS wrote:
> Hello,
> 
> I believe currently there is no possibility to change the modifier keys used
> for the default keybindings. This means that if you want to use the Mod4 key
> instead of Meta, you must unbind all the respective keys and remap them. With
> this new option you can achieve it in a simple way. Use case for this arrives
> when you want to use the Alt key for your applications, and move the default
> Meta modifier to Mod4 for example.
> 
> Example of configuration:
> # Swap Meta with Mod4 and Control with Shift
> swap-mods MC 4S

Something like this has been proposed in the past, but why do this at the
window manager layer and not in your x session (i.e. via xmodmap)?

> Here is the patch:
> 
> Index: cwmrc.5
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/cwmrc.5,v
> retrieving revision 1.78
> diff -u -p -r1.78 cwmrc.5
> --- cwmrc.5	20 Jul 2023 14:39:34 -0000	1.78
> +++ cwmrc.5	10 Apr 2024 19:02:53 -0000
> @@ -207,6 +207,16 @@ The default behavior for new windows is 
>  By enabling sticky group mode,
>  .Xr cwm 1
>  will assign new windows to the currently selected group.
> +.It Ic swap-mods Ar mods1 mods2
> +Swap modifiers for mouse and keyboard. Modifiers in
> +.Ar mods1
> +are swapped with
> +.Ar mods2
> +in order. The same modifiers are recognised as for
> +.Ar key 
> +in
> +.Nm bind-key .
> +.Pp
>  .It Ic unbind-key Ar key
>  Unbind function bound to
>  .Ar key .
> @@ -498,6 +508,9 @@ unbind-key CMS-equal
>  # Mouse bindings
>  bind-mouse M-2		window-lower
>  bind-mouse M-3		window-resize
> +
> +# Swap Meta with Mod4 and Shift with Control
> +swap-mods MS 4C
>  .Ed
>  .Sh SEE ALSO
>  .Xr cwm 1
> Index: conf.c
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/conf.c,v
> retrieving revision 1.256
> diff -u -p -r1.256 conf.c
> --- conf.c	20 Jul 2023 14:39:34 -0000	1.256
> +++ conf.c	10 Apr 2024 19:02:53 -0000
> @@ -665,6 +665,46 @@ conf_unbind_mouse(struct conf *c, struct
>  	}
>  }
>  
> +int
> +conf_swap_mods(struct conf *c, const char *mods1, const char *mods2)
> +{
> +	struct bind_ctx *bind = NULL;
> +	unsigned int i;
> +	unsigned int mask1, mask2;
> +
> +	if (strlen(mods1) != strlen(mods2))
> +		return 0;
> +
> +	for (;*mods1; ++mods1, ++mods2) {
> +		mask1 = mask2= 0;
> +		for (i = 0; i < nitems(bind_mods); ++i) {
> +			if (bind_mods[i].ch == *mods1)
> +				mask1 = bind_mods[i].mask;
> +			if (bind_mods[i].ch == *mods2)
> +				mask2 = bind_mods[i].mask;
> +		}
> +
> +		if (!mask1 || !mask2)
> +			return 0;
> +
> +		TAILQ_FOREACH(bind, &c->keybindq, entry) {
> +			bind->modmask =
> +			    (bind->modmask & ~(mask1 | mask2)) |
> +			    ((bind->modmask & mask1) ? mask2 : 0) |
> +			    ((bind->modmask & mask2) ? mask1 : 0);
> +		}
> +
> +		TAILQ_FOREACH(bind, &c->mousebindq, entry) {
> +			bind->modmask =
> +			    (bind->modmask & ~(mask1 | mask2)) |
> +			    ((bind->modmask & mask1) ? mask2 : 0) |
> +			    ((bind->modmask & mask2) ? mask1 : 0);
> +		}
> +	}
> +
> +	return 1;
> +}
> +
>  void
>  conf_grab_kbd(Window win)
>  {
> Index: calmwm.h
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/calmwm.h,v
> retrieving revision 1.379
> diff -u -p -r1.379 calmwm.h
> --- calmwm.h	20 Jul 2023 14:39:34 -0000	1.379
> +++ calmwm.h	10 Apr 2024 19:02:53 -0000
> @@ -543,6 +543,8 @@ int			 conf_bind_key(struct conf *, cons
>      			     const char *);
>  int			 conf_bind_mouse(struct conf *, const char *,
>      			     const char *);
> +int			 conf_swap_mods(struct conf *, const char*,
> +			     const char *);
>  void			 conf_clear(struct conf *);
>  void			 conf_client(struct client_ctx *);
>  void			 conf_cmd_add(struct conf *, const char *,
> Index: parse.y
> ===================================================================
> RCS file: /cvs/xenocara/app/cwm/parse.y,v
> retrieving revision 1.75
> diff -u -p -r1.75 parse.y
> --- parse.y	24 Dec 2021 16:00:47 -0000	1.75
> +++ parse.y	10 Apr 2024 19:02:53 -0000
> @@ -68,7 +68,7 @@ typedef struct {
>  
>  %}
>  
> -%token	BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE
> +%token	BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE SWAPMODS
>  %token	FONTNAME STICKY GAP
>  %token	AUTOGROUP COMMAND IGNORE WM
>  %token	YES NO BORDERWIDTH MOVEAMOUNT HTILE VTILE
> @@ -256,6 +256,16 @@ main		: FONTNAME STRING		{
>  			}
>  			free($2);
>  		}
> +		| SWAPMODS numberstring numberstring {
> +			if (!conf_swap_mods(conf, $2, $3)) {
> +				yyerror("invalid swap-mods: %s %s", $2, $3);
> +				free($2);
> +				free($3);
> +				YYERROR;
> +			}
> +			free($2);
> +			free($3);
> +		}
>  		;
>  
>  color		: COLOR colors
> @@ -351,6 +361,7 @@ lookup(char *s)
>  		{ "selfont", 		FONTSELCOLOR},
>  		{ "snapdist",		SNAPDIST},
>  		{ "sticky",		STICKY},
> +		{ "swap-mods",		SWAPMODS},
>  		{ "unbind-key",		UNBINDKEY},
>  		{ "unbind-mouse",	UNBINDMOUSE},
>  		{ "ungroupborder",	UNGROUPBORDER},
> 
>