Roll your own Linux desktop using Sway

Last edited on 2023-07-23 Tagged under  #sway   #wayland   #debian   #linux 

Sway logo

Wayland is the future of graphical desktops on Linux.

With the arrival of the latest stable release of Debian I decided that - instead of my usual setup of Xorg + Openbox - I would explore Wayland and a different desktop environment.

The first big change in making the switch is that - whereas Xorg the (graphical) server and the chosen (graphical) desktop client are separate entities - in Wayland they are one and the same thing and are called compositors. You can't simply drop Openbox or GNOME on top of Wayland. Each desktop must be created or re-written for Wayland.

The next big change is what to do about the array of utilities typically used in an X session: either use Wayland-native replacements, or continue to use - if possible - the current apps courtesy of Xwayland (an X server for running X clients under Wayland).

Browsing through the list of Wayland compositors, it appears that Sway is one of most solid implementations currently available. Another point in favour of Sway is that its already packaged in Debian, so I decided to start there.

I've never used i3 window manager (which Sway is modelled on) or a tiling environment (with windows arranged in a grid vs "floating" in Openbox) for any length of time, but after making the switch to Sway and a few weeks of use I find myself liking it very much!

Sway quickly gets you 90% towards a usable desktop. Its that 10% where you're replacing all your X11 tools and crafting your own desktop just the way you like it that takes some experimenting!

This is how I do it, with links to my config files ...

1. Install

My setup: Laptop is a Thinkpad T480s with Intel video, running Debian 12 aka "Bookworm", attached to a 32" 2560x1440 external display.

Install the Sway compositor and a few essentials ...

$ sudo apt install sway swaybg swayidle swaylock xdg-desktop-portal-wlr xwayland

Some extras that I add and use in this HOWTO ...

$ sudo apt install adwaita-qt alsa-utils brightnessctl copyq fonts-dejavu fonts-firacode fonts-font-awesome fonts-ubuntu grimshot gthumb libglib2.0-bin libgtk-3-0 libgtk-4-1 libnotify-bin mako-notifier network-manager network-manager-gnome papirus-icon-theme pipewire-audio qt5-style-plugins qt5ct waybar wob wofi x11-utils

2. Start

I don't use a login manager, so to start Sway from a tty console simply run ...

$ sway

That's it to get started!

There are a few environmental variables that should be set when running sway. There are a few different methods to accomplish this.

I found it convenient to create a small script - startw - that includes these variables ...

# Set env variables when starting a wayland session
# For sway
sway $@

Run ...

$ startw

Source: startw

3. Custom configuration

To begin customizing your own Sway experience there are two possible methods:

  • copy the sample configuration installed on the system into $HOME and make changes to a single, unified file
  • or copy the sample configuration installed on the system into $HOME and make changes split across several sub-files (my preferred method)

Method 1: Single config

Create a new Sway directory in HOME for the custom configuration ...

$ mkdir -p ~/.config/sway

Create a new config file by copying the sample configuration /etc/sway/config to ~/.config/sway/config ...

$ cp /etc/sway/config ~/.config/sway/config

Make any desired modifications. Enable any changes made in the current session by reloading the config with the key combo Super+Shift+c.

Method 2: Config with sub-files

I favour the modular approach of splitting the configuration into smaller sub-files, finding it easier to modify discrete components of the Sway config vs working with a single large file.

Create a new Sway directory in HOME for the custom configuration ...

$ mkdir -p ~/.config/sway/config.d

Create a new default configuration file by copying the sample configuration /etc/sway/config to ~/.config/sway/config.d/default ...

$ cp /etc/sway/config ~/.config/sway/config.d/default

Most of the changes will be made in sub-files that we create from scratch.

Note: Some of those changes stored in sub-files will involve deleting the corresponding entry in default (otherwise you may have conflicting settings being loaded).

Create a new config file as ~/.config/sway/config that will load the sub-files in the config.d directory ...

# Config for sway
# Read `man 5 sway` for a complete reference.

