Robust, zero-config X11 display hotplug policy daemon for dwm/i3
Project description
xrandrw
Zero-config, self-healing X11 display-layout daemon for dwm/i3 and other bare-X11 window managers. It watches for monitor hotplug/unplug, remembers each display by its EDID identity, and auto-places externals relative to a primary using a persistent attach-order policy — so your monitors end up where you left them, every time.
Pure Python standard library (optional systemd-python for journald logging).
Install
End-user (isolated, lands the xrandrw console-script at ~/.local/bin):
pipx install .
Development (editable):
pip install -e .
Optional journald logging extra:
pip install ".[journald]"
Usage
xrandrw exposes six modes:
| Command | Description |
|---|---|
xrandrw --apply |
Apply the layout once (default when no flag is given). |
xrandrw --watch |
Poll topology and re-apply on change. |
xrandrw --daemon |
Watch for display changes via event-driven RandR notifications and re-apply (systemd entry point). |
xrandrw --print |
Print xrandr --query output and exit. |
xrandrw --set-pref OUTPUT_OR_ID SIDE |
Set a display's preferred side: right-of, left-of, above, below. |
xrandrw --list-state |
Dump the placement state JSON. |
Configuration
Config resolves from (lowest to highest precedence): built-in defaults →
/etc/xdg/xrandrw.conf → ~/.config/xrandrw.conf → process environment. Each
key can be set in a config file (KEY=value lines) or via an environment
variable of the same name.
| Key | Purpose |
|---|---|
USE_XWALLPAPER |
0 = feh/fehbg, 1 = xwallpaper. |
WALL |
Wallpaper image path. |
HIDPI_WIDTH |
Treat internal panel as HiDPI when preferred-mode width ≥ this. |
POLL_INTERVAL |
Watch-loop poll interval in seconds. |
LOG_LEVEL |
none, err, info, notice, debug. |
LOG_FILE |
Optional JSON-lines log file (unset = journald/stderr). |
LOCKFILE |
Apply-lock path. |
PREF_DEFAULT_SIDE |
Default side for new/unknown monitors. |
EXCESS_WINDOW_SEC / EXCESS_THRESHOLD |
Churn-backoff window and threshold. |
See xrandrw.conf.sample for an annotated template —
copy it to ~/.config/xrandrw.conf and edit.
systemd user service
The repo ships a --user unit that runs xrandrw --daemon with Restart=always
and sd_notify integration. Install and enable it via the Makefile:
make install # pipx install . + copy conf sample + unit
make enable # systemctl --user daemon-reload && enable --now
make install uses pipx install --force ., which places the console-script at
~/.local/bin/xrandrw — exactly the ExecStart path the unit expects. Run
systemctl --user daemon-reload after any reinstall.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xrandrw-0.1.1.tar.gz.
File metadata
- Download URL: xrandrw-0.1.1.tar.gz
- Upload date:
- Size: 37.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4383904df26129c5377b837e45753f262b4262a3e8510648655adc6c1614334
|
|
| MD5 |
9f365c1f56d02a4f8ad02b7931d394d8
|
|
| BLAKE2b-256 |
f0a5518ea00ef24354599a9cd5cb542fa3d5f5bd3307d66820aed9d9cabed5ed
|
File details
Details for the file xrandrw-0.1.1-py3-none-any.whl.
File metadata
- Download URL: xrandrw-0.1.1-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea2b11f75d13fbcc8ccea1cf2c6131e4017903c68b4efbae3485f2c54eb4e8e2
|
|
| MD5 |
e5d2feb8ed0e8896f81636bc343c62c1
|
|
| BLAKE2b-256 |
f2a230f7eec5e173ef18db1ec1e22211ba3063e3261d5798f3e7978ca2c82253
|