wlc-displays is an output management utility for Wayland compositors like Labwc inspired by wdisplays and nwg-displays.
Why yet another output management utility? Because I couldn't find one that
a) is written in Python — except nwg-displays. But I didn't like its GUI behaviour when saving a profile: it enlarged the viewport while pushing elements below out of the visible area. Scrollbars appeared, but they couldn't be moved.
b) supports profiles — different display configurations and layouts. Profiles are used by Kanshi, which lets you define output profiles that are automatically activated and deactivated on hotplug. This can be used, for example, to turn off a laptop's internal display when docked and activate an external monitor instead.
And c) It was a good opportunity to test SimpleWx and its GUI builder under real-world conditions ^^.
- Interactive monitor canvas — drag & drop, zoom, magnetic snapping, collision detection
- Per-monitor settings — resolution, refresh rate, scale, transform, DPMS, adaptive sync, custom mode
- Profile management — create, edit, save and live-apply kanshi profiles
- Automatic profile matching — active profile is detected at startup based on connected hardware
- Kanshi integration — reads and writes the kanshi config directly; supports hotplug automation
- Known Look & Feel - nwg-display sends its regards ;-)
Currently labwc only. But it should also work on other wayland compositors.
Remark Currently it is not tested in a real wayland environment but it will come soon.
System packages (install via your distribution's package manager):
- Python 3.10+
wlr-randr— reads current monitor configurationwlopm— reads DPMS power state per outputkanshi— hotplug profile automation
Python packages (see requirements.txt):
wxPython— GUI framework
SimpleWx — thin wxPython wrapper (included via symlink, no pip install needed):
# Clone SimpleWx next to this repo:
git clone https://github.com/ThomasFunk/SimpleWx ../SimpleWx
# Then create the symlink inside the project:
ln -s ../SimpleWx/simplewx.py simplewx.pyClone repository:
git clone https://github.com/ThomasFunk/wlc-displays
cd wlc-displaysCreate and activate a virtual environment, then install Python dependencies:
python3 -m venv venv
venv/bin/pip install -r requirements.txtFor development in VS Code, the workspace is pre-configured to use venv/. The
debug configurations in .vscode/launch.json launch wlc-display.py directly.
System-wide installation (default: /usr/local):
make
sudo make installUser-local installation (without sudo):
make PREFIX="$HOME/.local" installUninstall:
sudo make uninstall
# or for user-local install:
make PREFIX="$HOME/.local" uninstallThis tool is not fully tested yet. Everyone who wants to contribute is very welcome. ^^
The test suite covers the pure Python logic in modules/tools.py and
modules/profiles.py — no Wayland compositor, wlr-randr, or display
hardware is required.
Run the tests:
venv/bin/python -m pytest tests/ -vWhat is tested:
| Module | Areas |
|---|---|
tools.py |
Monitor dataclass (serialisation, rotation, mode string), bounding-box math, canvas-coordinate round-trips, scale factor, collision detection, snap-point logic, app config I/O, profile JSON round-trip, _monitors_equal_to_json, kanshi config parse + write |
profiles.py |
_profiles_match, _positions_match, ProfileManager initialisation, orphan detection (!-prefix), select, save, delete, ensure_default_profile, get_profile_config |
pytest is the only additional test dependency — install it once into the
virtual environment if needed:
venv/bin/pip install pytestIntegration tests (require a live Wayland session with wlr-randr and wlopm):
venv/bin/python -m pytest tests/test_integration.py -vThese tests are skipped automatically outside a Wayland session and never write to wlr-randr — they do not change the display configuration.
| Integration test class | What is verified |
|---|---|
TestDependencies |
All required system commands are found |
TestListOutputs |
wlr-randr output parses to valid Monitor objects; serialisation round-trip |
TestDpmsMap |
wlopm DPMS map keys match known outputs; values are bool |
TestListOutputsActivity |
Activity map is consistent with list_outputs() |
TestCanvasOnRealData |
Bounding box, scale factor and coordinate round-trip on real monitor layout; live layout has no collisions |
TestKanshiRoundtripWithRealData |
save_kanshi_config → load_kanshi_config preserves all monitor fields |
TestProfileManagerWithRealKanshi |
ProfileManager loads the real kanshi config without errors |
This project is licensed under the GPL-3 License - see the LICENSE file for details
