I spend few hours trying to figure this out without being lame and using large sleep.
The problem is basically this:
- You start sway service and that executed the sway binary,
- You have to set
Environment="XDG_SESSION_ID=1"without it Sway will bail and exits
- All other graphical services (redshift, waybar, …etc) that starts after sway.service fails because the wayland display is not yet initialized.
It’s not a bug, it’s like this by design “ddevault” and “emersion” even warn people from not launching sway as a systemd --user service because of that fact it forks and never calls sd_ready or whatever.
Simple script I made as a post start command
the content of the sway-wait-for-wayland-display.sh I put that next to the service fail.
It basically ask systemd what the user’s environment is which is not tied to the running context.
#!/bin/sh i=1 while [ "$i" -ne 100 ] do systemctl --user show-environment | grep WAYLAND_DISPLAY > /dev/null # Return status of grep is 0 when found 1 if not found status=$? # Break loop to skip sleep if found on first try if [ $status -eq 0 ]; then echo Display has been found. break fi sleep 0.1s # Increment i=$((i + 1)) done
If you are just thinking now "Why the frik he didn’t just poll
Jokes on you, once you start runnning service the environment is passed to it and is being static.
You can look at my dotfiles, I made them little bit more complex by splitting them into sway-session-pre target and sway session target similarly as graphical session target.
Else, what do you thing? Is it worth mentioning it upstream? I think this is nice cherry on top of what they have in git repo wiki.