Remember the internal monitor's position across clamshell recoveryFix clamshell remember internal position - #10664
Open
Roriz wants to merge 2 commits into
Open
Conversation
Hyprland's position="auto" is order-dependent, not identity-based: it appends a newly re-enabled output after whatever else is already positioned. Docking (lid closed + external active) disables the internal panel via a reload, leaving the external monitor as the sole active output at 0x0. Undocking re-enables the internal panel with "auto" again, but by then the external monitor already occupies the first slot, so the internal panel gets appended after it -- silently swapping their left/right arrangement on every dock/undock cycle. Extend the existing scale-remembering pattern (remember_internal_scale / SCALE_STATE) to position: capture the internal panel's live x/y right before disabling it, and prefer that remembered value over "auto" on recovery, behind the existing configured-rule check so an explicit per-output rule still wins. A machine that has never docked still falls back to "auto" exactly as before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Extend the coverage added in the previous commit with the edge cases worth nailing down before this touches a live desktop's monitor state: - Negative coordinates round-trip (a monitor above/left of the origin). - A corrupted or injection-crafted position state file is validated on read and never forwarded into the generated hyprctl eval string, mirroring the omacom#8129 hardening for the internal connector name. - A non-integer reported position is never remembered in the first place. - A manual internal-monitor disable keeps the clamshell layer from touching scale or position at all. - A poll tick re-running disable_internal while already docked does not clobber the remembered value with a disabled panel's empty read. - Two successive dock/undock cycles track a rearranged position without leaking a stale one from the first cycle. - A live scale-drift correction (panel never disabled) carries the remembered position instead of slipping back to "auto". - A configured position variable reference, and the catch-all rule's own position, are both confirmed against precedence: a rule specific to the internal output wins, a remembered value beats the catch-all, and the catch-all's position is never read for the internal panel. Also made the hyprctl stub list an external monitor alongside the internal one, like real `hyprctl monitors all -j` output, so every case in the file exercises the by-name jq selection instead of a single-monitor array that could never expose a selection bug. Verified these fail without the previous commit's fix (reverted the script only, kept the new tests: fails immediately on "clamshell disable remembers internal position"). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's wrong?
Undock a laptop and the internal panel can come back on the wrong side of the external monitor.
The panel was at
0x0, to the left of the external. Close the lid, work docked, open it again, and it now sits on the right, with every window that was on it.Why
On clamshell entry the script disables the panel. On exit it re-enables the panel with
position = "auto", because the shippedmonitors.luahas no rule naming the internal output, soread_monitor_positionfinds nothing and falls back toauto.autoplaces a panel after whatever is already positioned, rather than putting it back where it was. The external monitor never went down, so it keeps0x0and the returning panel goes after it. Hyprland recomputes the layout instead of restoring it, and with the external already placed, the result differs from before.@mokkabonna measured the same ordering on #7326, where two externals "effectively switched sides" after a scale change.
The fix: save and restore
Read the panel's real position from the compositor just before it goes down, and put it back when it comes up.
read_monitor_positionnow tries a rule for the internal output, then the saved position, thenauto. The new step sits between the two that were already there.Nothing here reconstructs the layout. It reads no more config than before and adds no fallback chain. It records the position the panel actually had, from
hyprctl monitors, while that value still exists, and hands the same value back on recovery.The source is the compositor, not
monitors.lua, so there is no config evaluation to replicate. Whateverhyprctlreported for the panel is what goes back. A machine that has never docked has no saved value and behaves as it does today.Scope
The production diff is 38 added lines with no changed lines: one constant, three functions, one
ifblock, and one call. Every existing code path is byte-identical.It does not touch:
omarchy-hyprland-monitor-scaling, which is the other half of Internal monitor position cannot be made to stick: clamshell watcher and Display panel scaling both re-apply position = "auto" #7326 and belongs in Fix: Use relative positioning (auto-right) in multi-monitor defaults to prevent scaling cursor traps #8362 / Fix monitor scaling on per-output rules, and three defects the other fixes share #8300References #7326 rather than closing it. That issue also covers the scaling path, which this PR leaves alone.