Browse Source

Ignore Opacity for hit-testing purposes

pull/9831/head
Nikita Tsukanov 3 years ago
parent
commit
78b4c6a96e
  1. 13
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
  2. 33
      tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs

13
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs

@ -162,8 +162,14 @@ namespace Avalonia.Rendering.Composition.Server
EffectiveOpacity = Opacity * (Parent?.EffectiveOpacity ?? 1);
IsVisibleInFrame = _parent?.IsVisibleInFrame != false && Visible && EffectiveOpacity > 0.04 && !_isBackface &&
!_combinedTransformedClipBounds.IsDefault;
IsHitTestVisibleInFrame = _parent?.IsHitTestVisibleInFrame != false
&& Visible
&& !_isBackface
&& !_combinedTransformedClipBounds.IsDefault;
IsVisibleInFrame = IsHitTestVisibleInFrame
&& _parent?.IsVisibleInFrame != false
&& EffectiveOpacity > 0.04;
if (wasVisible != IsVisibleInFrame || positionChanged)
{
@ -187,7 +193,7 @@ namespace Avalonia.Rendering.Composition.Server
readback.Revision = root.Revision;
readback.Matrix = GlobalTransformMatrix;
readback.TargetId = Root.Id;
readback.Visible = IsVisibleInFrame;
readback.Visible = IsHitTestVisibleInFrame;
}
void AddDirtyRect(Rect rc)
@ -248,6 +254,7 @@ namespace Avalonia.Rendering.Composition.Server
}
public bool IsVisibleInFrame { get; set; }
public bool IsHitTestVisibleInFrame { get; set; }
public double EffectiveOpacity { get; set; }
public Rect TransformedOwnContentBounds { get; set; }
public virtual Rect OwnContentBounds => new Rect(0, 0, Size.X, Size.Y);

33
tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs

@ -82,6 +82,39 @@ public class CompositorHitTestingTests : CompositorTestsBase
}
}
[Theory,
InlineData(false, false),
InlineData(true, false),
InlineData(false, true),
InlineData(true, true),
]
public void HitTest_Should_Find_Zero_Opacity_Controls_At_Point(bool parent, bool child)
{
using (var s = new CompositorServices(new Size(200, 200)))
{
Border visible, border;
s.TopLevel.Content = border = new Border
{
Width = 100,
Height = 100,
Background = Brushes.Red,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Opacity = parent ? 0 : 1,
Child = visible = new Border
{
Opacity = child ? 0 : 1,
Background = Brushes.Red,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
}
};
s.AssertHitTest(new Point(100, 100), null, visible, border);
}
}
[Fact]
public void HitTest_Should_Not_Find_Control_Outside_Point()
{

Loading…
Cancel
Save