State of Wayland

Table of Contents

I’ve been using Wayland, Sway to be precise, since 2020. My dotfiles show that I made the very first commit with Sway-related configuration on 6 November 2020. Since then I’ve made a lot of fights with different aspects of “Waylanding” on Linux and I’d like to document at least some of them. Maybe someone will find it helpful.

I use Debian Stable, which isn’t known for being bleeding-edge. I try to keep it rather pure, i.e. with very few exceptions I don’t manually compile and install system-wide packages or use many third-party repositories. I usually update to the new stable version as soon as it’s possible. If I feel impatient, then I update my repositories to testing ones once they are frozen (meaning, once Debian team decides that no more new packages go into testing repositories and they will be releasing new major Debian version soon).

Debian 11 is the first version of Debian which included Sway, a Wayland compositor based on i3, which is extraordinary Window Manager. On Debian 10 I had to manually compile Sway and a lot of its dependencies, plus some other manual labor. Not pleasant, not at all, but it had worked. Today installing Wayland on Debian is as easy as apt install sway.

From the very beginning of my Waylanding, the experience was delightful. Most things which I had expected work from the start. The others need some tweaking. Some, unfortunately, might be beyond the skills of ordinary users.

With that preface, let’s see what works and what doesn’t.

Starting Sway

Display Managers

If you’re coming from X11 world, you probably either use a Display Manager (like GDM, LightDM, SDDM), or startx script to start your graphical session. Sway developers discourage using such things for starting Sway and after being stubborn for 2 years, I finally start understanding why.

I was using Lightdm to start Sway for a long time, all Display Managers are very tightly integrated with X sessions. They perform some steps which are useful for Sway as well (like starting DBus, SSH Agent), but a lot is related only to X11 initialization. All your settings, environment variables etc. are miraculously sourced at some point either by Xsession script, or by startx + xinit tandem. This might or might not pose a problem.

Additionally, most of Display Managers are still X11-only programs, meaning that you’re going to run Xserver anyway, even though you’re on Wayland session.

Honestly, using your old Xsession-coupled Display Manager might be easier for you than running Sway directly from the console. This is because Xsession does a lot of things behind the scenes which are rarely mentioned in Sway tutorials, but are necessary to set up a fully functional graphical desktop. The two most important steps are setting up DBus and setting up systemd environment.

Sway doesn’t supply any .desktop session file by itself, but I have written one initially to imitate XSessions. There were 3 files involved:

  • wayland-user-session.desktop, which is a session file responsible for executing xsession-like script. I put it in /usr/local/share/wayland-sessions. It’s non-standard location, which might need to be added in your DM’s configuration (e.g. for LightDM to sessions-directory inside lightdm.conf)

    [Desktop Entry]
    Name=Default Wayland Session
    DesktopNames=Wayland
    Exec=/usr/local/bin/wayland-user-session
    Type=Application
    X-LightDM-Session-Type=waylandw
    
  • wayland-user-session, which is the script executed by DM:

     #!/bin/sh
     exec $HOME/.wayland-session
    
  • ~/.wayland-session, where all your initialization goes.

    #/bin/sh
    . "$HOME/.env"
    test -f "$HOME/.env.$(hostname)" && . "$HOME/.env.$(hostname)"
    export XDG_CURRENT_DESKTOP=sway
    exec /usr/bin/sway
    

TTY

Sway Developers recommend starting it from TTY and this is what I’m currently doing. There are many ways to do it, the simplest one is probably adding a conditional to your .bash_profile, or .profile, or .zprofile, or any other configuration file your shell uses:

[ -z "$DISPLAY" ] && \
[ -z "$WAYLAND_DISPLAY" ] && \
[ "$(tty)" = "/dev/tty1" ] && \
  exec sway

I, being, well, me, have created a wrapper around this simple initialization. Called it mydm. There are few other similar wrappers which might suit your needs better. mydm is really simple and out-of-the-way though, so if something doesn’t work, it’s really easy to debug.

