Window switching in Sway

Sway has many commands for switching the active workspace and focused window. However, I find that most of my window switching comes down to a few simple commands that focus a specific application, or open it first when it has no open windows yet. E.g.:

  • $mod+s: open and/or focus slack
  • $mod+i: open and/or focus signal
  • $mod+m: open and/or focus emacs
  • $mod+c: open and/or focus chromium

In addition to this, some apps like emacs have a separate $mod+Shift+m command that always opens a new window/instance.

The configuration for this is the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Each app has its own dedicated workspace
assign [app_id="Slack"] 9
assign [app_id="Signal"] 10

# Bind commands to quickly switch to the app
bindsym $mod+s exec ~/bin/launch/slack
bindsym $mod+i exec ~/bin/launch/signal

# Exec the app on startup
exec slack
exec signal-desktop

Then, for each of these applications, there is a script that tries to focus the application. If the application is not running yet it is started, and if it is running in the background only, a new window is opened.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
# ~/bin/launch/slack

BINARY='slack'
FOCUS='[app_id="Slack"]'

focus() {
    swaymsg "$FOCUS focus" >/dev/null
}
open_or_run() {
    if pgrep -fa "/usr/.*/$BINARY" >/dev/null; then
        # When the application is already running in the background, starting it
        # again will typically open the window and exit.
        $BINARY
    else
        # If the application is not running, start it but do not wait for it.
        $BINARY >/dev/null 2>/dev/null &
    fi
}
focus_wait() {
    # For applications that are slow to start, we try every 0.1s until their
    # window is open.
    for i in {1..30}; do
        if focus; then
            break
        fi
        sleep 0.1
    done
}

focus || (
    open_or_run
    focus_wait
)

For Signal, the script is the same but with variables

1
2
BINARY='signal-desktop'
FOCUS='[app_id="Signal"]'

This can also be extended to focus one specific instance of an application by filtering on title as well as app_id.

Back and forth

In addition to the above, it can be nice to quickly switch to the previously active workspace or window.

For workspaces, Sway has the command

1
workspace back_and_forth

which can be bound to any shortcut.

For switching to previously active windows, I’m using i3-focus-last (AUR package), a window switcher using Rofi that also works with Sway. This needs exec_always i3-focus-last server in your Sway config. When invoked as i3-focus-last menu, it opens a rofi menu listing all windows, sorted by most recently focused first.

Figure 1: Window switching with rofi.

Figure 1: Window switching with rofi.

Previous browser tab using Vimium

With Vimium, you can also switch back to the most recently active tab, by doing map <key> visitPreviousTab. You can find some more of my Vimium config here.