-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Ignore child margin when positioning a popup #18827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Ignore child margin when positioning a popup #18827
Conversation
9ebc173
to
c3aea3e
Compare
You can test this PR using the following package version. |
Avoids drop shadows and other out-of-bounds visual effects from affecting popup positioning
c3aea3e
to
fc669e4
Compare
Sorry, we can't change PopupPositionerParameters and ManagedPopupPositioner logic, it was designed specifically to mirros xdg_positioner protocol, so we can have Wayland support in the future. |
i. e. those are the only values we can pass to the OS window system when using wayland: IPopupPositioner is meant to have a managed implementation (which positions the popup according to specified parameters) and Wayland-specific implementation that simply passed those through. So, check if logic required for your change could be implemented by adjusting positioner parameters before passing them to positioner. |
So our only option is to adjust Horizontal/VerticalOffset properties before passing these to the positioner. Right? |
This can be part of Popup.cs logic and not IPopupHost, since all the popup-like controls have been already rewriten to use Popup internally. That includes Tooltip. IPopupHost itself is going to be a private api eventually. |
What you are asking for is difficult, if it's possible at all. The positioner both calculates the position and applies it in one operation. Because we want the position to be calculated with popup size A, but then to apply a different size and position, we have no choice but to execute during the positioner's operation. We can't give the positioner the deflated size and add an offset because the positioner could have flipped, slid, or squashed the popup in an unpredictable way, and this would cause the offset to have the wrong effect in many cases. I think the only way this will work is if we give the deflated bounds to the positioner, and then intercept the window bounds update which comes out of it. If we want to do this in an XDG-compatible way, this means intercepting a platform message in each platform implementation. Then hoping that we don't get a flicker or any other glitch when we immediately alter the window position that was just set. I'm probably not the first person to point out that restricting the feature set of every platform to the feature set of one platform which isn't even supported yet doesn't seem wise... |
Before making a decision on this, we'll need to check what can be done about Wayland. Maybe it's possible to have content outside of the rect that's being positioned, e. g. However, to make changes into the positioner interface we'll need to
Once that happens, we can change the API and maybe even backport the implementation into 11.x. |
This PR brings an overlooked aspect of WPF's popup positioning to Avalonia. The margins of a popup's child are now ignored when positioning the popup, but still count toward the popup's size. This enables the child's margin to be used as a drawing surface for out-of-bounds effects like drop shadows, without affecting the child's final position.
This means that a popup with a child margin now sits closer to the target, and can also fit into smaller gaps without being repositioned.
What is the current behavior?
WPF:
Avalonia:
See #18810 for the XAML which generates the screenshots above.
What is the updated/expected behavior with this PR?
Note that on desktop platforms the margin area is part of the popup window, and so cannot be clicked through to reach the target window. WPF behaves in the same way, and if Microsoft couldn't make click-through work then I don't think I will fare any better! There may be a solution on other desktop platforms but I've not done any investigation into this.
If overlay popups are used then the popup margin (and any effects drawn within it) can be clicked through, the same as with any other Avalonia visual.
How was the solution implemented (if it's not obvious)?
A new property has been added:
PopupPositionerParameters.Deflate
. We deflate the popup size by this amount when calculating a position, then inflate the returned bounds by the same amount before generating popup geometry. Render scaling is accounted for.Changes to the margin of the popup child now trigger repositioning of the popup, even if the overall size didn't change.
Checklist
Breaking changes
If the popup child's margin actually was intended to affect the popup's position, the UI author will have to wrap the child in a new panel/grid/decorator without a margin to restore their intended popup position.
Obsoletions / Deprecations
None.
Fixed issues
Fixes #18810