Displays: mirror-aware layout, backend keep-or-revert guard, duplicate-mode crash fix #67
No reviewers
Labels
No labels
breadbug
bug
displays
enhancement
keybinds
network
phase-1
power
privacy
recovery
search
snapshots
sound
ui
ux
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Breadway/bos-settings!67
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/displays-safety-mirroring"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes BSET-48
Closes BSET-49
Closes BSET-62
What
BSET-62 (crash on DVI outputs). Hyprland reports some modes twice (DVI-I-1 and DVI-I-2: 30 modes, 25 unique). The resolution picker was keyed by the mode string, so Svelte threw each_key_duplicate and the whole Displays section failed to load. The backend now drops repeated modes and repeated output names, keeping order. The frontend also runs compositor lists through
uniqueBybefore any keyed each, so a backend that sends duplicates cannot crash the page. All keyed each blocks on the Displays pages were audited: the others use static lists (SCALES,TURNS,MODES,tabs) or output names, which are now de-duplicated.BSET-49 (mirrors misrepresented).
mirrorOffromhyprctl monitors all -jis the numeric id of the source output ("0" means eDP-1), not a name. The old code used it as a name, so a mirror could never match. It is now resolved to a name, and names, numbers, "none", "" and "-1" are all handled.monitors all, so turned-off outputs are known too.BSET-48 (safeguards). Every change to resolution, scale, rotation, adaptive sync, position (drag) and mirroring goes through a new
DisplayGuardinsrc/src/commands/display_guard.rs, which extends the existing Keep/Revert dialog instead of adding a second one.hyprctl eval(the reply must be "ok") and reads the compositor back to check it matches. On an apply failure or a mismatch it restores the snapshot, checks that too, and reports the error.display-guard-outcomeevent clears it when the backend decides.Commands:
apply_display_layout,keep_display_layout,revert_display_layoutanddisplay_guard_statusreplaceapply_monitor_layoutandpersist_monitor_layout(only Display.svelte used them).Checked
npm ci,npm run check(0 errors, 0 warnings),npm test(all pass, including newuniqueByanddisplayLayouttests),npm run build.cargo fmt --all -- --check,cargo clippy --all-targets --locked -- -D warnings,cargo test --locked(167 passed).src/src/commands/testdata/hyprctl-monitors-all.json). Tests cover: mirror parsing (DVI-I-1 mirrors eDP-1, DVI-I-2 separate with transform 1), duplicate mode removal (25 unique), snapshot and restore planning (mirror sources first, replayed on restore), the no-enabled-display guard, bad mirror layouts, apply failure, a compositor that ignores the change (caught by read-back), keep then nothing reverts, explicit revert, unattended timeout revert from the backend with no frontend involved, revert after timeout, unplug while pending, second change refused while one is pending, exit revert, save failure after Keep, and stopping then restarting a mirror.hl.monitor, so syntax errors or missing keys fail the tests. The guard tests were repeated 60 times with no failures (one early flaky test was fixed: it polled pending instead of the recorded outcome).Not verified live
No hyprctl command was run against a real session and the app was not launched, by design. So these are untested on a real Hyprland 0.56:
hl.monitor({ output = ..., disabled = true })is accepted (only used if a layout ever carries a disabled output; the page itself never turns a display off);hl.monitorwithmirror = "<name>"re-applies an existing mirror without visible flicker, and that a mirror source listed first is really required;RunEvent::Exit).Limit: the deadline lives in the app process. If the app is killed hard (SIGKILL, crash) while a change is pending, nothing can revert it. Closing the window, leaving the page and a normal exit do revert.
Capability changes
Nothing was removed outright. Behaviour that changed or narrowed: