Browse Source

Merge branch 'master' into fixes/Warnings/Nullable/iOS

pull/10190/head
Max Katz 4 years ago
committed by GitHub
parent
commit
d047e21828
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      samples/IntegrationTestApp/MainWindow.axaml
  2. 10
      src/Avalonia.Base/AvaloniaObject.cs
  3. 4
      src/Avalonia.Base/Data/Core/IndexerNodeBase.cs
  4. 4
      src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
  5. 27
      src/Avalonia.Base/Layout/LayoutInformation.cs
  6. 3
      src/Avalonia.Base/Layout/Layoutable.cs
  7. 5
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
  8. 8
      src/Avalonia.Base/StyledElement.cs
  9. 24
      src/Avalonia.Base/Utilities/WeakEvents.cs
  10. 2
      src/Avalonia.Base/Visual.cs
  11. 1
      src/Avalonia.Base/composition-schema.xml
  12. 22
      src/Avalonia.Controls/Automation/Peers/SliderAutomationPeer.cs
  13. 5
      src/Avalonia.Controls/Primitives/AdornerLayer.cs
  14. 10
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  15. 39
      src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
  16. 6
      src/Avalonia.Controls/Slider.cs
  17. 2
      src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml
  18. 4
      src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs
  19. 3
      src/Avalonia.OpenGL/GlInterface.cs
  20. 1
      src/Avalonia.OpenGL/IGlContext.cs
  21. 4
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
  22. 65
      src/Windows/Avalonia.Win32/Automation/AutomationNode.cs
  23. 35
      src/Windows/Avalonia.Win32/Automation/RootAutomationNode.cs
  24. 35
      tests/Avalonia.IntegrationTests.Appium/SliderTests.cs
  25. 81
      tests/Avalonia.RenderTests/Controls/AdornerTests.cs
  26. BIN
      tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_False.expected.png
  27. 0
      tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_True.expected.png
  28. BIN
      tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_False.expected.png
  29. 0
      tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_True.expected.png

3
samples/IntegrationTestApp/MainWindow.axaml

@ -153,6 +153,9 @@
</StackPanel>
</Grid>
</TabItem>
<TabItem Header="SliderTab">
<Slider VerticalAlignment="Top" Name="Slider" Value="30"/>
</TabItem>
</TabControl>
</DockPanel>
</Window>

10
src/Avalonia.Base/AvaloniaObject.cs

@ -664,14 +664,12 @@ namespace Avalonia
/// <param name="property">The property that has changed.</param>
/// <param name="oldValue">The old property value.</param>
/// <param name="newValue">The new property value.</param>
/// <param name="priority">The priority of the binding that produced the value.</param>
protected void RaisePropertyChanged<T>(
DirectPropertyBase<T> property,
Optional<T> oldValue,
BindingValue<T> newValue,
BindingPriority priority = BindingPriority.LocalValue)
T oldValue,
T newValue)
{
RaisePropertyChanged(property, oldValue, newValue, priority, true);
RaisePropertyChanged(property, oldValue, newValue, BindingPriority.LocalValue, true);
}
/// <summary>
@ -720,7 +718,7 @@ namespace Avalonia
/// <returns>
/// True if the value changed, otherwise false.
/// </returns>
protected bool SetAndRaise<T>(AvaloniaProperty<T> property, ref T field, T value)
protected bool SetAndRaise<T>(DirectPropertyBase<T> property, ref T field, T value)
{
VerifyAccess();

4
src/Avalonia.Base/Data/Core/IndexerNodeBase.cs

@ -22,7 +22,7 @@ namespace Avalonia.Data.Core
if (target is INotifyPropertyChanged inpc)
{
WeakEvents.PropertyChanged.Subscribe(inpc, this);
WeakEvents.ThreadSafePropertyChanged.Subscribe(inpc, this);
}
ValueChanged(GetValue(target));
@ -39,7 +39,7 @@ namespace Avalonia.Data.Core
if (target is INotifyPropertyChanged inpc)
{
WeakEvents.PropertyChanged.Unsubscribe(inpc, this);
WeakEvents.ThreadSafePropertyChanged.Unsubscribe(inpc, this);
}
}
}

4
src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs

@ -160,7 +160,7 @@ namespace Avalonia.Data.Core.Plugins
var inpc = GetReferenceTarget() as INotifyPropertyChanged;
if (inpc != null)
WeakEvents.PropertyChanged.Unsubscribe(inpc, this);
WeakEvents.ThreadSafePropertyChanged.Unsubscribe(inpc, this);
}
private object? GetReferenceTarget()
@ -185,7 +185,7 @@ namespace Avalonia.Data.Core.Plugins
var inpc = GetReferenceTarget() as INotifyPropertyChanged;
if (inpc != null)
WeakEvents.PropertyChanged.Subscribe(inpc, this);
WeakEvents.ThreadSafePropertyChanged.Subscribe(inpc, this);
}
}
}

27
src/Avalonia.Base/Layout/LayoutInformation.cs

@ -0,0 +1,27 @@
namespace Avalonia.Layout;
/// <summary>
/// Provides access to layout information of a control.
/// </summary>
public static class LayoutInformation
{
/// <summary>
/// Gets the available size constraint passed in the previous layout pass.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>Previous control measure constraint, if any.</returns>
public static Size? GetPreviousMeasureConstraint(Layoutable control)
{
return control.PreviousMeasure;
}
/// <summary>
/// Gets the control bounds used in the previous layout arrange pass.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>Previous control arrange bounds, if any.</returns>
public static Rect? GetPreviousArrangeBounds(Layoutable control)
{
return control.PreviousArrange;
}
}

3
src/Avalonia.Base/Layout/Layoutable.cs

@ -323,6 +323,9 @@ namespace Avalonia.Layout
set { SetValue(UseLayoutRoundingProperty, value); }
}
/// <summary>
/// Gets the available size passed in the previous layout pass, if any.
/// </summary>
internal Size? PreviousMeasure => _previousMeasure;
/// <summary>

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

@ -48,7 +48,8 @@ namespace Avalonia.Rendering.Composition.Server
{
canvas.PostTransform = Matrix.Identity;
canvas.Transform = Matrix.Identity;
canvas.PushClip(AdornedVisual._combinedTransformedClipBounds);
if (AdornerIsClipped)
canvas.PushClip(AdornedVisual._combinedTransformedClipBounds);
}
var transform = GlobalTransformMatrix;
canvas.PostTransform = MatrixUtils.ToMatrix(transform);
@ -74,7 +75,7 @@ namespace Avalonia.Rendering.Composition.Server
canvas.PopGeometryClip();
if (ClipToBounds && !HandlesClipToBounds)
canvas.PopClip();
if (AdornedVisual != null)
if (AdornedVisual != null && AdornerIsClipped)
canvas.PopClip();
if(Opacity != 1)
canvas.PopOpacity();

8
src/Avalonia.Base/StyledElement.cs

@ -524,13 +524,7 @@ namespace Avalonia
NotifyResourcesChanged();
}
#nullable disable
RaisePropertyChanged(
ParentProperty,
new Optional<StyledElement>(old),
new BindingValue<StyledElement>(Parent),
BindingPriority.LocalValue);
#nullable enable
RaisePropertyChanged(ParentProperty, old, Parent);
}
}

24
src/Avalonia.Base/Utilities/WeakEvents.cs

@ -2,6 +2,7 @@ using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Input;
using Avalonia.Threading;
namespace Avalonia.Utilities;
@ -20,15 +21,30 @@ public class WeakEvents
});
/// <summary>
/// Represents PropertyChanged event from <see cref="INotifyPropertyChanged"/>
/// Represents PropertyChanged event from <see cref="INotifyPropertyChanged"/> with auto-dispatching to the UI thread
/// </summary>
public static readonly WeakEvent<INotifyPropertyChanged, PropertyChangedEventArgs>
PropertyChanged = WeakEvent.Register<INotifyPropertyChanged, PropertyChangedEventArgs>(
ThreadSafePropertyChanged = WeakEvent.Register<INotifyPropertyChanged, PropertyChangedEventArgs>(
(s, h) =>
{
PropertyChangedEventHandler handler = (_, e) => h(s, e);
bool unsubscribed = false;
PropertyChangedEventHandler handler = (_, e) =>
{
if (Dispatcher.UIThread.CheckAccess())
h(s, e);
else
Dispatcher.UIThread.Post(() =>
{
if (!unsubscribed)
h(s, e);
});
};
s.PropertyChanged += handler;
return () => s.PropertyChanged -= handler;
return () =>
{
unsubscribed = true;
s.PropertyChanged -= handler;
};
});

2
src/Avalonia.Base/Visual.cs

@ -573,7 +573,7 @@ namespace Avalonia
/// <param name="newParent">The new visual parent.</param>
protected virtual void OnVisualParentChanged(Visual? oldParent, Visual? newParent)
{
RaisePropertyChanged(VisualParentProperty, oldParent, newParent, BindingPriority.LocalValue);
RaisePropertyChanged(VisualParentProperty, oldParent, newParent);
}
internal override ParametrizedLogger? GetBindingWarningLogger(

1
src/Avalonia.Base/composition-schema.xml

@ -26,6 +26,7 @@
<Property Name="Scale" Type="Vector3" DefaultValue="new Vector3(1, 1, 1)" Animated="true"/>
<Property Name="TransformMatrix" Type="Matrix4x4" DefaultValue="Matrix4x4.Identity" Animated="true"/>
<Property Name="AdornedVisual" Type="CompositionVisual?" Internal="true" />
<Property Name="AdornerIsClipped" Type="bool" Internal="true" />
<Property Name="OpacityMaskBrush" Type="Avalonia.Media.IBrush?" Internal="true" />
</Object>
<Object Name="CompositionContainerVisual" Inherits="CompositionVisual"/>

22
src/Avalonia.Controls/Automation/Peers/SliderAutomationPeer.cs

@ -0,0 +1,22 @@
using Avalonia.Automation.Peers;
namespace Avalonia.Controls.Automation.Peers
{
public class SliderAutomationPeer : RangeBaseAutomationPeer
{
public SliderAutomationPeer(Slider owner) : base(owner)
{
}
override protected string GetClassNameCore()
{
return "Slider";
}
override protected AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Slider;
}
}
}

5
src/Avalonia.Controls/Primitives/AdornerLayer.cs

@ -279,8 +279,11 @@ namespace Avalonia.Controls.Primitives
private void UpdateAdornedElement(Visual adorner, Visual? adorned)
{
if (adorner.CompositionVisual != null)
{
adorner.CompositionVisual.AdornedVisual = adorned?.CompositionVisual;
adorner.CompositionVisual.AdornerIsClipped = GetIsClipEnabled(adorner);
}
var info = adorner.GetValue(s_adornedElementInfoProperty);
if (info != null)

10
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -345,10 +345,7 @@ namespace Avalonia.Controls.Primitives
if (_oldSelectedItems != SelectedItems)
{
RaisePropertyChanged(
SelectedItemsProperty,
new Optional<IList?>(_oldSelectedItems),
new BindingValue<IList?>(SelectedItems));
RaisePropertyChanged(SelectedItemsProperty, _oldSelectedItems, SelectedItems);
_oldSelectedItems = SelectedItems;
}
}
@ -909,10 +906,7 @@ namespace Avalonia.Controls.Primitives
else if (e.PropertyName == nameof(InternalSelectionModel.WritableSelectedItems) &&
_oldSelectedItems != (Selection as InternalSelectionModel)?.SelectedItems)
{
RaisePropertyChanged(
SelectedItemsProperty,
new Optional<IList?>(_oldSelectedItems),
new BindingValue<IList?>(SelectedItems));
RaisePropertyChanged(SelectedItemsProperty, _oldSelectedItems, SelectedItems);
_oldSelectedItems = SelectedItems;
}
else if (e.PropertyName == nameof(ISelectionModel.Source))

39
src/Avalonia.Controls/RelativePanel.AttachedProperties.cs

@ -1,37 +1,30 @@
using Avalonia.Layout;
using Avalonia.Threading;
namespace Avalonia.Controls
{
public partial class RelativePanel
{
private static void OnAlignPropertiesChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
if (d is Layoutable layoutable && layoutable.Parent is Layoutable layoutableParent)
{
layoutableParent.InvalidateArrange();
}
}
static RelativePanel()
{
ClipToBoundsProperty.OverrideDefaultValue<RelativePanel>(true);
AboveProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignBottomWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignBottomWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignHorizontalCenterWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignHorizontalCenterWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignLeftWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignLeftWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignRightWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignRightWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignTopWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignTopWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignVerticalCenterWithPanelProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AlignVerticalCenterWithProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
BelowProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
LeftOfProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
RightOfProperty.Changed.AddClassHandler<Layoutable>(OnAlignPropertiesChanged);
AffectsParentArrange<RelativePanel>(
AlignLeftWithPanelProperty, AlignLeftWithProperty, LeftOfProperty,
AlignRightWithPanelProperty, AlignRightWithProperty, RightOfProperty,
AlignTopWithPanelProperty, AlignTopWithProperty, AboveProperty,
AlignBottomWithPanelProperty, AlignBottomWithProperty, BelowProperty,
AlignHorizontalCenterWithPanelProperty, AlignHorizontalCenterWithProperty,
AlignVerticalCenterWithPanelProperty, AlignVerticalCenterWithProperty);
AffectsParentMeasure<RelativePanel>(
AlignLeftWithPanelProperty, AlignLeftWithProperty, LeftOfProperty,
AlignRightWithPanelProperty, AlignRightWithProperty, RightOfProperty,
AlignTopWithPanelProperty, AlignTopWithProperty, AboveProperty,
AlignBottomWithPanelProperty, AlignBottomWithProperty, BelowProperty,
AlignHorizontalCenterWithPanelProperty, AlignHorizontalCenterWithProperty,
AlignVerticalCenterWithPanelProperty, AlignVerticalCenterWithProperty);
}
/// <summary>

6
src/Avalonia.Controls/Slider.cs

@ -10,6 +10,7 @@ using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Utilities;
using Avalonia.Automation;
using Avalonia.Controls.Automation.Peers;
namespace Avalonia.Controls
{
@ -380,6 +381,11 @@ namespace Avalonia.Controls
}
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new SliderAutomationPeer(this);
}
/// <inheritdoc />
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{

2
src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml

@ -16,6 +16,8 @@
<StackPanel Orientation="Horizontal" Spacing="1">
<Button Margin="0,0,2,0"
Classes="textBoxClearButton"
Theme="{StaticResource SimpleTextBoxClearButtonTheme}"
Focusable="False"
ToolTip.Tip="Clear"
Cursor="Hand"
Command="{Binding $parent[TextBox].Clear}"

4
src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs

@ -103,13 +103,13 @@ namespace Avalonia.Diagnostics.ViewModels
public HorizontalAlignment HorizontalAlignment
{
get => _horizontalAlignment;
private set => RaiseAndSetIfChanged(ref _horizontalAlignment, value);
set => RaiseAndSetIfChanged(ref _horizontalAlignment, value);
}
public VerticalAlignment VerticalAlignment
{
get => _verticalAlignment;
private set => RaiseAndSetIfChanged(ref _verticalAlignment, value);
set => RaiseAndSetIfChanged(ref _verticalAlignment, value);
}
public bool HasPadding { get; }

3
src/Avalonia.OpenGL/GlInterface.cs

@ -73,9 +73,6 @@ namespace Avalonia.OpenGL
[GetProcAddress("glFinish")]
public partial void Finish();
[GetProcAddress("glGetIntegerv")]
public partial void GetIntegerv(int name, out int rv);
[GetProcAddress("glGenFramebuffers")]
public partial void GenFramebuffers(int count, int* res);

1
src/Avalonia.OpenGL/IGlContext.cs

@ -12,7 +12,6 @@ namespace Avalonia.OpenGL
int SampleCount { get; }
int StencilSize { get; }
IDisposable MakeCurrent();
IDisposable EnsureCurrent();
bool IsSharedWith(IGlContext context);
bool CanCreateSharedContext { get; }
IGlContext? CreateSharedContext(IEnumerable<GlVersion>? preferredVersions = null);

4
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs

@ -121,7 +121,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
{
if (_reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc)
{
WeakEvents.PropertyChanged.Unsubscribe(inpc, this);
WeakEvents.ThreadSafePropertyChanged.Unsubscribe(inpc, this);
}
}
@ -138,7 +138,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
private void SubscribeToChanges()
{
if (_reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc)
WeakEvents.PropertyChanged.Subscribe(inpc, this);
WeakEvents.ThreadSafePropertyChanged.Subscribe(inpc, this);
}
}

65
src/Windows/Avalonia.Win32/Automation/AutomationNode.cs

@ -20,7 +20,6 @@ namespace Avalonia.Win32.Automation
IRawElementProviderSimple,
IRawElementProviderSimple2,
IRawElementProviderFragment,
IRawElementProviderAdviseEvents,
IInvokeProvider
{
private static Dictionary<AutomationProperty, UiaPropertyId> s_propertyMap = new()
@ -47,14 +46,31 @@ namespace Avalonia.Win32.Automation
private static ConditionalWeakTable<AutomationPeer, AutomationNode> s_nodes = new();
private readonly int[] _runtimeId;
private int _raiseFocusChanged;
private int _raisePropertyChanged;
public AutomationNode(AutomationPeer peer)
{
_runtimeId = new int[] { 3, GetHashCode() };
Peer = peer;
s_nodes.Add(peer, this);
peer.ChildrenChanged += Peer_ChildrenChanged;
peer.PropertyChanged += Peer_PropertyChanged;
}
private void Peer_ChildrenChanged(object? sender, EventArgs e)
{
ChildrenChanged();
}
private void Peer_PropertyChanged(object? sender, AutomationPropertyChangedEventArgs e)
{
if (s_propertyMap.TryGetValue(e.Property, out var id))
{
UiaCoreProviderApi.UiaRaiseAutomationPropertyChangedEvent(
this,
(int)id,
e.OldValue as IConvertible,
e.NewValue as IConvertible);
}
}
public AutomationPeer Peer { get; protected set; }
@ -86,14 +102,6 @@ namespace Avalonia.Win32.Automation
0);
}
public void PropertyChanged(AutomationProperty property, object? oldValue, object? newValue)
{
if (_raisePropertyChanged > 0 && s_propertyMap.TryGetValue(property, out var id))
{
UiaCoreProviderApi.UiaRaiseAutomationPropertyChangedEvent(this, (int)id, oldValue, newValue);
}
}
[return: MarshalAs(UnmanagedType.IUnknown)]
public virtual object? GetPatternProvider(int patternId)
{
@ -188,32 +196,6 @@ namespace Avalonia.Win32.Automation
void IRawElementProviderSimple2.ShowContextMenu() => InvokeSync(() => Peer.ShowContextMenu());
void IInvokeProvider.Invoke() => InvokeSync((AAP.IInvokeProvider x) => x.Invoke());
void IRawElementProviderAdviseEvents.AdviseEventAdded(int eventId, int[] properties)
{
switch ((UiaEventId)eventId)
{
case UiaEventId.AutomationPropertyChanged:
++_raisePropertyChanged;
break;
case UiaEventId.AutomationFocusChanged:
++_raiseFocusChanged;
break;
}
}
void IRawElementProviderAdviseEvents.AdviseEventRemoved(int eventId, int[] properties)
{
switch ((UiaEventId)eventId)
{
case UiaEventId.AutomationPropertyChanged:
--_raisePropertyChanged;
break;
case UiaEventId.AutomationFocusChanged:
--_raiseFocusChanged;
break;
}
}
protected void InvokeSync(Action action)
{
if (Dispatcher.UIThread.CheckAccess())
@ -266,15 +248,6 @@ namespace Avalonia.Win32.Automation
throw new NotSupportedException();
}
protected void RaiseFocusChanged(AutomationNode? focused)
{
if (_raiseFocusChanged > 0)
{
UiaCoreProviderApi.UiaRaiseAutomationEvent(
focused,
(int)UiaEventId.AutomationFocusChanged);
}
}
private AutomationNode? GetRoot()
{

35
src/Windows/Avalonia.Win32/Automation/RootAutomationNode.cs

@ -10,8 +10,11 @@ namespace Avalonia.Win32.Automation
{
[RequiresUnreferencedCode("Requires .NET COM interop")]
internal class RootAutomationNode : AutomationNode,
IRawElementProviderFragmentRoot
IRawElementProviderFragmentRoot,
IRawElementProviderAdviseEvents
{
private int _raiseFocusChanged;
public RootAutomationNode(AutomationPeer peer)
: base(peer)
{
@ -42,6 +45,36 @@ namespace Avalonia.Win32.Automation
return GetOrCreate(focus);
}
void IRawElementProviderAdviseEvents.AdviseEventAdded(int eventId, int[] properties)
{
switch ((UiaEventId)eventId)
{
case UiaEventId.AutomationFocusChanged:
++_raiseFocusChanged;
break;
}
}
void IRawElementProviderAdviseEvents.AdviseEventRemoved(int eventId, int[] properties)
{
switch ((UiaEventId)eventId)
{
case UiaEventId.AutomationFocusChanged:
--_raiseFocusChanged;
break;
}
}
protected void RaiseFocusChanged(AutomationNode? focused)
{
if (_raiseFocusChanged > 0)
{
UiaCoreProviderApi.UiaRaiseAutomationEvent(
focused,
(int)UiaEventId.AutomationFocusChanged);
}
}
public void FocusChanged(object? sender, EventArgs e)
{
RaiseFocusChanged(GetOrCreate(Peer.GetFocus()));

35
tests/Avalonia.IntegrationTests.Appium/SliderTests.cs

@ -0,0 +1,35 @@
using System;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Interactions;
using Xunit;
namespace Avalonia.IntegrationTests.Appium
{
[Collection("Default")]
public class SliderTests
{
private readonly AppiumDriver<AppiumWebElement> _session;
public SliderTests(TestAppFixture fixture)
{
_session = fixture.Session;
var tabs = _session.FindElementByAccessibilityId("MainTabs");
var tab = tabs.FindElementByName("SliderTab");
tab.Click();
}
[Fact]
public void Changes_Value_When_Clicking_Increase_Button()
{
var slider = _session.FindElementByAccessibilityId("Slider");
// slider.Text gets the Slider value
Assert.True(double.Parse(slider.Text) == 30);
new Actions(_session).Click(slider).Perform();
Assert.Equal(50, Math.Round(double.Parse(slider.Text)));
}
}
}

81
tests/Avalonia.RenderTests/Controls/AdornerTests.cs

@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -18,56 +19,70 @@ public class AdornerTests : TestBase
{
}
[Fact]
public async Task Focus_Adorner_Is_Properly_Clipped()
async Task CheckAdornedContent(Control content, Control adorned, Control adorner, int width = 200, int height = 200,
[CallerMemberName] string testName = "")
{
Border adorned;
var tree = new Decorator
{
Child = new VisualLayerManager
{
Child = new Border
{
Background = Brushes.Red,
Padding = new Thickness(10, 50, 10,10),
Child = new Border()
{
Background = Brushes.White,
ClipToBounds = true,
Padding = new Thickness(0, -30, 0, 0),
Child = adorned = new Border
{
Background = Brushes.Green,
VerticalAlignment = VerticalAlignment.Top,
Height = 100,
Width = 50
}
}
}
Child = content
},
Width = 200,
Height = 200
};
var adorner = new Border
{
BorderThickness = new Thickness(2),
BorderBrush = Brushes.Black
Width = width,
Height = height
};
var size = new Size(tree.Width, tree.Height);
tree.Measure(size);
tree.Arrange(new Rect(size));
adorned.AttachedToVisualTree += delegate
{
AdornerLayer.SetAdornedElement(adorner, adorned);
AdornerLayer.GetAdornerLayer(adorned)!.Children.Add(adorner);
};
tree.Measure(size);
tree.Arrange(new Rect(size));
await RenderToFile(tree);
CompareImages(skipImmediate: true);
await RenderToFile(tree, testName: testName);
CompareImages(skipImmediate: true, testName: testName);
}
[Theory,
InlineData(true),
InlineData(false)
]
public async Task Focus_Adorner_Is_Properly_Clipped(bool clip)
{
Border adorned;
var content = new Border
{
Background = Brushes.Red,
Padding = new Thickness(10, 50, 10, 10),
Child = new Border()
{
Background = Brushes.White,
ClipToBounds = true,
Padding = new Thickness(0, -30, 0, 0),
Child = adorned = new Border
{
Background = Brushes.Green,
VerticalAlignment = VerticalAlignment.Top,
Height = 100,
Width = 50
}
}
};
var adorner = new Border
{
BorderThickness = new Thickness(2),
BorderBrush = Brushes.Black
};
if (!clip)
AdornerLayer.SetIsClipEnabled(adorner, false);
await CheckAdornedContent(content, adorned, adorner,
testName: "Focus_Adorner_Is_Properly_Clipped_Clip_" + clip);
}
}

BIN
tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_False.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

0
tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png → tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_True.expected.png

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 673 B

BIN
tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_False.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

0
tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png → tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped_Clip_True.expected.png

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 673 B

Loading…
Cancel
Save