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 Link to heading

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 Link to heading

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.