A common task people want to perform is running a set of given programs during every Wayland session.
GNOME and KDE have their own approaches and graphical utilities for down this. For those of us who donāt use a desktop environment, how about in Sway?
A bit of experimentation appears to show that this syntax is a pretty reasonable way to do this:
# Power notification support
exec_always flock -n $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY-poweralertd poweralertd -s
# Make clipboard persist after application termination
exec_always flock -n $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY-wl-paste wl-paste --watch clipman store
Thought Iād share for anyone else running into this.
For some Sway users, that may be enough. But if anyone wants to read more history, here goes!
Background and rationale:
Once upon a time, it was conventional to have a shell script, ~/.xinitrc
, that was invoked whenever someone started up an X server with startx
after logging in on an (initially) text terminal. Any per-session commands could be invoked here.
Later, when display managers showed up, it became common for a Linux machine to go straight to a graphical display at boot and show a login prompt from there. xdm
showed up; if it was started, itād run another shell script, ~/.xsession
. A lot of people, including myself, just symlinked ~/.xsession
to ~/.xinitrc
.
Still later, some desktop environments, like GNOME or KDE or some less-popular ones, introduced their own schemes for storing a list of programs to start when the graphical environment came up.
Wayland+sway ā to my initial surprise and annoyance ā isnāt really geared up for that. In theory, you can use whatever login manager you want. I use a non-standard login manager ā greetd to launch agreety
(and Iād use emptty if it were in Debian bookworm) which lets me log in on a terminal. But these donāt provide functionality to run a startup script. This kind of makes sense ā on X11, once the display manager starts things up, X11 can run programs, whereas Wayland really requires a functioning compositor to be going, which means that Sway really needs to be up and running. So maybe it makes sense for the compositor, Sway, to handle launching startup programs in the graphical environment, rather than the login manager. but Wayland compositors donāt have even a semi-convention for a ālogin scriptā like ~/.xinitrc
or ~/.xsessionor
~/.xprofile` or an equivalent, which surprised me. That might be because Wayland compositors are heavier than their X11 window manager analogs, and perhaps its less-expected for people to be switching among them.
What Sway does is to, in its config file, ~/.config/sway/config
, have two directives, exec
and exec_always
. One can make them invoke a script. These can be handy. But they donāt quite what Iād ideally like them to do.
You see, Sway ā like some X11 window managers ā has the ability to permit a āreloadā, where it re-reads its config files. Thatās handy! If an X11 window manager couldnāt do that, when you changed its config file, youād have to close all your graphical programs, log out, and log in again to confirm that it did what you wanted. You donāt have that problem with Sway. You can just change its config file, ask Sway to do a reload, and itāll be āre-appliedā. And then exec
and exec_always
come into play ā the former will run a program only when Sway initially starts, but not when it does a āreloadā. The latter will run a command each time, both at Sway start and each time Sway reloads its config file.
For some programs, exec
and exec_always
are sufficient. Maybe you just want to make sure that a program has been run and then terminated at least once in your current session.
But that isnāt normally what I want to do. By far my overwhelming need ā and I suspect this is true of others ā is that I want to have some kind of daemon running and persisting in the background of my session.
Some daemons try to be clever. If you try to run multiple instances at once, the new instance will just bail out. blueman-applet
is like this. And if your daemon works like this, then running exec_always
is fine. If you run a new instance and thereās an already-running instance, the new one will just bail out.
But some daemons donāt ā they just start up another instance. So every time you reload your Sway config, exec_always
will start another instance of that daemon. I have a couple of daemons like that. poweralertd
notifies me when my laptop battery is getting low, for example. If I just let poweralertd
do its own thing and start it via exec_always
, then when my battery gets low, if Iāve reloaded my Sway config 5 times, Iāll have 5 instances running, and get 5 warnings when my battery gets low.
But running exec
isnāt ideal either, because then you have to give up on Sway āreapplyingā your config when you reload it. If I want to have a new daemon running in the background of my Wayland session, I donāt want to have to log out to ensure that my config is working correctly.
Now, at this point, I suspect that a number of people think āAha! What about systemd?ā
So, not everyone is a huge fan of systemd. It is a very large software package that provides a lot of useful functionality to most present-day Linux systems. So you might not want to tie yourself to systemd.
But more-problematic ā while systemd does have the ability to manage both āsystemā daemons that run one instance per system, typically come up when the system does, and āuserā daemons, one instance per userā¦that isnāt quite correct for Wayland. Itās reasonable for a user to have multiple concurrent Wayland sessions on a Linux machine. Maybe it might make sense to selectively share some functionality among those, like one mpd
instance to play music ā dunno about that. But you definitely donāt want to have random Wayland programs run in each session running one-instance-per-user, because otherwise, any additional Wayland session will have the programs just not come up in that new session.
It looks like some people out there have recognized that this is an issue. uwsm looks to my quick glance at being a stab in the direction of āper-Wayland-session systemd-based managementā. But whether-or-not it could be used, itās not in Debian bookworm, and I want to use stock software for basic stuff like getting my desktop up on a new system.
Hence, we get to the above flock-based approach.
So, letās say that one wants to have a program like wl-paste
running persistently, but only one per-session. How?
We want to have only one instance running at once. Traditionally, the way to achieve that on a Unix system is to create a file, then establish a āfile lockā on it via the flock(2)
function; this is guaranteed by the OS to be an atomic operation, only one can occur. Thereās a command, flock(1)
, which does all this at one go ā it creates a file if it doesnāt exist, establishes a file lock on it, and then, while continuing to run, runs a specified command. When a process goes away, the OS releases the file lock, so when the invoked command (here, wl-paste
) exits, the flock
process exits, and the file lock goes away. By default, flock
will block if thereās a lockfile with a held lock, which is what you want if you just want to make sure that two commands wait to avoid interfering with each other but with -n
, itāll just fail; this is the behavior you want if you want to make sure that you have one, but only one, daemon active.
And we want to have one instance per session, not per user. The $XDG_RUNTIME_DIR
environment variable provides a temporary directory per-userā¦but not per session. $WAYLAND_DISPLAY
is guaranteed to be unique per session for a given user. So any path containing both $XDG_RUNTIME_DIR
AND $WAYLAND_DISPLAY
is going to be unique per-session; we just need an extra bit of text (ā-poweralertdā) to make it unique to a given daemon per session.
Given how this wasnāt an immediately-obvious approach to me, thought that Iād point it out to anyone else who might be using Sway and want per-session daemons running.
I figured Iād also add a bit of text about why Iām using
wl-paste
andclipman
above, for anyone interested in clipboard management.So, the specific problem Iām trying to solve with this daemon: On Windows and (traditional, dunno if this has changed, decades out-of-date on MacOS) MacOS, the desktop environment maintains a persistent clipboard buffer. When you hit Control-C (or, on MacOS, Command-C), the program tells the OS to save a copy of the copied/cut content.
This is not actually what X11 or Wayland do. Neither X11 nor Wayland maintain a persistent clipboard. What they do is act as a broker between two X11 or Wayland programs. So, if you you launch Program A and select text (for PRIMARY) or hit Copy (for CLIPBOARD) and then in Program B, middle-click (for PRIMARY) or hit Paste (for CLIPBOARD), then Wayland tells Program B to go get data from Program A.
For X11, this was particularly important in that the system was designed to run on very low-resource thin terminals. That terminal may not have the ability to store a whole lot of clipboard data.
This becomes user-visible If someone closes Program A prior to pasting in Program B, because their content also disappears.
Some people found this obnoxious, and introduced a solution many years back, reusing an approach used by software on Windows and MacOS to solve a different issue.
On both Windows and MacOS, some people ran into the limitations of having a single clipboard. They didnāt want a ācopyā to destroy whatever was already in their clipboard, wanted a history.
Some software packages dealt with this ā I believe Microsoft Office was among these ā by introducing its own āclipboard historyā. Emacs has its own sophisticated system with a history, the kill-ring, thatās been extended in all kinds of exotic ways (e.g. to be a ākill-torusā). But while these mitigate the problem for a particular important program, these are not system-wide.
So what folks on MacOS and Windows did was introduce āclipboard managersā. The idea here is that you have a very small, simple program. It just sits and waits for the clipboard contents to change. When they do, it saves a copy. It typically saves some finite number of clipboard entries, and lets you go back in a time-ordered list and choose saved clipboard contents. Some provide more-sophisticated functionality, like searching through history. Thatās nice if you just chose ācopyā and realize that you just blew away some content that youād copied. Based on a quick glance, neither MacOS nor Windows ships out-of-box with a clipboard manager in the base OS in 2024, but itās a simple program to write, so people who want it donāt have trouble adding it on.
X11 has three clipboards (PRIMARY, SECONDARY, CLIPBOARD) and Wayland can do at least PRIMARY and CLIPBOARD, dunno about SECONDARY. Thatās a bit more state that can be retained, but they arenāt really intended to provide a āhistoryā.
Some people on X11 or Wayland also want that āclipboard managerā functionality. And a āclipboard managerā also has the nice side-benefit of providing clipboard persistence beyond the lifetime of the program from which you copied the data. You donāt have the āProgram A was closed before pasting to Program Bā issue, because what happens is that you copy in Program A, then the clipboard manager detects that the clipboard contents have changed and internally transfers the clipboard contents from Program A to its own memory, then announces that it has new clipboard contents, a copy of what was just stored, so when the user pastes in Program B, heās actually asking the clipboard manager to send data to Program B. I donāt actually know how fast the clipboard managers detect new data in the clipboard ā depending upon how the clipboard API works, I suppose that there might be a window for data loss, where someone copies in Program A and then immediately closes Program A ā but it seems to work well-enough on a day-to-day basis.
This is particularly obnoxious for software packages like
xsel
on X11 andwl-clipboard
on Wayland. Theyāre command-line programs that you can use to ācopyā text. They need to provide the appearance to the user of looking like any other command-line program and exiting once theyāve run. But the X11 and Wayland protocols donāt permit for that ā a program from which one is copying data has to stay alive long enough to send data to whatever program is requesting it. Soxsel
andwl-clipboard
have to fork off a process to stay alive until the clipboard contents change, which is kind of a kludge.I donāt personally need a clipboard manager. I donāt care about a clip history. I use emacsā kill ring, but the overwhelming remainder of copy-pasting I do is very simple. And my experience has been that clipboard managers tend to come-and-go, and tend to be tied to a particular desktop environment or widget toolkit, and come with a bunch of library dependencies.
What I do want, though, is clip persistence past the lifetime of a given program. I donāt like having to think about whether a program is still running or not. I want the clipboard to act like my X11 server or or Wayland contains an independent clip buffer, and when I choose ācopyā, it saves a copy to the thing.
The combination of
clipman
pluswl-paste --watch
can be made to act as a very minimalist clipboard manager. It doesnāt use KDE or GNOME or GTK or Qt or anything like that. All it does is talk directly to Wayland. That fits my bill well. Note that it does store a copy of the clipboard on-disk, which some people may want (so that it lasts across sessions, which I donāt care about). Thatās necessary becausewl-paste
doesnāt retain state andclipman
doesnāt stay running. Some people may not like this in that they may not want clipboard contents sitting around on disk from session to session; stuff like passwords might be persisted there; just a heads-up. There are clipboard managers out there that wonāt persist state to disk, if thatās a concern for anyone.