Switching between sway and i3

When I decided to fully switch to Wayland 6 months ago, I accepted that there might be some rough edges. And there are, but I am positively surprised that there are so few of them and everything generally just works. However, there is one thing which still haunts my childlike dreams: screen sharing.

Can’t blame Wayland developers1 with this one. They do an outstanding job and screen sharing usually doesn’t work because third-party applications don’t support the technology provided by Wayland. For example, to enable screen sharing in Electron applications (e.g. Teams), we need Electron 8.2.2, pipewire and rtc_use_pipewire=true build flag enabled. Which is impossible to enforce in most proprietary inferior chat systems.

There are hacks, like setting up a virtual camera, but quality of such solutions is shit due to video compression, to the point that your audience can’t even read the text that you show. The only viable workaround which I know is switching back to X11 session whenever you need to share a screen.

Which doesn’t work out of the box for sway-i3 tandem. Or it does, but really doesn’t in some startup scenarios.

What’s the problem? Generally, if you use systemd, I bet my breakfast that your distribution at some point calls systemctl --user import-environment (or dbus-update-activation-environment --systemd). This command imports the current environment to the systemd session. Most likely, it is even called several times at different stages of system startup. And if you use systemd to manage your user session, you’re practically required to call it manually from sway config:

# part of sway config
exec_always "systemctl --user import-environment"
exec_always "systemctl --user restart kanshi.service"

Bad news is that this environment outlives Wayland or X session because systemd is, at its root, an init system. Sway is compatible with i3, so certain variables are used by both of them. One such variable is $I3SOCK2, which provides a path to the socket used for Inter Process Communication (IPC). When this variable is left by sway, i3 is forced to use it, resulting in some happy flips: sometimes everything works, other times i3 will crash or hang. You can also forget about any programs which use this socket for actual communication.

Thankfully the fix is easy: just clean sway parts of environment before starting i3, so it isn’t fooled to use incorrect path. We can do it e.g. in ~/.xsession, if it’s a part of your X11 startup:

systemctl --user unset-environment SWAYSOCK I3SOCK WAYLAND_DISPLAY
exec /usr/bin/i3

Repeating this for sway is unnecessary. Sway’s IPC server disregards $I3SOCK and simply overwrites it by itself. And even if $SWAYSOCK from the old sway session leaks, sway is intelligent enough to handle this situation – it unlinks it first. IPC clients can then use either $SWAYSOCK or $I3SOCK, both pointing to the correct sway socket.

  1. Meaning, all the people who maintain the whole Wayland software stack (specifictation, libraries, compositors, applications). ↩︎

  2. Other is $DISPLAY, for XWayland, but it should be safely overwritten by distro’s regular XSession scripts ↩︎