Hyprland and wlroots accept topology: primary/exclusive, echo it back, and silently do nothing
#284
Closed
opened 2026-08-17 12:31:12 +00:00 by enricobuehler
·
0 comments
No Branch/Tag Specified
main
feat/installer-v2-ship
feat/installer-v2-client
feat/installer-v2-tui
feat/gamescope-multiuser-isolation
feat/installer-v2-engine
worktree-omarchy-client-theme
release/v0.34.0
docs/stale-support-claims
fix/openapi-spec-drift
worktree-sc2-usb-macos
pr-425-gapfix
worktree-host-actions
worktree-omarchy-installer-gaps
worktree-docs-universal-installer
worktree-keep-host-audio-parity
worktree-standby-sink-investigation
worktree-security-review-fixes
worktree-abr-dscp-default
worktree-abr-control-loop
worktree-abr-transmission-plane
worktree-pyrowave-forces-auto
worktree-web-console-native-identity
worktree-abr-encode-downdriver
worktree-gamescope-exclusive-panel-off
worktree-bitrate-picker
worktree-fix-mic-tap-format-abort
worktree-release-0313-recut
ci-skia-download-retry
worktree-audio-devnode-orphans
worktree-gamescope-rebuild-keeps-hdr
worktree-gamescope-idled-handback
worktree-hevc-idr-storm-coalesce
worktree-gamestream-pad-heartbeat
worktree-steam-prelaunch-latch
worktree-release-0312-prep
worktree-firewall-program-scoped-rules
worktree-blackscreen-data-plane-source-ip
worktree-fix-frozen-local-ip
worktree-android-pad-mapping-regression
worktree-android-console-extra-keys
worktree-data-plane-firewall-and-delivery-truth
worktree-android-gamepad-ui-and-corner
worktree-android-pad-hid-remap
worktree-gamestream-xbox-hid-parity
worktree-release-next-prep
worktree-win-client-installer
worktree-kwin-vout-enable-repair
worktree-wp4-install-script
docs-wp2-to-main
worktree-docs-wp0-wp1-anti-drift
worktree-kwin-vout-failed-permanent
worktree-android-asc-hdr-dataspace
worktree-console-controllers-page
worktree-gamepad-probe-stack
worktree-agents-md-setup
worktree-android-skia-console
worktree-android-asc-presenter
worktree-win-teardown-abort
worktree-audio-hires-default-on
worktree-console-ui-aa
worktree-pr270-review-fixes
worktree-console-ui-overhaul
worktree-hires-audio-pcm
worktree-audio-stutter-fixes
worktree-ds-pad-sink-pro-audio
worktree-console-diagnostics
worktree-ds-inhibit-storm
worktree-security-review-2026-08-15-fixes
worktree-pairing-friendly-device-name
worktree-shield-select-back-quit
worktree-android-canary-open-testing
fix-host-cer-alias-null-key
worktree-azure-trusted-signing
worktree-audio-soft-limit-gain
worktree-gamescope-exclusive-dpms
fix/playnite-launcher-resolve
worktree-macos-mic-rebuild-loop
worktree-hyprland-cursor-mode-negotiation
worktree-hd2-idle-recording-default
worktree-steam-art-root-windows
worktree-android-aaudio-shield-silence
worktree-unpair-all-button
worktree-appletv-present-depth
worktree-av1-level-sentinel
worktree-nix-plugin-runner-resolve
worktree-release-0280
worktree-console-plugin-update-all
worktree-flatpak-skia-099-pin
worktree-debian-ubuntu-support
worktree-wowlan-support
worktree-decky-shortcut-dup
worktree-vk-level-gate-clamp
worktree-edition-2024
worktree-win-sleep-blockers
worktree-rt-gpu-priority-defaults
worktree-black-stream-fixes
worktree-edid-lock-toggle
worktree-gate-double-arm-fix
chore/rust-safety-programme
worktree-console-pinned-profile-library
worktree-blackscreen-fixes
build/web-silence-rollup-directive-warnings
worktree-android-console-visual-refresh
worktree-nixos-capped-compositor-exe-denied
worktree-release-0270
worktree-dm-helper-diagnosis
worktree-gamescope-pin-bump-nobara
worktree-notes-capsysnice-correction
worktree-bazzite-docs-warning
worktree-kwin-capability-identification
worktree-gamescope-rpm-deb-builddeps
worktree-pyrowave-wire-dead-code
worktree-release-0260
worktree-cursor-composite-hardening
worktree-library-settings-origin-split
worktree-native-decode-m0
worktree-july-rpm-and-cursor
worktree-presenter-cadence-wp1
worktree-decky-brand-name
worktree-win-amd-decoder-order
worktree-stall-ride-through
fix/pad-audio-wasapi-module-path
feat/android-pad-audio
worktree-adl-emul-probe
worktree-haptics-m12-dry
worktree-haptics-m9-richfb
worktree-haptics-m11-settings
worktree-apple-store-screenshots
worktree-decky-slim-rework
worktree-appstore-copy
worktree-haptics-m10-wire
worktree-haptics-m8-proto
worktree-haptics-m7-windows
worktree-haptics-m6-presenter
worktree-wire-mtu-resilience
worktree-haptics-m5-android
worktree-haptics-m4-apple
worktree-haptics-m3-rumble-engine
worktree-android-presenter-023-triage
worktree-vdisplay-resume-recovery
worktree-kwin-vout-demirror
fix/web-console-sweep
fix/windows-web-console-lifecycle
chore/windows-rerender-semantics
fix/pf-encode-phase8
fix/pf-encode-phase7
feat/cursor-channel
feat/desktop-mouse-mode
feat/plugin-kit
fix/network-split-standing-latency
fix/windows-msix-arm64-and-manifest
fix/encode-medium-tier
fix/encode-rfi-taint-and-oob
fix/encode-init-leak-and-twin-drift
fix/encode-teardown-uaf
feat/pyrowave-windows
fix/ubuntu-2404-host-deb
fix/ios-archive-provisioning
merge/first-frame-latency
feat/shared-clipboard-v2
feat/apple-live-activities-widgets
debug/touch-finger-logging
feat/shared-clipboard
midstream-resize
v0.34.0
v0.33.0
v0.32.0
v0.31.4
sdk-v0.1.6
v0.31.3
v0.31.2
v0.31.1
plugin-kit-v0.4.4
v0.31.0
sdk-v0.1.5
plugin-kit-v0.4.3
v0.30.0
plugin-kit-v0.4.2
v0.29.0
v0.28.1
v0.28.0
plugin-kit-v0.4.1
v0.27.0
v0.26.0
plugin-kit-v0.4.0
sdk-v0.1.4
plugin-kit-v0.3.3
sdk-v0.1.3
plugin-kit-v0.3.2
v0.25.0
plugin-kit-v0.3.1
plugin-kit-v0.3.0
v0.24.0
v0.23.0
v0.22.3
v0.22.2
v0.22.1
v0.22.0
v0.21.0
v0.20.1
v0.20.0
plugin-kit-v0.2.0
v0.19.2
v0.19.1
v0.19.0
v0.18.0
v0.17.2
v0.17.1
v0.17.0
v0.16.0
v0.15.0
v0.14.0
v0.13.0
v0.12.0
v0.11.0
v0.10.1
v0.10.0
v0.9.2
v0.9.1
v0.9.0
v0.8.4
v0.8.3
v0.8.2
v0.8.1
v0.8.0
v0.7.4
v0.7.3
v0.7.2
v0.7.1
v0.7.0
v0.6.0
v0.5.1
v0.5.0
v0.4.2
v0.4.1
v0.4.0
v0.3.1
v0.3.0
v0.2.1
v0.2.0
v0.1.1
v0.1.0
Labels
No items
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: unom/punktfunk#284
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Split out of #283, which fixed the symptom an operator actually hits (library launches opening on the physical head) but deliberately left the topology axis unimplemented.
The state today
Topologyhas three concrete levels —extend,primary,exclusive— plusauto. Five backends apply them. Two do not: Hyprland and wlroots/sway accept the setting, the management API echoes it back as the session's effective topology, and the backend drops it with a warning:This is sweep item 13.18 (
punktfunk-planning/design/pf-vdisplay-sweep.md). Worth being precise about what landed for it: the item asked for the axis to stop being silently dropped, and the shipped fix was the warning only. The behaviour was never implemented, and the checkbox reading as addressed is part of why this is easy to lose track of.Why it bites harder than "an unimplemented setting"
resolve_topologymakesauto— the default — resolve toExclusiveon any host without aPUNKTFUNK_COMPOSITORpin:Hyprland and sway are auto-detected, so they are not pinned, so the default policy on every such box is an Exclusive that does nothing. The console shows Exclusive,
/display/statereports Exclusive, and the box behaves as Extend. The docs' own per-backend table saysPrimaryis "⚠️ treated as Extend" andExclusiveis "⏳ following release", so the documented intent is already that these should land.What "implemented" means here
punktfunk-planning/design/pf-vdisplay-sweep.md§5.2 already specifies the mapping, and calls it "new, small":swaymsg output <phys> disable+ re-enable on teardownSo the work is:
primary— genuinely unsupported on both: Wayland has no primary-output concept, and Hyprland has only a focused monitor. The honest implementation is to keep treating it as extend, but say so once per create rather than lumping it in withexclusive(#283's focus claim is arguably already the closest thing toprimarythese compositors can express).exclusive— disable the non-managed heads for the session and restore them on teardown.hyprctl keyword monitor <name>,disable/swaymsg output <name> disable.Constraints worth carrying over from the backends that shipped it
hyprctl -j monitors alllists disabled heads too (that is whylist_monitorsusesall), so the state is readable; on Hyprland,keyword monitorsets a runtime override, so restoring means re-applying the head's own mode/position/scale/transform rather than assuming ahyprctl reloadis safe — reload would also drop the monitor rule for our headless output and any other runtime keyword the operator set.keep_alive+exclusiveleaves the physical monitors dark after disconnect. Already documented as intentional for a dedicated box; it becomes true for two more backends here.Not blocked on, but relevant
Nothing restores the operator's previously-focused monitor at teardown either (
OutputGuard::droponly removes the output, and the compositor then picks a replacement head). That is a smaller sibling gap and would naturally be fixed alongside the exclusive restore path.Validation
Hyprland can be exercised headless in a transient scope, no GPU session and no host build needed — this is how #283's focus contract was confirmed on Hyprland 0.56.2:
⚠️ Hyprland does not always clean its instance dir up on stop — it can leave a socket-less
$XDG_RUNTIME_DIR/hypr/<sig>/, which is the same directory the host discovers signatures from. Remove it after a probe.sway has no on-glass coverage in the fleet at all (
.21has Hyprland but nosway/swaymsg;.138is the NixOS Hyprland box). The wlroots half of #283 shipped unverified for that reason, and the same gap applies to anything done here — §5.2's own status notes list wlrootsexclusiveas "needs a Sway box". Standing up one is arguably a prerequisite.