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.

  • talOP
    link
    fedilink
    English
    arrow-up
    5
    ·
    edit-2
    4 months ago

    I figured I’d also add a bit of text about why I’m using wl-paste and clipman 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 and wl-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. So xsel and wl-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 plus wl-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 because wl-paste doesn’t retain state and clipman 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.