Roll your own Linux desktop using Sway

Last edited on 2024-01-07 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 using it on both Linux and FreeBSD 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 ...

1. Install

My setup: My primary computer is a Thinkpad T480s running Debian 12 with a 14" 1920x1080 display powered by Intel video. At home, this laptop is attached to a 32" 2560x1440 external display.

Install the Sway compositor and a few extras ...

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

Additional packages used in this HOWTO ...

$ sudo apt install alsa-utils copyq fonts-dejavu fonts-firacode fonts-font-awesome \
  fonts-ubuntu grimshot lximage-qt mako-notifier mesa-vulkan-drivers vulkan-tools \
  network-manager network-manager-gnome pavucontrol papirus-icon-theme pipewire-audio \
  qt5-style-plugins waybar 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 ...

export QT_QPA_PLATFORM=wayland
# start sway
sway -c ~/.config/sway/config

Run ...

$ startw

Source: startw

3. Custom configuration: sway/config

My own custom configuration.

To begin customizing your own Sway experience, copy the sample configuration installed on the system into $HOME ...

$ mkdir -p ~/.config/sway
$ 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.

3.1 Application defaults

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

# Workspaces:
assign [app_id="firefox"] 3
for_window [app_id="firefox"] focus

assign [app_id="rhythmbox"] 9
for_window [app_id="rhythmbox"] focus

assign [app_id="transmission-gtk"] 9
for_window [app_id="transmission-gtk"] focus

# Windows:
# Find the app_id or class of a window by inspecting the result of swaymsg -t get_tree.
# set floating for certain apps
for_window [class="vlc"] floating enable, border normal
for_window [app_id="virt-manager"] floating enable, border normal
for_window [app_id="copyq"] floating enable, sticky enable, resize set height 600px width 550px, move position cursor, move down 330
# set floating for window roles
for_window [window_role="pop-up"] floating enable
for_window [window_role="bubble"] floating enable
for_window [window_role="task_dialog"] floating enable
for_window [window_role="Preferences"] floating enable
for_window [window_type="dialog"] floating enable
for_window [window_type="menu"] floating enable
for_window [window_role="About"] floating enable
for_window [title="File Operation Progress"] floating enable, border pixel 1, sticky enable, resize set width 40 ppt height 30 ppt

3.2 Autostart applications

Set certain applications to start when Sway is launched:

  • terminal: foot
  • clipboard: copyq
  • desktop notifications: mako
  • network manager: nm-applet
# Autostart:
exec swaymsg "workspace 1; exec $term"
exec swaymsg "workspace 2; exec $term"
exec copyq
exec mako
exec nm-applet --indicator

3.3 Input

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

### Input configuration

# You can get the names of your inputs by running: swaymsg -t get_inputs
# Read `man 5 sway-input` for more information about this section.

# evdev is an Xorg input driver	for Linux's generic event devices,
# including most mice, keyboards, tablets and touchscreens.
input * xkb_rules evdev

input "*" {
  xkb_layout us
  xkb_variant colemak

input type:touchpad {
  dwt enabled
  tap enabled
  natural_scroll disabled

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, and have different settings per device.

Example: My laptop display defaults to 1920x1080, and I configure it to use fractional scaling in a custom output file separate from Sway's main config ...

$ mkdir ~/.config/sway/config.d
$ touch ~/.config/sway/config.d/output

I then edit output to set my laptop display - identified as ePD-1 - to use fractional scaling ...

# You can get the names of your outputs by running: swaymsg -t get_outputs
output eDP-1 scale 1.3

3.5 Theme

I use the Nordic GTK theme paired with Papirus Dark icons.


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

gtk-font-name=Ubuntu 10

Set theme details for Sway in its config ...

### Theme

font pango:Fira Sans SemiBold 10

# border without title bar
default_border pixel 3
client.focused #000000 #5e81ac #ffffff

# gtk
set $gnome-schema org.gnome.desktop.interface

exec_always {
  gsettings set $gnome-schema gtk-theme Nordic
  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 sway/config ...

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


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

# Styling QT apps


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 sway/config ...

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 sway/config ...

set $menu wofi -show run

Activate menu with Super+spacebar ...

bindsym $mod+space 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 sway/config 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 sway/config. ...

set $lock swaylock -C ~/.config/swaylock/config
exec swayidle -w \
  timeout 900 'swaylock -C ~/.config/swaylock/config' \
  timeout 1800 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
  before-sleep 'swaylock -C ~/.config/swaylock/config'
# This will lock your screen after 900 seconds of inactivity, then turn off
# your displays after another 900 seconds, and turn your screens back on when
# resumed. It will also lock your screen before your computer goes to sleep.

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 or pavucontrol can be used to set audio and enable/mute devices from the console and GUI respectively.

4.6 Screenshots: wayshot (grimshot)

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

Source: wayshot

4.7 Clipboard manager: copyq

Set a keybinding in sway/config 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.8 Notifications: mako

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

Send a test notification ...

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

Source: .config/mako/config

5. Resources

6. Finish

My sway desktop

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

Thanks for reading! Read other posts?

» Next: Automatic upgrades in Debian

« Previous: Install Debian 12 with encrypted Root-on-ZFS