-
Notifications
You must be signed in to change notification settings - Fork 708
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
fix(skia): make UIElement.HitTest strictly stronger than UIElement.IsViewHit #17948
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -296,4 +296,10 @@ internal override bool IsViewHit() | |
|
||
return Popup?.IsLightDismissEnabled ?? false; | ||
} | ||
|
||
// This shouldn't be needed, but due to the way we implement Popups, we might | ||
// need to make Popups not hit-testable even if the PopupPanel has a Background. | ||
#if __SKIA__ | ||
internal override bool HitTest(Point point) => IsViewHit(); | ||
#endif | ||
} | ||
Comment on lines
+300
to
305
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really feeling comfortable with this. I'd personally prefer if we still keep the HitTestability.Visible check in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do agree that is weird ... why we cannot rely on the Also in all cases, please remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relying on Visual here is probably buggy due to bugs in popup implementation itself that will need to be their own separate work. In this case, For now, the only place we know it's not stronger is PopupPanel, and this PR forces it to be strongly by basically just calling IsViewHit. (btw, if we proceeded with this PR, it will be a better idea to |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -501,12 +501,6 @@ internal static (UIElement? element, Branch? stale) SearchDownForTopMostElementA | |
clippingBounds = clippingBounds.IntersectWith(transformToElement.Transform(clip)) ?? default; | ||
} | ||
TRACE($"- clipping (absolute): {clippingBounds.ToDebugString()}"); | ||
|
||
// The region where the current element draws itself. | ||
// Be aware that children might be out of this rendering bounds if no clipping defined. | ||
// This is expressed in the window (absolute) coordinate space. | ||
var renderingBounds = transformToElement.Transform(new Rect(new Point(), element.LayoutSlotWithMarginsAndAlignments.Size)).IntersectWith(clippingBounds) ?? Rect.Empty; | ||
TRACE($"- rendering (absolute): {renderingBounds.ToDebugString()}"); | ||
#else | ||
// First compute the transformation between the element and its parent coordinate space | ||
var matrix = Matrix3x2.Identity; | ||
|
@@ -662,12 +656,19 @@ internal static (UIElement? element, Branch? stale) SearchDownForTopMostElementA | |
// We didn't find any child at the given position, validate that element can be touched, | ||
// and the position is in actual bounds(which might be different than the clipping bounds) | ||
#if __SKIA__ | ||
if (element.HitTest(transformToElement.Inverse().Transform(testPosition)) && renderingBounds.Contains(testPosition)) | ||
if (element.HitTest(transformToElement.Inverse().Transform(testPosition))) | ||
#else | ||
|
||
if (elementHitTestVisibility == HitTestability.Visible && renderingBounds.Contains(testPosition)) | ||
#endif | ||
{ | ||
// UIElement.HitTest should be a stronger condition than elementHitTestVisibility == HitTestability.Visible | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UIElement.HitTest just does Visual hit testing, which isn't aware of whether the UIElement's background is NULL or not. Aren't we creating transparent background in both cases? Also, what if the user gets the Visual and modifies the background, in this case they are not the same. I tend to think we should really restore There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if it's the case so far, but the |
||
// On WASM we match the native-element hit-testability (i.e. the `pointer-events` css property) to the | ||
// HitTestVisibility of the corresponding managed element, so if we implement UIElement.HitTest for WASM | ||
// in the future, this assertion makes sure that we're not regressing. If at some point | ||
// elementHitTestVisibility != Visible but element.HitTest returns true, then this would break WASM | ||
// hit-testing because `pointer-events` will be `none`, but element.HitTest is true. | ||
global::System.Diagnostics.Debug.Assert(elementHitTestVisibility == HitTestability.Visible); | ||
|
||
TRACE($"> LEAF! ({element.GetDebugName()} is the OriginalSource) | stale branch: {stale?.ToString() ?? "-- none --"}"); | ||
return (element, stale); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may change behavior on non-Skia. It was already not correct behavior, but now will be incorrect in a different way, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could guard this with
#if __SKIA__
, but the change makes sense in general I think, so I would say it's better to change the behaviour on non-skia targets even if it's still not accurate.