Skip to content

Commit

Permalink
fix(skia): make UIElement.HitTest strictly stronger than UIElement.Is…
Browse files Browse the repository at this point in the history
…ViewHit
  • Loading branch information
ramezgerges committed Aug 15, 2024
1 parent f3de6ac commit d9aa625
Show file tree
Hide file tree
Showing 11 changed files with 28 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/Uno.UI.Composition/Composition/ShapeVisual.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ internal override void Paint(in PaintingSession session)
return shape;
}

/// <remarks>This does NOT take the clipping into account.</remarks>
internal virtual bool HitTest(Point point)
/// <inheritdoc />
internal override bool HitTest(Point point)
{
if (_shapes is null)
{
Expand Down
4 changes: 4 additions & 0 deletions src/Uno.UI.Composition/Composition/Visual.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using Windows.Foundation;
using SkiaSharp;
using Uno.Extensions;
using Uno.UI.Composition;
Expand Down Expand Up @@ -344,6 +345,9 @@ private PaintingSession CreateLocalSession(in PaintingSession parentSession)
return session;
}

/// <remarks>This does NOT take the clipping into account.</remarks>
internal virtual bool HitTest(Point point) => false;

[Flags]
internal enum VisualFlags : byte
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ partial void InitializePartial()
private protected override ShapeVisual CreateElementVisual() => Compositor.GetSharedCompositor().CreateBorderVisual();
#endif

internal override bool IsViewHit() => ((IBorderInfoProvider)this).IsViewHit();

Brush IBorderInfoProvider.Background => Background;

BackgroundSizing IBorderInfoProvider.BackgroundSizing => BackgroundSizing.InnerBorderEdge;
Expand Down
12 changes: 1 addition & 11 deletions src/Uno.UI/UI/Xaml/Controls/Border/Border.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,17 +322,7 @@ protected override void OnBackgroundChanged(DependencyPropertyChangedEventArgs e

internal override bool CanHaveChildren() => true;

internal override bool IsViewHit() => IsViewHitImpl(this);

internal static bool IsViewHitImpl(FrameworkElement element)
{
_Debug.Assert(element is Panel
|| element is Border
|| element is ContentPresenter
);

return element.Background != null;
}
internal override bool IsViewHit() => ((IBorderInfoProvider)this).IsViewHit();

#if !UNO_HAS_BORDER_VISUAL
private void UpdateBorder() => BorderRenderer.Update();
Expand Down
2 changes: 2 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/Border/IBorderInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ internal partial interface IBorderInfoProvider
#if UNO_HAS_BORDER_VISUAL
BorderVisual BorderVisual { get; }
#endif

bool IsViewHit() => Background != null || BorderBrush != null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ protected override Size MeasureOverride(Size size)

internal override bool CanHaveChildren() => true;

internal override bool IsViewHit() => Border.IsViewHitImpl(this);
internal override bool IsViewHit() => ((IBorderInfoProvider)this).IsViewHit();

/// <summary>
/// Registers the provided native element in the native shell
Expand Down
2 changes: 2 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/Page/Page.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ private void UpdateBorder()
}
#endif

internal override bool IsViewHit() => ((IBorderInfoProvider)this).IsViewHit();

protected internal virtual void OnNavigatedFrom(NavigationEventArgs e) { }

protected internal virtual void OnNavigatedTo(NavigationEventArgs e) { }
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/Controls/Panel/Panel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ private protected void OnBackgroundSizingChangedInnerPanel(DependencyPropertyCha
#endif
}

internal override bool IsViewHit() => Border.IsViewHitImpl(this);
internal override bool IsViewHit() => ((IBorderInfoProvider)this).IsViewHit();

#if !UNO_HAS_BORDER_VISUAL
private void UpdateBorder() => _borderRenderer.Update();
Expand Down
3 changes: 3 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/Popup/PopupPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,7 @@ internal override bool IsViewHit()

return Popup?.IsLightDismissEnabled ?? false;
}

// This shouldn't be needed, see the above comment in IsViewHit
internal override bool HitTest(Point point) => IsViewHit();
}
2 changes: 2 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/TextBlock/TextVisual.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,7 @@ internal override void Paint(in PaintingSession session)
owner.Inlines.Draw(in session);
}
}

internal override bool HitTest(Point point) => new Rect(Offset.X, Offset.Y, Size.X, Size.Y).Contains(point);
}
}
16 changes: 8 additions & 8 deletions src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -662,12 +656,18 @@ 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
// 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 (e.g. imagine
// elementHitTestVisibility != Visible, but element.HitTest returns true).
global::System.Diagnostics.Debug.Assert(elementHitTestVisibility == HitTestability.Visible);

TRACE($"> LEAF! ({element.GetDebugName()} is the OriginalSource) | stale branch: {stale?.ToString() ?? "-- none --"}");
return (element, stale);
}
Expand Down

0 comments on commit d9aa625

Please sign in to comment.