Repository navigation
fix(PopoverHost): keep dropdown panels on screen (right-align to trigger, flip, clamp, follow resizes) - #446
Open
lucianoltx wants to merge 1 commit into
Open
lucianoltx wants to merge 1 commit into
lucianoltx wants to merge 1 commit into
Conversation
Icon-only triggers (the device picker in app rows) sit at the far right of the menu bar popup, which itself hugs the screen edge, so the left-aligned NSPanel routinely ran past the right edge and was clipped: device names unreadable and the Multi toggle unreachable. - right-align the panel with its trigger when it would overflow to the right - flip it above the trigger when there is no room below - clamp to the visible frame of the screen containing the trigger's center - recompute the trigger's screen frame on every placement, so the panel follows its parent window if that window moves while the panel is open - re-run placement on content resize (setContentSize keeps the bottom-left origin, so a growing panel used to creep upward) and on async Auto Layout resizes of the NSHostingView Verified with a headless AppKit harness (4 scenarios): the original code places the panel 208pt off screen for a trigger at the right edge; the patched code keeps it within an 8pt margin, right-aligned to the trigger, anchored through resizes and parent-window moves.
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.
Summary
The per-app device picker (and any other
PopoverHostdropdown) is positioned left-aligned with its trigger without looking at the screen. Icon-only triggers sit at the far right of the menu bar popup, and the popup itself hugs the menu bar icon near the screen edge, so the panel routinely ran past the right edge and was clipped — device names unreadable, "Multi" toggle unreachable.Fixes #399, fixes #391, fixes #338, fixes #325.
What changes (single file:
PopoverHost.swift)visibleFrameof the screen containing the trigger's center (multi-monitor safe; excludes menu bar and Dock).updateContent(using the intended size:setContentSizekeeps the bottom-left origin and, in my testing,panel.frame.sizeis not yet updated at that point, so re-clamping with the old size leaves a growing panel off screen) and onNSWindow.didResizeNotification(NSHostingView can resize the panel asynchronously through Auto Layout).Evidence
Verified with a small headless AppKit harness that compiles
PopoverHost.swiftalone and drivesCoordinator.showPanel/updateContentagainst a borderless window placed like the menu bar popup (4 scenarios, 14 checks):maxX= 1928 on a 1728-wide screen (208 pt off screen), still off screen after content growsminY= −118Also tested by hand on macOS 26.5.2 (MacBook Pro 16", built-in display): Spotify → globe → picker fully visible; System Audio / built-in speakers / Bluetooth headphones all selectable.
Relation to #412
#412 also clamps this panel as part of a 12-file batch. This PR is a focused, single-file alternative that additionally keeps the panel attached to its trigger, handles the async resize path, and follows a moved parent window. Happy to close this one if #412 lands first, or rebase on it.