Save held inhibits to $XDG_RUNTIME_DIR/xautolock-inhibit.json and restore them on start if the previous instance stopped within --restore-window (default 30s) on the same bus and the senders are still connected. The file is touched every 10s while inhibits are held, so crashes are timed too.
96 lines
5.1 KiB
Markdown
96 lines
5.1 KiB
Markdown
# xautolock-inhibit
|
|
|
|
Makes screen locking with `xautolock` respect the "don't lock the screen" requests that apps send, on X11 sessions without a desktop environment (for example a plain window manager like xmonad).
|
|
|
|
Browsers, Steam, gamemode and other apps ask the desktop not to lock or blank the screen while a video or game is running, through the D-Bus service `org.freedesktop.ScreenSaver`. Without a desktop environment nothing provides that service, so the requests are dropped and the screen locks in the middle of a video. xautolock-inhibit provides it:
|
|
|
|
- While at least one request is active, it runs `xautolock -disable` and pauses X screen blanking and DPMS.
|
|
- When the last request is released, it waits a few seconds, then runs `xautolock -enable` and resumes blanking.
|
|
|
|
xautolock stays your locker; xautolock-inhibit only switches it off and on.
|
|
|
|
## How it works
|
|
|
|
- Owns `org.freedesktop.ScreenSaver` on the session bus at both `/org/freedesktop/ScreenSaver` and `/ScreenSaver` (apps differ on the path), and implements `Inhibit` and `UnInhibit`.
|
|
- Tracks requests per D-Bus client. If a client disconnects without releasing them (for example a browser crash), its requests are released.
|
|
- Runs `xautolock` only when the number of active requests goes from 0 to 1 or back to 0. Re-enabling waits a few seconds (`--release-delay`), because browsers send short bursts of requests when a video starts.
|
|
- Pauses X blanking with `XScreenSaverSuspend`, the same mechanism mpv uses, instead of changing `xset` settings. The X server ends the pause by itself if the daemon exits or crashes.
|
|
- Requests whose reason is on an ignore list (default: `Playing audio`) are accepted and logged, but don't block locking. Firefox-based browsers send one for audio playback, which would otherwise keep the screen unlocked while music plays with nobody at the computer.
|
|
- Keeps the requests it holds in `$XDG_RUNTIME_DIR/xautolock-inhibit.json`, so a restarted or crashed daemon takes them over. They are taken over only if the previous daemon stopped at most 30 seconds ago (`--restore-window`) on the same session bus, and only for clients still connected. A request released while no daemon was running can't be seen, so an old file isn't trusted.
|
|
- On exit (including SIGTERM), it re-enables xautolock. The systemd unit also runs `xautolock -enable` when it stops, as a fallback.
|
|
- If another program (a desktop environment) already owns `org.freedesktop.ScreenSaver`, it exits with status 2 instead of taking over.
|
|
|
|
## Requirements
|
|
|
|
- `xautolock`, already running in the session
|
|
- `python`, `python-gobject`
|
|
- `libx11`, `libxss`
|
|
|
|
## Installation
|
|
|
|
Build and install the package with the included PKGBUILD:
|
|
|
|
```
|
|
makepkg -si
|
|
```
|
|
|
|
Then start it from your window manager's startup, after `xautolock`. For xmonad:
|
|
|
|
```haskell
|
|
spawnOnce "xautolock -time 10 -locker slock -detectsleep"
|
|
spawnOnce "systemctl --user start xautolock-inhibit"
|
|
```
|
|
|
|
The unit has no `[Install]` section on purpose. Enabling it at login would also start it in a desktop environment, or before X is up; starting it from the window manager limits it to that session. The user service manager needs `DISPLAY` (and `XAUTHORITY`) in its environment, which `/etc/X11/xinit/xinitrc.d/50-systemd-user.sh` sets up for `startx` sessions.
|
|
|
|
## Usage
|
|
|
|
```
|
|
xautolock-inhibit [-i REASON] [--count-all] [-d SECONDS] [--restore-window SECONDS]
|
|
```
|
|
|
|
- `-i`, `--ignore-reason REASON`: request reason that doesn't block locking. Can be repeated; replaces the default (`Playing audio`).
|
|
- `--count-all`: every request blocks locking; no reasons are ignored.
|
|
- `-d`, `--release-delay SECONDS`: wait this long after the last release before re-enabling xautolock (default 5).
|
|
- `--restore-window SECONDS`: take over requests from a previous daemon that stopped at most this long ago (default 30; 0 disables).
|
|
|
|
To change the options used by the service:
|
|
|
|
```
|
|
systemctl --user edit xautolock-inhibit.service
|
|
```
|
|
|
|
```ini
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/bin/xautolock-inhibit --count-all
|
|
```
|
|
|
|
Every request, release and xautolock call is logged to the journal:
|
|
|
|
```
|
|
journalctl --user -u xautolock-inhibit
|
|
```
|
|
|
|
## App notes
|
|
|
|
- **Sandboxed apps** may be blocked from reaching the service. For a firejail profile that filters D-Bus (`dbus-user filter`, as the Firefox-based profiles do), allow it in the app's `.local` file, e.g. `zen-browser.local`:
|
|
|
|
```
|
|
dbus-user.talk org.freedesktop.ScreenSaver
|
|
```
|
|
|
|
- **Games**: Steam's overlay and gamemode (`inhibit_screensaver=1`) send requests on their own.
|
|
- **scrcpy** only sends a request when started with `--disable-screensaver`.
|
|
- **mpv** talks to the X server directly and doesn't need this daemon.
|
|
|
|
## Limitations
|
|
|
|
- A release sent while the daemon is down is lost: if the daemon is back within `--restore-window`, that request stays active until its app exits. After a longer stop, all held requests are dropped and apps don't send them again.
|
|
- `SimulateUserActivity` is accepted but does nothing. Calls are logged once when a client starts sending them and once, with a count, after 5 minutes without any.
|
|
- `GetActive` always returns `false`.
|
|
|
|
## License
|
|
|
|
GPL-3.0-or-later. See [LICENSE](LICENSE).
|