Expand description
Holding devices across a VT switch.
A compositor that owns the display cannot simply open /dev/dri/card0 and
keep it: switching to another virtual terminal has to take the display away
and give it back. A seat – logind, seatd, or a bare-root fallback – is
what arbitrates that, handing out descriptors it can revoke.
What arrives from the seat is two events. Paused: stop touching every
descriptor immediately, because the ioctls will start failing. Resumed:
here are fresh descriptors, and every per-descriptor kernel object you had
– framebuffers, property blobs, client caps, GEM handles – is gone.
drmkit_cursor::Paused is the shape that pairs with this on the other
side.
§Why the backend is a trait
Because a seat cannot be opened on a machine that has no session. Over SSH, in a container, on a CI runner, logind says the session is busy, seatd is not running, and the builtin backend wants root and a TTY. That is most places this code will be built.
So the sequencing – which devices are held, what happens to them across a
pause, when the pause is acknowledged, what a caller is allowed to do while
inactive – lives in Session over a Backend, and is tested against
a fake. The libseat binding is a thin adapter behind the libseat feature;
libseat-log, also on by default, routes libseat’s own diagnostics into
the log crate.
§Not here yet
Three things the reference has and this does not.
TakeDeviceOpts::preserve_fd_across_resume asks the seat to hand back the
same descriptor rather than a fresh one, on the grounds that the
capability-revoking backends leave it valid. Plausible, and it saves a
reopen per device per switch, but it is an optimisation over a path that is
already correct – and getting it wrong means scanning out through a
descriptor the kernel has stopped honoring, on a machine none of the CI
lanes resemble. It waits for a device to be proved on.
Seat::input_opener routes libinput’s privileged device opens through the
same seat, so input descriptors get the revocable lifetime the DRM one has.
Both halves it needs now exist: this crate opens devices through a seat,
and drmkit_input::Seat::open takes any LibinputInterface the caller
supplies. What is missing is the piece between them — an implementation of
that trait backed by a Session, so an input descriptor is revoked and
reissued on a VT switch the way the DRM one is. Until it exists a caller
passing their own opener gets input descriptors with an ordinary lifetime,
which works and is not what the seat is for.
The reference installs its own handler for libseat’s log, at error level,
and sends what arrives to drm::log. Here the binding’s handler sends it
at debug level to the log crate, which drmkit-log does not read: a
caller with no log logger never sees libseat’s reasons for refusing a
seat. Taking it over means a C shim, since libseat hands a handler a
va_list, and the binding already builds one.
Structs§
- Device
Id - A seat’s handle for one open device.
- Libseat
Backend libseat - A session backed by libseat.
- Session
- Devices held across VT switches.
- Taken
Device - A device this session is holding.
Enums§
- RawEvent
- What a seat says, before the session has made sense of it.
- Session
Error - What can go wrong holding a session.
- Session
Event - What a caller needs to act on.
Constants§
- DEFAULT_
ENABLE_ TIMEOUT libseat - How long
LibseatBackend::openwaits for the seat to activate.
Traits§
- Backend
- What a seat has to be able to do.