Files
Daniele Fucini 4067579a2f Point README installation to the AUR
Drop the xautolock-inhibit upgrade section, which only applied to the local package.
2026-11-11 20:26:04 +01:00

7.2 KiB

xidle-inhibit

Makes screen locking with xautolock or xss-lock 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. xidle-inhibit provides it:

  • While at least one request is active, it pauses X screen blanking and DPMS, and with xautolock also runs xautolock -disable. xss-lock locks when the X screensaver starts, so pausing it is enough.
  • When the last request is released, it waits a few seconds, then resumes blanking (and runs xautolock -enable).

Your locker setup stays as it is; xidle-inhibit only holds it off.

Formerly xautolock-inhibit, which supported only xautolock.

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, UnInhibit and Lock.
  • Tracks requests per D-Bus client. If a client disconnects without releasing them (for example a browser crash), its requests are released.
  • Blocks and unblocks only when the number of active requests goes from 0 to 1 or back to 0. Unblocking 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/xidle-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.
  • With xautolock, it re-enables xautolock on exit (including SIGTERM). The systemd unit also runs xidle-inhibit --cleanup when it stops, which does the same, as a fallback.
  • Lock runs xautolock -locknow, or loginctl lock-session with xss-lock.
  • If another program (a desktop environment) already owns org.freedesktop.ScreenSaver, it exits with status 2 instead of taking over.

Requirements

  • xautolock or xss-lock, already running in the session
  • python, python-gobject
  • libx11, libxss
  • For xidle-dim: a compositor, such as picom

Installation

Install xidle-inhibit from the AUR, for example with aurutils:

aur sync xidle-inhibit
pacman -S xidle-inhibit

The PKGBUILD builds the signed release tag, so import the signing key first:

gpg --recv-keys 7E12BC1FF3B6EDB2CD8053EB981A2B2A3BBF5514

Then start it from your window manager's startup, after the locker. For xmonad with xautolock:

spawnOnce "xautolock -time 10 -locker slock -detectsleep"
spawnOnce "systemctl --user start xidle-inhibit"

With xss-lock, the lock timeout is the X screensaver timeout (xset s TIMEOUT CYCLE). This dims the screen with xidle-dim at 9:50 and locks at 10:00:

spawnOnce "xset s 590 10"
spawnOnce "xss-lock -n xidle-dim -- slock"
spawnOnce "systemctl --user start xidle-inhibit"

Without dimming, use xset s 600 0 and xss-lock -- slock. Start xss-lock from the window manager, not from a terminal: terminals like kitty run commands outside the login session, and xss-lock then ignores loginctl lock-session.

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.

Configuration

The backend is set in ~/.config/xidle-inhibit/config ($XDG_CONFIG_HOME):

backend = xss-lock

Values are xautolock and xss-lock. Without the file, xidle-inhibit uses whichever of the two is installed, and xautolock if both are. Restart the service after changing it.

Usage

xidle-inhibit [-i REASON] [--count-all] [-d SECONDS] [--restore-window SECONDS] [--cleanup]
  • -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 unblocking locking (default 5).
  • --restore-window SECONDS: take over requests from a previous daemon that stopped at most this long ago (default 30; 0 disables).
  • --cleanup: run xautolock -enable if xautolock is the backend, then exit. Used by the unit's ExecStopPost.

To change the options used by the service:

systemctl --user edit xidle-inhibit.service
[Service]
ExecStart=
ExecStart=/usr/bin/xidle-inhibit --count-all

Every request, release and locker command is logged to the journal:

journalctl --user -u xidle-inhibit

Dimming before the lock

xidle-dim is an xss-lock notifier (-n). It fades a black window over the screen until xss-lock stops it, on user activity or when the locker starts. It needs a compositor such as picom and does nothing without one. Because it doesn't change gamma, it works alongside redshift.

xidle-dim [--opacity 0-1] [--fade SECONDS]
  • --opacity: final darkness (default 0.6).
  • --fade: fade-in time (default 1.5).

Options go inside the notifier command: xss-lock -n "xidle-dim --opacity 0.8" -- slock.

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.
  • With xss-lock, requests block only the idle timeout: suspending, or loginctl lock-session from elsewhere, still locks.
  • 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.