Doing this kind manual labor, we must do all the necessary initialization, so it’s best to not execute sway directly, but put all the commands in a separate script. Here’s how it could look like:

#!/bin/bash

# user-session socket has already been set up, but it's not available in a
# current environment
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ] && \
  [ -n "$XDG_RUNTIME_DIR" ] && \
  [ "$XDG_RUNTIME_DIR" = "/run/user/`id -u`" ] && \
  [ -S "$XDG_RUNTIME_DIR/bus" ]; then
  DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus"
  export DBUS_SESSION_BUS_ADDRESS
fi

# X11-related env variables are exported in case we switch sessions between
# X11 and Wayland. Maybe it's unnecessary though
dbus-update-activation-environment --verbose --systemd DBUS_SESSION_BUS_ADDRESS

# somewhere here we're going to put our own environment variables
export XDG_CURRENT_DESKTOP=sway
export XDG_SESSION_TYPE=wayland

# launch dbus if it isn't launched yet
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
  eval $(/usr/bin/dbus-launch --exit-with-session --sh-syntax)
fi

# unset unnecessary env variables safely in a subshell and export environment
# to dbus
if [ -n "$DBUS_SESSION_BUS_ADDRESS" ]; then
  (
    unset XDG_SEAT
    unset XDG_SESSION_ID
    unset XDG_VTNR
    dbus-update-activation-environment --verbose --systemd --all
  )
fi

# unset variables from the old sessions which might interfere with the new one
systemctl --user unset-environment SWAYSOCK I3SOCK WAYLAND_DISPLAY DISPLAY

# dbus-update-activation-environment --systemd works only if systemd --user
# is available on dbus, so as a kind of workaround and/or safeguard, we'll
# export it once again
systemctl --user import-environment

exec sway

Additionally it’s a good idea to put exec_always "systemctl --user import-environment" inside .config/sway/config, before executing any services via systemctl, because sway sets some environment variables by itself. Yes, it means that import-environment is called many times and I really don’t see how it could be avoided.

Running Programs

I haven’t encountered any app-breaking bugs so far. There are some graphical glitches though. Some of them might be worked around though.

  • Firefox: sometimes pop-up menus flicker, which makes them harder to use
  • Firefox: Sharing Indicator is considered as ordinary window by Sway, which usually enlarges it to the size of half of the screen. It can be worked around e.g. by adding for_window [app_id="[Ff]irefox" title="Firefox . Sharing Indicator"] kill to Sway configuration
  • Libre Office: I had to install libreoffice-gtk3 package to get rid of Wayland-related bugs with the default Libre Office UI

X11-specific Applications

XWayland works beautifully for X-specific programs. I don’t mind them, but I’m not Wayland purist.

Games

Games just work. Sometimes there are problems with resolutions in fullscreen games, but the quick workaround is usually to “float” their windows and set them to fullscreen by Sway commands.

I can’t provide any comparison of games performance between X11 and Sway. I don’t have a gaming rig and I don’t play AAA titles. I believe that most of frame drops are related with my poor integrated GPU rather than with Wayland though.

Screen Sharing

Provided that you have installed pipewire, xdg-desktop-portal and some specific implementations of xdg-desktop-portal (e.g. -wlr, -gtk), then screen sharing just works. It is also important to export XDG_CURRENT_DESKTOP=sway and XDG_SESSION_TYPE=wayland (see Starting Sway/TTY section for example).

The exact support depends on the application which tries to share the screen though. At work I am unfortunately forced to use MS Teams. To enable screen sharing on it, I must use Google Chrome. Chromium for some reason doesn’t share my screen, although it looks like it would like to (it shows screen’s preview). Although Firefox isn’t officially supported by Microsoft, Screen Sharing works with Teams Phone Fix extension configured to use Google Chrome’s User Agent instead of the default MS Edge’s one:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36

Teams are glitchy on my Firefox though, so I don’t use it for Teams. It may be related to somewhat hardened privacy-oriented configuration of the browser.