Switching i3 workspaces with trackpad gestures
For various reasons, I find myself working on a laptop with no external screen, mouse, or separate keyboard for a time. Of course, since I don’t normally use this setup, I obviously needed an entirely new Linux setup to celebrate the occasion and so that I could spend the requisite day of setup before going back to real work.
This time I’m on a minimal kick and so started with Ubuntu Server with the
minimize option to have basically nothing, and build up just the parts I want
and need. I’m opting for X11 over wayland, which means i3 because tiling window
managers are awesome and i3 is closest to the config muscle memory I have from
sway and hyprland. So far so good and it’s mostly the way I like it, but since
I have a trackpad that’s so close to my fingers that it might as well be the
keyboard, I might as well take advantage of that and get some swipe gestures
that I want to use. Mostly this means swipe up and down to change workspaces,
with the added requirement that swiping up when there are no more active
workspaces, i3 should create a new workspace at the next highest number rather
than its default behavior of cycling back to the lowest-numbered workspace.
Here we go. This will be concise and to the point, as usual mostly for future me to find and not need to re-invent this particular wheel.
Prerequisites
sudo apt update
sudo apt install xdotool libinput-tools wmctrl
I’m pretty sure that for my setup wmctrl and xdotool are not required,
but the author of libinput-gestures
recommends them both “just in case”, and I may want an action that actually
uses them in the future.
Next, add yourself to the input group so that you can read the touchpad device.
sudo gpasswd -a $USER input
After this, logout and log back in or else restart.
Installing libinput-gestures
Finally, actually get libinput-gestures itself.
git clone https://github.com/bulletmark/libinput-gestures.git
cd libinput-gestures
sudo ./libinput-gestures-setup install
You can libinput-gestures-setup autostart to have it start from an autostart
desktop entry, but I opted to add it to my i3 config instead
# ~/.config/i3/config
...
exec --no-startup-id libinput-gestures-setup start
...
Custom action for next workspace
By default, i3 will wrap around on i3-msg workspace next, meaning that
if I’m at my highest-numbered workspace and 3-finger-swipe up, I’ll go back
to my lowest-numbered workspace. That’s not usually what I want, though, and
instead I want it to (on the highest workspace) just create a new one instead.
So, here’s the script I made for that
#!/bin/bash
# in ~/.config/i3/next-or-new.sh
CURRENT_NUM=$(i3-msg -t get_workspaces | jq -r '.[] | select(.focused==true).num')
ALL_NUMS=($(i3-msg -t get_workspaces | jq -r '.[].num' | sort -n))
NEXT_WORKSPACE_NUM=0
for NUM in "${ALL_NUMS[@]}"; do
if (( $CURRENT_NUM < $NUM )); then
NEXT_WORKSPACE_NUM=$NUM
break
fi
done
if [ "$NEXT_WORKSPACE_NUM" -eq 0 ]; then
HIGHEST_NUM=$(echo "${ALL_NUMS[@]}" | tr ' ' '\n' | sort -nr | head -1)
[ -z "$HIGHEST_NUM" ] && NEXT_WORKSPACE_NUM=1 || NEXT_WORKSPACE_NUM=$((HIGHEST_NUM + 1))
fi
i3-msg workspace number "$NEXT_WORKSPACE_NUM"
With the script in place, chmod +x ~/.config/i3/next-or-new.sh and then
move on to actually calling it.
Configuring libinput-gestures
Copy the default config to a local dir:
cp /etc/libinput-gestures.conf ~/.config/libinput-gestures.conf
Then, edit this file to replace the default swipe gestures
# ~/.config/libinput-gestures.conf
# On a 3-fingered down swipe, go to previous i3 workspace
gesture swipe down 3 i3-msg workspace prev
# On a 3-fingered up swipe, go to next i3 workspace or create a new one
gesture swipe up 3 ~/.config/i3/next-or-new.sh
# On a 4-fingered up swipe, go to next i3 workspace or cycle to first
gesture swipe up 4 i3-msg workspace next
Restart the daemon:
libinput-gestures-setup restart
Done!