Bryan Grohman

All Writing

Switching i3wm Workspaces with Alt + Tab

2017-12-07

When I started using i3, one feature I missed from more traditional window managers such as Gnome's Mutter, KDE's KWin, or even Microsoft Windows was the ability to quickly switch between applications using the Alt + Tab keyboard shortcut. I recently added a key binding to my Vim configuration for switching between tabs with Ctrl + Tab to match Firefox, and that gave me the idea to implement a similar key binding for i3.

After some DuckDuckGo searches and reading the i3-msg man pages, I came up with a short Bash script to make it happen. I usually have only one or two windows open per workspace in i3, though, and I already use the h/j/k/l keys with $mod for changing the window focus, so I decided to map Alt + Tab and Alt + Shift + Tab to cycle forwards and backwards between open workspaces instead.

The i3-msg command has the ability to send a few different commands to i3 using the -t option. Running i3-msg -t get_workspaces returns a JSON list describing each workspace, including which one is focused. I'm using jq to parse the results. The i3-msg workspace <workspace_number> command tells i3 to switch to a particular workspace. And a short i3-workspace-switcher Bash script ties it all together:

#!/bin/bash
direction=$1
workspaces=(`i3-msg -t get_workspaces | jq -r 'map(.num)' | jq -r '.[]'`)
current=$(i3-msg -t get_workspaces | jq -r 'map(select(.focused))' | jq -r '.[]' | jq -r '.num')
current_index=0
last_index=0
i=0

for n in "${workspaces[@]}"
do
    last_index=$i

    if [ $n == $current ]; then
        current_index=$i
    fi

    ((i++))
done

next_index=0

if [ $direction == "backward" ]; then
    if [ $current_index == 0 ]; then
        next_index=$last_index
    else
        next_index=$(($current_index - 1))
    fi
else
    if [ $current_index == $last_index ]; then
        next_index=0
    else
        next_index=$(($current_index + 1))
    fi
fi

next=${workspaces[$next_index]}
i3-msg workspace $next

Lastly, I have the following two key bindings in my ~/.config/i3/config file. Since I'm using a Chromebook that doesn't have a meta key, I have $mod bound to Alt.

bindsym $mod+Tab exec "i3-workspace-switcher"
bindsym $mod+Shift+Tab exec "i3-workspace-switcher backward"

And now I can cycle through my workspaces quickly using Alt + Tab and Alt + Shift + Tab.