Configure herbstluftwm
to behave like i3
on tag switching
May 20, 2021
I recently switched from i3
to herbstluftwm
, motivated by the promise,
that herbstluftwm
really does decline to try to guess what is the
correct behaviour for me, but really just does what I tell it to.
herbstluftwm
is fast, lightweight, renders everything I throw at it
correctly: Want a second, autohiding panel at the bottom? Sure thing;
switching resolutions when accessing the desktop session from remote
via nomachine's nx
? Just tell me to detect monitors, I’ll adept.
The standard behaviour of the i3
window manager when switching tags is
a toggling behaviour on multiple keypresses to activate a specific
tag, that is it will toggle between the activated and the previously
active tab. This is something that really grew on me - switching
between documentation and shell or editor, etc. without extranious
finger movement.
herbstluftwm
suggests the following keybindings in it’s default
autostart file, at least on ubuntu as well as manjaro linux:
for i in "${!tag_names[@]}" ; do hc add "${tag_names[$i]}" key="${tag_keys[$i]}" if ! [ -z "$key" ] ; then hc keybind "$Mod-$key" use_index "$i" hc keybind "$Mod-Shift-$key" move_index "$i" fi done
At the moment of writing this text, there is no other aspect of using
i3
that I miss – they both are minimalistic, tiling window managers,
i.e. not that different. My first thought was to somehow imitate i3
’s behaviour with a shellscript, and use the spawn
command instead of use_index
:
hc keybind "$Mod-$key" spawn ${HOME}/.config/herbstluftwm/switch "${tag_names[$i]}"
The switch
command is simple enough - compare the argument given with
the currently active tag and use_previous
if they are the same, or
switch to the given tag if not:
#!/bin/bash hc() { herbstclient "$@" } if [ "${1}" == "$(hc attr monitors.focus.tag)" ]; then hc use_previous else hc use "${1}" fi
This worked like a charm. But it bothered me a little, that there were a lot of processes spawned that I felt shouldn’t be necessary. On further digging into the possibilities, I discovered the compare
command. In combination with and
and or
the simple script switch
can be translated into a single herbstclient
call:
hc keybind "$Mod-$key" or / and + compare monitors.focus.tag "=" "${tag_names[$i]}" + use_previous / use "${tag_names[$i]}"
Feels more responsive too - the brain is a magical place :-)
The complete loop for all the copy ’n paste needs you (or I) might have:
for i in "${!tag_names[@]}" ; do hc add "${tag_names[$i]}" key="${tag_keys[$i]}" if ! [ -z "$key" ] ; then hc keybind "$Mod-$key" or / and + compare monitors.focus.tag "=" "${tag_names[$i]}" + use_previous / use "${tag_names[$i]}" hc keybind "$Mod-Shift-$key" move_index "$i" fi done