diff --git a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
index 549815a036..251a177432 100644
--- a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
+++ b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
@@ -81,7 +81,7 @@ namespace Avalonia.Android.Platform
var renderScaling = _topLevel.RenderScaling;
var inset = insets.GetInsets(
- (DisplayEdgeToEdge ?
+ (_displayEdgeToEdge ?
WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars() |
WindowInsetsCompat.Type.DisplayCutout() :
0) | WindowInsetsCompat.Type.Ime());
@@ -91,8 +91,8 @@ namespace Avalonia.Android.Platform
return new Thickness(inset.Left / renderScaling,
inset.Top / renderScaling,
inset.Right / renderScaling,
- (imeInset.Bottom > 0 && ((_usesLegacyLayouts && !DisplayEdgeToEdge) || !_usesLegacyLayouts) ?
- imeInset.Bottom - navBarInset.Bottom :
+ (imeInset.Bottom > 0 && ((_usesLegacyLayouts && !_displayEdgeToEdge) || !_usesLegacyLayouts) ?
+ imeInset.Bottom - (_displayEdgeToEdge ? 0 : navBarInset.Bottom) :
inset.Bottom) / renderScaling);
}
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/CustomDrawOperation.cs b/src/Avalonia.Base/Rendering/SceneGraph/CustomDrawOperation.cs
index ff2616bfe4..8f5ccb4e51 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/CustomDrawOperation.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/CustomDrawOperation.cs
@@ -13,7 +13,7 @@ namespace Avalonia.Rendering.SceneGraph
Custom = custom;
}
- public override bool HitTest(Point p) => Custom.HitTest(p);
+ public override bool HitTestTransformed(Point p) => Custom.HitTest(p);
public override void Render(IDrawingContextImpl context)
{
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/DrawOperation.cs b/src/Avalonia.Base/Rendering/SceneGraph/DrawOperation.cs
index 5b93cd8cfc..786ce28d06 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/DrawOperation.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/DrawOperation.cs
@@ -37,5 +37,20 @@ namespace Avalonia.Rendering.SceneGraph
}
public Matrix Transform { get; }
+
+ public sealed override bool HitTest(Point p)
+ {
+ if (Transform.IsIdentity)
+ return HitTestTransformed(p);
+
+ if (!Transform.HasInverse)
+ return false;
+
+ var transformedPoint = Transform.Invert().Transform(p);
+
+ return HitTestTransformed(transformedPoint);
+ }
+
+ public abstract bool HitTestTransformed(Point p);
}
}
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/EllipseNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/EllipseNode.cs
index d5f0270cb2..0a2b74e46a 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/EllipseNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/EllipseNode.cs
@@ -43,7 +43,7 @@ namespace Avalonia.Rendering.SceneGraph
public override void Render(IDrawingContextImpl context) => context.DrawEllipse(Brush, Pen, Rect);
- public override bool HitTest(Point p)
+ public override bool HitTestTransformed(Point p)
{
var center = Rect.Center;
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
index e1f79e0e10..22fc49d30e 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
@@ -65,6 +65,6 @@ namespace Avalonia.Rendering.SceneGraph
}
///
- public override bool HitTest(Point p) => Rect.Rect.ContainsExclusive(p);
+ public override bool HitTestTransformed(Point p) => Rect.Rect.ContainsExclusive(p);
}
}
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs
index f64a3e845d..48af3b0e6b 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs
@@ -64,7 +64,7 @@ namespace Avalonia.Rendering.SceneGraph
}
///
- public override bool HitTest(Point p)
+ public override bool HitTestTransformed(Point p)
{
return (Brush != null && Geometry.FillContains(p)) ||
(Pen != null && Geometry.StrokeContains(Pen, p));
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
index 5b975e29e1..b4e28dc254 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
@@ -53,7 +53,7 @@ namespace Avalonia.Rendering.SceneGraph
}
///
- public override bool HitTest(Point p) => Bounds.ContainsExclusive(p);
+ public override bool HitTestTransformed(Point p) => Bounds.ContainsExclusive(p);
public override void Dispose()
{
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
index dd9787e8d1..ac946cc8b2 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
@@ -94,7 +94,7 @@ namespace Avalonia.Rendering.SceneGraph
}
///
- public override bool HitTest(Point p) => DestRect.ContainsExclusive(p);
+ public override bool HitTestTransformed(Point p) => DestRect.ContainsExclusive(p);
public override void Dispose()
{
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs
index 61bffc3260..1ac6cffe0a 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs
@@ -66,7 +66,7 @@ namespace Avalonia.Rendering.SceneGraph
context.DrawLine(Pen, P1, P2);
}
- public override bool HitTest(Point p)
+ public override bool HitTestTransformed(Point p)
{
var halfThickness = Pen.Thickness / 2;
var minX = Math.Min(P1.X, P2.X) - halfThickness;
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/OpacityMaskNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/OpacityMaskNode.cs
index b0584038a8..1c79a67944 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/OpacityMaskNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/OpacityMaskNode.cs
@@ -30,7 +30,7 @@ namespace Avalonia.Rendering.SceneGraph
///
- public override bool HitTest(Point p) => false;
+ public override bool HitTestTransformed(Point p) => false;
///
/// Determines if this draw operation equals another.
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/RectangleNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/RectangleNode.cs
index 94f61df47d..e85992be34 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/RectangleNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/RectangleNode.cs
@@ -74,7 +74,7 @@ namespace Avalonia.Rendering.SceneGraph
public override void Render(IDrawingContextImpl context) => context.DrawRectangle(Brush, Pen, Rect, BoxShadows);
///
- public override bool HitTest(Point p)
+ public override bool HitTestTransformed(Point p)
{
if (Brush != null)
{
diff --git a/src/Browser/Avalonia.Browser/WindowingPlatform.cs b/src/Browser/Avalonia.Browser/WindowingPlatform.cs
index 88e378bd79..be6e28f5cb 100644
--- a/src/Browser/Avalonia.Browser/WindowingPlatform.cs
+++ b/src/Browser/Avalonia.Browser/WindowingPlatform.cs
@@ -14,11 +14,11 @@ namespace Avalonia.Browser
private bool _signaled;
private static KeyboardDevice? s_keyboard;
- public IWindowImpl CreateWindow() => throw new NotSupportedException();
+ public IWindowImpl CreateWindow() => throw new NotSupportedException("Browser doesn't support windowing platform. In order to display a single-view content, set ISingleViewApplicationLifetime.MainView.");
IWindowImpl IWindowingPlatform.CreateEmbeddableWindow()
{
- throw new NotImplementedException();
+ throw new NotImplementedException("Browser doesn't support embeddable windowing platform.");
}
public ITrayIconImpl? CreateTrayIcon()
diff --git a/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs b/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
index 9d810fa110..34878bd08d 100644
--- a/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
@@ -74,6 +74,22 @@ namespace Avalonia.Base.UnitTests.Rendering.SceneGraph
geometryNode.HitTest(new Point());
}
+ [Fact]
+ public void HitTest_RectangleNode_With_Transform_Hits()
+ {
+ var geometry = Mock.Of();
+ var geometryNode = new RectangleNode(
+ Matrix.CreateTranslation(20,20),
+ Brushes.Black,
+ null,
+ new RoundedRect(new Rect(0,0,10,10)),
+ default);
+
+ var actual = geometryNode.HitTest(new Point(25,25));
+
+ Assert.True(actual);
+ }
+
private class TestRectangleDrawOperation : RectangleNode
{
public TestRectangleDrawOperation(Rect bounds, Matrix transform, Pen pen)
@@ -82,7 +98,7 @@ namespace Avalonia.Base.UnitTests.Rendering.SceneGraph
}
- public override bool HitTest(Point p) => false;
+ public override bool HitTestTransformed(Point p) => false;
public override void Render(IDrawingContextImpl context) { }
}