# user config directory
include $HOME/.config/sway/config.d/*

Enable any changes made in the current session by reloading the config with the key combo Super+Shift+c.


3.1 Application defaults

Assign certain applications and windows to open on certain workspaces and/or open in "floating" (non-tiling) mode.

Source: .config/sway/config.d/application_defaults

3.2 Autostart applications

Set certain applications to start when Sway is launched:

  • desktop notifications: mako
  • network manager: nm-applet
  • clipboard: copyq
  • terminal: foot

Source: .config/sway/config.d/autostart_applications

3.3 Input

Settings for items such as keyboard layouts (I use colemak) and mice/touchpads.

Source: .config/sway/config.d/input

3.4 Output

Sway does a good job at automatically detecting system displays at their optimal resolution and (with multiple displays connected) positioning them relative to each other. All of this can be modified by the user.

Example: My laptop display defaults to 1920x1080, but - instead of using fractional scaling - for reading I prefer a resolution of 1600x900 on this device.

Source: .config/sway/config.d/output

3.5 Theme

I use the Adwaita Dark theme paired with Papirus Dark icons. Adwaita is the default GTK theme and has good coverage in QT courtesy of the adwaita-qt package in Debian.


GTK settings on Wayland are set in ~/.config/gtk-3.0/settings.ini ...


Create ~/.config/sway/config.d/theme with settings ...

set $gnome-schema org.gnome.desktop.interface                                                      
exec_always {                                                                                      
  gsettings set $gnome-schema gtk-theme Adwaita                                                    
  gsettings set $gnome-schema gtk-application-prefer-dark-theme true                               
  gsettings set $gnome-schema icon-theme Papirus-Dark                                              
  gsettings set $gnome-schema cursor-theme Adwaita                                                 

Note: Do not put gsettings selections in double quotes or it will fail to display properly.


Set a default desktop wallpaper in ~/.config/sway/config.d/theme ...

output * bg /path/to/wallpaper.jpg fill


Use adwaita-qt as the theme and select it by running qt5ct.

Set qt5ct as QT_QPA_PLATFORMTHEME in ~/.profile ...


Also export QT_QPA_PLATFORM as wayland (included in my startw script) ...

export QT_QPA_PLATFORM=wayland


4. Applications

Hint: Run the command xlsclients in a terminal to view which open applications are running in xwayland (that is, running as legacy X11 applications) vs Wayland proper.

4.1 Terminal: foot

Set foot as the default terminal emulator in .config/sway/config.d/default ...

set $term foot

Create a local config ...

$ mkdir ~/.config/foot
$ cp /etc/xdg/foot/foot.ini ~/.config/foot/

To have the terminal behave properly when ssh'ing into remote machines, on the remote machine install the terminfo files for foot ...

$ sudo apt install foot-terminfo

Source: .config/foot/foot.ini

4.2 Application launcher: wofi

Wofi is a Wayland-native dynamic menu/launcher for applications in a user's PATH. Frequently-used applications are positioned near the top of the list.

Set launcher to wofi in ~/.config/sway/config.d/default ...

set $menu wofi  -c ~/.config/wofi/config --show

Activate menu with Super+d ...

bindsym $mod+d exec $menu

Create a local config and style.css in ~/.config/wofi.

Source: .config/wofi

4.3 Status bar: waybar

Sway includes a status bar, but I prefer this highly configurable Wayland bar: waybar

Configure ~/.config/sway/config.d/default to use this alternative status bar ...

bar {
  swaybar_command waybar

Create a local config and style.css inside ~/.config/waybar.

Source: .config/waybar

4.4 System idle: swayidle + swaylock

Set a display timeout (in seconds), lock screen, and actions to take on suspend using swayidle and swaylock in ~/.config/sway/config.d/default ...

exec swayidle -w \
  timeout 1200 'swaylock -C ~/.config/swaylock/config' \
  timeout 1500 'swaymsg "output * dpms off"' \
  resume 'swaymsg "output * dpms on"' \
  before-sleep 'swaylock -C ~/.config/swaylock/config'

Create a local config for swaylock in ~/.config/swaylock/config.

Source: .config/swaylock/config

4.5 Sound: pipewire + alsamixer

Sound is managed by pipewire and alsamixer can be used to set audio and enable/mute devices.

4.6 Volume|Backlight: wob + amixer + brightnessctl

Overlay bar wob can be used to display changes in volume|backlight levels.

Configure keybindings in ~/.config/sway/config.d/default that use amixer for volume and brightnessctl for the backlight ...

exec rm -f $WOBSOCK && mkfifo $WOBSOCK && tail -f $WOBSOCK | wob

bindsym XF86AudioRaiseVolume exec amixer sset Master 5%+ | sed -En 's/.*\[([0-9]+)%\].*/\1/p' | head -1 > $WOBSOCK
bindsym XF86AudioLowerVolume exec amixer sset Master 5%- | sed -En 's/.*\[([0-9]+)%\].*/\1/p' | head -1 > $WOBSOCK
bindsym XF86AudioMute exec amixer sset Master toggle | sed -En '/\[on\]/ s/.*\[([0-9]+)%\].*/\1/ p; /\[off\]/ s/.*/0/p' | head -1 > $WOBSOCK

bindsym XF86MonBrightnessDown exec brightnessctl set 5%- | sed -En 's/.*\(([0-9]+)%\).*/\1/p' > $WOBSOCK
bindsym XF86MonBrightnessUp exec brightnessctl set +5% | sed -En 's/.*\(([0-9]+)%\).*/\1/p' > $WOBSOCK

4.7 Screenshots: grimshot

I created a script - swayshot - that uses grimshot (a wrapper around grim and slurp) to capture and save screenshots, and gthumb to view images.

Source: swayshot

4.8 Clipboard manager: copyq

Modify ~/.config/sway/config.d/autostart_applications to start copyq when Sway opens up ...

exec copyq

Modify ~/.config/sway/config.d/application_defaults to display the clipboard as a floating window ...

for_window [app_id="copyq"] floating enable, sticky enable, resize set height 600px width 550px, move position cursor, move down 330

Set a keybinding in ~/.config/sway/config.d/default to toggle clipboard visibility ...

bindsym $mod+Shift+v exec copyq toggle

Open the clipboard window, select File->Preferences... and under the General tab deselect Close When Unfocused ...


Under Layout check Hide main window ...


4.9 Notifications: mako

Modify ~/.config/sway/config.d/autostart_applications to start mako when Sway opens up ...

exec mako

Create a local config in ~/.config/mako/config.

Send a test notification ...

$ notify-send -u low|normal|critical "Testing ..."

Source: .config/mako/config

4.10 Web browser: Firefox

Recent versions of Firefox enable Wayland mode by setting an environmental variable at runtime ...


Verify it worked by opening about:support in Firefox, looking for Window Protocol, and confirm it indicates wayland.

Make it permanent with export MOZ_ENABLE_WAYLAND=1 (I include this in my startw script).

5. Helpful

6. Finish

My customized sway

You can like, share, or comment on this post on Mastodon 💬

Thanks for reading! Read other posts?

» Next: #24. Embedded Linux in Space

« Previous: Minimal Debian Bookworm