2021-04-11

Switch Keyboard Layouts with Mouse Buttons and sxhkd

linux   keyboard   index

Switching keyboard layouts quickly and efficiently has been a long-standing problem for me. My latest attempt is by utilizing the extra buttons, that some mice and trackballs have.

The solution that eventually worked for me, was switching between two layouts for every button. The decision to switch is made based on the current active layout.

This allows me to switch between the second and third layout, by pressing the corresponding buttons, without going through the default layout.

Getting the current layout was surprisingly involved though, and I ended up with this.

setxkbmap -query | grep -P 'layout:\s+\K[a-z]{2}' -o

The -P instructs grep to use Perl style regular expressions, and the revelation for me that did the trick was \K, which effectively discards what comes before from getting captured.

I also need to choose variants for every layout, so the full switchkb script ended up like this.

SWITCH=${1:-us}

current=$(setxkbmap -query | grep -P 'layout:\s+\K[a-z]{2}' -o)

if [[ "${current}" == "${SWITCH}" ]] ; then
    setxkbmap us altgr-intl
    exit 0
fi

case "${SWITCH}" in
    am)
        setxkbmap am western
        ;;
    ru)
        setxkbmap ru phonetic
        ;;
    us|*)
        setxkbmap us altgr-intl
        ;;
esac

Most mice have a button under the scroll wheel, equivalent to double-click, this is button2. Other button names are usually button8, button9, etc. They can be retrieved with xev.

Mapping the mouse buttons to the switch script was simple enough with sxhkd.

button2
    switchkb am

button8
    switchkb ru

The above can be rewritten simply like this:

button{2,8}
    switchkb {am,ru}

Worth noting here, that I find sxhkd indispensable, especially with tiling window managers. In addition to its powerful and concise config style, it makes using multiple window managers trivial, by making the keyboard mapping definitions independent.