Building and Installing the Sway Wayland Window Manager on Debian 10 Buster

Wayland isn’t mainstream quite yet, but if you want to experiment with it and you prefer tiling window managers, then Sway is the way to go. However, building it on Debian requires a little work.

I tested the below script on a clean install of Debian Buster installed with just ssh server and standard system tools selected in task select. No desktop system was installed.

The only other packages I had installed were vim-nox, sudo, and open-vm-tools (I did this on a VM - vmware workstation with 3D acceleration enabled).

#!/bin/bash
# show commands as they are ran
set -x
# exit on first error
set -e

# meson must be newer than what's available in Debian packages to build wlroots:
REPOS=~/repos
mkdir -p $REPOS
sudo apt install python3-pip git ninja-build -y
sudo pip3 install meson

# prequisites for wlroots:
sudo apt install \
  libwayland-dev \
  wayland-protocols \
  libgles2-mesa-dev \
  libdrm-dev \
  libgbm-dev \
  libinput-dev \
  libxkbcommon-dev \
  libudev-dev \
  libpixman-1-dev \
  libsystemd-dev \
  libcap-dev \
  libavutil-dev \
  libavcodec-dev \
  libavformat-dev \
  libpng-dev -y

# Additional prerequisites for sway. There are more if you want to be able to
run # X11 apps in Sway using Xwayland, but I just want to run native apps.
sudo apt install \
  libpcre3-dev \
  libpango1.0-dev \
  libcairo2-dev \
  libgdk-pixbuf2.0-dev -y

#wlroots:
cd $REPOS
mkdir -p github.com/swaywm
cd github.com/swaywm
git clone https://github.com/swaywm/wlroots.git
cd wlroots
# Cannot install from git master because it requires wayland-server >=1.18
# and Debian has 1.16
git checkout 0.10.1
meson build
ninja -C build
sudo ninja -C build install

# json-c
sudo apt install cmake -y
cd $REPOS
mkdir -p github.com/json-c
cd github.com/json-c
git clone https://github.com/json-c/json-c.git
cd json-c
# build a released version:
git checkout json-c-0.14
mkdir json-c-build
cd json-c-build
cmake ../
make
sudo make install
# move libs to correct location
cd /usr/local/lib
sudo mv libjson-c.so* x86_64-linux-gnu/
sudo ldconfig

# scdoc: debian has 1.9, need >=1.9.2
cd $REPOS
mkdir -p git.sr.ht/~sircmpwn
cd git.sr.ht/~sircmpwn
git clone https://git.sr.ht/~sircmpwn/scdoc
cd scdoc
git checkout 1.10.1
make
sudo make install

# Sway:
cd $REPOS
mkdir -p github.com/swaywm
cd github.com/swaywm
git clone https://github.com/swaywm/sway.git
cd sway
# I got errors if I tried to build against git master, probably b/c it
# expects the latest version of wlroots
git checkout 1.4
meson build
ninja -C build
sudo ninja -C build install

# Firefox: you'll need a browser that supports native Wayland. The stock
# Debian version didn't work for me, so use a later release:
mkdir -p ~/Downloads
cd ~/Downloads
wget https://ftp.mozilla.org/pub/firefox/releases/75.0/linux-x86_64/en-US/firefox-75.0.tar.bz2
tar xf firefox-75.0.tar.bz2
sudo mv firefox /usr/local/bin/firefox-75.0
sudo ln -s firefox-75.0/firefox /usr/local/bin/
# other packages Firefox expects to be install
sudo apt install libgtk-3-0 libdbus-glib-1-2 libxt6 -y

# kitty: you'll need a terminal that supports native Wayland. The stock
# Debian version of kitty is too old to support Wayland. Alacritty is
# another option, but I like to use FiraCode font with ligatures and
# Alacritty does not support ligatures.
cd ~/Downloads
wget https://github.com/kovidgoyal/kitty/releases/download/v0.17.3/kitty-0.17.3-x86_64.txz
sudo mkdir /usr/local/bin/kitty-0.17.3
sudo tar -C /usr/local/bin/kitty-0.17.3 -xf kitty-0.17.3-x86_64.txz
sudo ln -s kitty-0.17.3/bin/kitty /usr/local/bin/
mkdir -p ~/.config/sway
cp /usr/local/etc/sway/config ~/.config/sway/
sed -i 's/alacritty/kitty/' ~/.config/sway/config

# wofi: this is a application laucher like rofi/dmenu that is Wayland native.
sudo apt install mercurial libgtk-3-dev pkg-config -y
cd $REPOS
mkdir -p hg.sr.ht/~scoopta
cd hg.sr.ht/~scoopta
hg clone https://hg.sr.ht/~scoopta/wofi
cd wofi
hg checkout v1.1.2
# wofi needs libglib 2.60 to support g_app_info_launch_uris_async, but Debian
# has 2.58, so I added this patch to not use the async version.
patch -p1 << 'EOF'
diff -r 96d47bb081be modes/drun.c
--- a/modes/drun.c	Mon Mar 09 22:37:36 2020 -0700
+++ b/modes/drun.c	Sat May 02 17:18:15 2020 -0500
@@ -315,21 +315,6 @@
 	return NULL;
 }
 
-static void launch_done(GObject* obj, GAsyncResult* result, gpointer data) {
-	GError* err = NULL;
-	if(g_app_info_launch_uris_finish(G_APP_INFO(obj), result, &err)) {
-		exit(0);
-	} else if(err != NULL) {
-		char* cmd = data;
-		fprintf(stderr, "%s cannot be executed: %s\n", cmd, err->message);
-		g_error_free(err);
-	} else {
-		char* cmd = data;
-		fprintf(stderr, "%s cannot be executed\n", cmd);
-	}
-	exit(1);
-}
-
 void wofi_drun_exec(const gchar* cmd) {
 	GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(cmd);
 	if(G_IS_DESKTOP_APP_INFO(info)) {
@@ -338,7 +323,12 @@
 			printf("%s\n", g_app_info_get_commandline(G_APP_INFO(info)));
 			exit(0);
 		} else {
-			g_app_info_launch_uris_async(G_APP_INFO(info), NULL, NULL, NULL, launch_done, (gchar*) cmd);
+			gboolean ret = g_app_info_launch_uris(G_APP_INFO(info), NULL, NULL, NULL);
+			if (!ret) {
+				fprintf(stderr, "%s cannot be executed\n", cmd);
+				exit(1);
+			}
+
 		}
 	} else if(strrchr(cmd, ' ') != NULL) {
 		char* space = strrchr(cmd, ' ');
EOF
meson build
ninja -C build
sudo ninja -C build install
sed -i 's/\sdmenu\s/ wofi --show run /' ~/.config/sway/config

exit 0

To start sway, from a virtual terminal you should be able to just type sway, however, with my hardware/VM, I had to set WLR_NO_HARDWARE_CURSORS=1 otherwise I had no cursor. Also, for Firefox, the MOZ_ENABLE_WAYLAND=1 environment variable must be set. For convenience, I just set that when launching Sway. So my actual command line to launch Sway looks like this:

WLR_NO_HARDWARE_CURSORS=1 MOZ_ENABLE_WAYLAND=1 sway