diff --git a/Avalonia.sln b/Avalonia.sln
index 8cb36c1ae4..be80f44ce0 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -100,7 +100,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\EmbedXaml.props = build\EmbedXaml.props
build\HarfBuzzSharp.props = build\HarfBuzzSharp.props
build\ImageSharp.props = build\ImageSharp.props
- build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Microsoft.CSharp.props = build\Microsoft.CSharp.props
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
diff --git a/NOTICE.md b/NOTICE.md
index e97fc654c9..bd26b65d70 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -303,3 +303,34 @@ https://github.com/chromium/chromium
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Flutter
+
+https://github.com/flutter/flutter
+
+//Copyright 2014 The Flutter Authors. All rights reserved.
+
+//Redistribution and use in source and binary forms, with or without modification,
+//are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+//ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS;
+//OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/build/Base.props b/build/Base.props
index 100c9088cd..9ec1c3c2d3 100644
--- a/build/Base.props
+++ b/build/Base.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/JetBrains.Annotations.props b/build/JetBrains.Annotations.props
deleted file mode 100644
index 7bc12cbd84..0000000000
--- a/build/JetBrains.Annotations.props
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/build/System.Memory.props b/build/System.Memory.props
index b36998a780..a413e18927 100644
--- a/build/System.Memory.props
+++ b/build/System.Memory.props
@@ -1,5 +1,5 @@
-
+
diff --git a/nukebuild/DotNetConfigHelper.cs b/nukebuild/DotNetConfigHelper.cs
index eca1e2684d..9d43261616 100644
--- a/nukebuild/DotNetConfigHelper.cs
+++ b/nukebuild/DotNetConfigHelper.cs
@@ -1,5 +1,4 @@
using System.Globalization;
-using JetBrains.Annotations;
using Nuke.Common.Tools.DotNet;
// ReSharper disable ReturnValueOfPureMethodIsNotUsed
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 4a5f5bc96c..9e0fb3f852 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -92,6 +92,9 @@
+
+
+
diff --git a/samples/ControlCatalog/Pages/GesturePage.cs b/samples/ControlCatalog/Pages/GesturePage.cs
new file mode 100644
index 0000000000..ee10f21317
--- /dev/null
+++ b/samples/ControlCatalog/Pages/GesturePage.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Numerics;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.LogicalTree;
+using Avalonia.Markup.Xaml;
+using Avalonia.Rendering.Composition;
+
+namespace ControlCatalog.Pages
+{
+ public class GesturePage : UserControl
+ {
+ private bool _isInit;
+ private float _currentScale;
+
+ public GesturePage()
+ {
+ this.InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+
+ if(_isInit)
+ {
+ return;
+ }
+
+ _isInit = true;
+
+ SetPullHandlers(this.Find("TopPullZone"), false);
+ SetPullHandlers(this.Find("BottomPullZone"), true);
+ SetPullHandlers(this.Find("RightPullZone"), true);
+ SetPullHandlers(this.Find("LeftPullZone"), false);
+
+ var image = this.Find("PinchImage");
+ SetPinchHandlers(image);
+
+ var reset = this.Find
-
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
index 2b715d6a9f..75101dc487 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
@@ -641,7 +641,7 @@ namespace Avalonia.Controls
public Control GetCellContent(DataGridRow dataGridRow)
{
- Contract.Requires(dataGridRow != null);
+ dataGridRow = dataGridRow ?? throw new ArgumentNullException(nameof(dataGridRow));
if (OwningGrid == null)
{
throw DataGridError.DataGrid.NoOwningGrid(GetType());
@@ -659,7 +659,7 @@ namespace Avalonia.Controls
public Control GetCellContent(object dataItem)
{
- Contract.Requires(dataItem != null);
+ dataItem = dataItem ?? throw new ArgumentNullException(nameof(dataItem));
if (OwningGrid == null)
{
throw DataGridError.DataGrid.NoOwningGrid(GetType());
diff --git a/src/Avalonia.Controls.DataGrid/DataGridRows.cs b/src/Avalonia.Controls.DataGrid/DataGridRows.cs
index 6c997f62c1..4d3bccee70 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridRows.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridRows.cs
@@ -16,7 +16,6 @@ using System.Diagnostics;
using System.Linq;
using Avalonia.Data;
using Avalonia.Styling;
-using JetBrains.Annotations;
namespace Avalonia.Controls
{
diff --git a/src/Avalonia.Controls.DataGrid/Primitives/DataGridFrozenGrid.cs b/src/Avalonia.Controls.DataGrid/Primitives/DataGridFrozenGrid.cs
index 9feca71cda..4fd0ca3d26 100644
--- a/src/Avalonia.Controls.DataGrid/Primitives/DataGridFrozenGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/Primitives/DataGridFrozenGrid.cs
@@ -26,7 +26,6 @@ namespace Avalonia.Controls.Primitives
/// true if the grid is frozen; otherwise, false. The default is true.
public static bool GetIsFrozen(Control element)
{
- Contract.Requires(element != null);
return element.GetValue(IsFrozenProperty);
}
@@ -38,7 +37,6 @@ namespace Avalonia.Controls.Primitives
/// is null.
public static void SetIsFrozen(Control element, bool value)
{
- Contract.Requires(element != null);
element.SetValue(IsFrozenProperty, value);
}
}
diff --git a/src/Avalonia.Controls/AppBuilder.cs b/src/Avalonia.Controls/AppBuilder.cs
index 5bcd87162e..cf79fcd1a8 100644
--- a/src/Avalonia.Controls/AppBuilder.cs
+++ b/src/Avalonia.Controls/AppBuilder.cs
@@ -1,4 +1,8 @@
-using Avalonia.Controls;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Linq;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform;
namespace Avalonia
@@ -6,15 +10,244 @@ namespace Avalonia
///
/// Initializes platform-specific services for an .
///
- public sealed class AppBuilder : AppBuilderBase
+ public class AppBuilder
{
+ private static bool s_setupWasAlreadyCalled;
+ private Action? _optionsInitializers;
+ private Func? _appFactory;
+ private IApplicationLifetime? _lifetime;
+
+ ///
+ /// Gets or sets the instance.
+ ///
+ public IRuntimePlatform RuntimePlatform { get; set; }
+
+ ///
+ /// Gets or sets a method to call the initialize the runtime platform services (e. g. AssetLoader)
+ ///
+ public Action RuntimePlatformServicesInitializer { get; private set; }
+
+ ///
+ /// Gets the instance being initialized.
+ ///
+ public Application? Instance { get; private set; }
+
+ ///
+ /// Gets the type of the Instance (even if it's not created yet)
+ ///
+ public Type? ApplicationType { get; private set; }
+
+ ///
+ /// Gets or sets a method to call the initialize the windowing subsystem.
+ ///
+ public Action? WindowingSubsystemInitializer { get; private set; }
+
+ ///
+ /// Gets the name of the currently selected windowing subsystem.
+ ///
+ public string? WindowingSubsystemName { get; private set; }
+
+ ///
+ /// Gets or sets a method to call the initialize the windowing subsystem.
+ ///
+ public Action? RenderingSubsystemInitializer { get; private set; }
+
+ ///
+ /// Gets the name of the currently selected rendering subsystem.
+ ///
+ public string? RenderingSubsystemName { get; private set; }
+
+ ///
+ /// Gets or sets a method to call after the is setup.
+ ///
+ public Action AfterSetupCallback { get; private set; } = builder => { };
+
+
+ public Action AfterPlatformServicesSetupCallback { get; private set; } = builder => { };
+
///
/// Initializes a new instance of the class.
///
public AppBuilder()
- : base(new StandardRuntimePlatform(),
+ : this(new StandardRuntimePlatform(),
builder => StandardRuntimePlatformServices.Register(builder.ApplicationType?.Assembly))
{
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ protected AppBuilder(IRuntimePlatform platform, Action platformServices)
+ {
+ RuntimePlatform = platform;
+ RuntimePlatformServicesInitializer = () => platformServices(this);
+ }
+
+ ///
+ /// Begin configuring an .
+ ///
+ /// The subclass of to configure.
+ /// An instance.
+ public static AppBuilder Configure()
+ where TApp : Application, new()
+ {
+ return new AppBuilder()
+ {
+ ApplicationType = typeof(TApp),
+ // Needed for CoreRT compatibility
+ _appFactory = () => new TApp()
+ };
+ }
+
+ ///
+ /// Begin configuring an .
+ ///
+ /// Factory function for .
+ /// The subclass of to configure.
+ /// is useful for passing of dependencies to .
+ /// An instance.
+ public static AppBuilder Configure(Func appFactory)
+ where TApp : Application
+ {
+ return new AppBuilder()
+ {
+ ApplicationType = typeof(TApp),
+ _appFactory = appFactory
+ };
+ }
+
+ protected AppBuilder Self => this;
+
+ public AppBuilder AfterSetup(Action callback)
+ {
+ AfterSetupCallback = (Action)Delegate.Combine(AfterSetupCallback, callback);
+ return Self;
+ }
+
+
+ public AppBuilder AfterPlatformServicesSetup(Action callback)
+ {
+ AfterPlatformServicesSetupCallback = (Action)Delegate.Combine(AfterPlatformServicesSetupCallback, callback);
+ return Self;
+ }
+
+ public delegate void AppMainDelegate(Application app, string[] args);
+
+ public void Start(AppMainDelegate main, string[] args)
+ {
+ Setup();
+ main(Instance!, args);
+ }
+
+ ///
+ /// Sets up the platform-specific services for the application, but does not run it.
+ ///
+ ///
+ public AppBuilder SetupWithoutStarting()
+ {
+ Setup();
+ return Self;
+ }
+
+ ///
+ /// Sets up the platform-specific services for the application and initialized it with a particular lifetime, but does not run it.
+ ///
+ ///
+ ///
+ public AppBuilder SetupWithLifetime(IApplicationLifetime lifetime)
+ {
+ _lifetime = lifetime;
+ Setup();
+ return Self;
+ }
+
+ ///
+ /// Specifies a windowing subsystem to use.
+ ///
+ /// The method to call to initialize the windowing subsystem.
+ /// The name of the windowing subsystem.
+ /// An instance.
+ public AppBuilder UseWindowingSubsystem(Action initializer, string name = "")
+ {
+ WindowingSubsystemInitializer = initializer;
+ WindowingSubsystemName = name;
+ return Self;
+ }
+
+ ///
+ /// Specifies a rendering subsystem to use.
+ ///
+ /// The method to call to initialize the rendering subsystem.
+ /// The name of the rendering subsystem.
+ /// An instance.
+ public AppBuilder UseRenderingSubsystem(Action initializer, string name = "")
+ {
+ RenderingSubsystemInitializer = initializer;
+ RenderingSubsystemName = name;
+ return Self;
+ }
+
+ ///
+ /// Configures platform-specific options
+ ///
+ public AppBuilder With(T options)
+ {
+ _optionsInitializers += () => { AvaloniaLocator.CurrentMutable.Bind().ToConstant(options); };
+ return Self;
+ }
+
+ ///
+ /// Configures platform-specific options
+ ///
+ public AppBuilder With(Func options)
+ {
+ _optionsInitializers += () => { AvaloniaLocator.CurrentMutable.Bind().ToFunc(options); };
+ return Self;
+ }
+
+ ///
+ /// Sets up the platform-specific services for the .
+ ///
+ private void Setup()
+ {
+ if (RuntimePlatformServicesInitializer == null)
+ {
+ throw new InvalidOperationException("No runtime platform services configured.");
+ }
+
+ if (WindowingSubsystemInitializer == null)
+ {
+ throw new InvalidOperationException("No windowing system configured.");
+ }
+
+ if (RenderingSubsystemInitializer == null)
+ {
+ throw new InvalidOperationException("No rendering system configured.");
+ }
+
+ if (_appFactory == null)
+ {
+ throw new InvalidOperationException("No Application factory configured.");
+ }
+
+ if (s_setupWasAlreadyCalled)
+ {
+ throw new InvalidOperationException("Setup was already called on one of AppBuilder instances");
+ }
+
+ s_setupWasAlreadyCalled = true;
+ _optionsInitializers?.Invoke();
+ RuntimePlatformServicesInitializer();
+ RenderingSubsystemInitializer();
+ WindowingSubsystemInitializer();
+ AfterPlatformServicesSetupCallback(Self);
+ Instance = _appFactory();
+ Instance.ApplicationLifetime = _lifetime;
+ AvaloniaLocator.CurrentMutable.BindToSelf(Instance);
+ Instance.RegisterServices();
+ Instance.Initialize();
+ AfterSetupCallback(Self);
+ Instance.OnFrameworkInitializationCompleted();
+ }
}
}
diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs
deleted file mode 100644
index a100d38d78..0000000000
--- a/src/Avalonia.Controls/AppBuilderBase.cs
+++ /dev/null
@@ -1,244 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Reflection;
-using System.Linq;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Platform;
-
-namespace Avalonia.Controls
-{
- ///
- /// Base class for initializing platform-specific services for an .
- ///
- /// The type of the AppBuilder class itself.
- public abstract class AppBuilderBase where TAppBuilder : AppBuilderBase, new()
- {
- private static bool s_setupWasAlreadyCalled;
- private Action? _optionsInitializers;
- private Func? _appFactory;
- private IApplicationLifetime? _lifetime;
-
- ///
- /// Gets or sets the instance.
- ///
- public IRuntimePlatform RuntimePlatform { get; set; }
-
- ///
- /// Gets or sets a method to call the initialize the runtime platform services (e. g. AssetLoader)
- ///
- public Action RuntimePlatformServicesInitializer { get; private set; }
-
- ///
- /// Gets the instance being initialized.
- ///
- public Application? Instance { get; private set; }
-
- ///
- /// Gets the type of the Instance (even if it's not created yet)
- ///
- public Type? ApplicationType { get; private set; }
-
- ///
- /// Gets or sets a method to call the initialize the windowing subsystem.
- ///
- public Action? WindowingSubsystemInitializer { get; private set; }
-
- ///
- /// Gets the name of the currently selected windowing subsystem.
- ///
- public string? WindowingSubsystemName { get; private set; }
-
- ///
- /// Gets or sets a method to call the initialize the windowing subsystem.
- ///
- public Action? RenderingSubsystemInitializer { get; private set; }
-
- ///
- /// Gets the name of the currently selected rendering subsystem.
- ///
- public string? RenderingSubsystemName { get; private set; }
-
- ///
- /// Gets or sets a method to call after the is setup.
- ///
- public Action AfterSetupCallback { get; private set; } = builder => { };
-
-
- public Action AfterPlatformServicesSetupCallback { get; private set; } = builder => { };
-
- protected AppBuilderBase(IRuntimePlatform platform, Action platformServices)
- {
- RuntimePlatform = platform;
- RuntimePlatformServicesInitializer = () => platformServices((TAppBuilder)this);
- }
-
- ///
- /// Begin configuring an .
- ///
- /// The subclass of to configure.
- /// An instance.
- public static TAppBuilder Configure()
- where TApp : Application, new()
- {
- return new TAppBuilder()
- {
- ApplicationType = typeof(TApp),
- // Needed for CoreRT compatibility
- _appFactory = () => new TApp()
- };
- }
-
- ///
- /// Begin configuring an .
- ///
- /// Factory function for .
- /// The subclass of to configure.
- /// is useful for passing of dependencies to .
- /// An instance.
- public static TAppBuilder Configure(Func appFactory)
- where TApp : Application
- {
- return new TAppBuilder()
- {
- ApplicationType = typeof(TApp),
- _appFactory = appFactory
- };
- }
-
- protected TAppBuilder Self => (TAppBuilder)this;
-
- public TAppBuilder AfterSetup(Action callback)
- {
- AfterSetupCallback = (Action)Delegate.Combine(AfterSetupCallback, callback);
- return Self;
- }
-
-
- public TAppBuilder AfterPlatformServicesSetup(Action callback)
- {
- AfterPlatformServicesSetupCallback = (Action)Delegate.Combine(AfterPlatformServicesSetupCallback, callback);
- return Self;
- }
-
- public delegate void AppMainDelegate(Application app, string[] args);
-
- public void Start(AppMainDelegate main, string[] args)
- {
- Setup();
- main(Instance!, args);
- }
-
- ///
- /// Sets up the platform-specific services for the application, but does not run it.
- ///
- ///
- public TAppBuilder SetupWithoutStarting()
- {
- Setup();
- return Self;
- }
-
- ///
- /// Sets up the platform-specific services for the application and initialized it with a particular lifetime, but does not run it.
- ///
- ///
- ///
- public TAppBuilder SetupWithLifetime(IApplicationLifetime lifetime)
- {
- _lifetime = lifetime;
- Setup();
- return Self;
- }
-
- ///
- /// Specifies a windowing subsystem to use.
- ///
- /// The method to call to initialize the windowing subsystem.
- /// The name of the windowing subsystem.
- /// An instance.
- public TAppBuilder UseWindowingSubsystem(Action initializer, string name = "")
- {
- WindowingSubsystemInitializer = initializer;
- WindowingSubsystemName = name;
- return Self;
- }
-
- ///
- /// Specifies a rendering subsystem to use.
- ///
- /// The method to call to initialize the rendering subsystem.
- /// The name of the rendering subsystem.
- /// An instance.
- public TAppBuilder UseRenderingSubsystem(Action initializer, string name = "")
- {
- RenderingSubsystemInitializer = initializer;
- RenderingSubsystemName = name;
- return Self;
- }
-
- protected virtual bool CheckSetup => true;
-
- ///
- /// Configures platform-specific options
- ///
- public TAppBuilder With(T options)
- {
- _optionsInitializers += () => { AvaloniaLocator.CurrentMutable.Bind().ToConstant(options); };
- return Self;
- }
-
- ///
- /// Configures platform-specific options
- ///
- public TAppBuilder With(Func options)
- {
- _optionsInitializers += () => { AvaloniaLocator.CurrentMutable.Bind().ToFunc(options); };
- return Self;
- }
-
- ///
- /// Sets up the platform-specific services for the .
- ///
- private void Setup()
- {
- if (RuntimePlatformServicesInitializer == null)
- {
- throw new InvalidOperationException("No runtime platform services configured.");
- }
-
- if (WindowingSubsystemInitializer == null)
- {
- throw new InvalidOperationException("No windowing system configured.");
- }
-
- if (RenderingSubsystemInitializer == null)
- {
- throw new InvalidOperationException("No rendering system configured.");
- }
-
- if (_appFactory == null)
- {
- throw new InvalidOperationException("No Application factory configured.");
- }
-
- if (s_setupWasAlreadyCalled && CheckSetup)
- {
- throw new InvalidOperationException("Setup was already called on one of AppBuilder instances");
- }
-
- s_setupWasAlreadyCalled = true;
- _optionsInitializers?.Invoke();
- RuntimePlatformServicesInitializer();
- RenderingSubsystemInitializer();
- WindowingSubsystemInitializer();
- AfterPlatformServicesSetupCallback(Self);
- Instance = _appFactory();
- Instance.ApplicationLifetime = _lifetime;
- AvaloniaLocator.CurrentMutable.BindToSelf(Instance);
- Instance.RegisterServices();
- Instance.Initialize();
- AfterSetupCallback(Self);
- Instance.OnFrameworkInitializationCompleted();
- }
- }
-}
diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
index 757db96799..fde401fb01 100644
--- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
+++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
@@ -200,9 +200,8 @@ namespace Avalonia
{
public static class ClassicDesktopStyleApplicationLifetimeExtensions
{
- public static int StartWithClassicDesktopLifetime(
- this T builder, string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
- where T : AppBuilderBase, new()
+ public static int StartWithClassicDesktopLifetime(
+ this AppBuilder builder, string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
{
var lifetime = new ClassicDesktopStyleApplicationLifetime()
{
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index 2710ac5cc2..cf4beab6d4 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -7,7 +7,6 @@
-
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index f02df2e9c1..a96cfe4690 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -95,19 +95,26 @@ namespace Avalonia.Controls
{
ItemsPanelProperty.OverrideDefaultValue(DefaultPanel);
FocusableProperty.OverrideDefaultValue(true);
- SelectedItemProperty.Changed.AddClassHandler((x, e) => x.SelectedItemChanged(e));
- KeyDownEvent.AddClassHandler((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel);
IsTextSearchEnabledProperty.OverrideDefaultValue(true);
- IsDropDownOpenProperty.Changed.AddClassHandler((x, e) => x.DropdownChanged(e));
}
+ ///
+ /// Occurs after the drop-down (popup) list of the closes.
+ ///
+ public event EventHandler? DropDownClosed;
+
+ ///
+ /// Occurs after the drop-down (popup) list of the opens.
+ ///
+ public event EventHandler? DropDownOpened;
+
///
/// Gets or sets a value indicating whether the dropdown is currently open.
///
public bool IsDropDownOpen
{
- get { return _isDropDownOpen; }
- set { SetAndRaise(IsDropDownOpenProperty, ref _isDropDownOpen, value); }
+ get => _isDropDownOpen;
+ set => SetAndRaise(IsDropDownOpenProperty, ref _isDropDownOpen, value);
}
///
@@ -115,8 +122,8 @@ namespace Avalonia.Controls
///
public double MaxDropDownHeight
{
- get { return GetValue(MaxDropDownHeightProperty); }
- set { SetValue(MaxDropDownHeightProperty, value); }
+ get => GetValue(MaxDropDownHeightProperty);
+ set => SetValue(MaxDropDownHeightProperty, value);
}
///
@@ -124,8 +131,8 @@ namespace Avalonia.Controls
///
protected object? SelectionBoxItem
{
- get { return _selectionBoxItem; }
- set { SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value); }
+ get => _selectionBoxItem;
+ set => SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value);
}
///
@@ -133,8 +140,8 @@ namespace Avalonia.Controls
///
public string? PlaceholderText
{
- get { return GetValue(PlaceholderTextProperty); }
- set { SetValue(PlaceholderTextProperty, value); }
+ get => GetValue(PlaceholderTextProperty);
+ set => SetValue(PlaceholderTextProperty, value);
}
///
@@ -142,8 +149,8 @@ namespace Avalonia.Controls
///
public IBrush? PlaceholderForeground
{
- get { return GetValue(PlaceholderForegroundProperty); }
- set { SetValue(PlaceholderForegroundProperty, value); }
+ get => GetValue(PlaceholderForegroundProperty);
+ set => SetValue(PlaceholderForegroundProperty, value);
}
///
@@ -151,8 +158,8 @@ namespace Avalonia.Controls
///
public ItemVirtualizationMode VirtualizationMode
{
- get { return GetValue(VirtualizationModeProperty); }
- set { SetValue(VirtualizationModeProperty, value); }
+ get => GetValue(VirtualizationModeProperty);
+ set => SetValue(VirtualizationModeProperty, value);
}
///
@@ -160,8 +167,8 @@ namespace Avalonia.Controls
///
public HorizontalAlignment HorizontalContentAlignment
{
- get { return GetValue(HorizontalContentAlignmentProperty); }
- set { SetValue(HorizontalContentAlignmentProperty, value); }
+ get => GetValue(HorizontalContentAlignmentProperty);
+ set => SetValue(HorizontalContentAlignmentProperty, value);
}
///
@@ -169,8 +176,8 @@ namespace Avalonia.Controls
///
public VerticalAlignment VerticalContentAlignment
{
- get { return GetValue(VerticalContentAlignmentProperty); }
- set { SetValue(VerticalContentAlignmentProperty, value); }
+ get => GetValue(VerticalContentAlignmentProperty);
+ set => SetValue(VerticalContentAlignmentProperty, value);
}
///
@@ -182,6 +189,7 @@ namespace Avalonia.Controls
ComboBoxItem.ContentTemplateProperty);
}
+ ///
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
@@ -213,7 +221,12 @@ namespace Avalonia.Controls
IsDropDownOpen = false;
e.Handled = true;
}
- else if (IsDropDownOpen && e.Key == Key.Enter)
+ else if (!IsDropDownOpen && (e.Key == Key.Enter || e.Key == Key.Space))
+ {
+ IsDropDownOpen = true;
+ e.Handled = true;
+ }
+ else if (IsDropDownOpen && (e.Key == Key.Enter || e.Key == Key.Space))
{
SelectFocusedItem();
IsDropDownOpen = false;
@@ -234,7 +247,7 @@ namespace Avalonia.Controls
}
// This part of code is needed just to acquire initial focus, subsequent focus navigation will be done by ItemsControl.
else if (IsDropDownOpen && SelectedIndex < 0 && ItemCount > 0 &&
- (e.Key == Key.Up || e.Key == Key.Down) && IsFocused == true)
+ (e.Key == Key.Up || e.Key == Key.Down) && IsFocused == true)
{
var firstChild = Presenter?.Panel?.Children.FirstOrDefault(c => CanFocus(c));
if (firstChild != null)
@@ -304,12 +317,11 @@ namespace Avalonia.Controls
e.Handled = true;
}
}
+
PseudoClasses.Set(pcPressed, false);
base.OnPointerReleased(e);
-
}
-
///
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
@@ -324,6 +336,22 @@ namespace Avalonia.Controls
_popup.Closed += PopupClosed;
}
+ ///
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ if (change.Property == SelectedItemProperty)
+ {
+ UpdateSelectionBoxItem(change.NewValue);
+ TryFocusSelectedItem();
+ }
+ else if (change.Property == IsDropDownOpenProperty)
+ {
+ PseudoClasses.Set(pcDropdownOpen, change.GetNewValue());
+ }
+
+ base.OnPropertyChanged(change);
+ }
+
protected override AutomationPeer OnCreateAutomationPeer()
{
return new ComboBoxAutomationPeer(this);
@@ -345,6 +373,8 @@ namespace Avalonia.Controls
{
Focus();
}
+
+ DropDownClosed?.Invoke(this, EventArgs.Empty);
}
private void PopupOpened(object? sender, EventArgs e)
@@ -374,6 +404,8 @@ namespace Avalonia.Controls
}
UpdateFlowDirection();
+
+ DropDownOpened?.Invoke(this, EventArgs.Empty);
}
private void IsVisibleChanged(bool isVisible)
@@ -384,12 +416,6 @@ namespace Avalonia.Controls
}
}
- private void SelectedItemChanged(AvaloniaPropertyChangedEventArgs e)
- {
- UpdateSelectionBoxItem(e.NewValue);
- TryFocusSelectedItem();
- }
-
private void TryFocusSelectedItem()
{
var selectedIndex = SelectedIndex;
@@ -489,11 +515,5 @@ namespace Avalonia.Controls
MoveSelection(NavigationDirection.Previous, WrapSelection);
}
}
-
- private void DropdownChanged(AvaloniaPropertyChangedEventArgs e)
- {
- bool newValue = e.GetNewValue();
- PseudoClasses.Set(pcDropdownOpen, newValue);
- }
}
}
diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs
index b8a45e102f..d47a7a7809 100644
--- a/src/Avalonia.Controls/ContentControl.cs
+++ b/src/Avalonia.Controls/ContentControl.cs
@@ -116,14 +116,19 @@ namespace Avalonia.Controls
return false;
}
- private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
+ protected virtual void ContentChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (e.OldValue is ILogical oldChild)
+ UpdateLogicalTree(e.OldValue, e.NewValue);
+ }
+
+ protected void UpdateLogicalTree(object? toRemove, object? toAdd)
+ {
+ if (toRemove is ILogical oldChild)
{
LogicalChildren.Remove(oldChild);
}
- if (e.NewValue is ILogical newChild)
+ if (toAdd is ILogical newChild)
{
LogicalChildren.Add(newChild);
}
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 88c9823952..26db431a0e 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -366,16 +366,29 @@ namespace Avalonia.Controls
{
base.OnAttachedToVisualTreeCore(e);
+ AddHandler(Gestures.HoldingEvent, OnHoldEvent);
+
InitializeIfNeeded();
ScheduleOnLoadedCore();
}
+ private void OnHoldEvent(object? sender, HoldingRoutedEventArgs e)
+ {
+ if(e.HoldingState == HoldingState.Started)
+ {
+ // Trigger ContentRequest when hold has started
+ RaiseEvent(new ContextRequestedEventArgs());
+ }
+ }
+
///
protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTreeCore(e);
+ RemoveHandler(Gestures.HoldingEvent, OnHoldEvent);
+
OnUnloadedCore();
}
diff --git a/src/Avalonia.Controls/LoggingExtensions.cs b/src/Avalonia.Controls/LoggingExtensions.cs
index ef14d0b477..f909ba8714 100644
--- a/src/Avalonia.Controls/LoggingExtensions.cs
+++ b/src/Avalonia.Controls/LoggingExtensions.cs
@@ -8,16 +8,14 @@ namespace Avalonia
///
/// Logs Avalonia events to the sink.
///
- /// The application class type.
/// The app builder instance.
/// The minimum level to log.
/// The areas to log. Valid values are listed in .
/// The app builder instance.
- public static T LogToTrace(
- this T builder,
+ public static AppBuilder LogToTrace(
+ this AppBuilder builder,
LogEventLevel level = LogEventLevel.Warning,
params string[] areas)
- where T : AppBuilderBase, new()
{
Logger.Sink = new TraceLogSink(level, areas);
return builder;
diff --git a/src/Avalonia.Controls/TransitioningContentControl.cs b/src/Avalonia.Controls/TransitioningContentControl.cs
index 70b21b7248..545032befb 100644
--- a/src/Avalonia.Controls/TransitioningContentControl.cs
+++ b/src/Avalonia.Controls/TransitioningContentControl.cs
@@ -71,6 +71,11 @@ public class TransitioningContentControl : ContentControl
}
}
+ protected override void ContentChanged(AvaloniaPropertyChangedEventArgs e)
+ {
+ // We do nothing becuse we should not remove old Content until the animation is over
+ }
+
///
/// Updates the content with transitions.
///
@@ -89,6 +94,8 @@ public class TransitioningContentControl : ContentControl
if (PageTransition != null)
await PageTransition.Start(this, null, true, localToken);
+ UpdateLogicalTree(CurrentContent, content);
+
if (localToken.IsCancellationRequested)
{
return;
diff --git a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs
index eb9f38894d..6239a5120d 100644
--- a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs
+++ b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs
@@ -4,7 +4,6 @@ using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
using Avalonia.Utilities;
-using JetBrains.Annotations;
namespace Avalonia.Controls.Utils
{
diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs
index b71dc6df44..65325aac92 100644
--- a/src/Avalonia.Controls/WindowBase.cs
+++ b/src/Avalonia.Controls/WindowBase.cs
@@ -8,7 +8,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Platform;
-using JetBrains.Annotations;
namespace Avalonia.Controls
{
diff --git a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
index 543d07f958..85605ccd9d 100644
--- a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
+++ b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
@@ -134,12 +134,12 @@ namespace Avalonia.DesignerSupport.Remote
IAvaloniaRemoteTransportConnection ConfigureApp(IAvaloniaRemoteTransportConnection transport, CommandLineArgs args, object obj);
}
- class AppInitializer : IAppInitializer where T : AppBuilderBase, new()
+ class AppInitializer : IAppInitializer
{
public IAvaloniaRemoteTransportConnection ConfigureApp(IAvaloniaRemoteTransportConnection transport,
CommandLineArgs args, object obj)
{
- var builder = (AppBuilderBase)obj;
+ var builder = (AppBuilder)obj;
if (args.Method == Methods.AvaloniaRemote)
builder.UseWindowingSubsystem(() => PreviewerWindowingPlatform.Initialize(transport));
if (args.Method == Methods.Html)
@@ -191,7 +191,7 @@ namespace Avalonia.DesignerSupport.Remote
Log($"Obtaining AppBuilder instance from {builderMethod.DeclaringType.FullName}.{builderMethod.Name}");
var appBuilder = builderMethod.Invoke(null, null);
Log($"Initializing application in design mode");
- var initializer =(IAppInitializer)Activator.CreateInstance(typeof(AppInitializer<>).MakeGenericType(appBuilder.GetType()));
+ var initializer =(IAppInitializer)Activator.CreateInstance(typeof(AppInitializer));
transport = initializer.ConfigureApp(transport, args, appBuilder);
s_transport = transport;
transport.OnMessage += OnTransportMessage;
diff --git a/src/Avalonia.Desktop/AppBuilderDesktopExtensions.cs b/src/Avalonia.Desktop/AppBuilderDesktopExtensions.cs
index 7c4a489328..13a4ac51d2 100644
--- a/src/Avalonia.Desktop/AppBuilderDesktopExtensions.cs
+++ b/src/Avalonia.Desktop/AppBuilderDesktopExtensions.cs
@@ -1,15 +1,13 @@
+using Avalonia.Compatibility;
using Avalonia.Controls;
-using Avalonia.Platform;
+using Avalonia.Logging;
namespace Avalonia
{
public static class AppBuilderDesktopExtensions
{
- public static TAppBuilder UsePlatformDetect(this TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new()
+ public static AppBuilder UsePlatformDetect(this AppBuilder builder)
{
- var os = builder.RuntimePlatform.GetRuntimeInfo().OperatingSystem;
-
// We don't have the ability to load every assembly right now, so we are
// stuck with manual configuration here
// Helpers are extracted to separate methods to take the advantage of the fact
@@ -17,37 +15,39 @@ namespace Avalonia
// Additionally, by having a hard reference to each assembly,
// we verify that the assemblies are in the final .deps.json file
// so .NET Core knows where to load the assemblies from,.
- if (os == OperatingSystemType.WinNT)
+ if (OperatingSystemEx.IsWindows())
{
LoadWin32(builder);
LoadSkia(builder);
}
- else if(os==OperatingSystemType.OSX)
+ else if(OperatingSystemEx.IsMacOS())
{
LoadAvaloniaNative(builder);
LoadSkia(builder);
}
- else
+ else if (OperatingSystemEx.IsLinux())
{
LoadX11(builder);
LoadSkia(builder);
}
+ else
+ {
+ Logger.TryGet(LogEventLevel.Warning, LogArea.Platform)?.Log(builder,
+ "Avalonia.Desktop package was referenced on non-desktop platform or it isn't supported");
+ }
+
return builder;
}
- static void LoadAvaloniaNative(TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new()
+ static void LoadAvaloniaNative(AppBuilder builder)
=> builder.UseAvaloniaNative();
- static void LoadWin32(TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new()
+ static void LoadWin32(AppBuilder builder)
=> builder.UseWin32();
- static void LoadX11(TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new()
+ static void LoadX11(AppBuilder builder)
=> builder.UseX11();
- static void LoadSkia(TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new()
+ static void LoadSkia(AppBuilder builder)
=> builder.UseSkia();
}
}
diff --git a/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs b/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
index fe2dd99100..bc5945441c 100644
--- a/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
+++ b/src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
@@ -24,16 +24,15 @@ namespace Avalonia.Dialogs
}
}
- public static TAppBuilder UseManagedSystemDialogs(this TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new()
+ public static AppBuilder UseManagedSystemDialogs(this AppBuilder builder)
{
builder.AfterSetup(_ =>
AvaloniaLocator.CurrentMutable.Bind().ToSingleton>());
return builder;
}
- public static TAppBuilder UseManagedSystemDialogs(this TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new() where TWindow : Window, new()
+ public static AppBuilder UseManagedSystemDialogs(this AppBuilder builder)
+ where TWindow : Window, new()
{
builder.AfterSetup(_ =>
AvaloniaLocator.CurrentMutable.Bind().ToSingleton>());
diff --git a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs
index b69ea68a76..4624a9c340 100644
--- a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs
+++ b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs
@@ -9,8 +9,7 @@ namespace Avalonia.FreeDesktop
{
public IDisposable Listen(ObservableCollection mountedDrives)
{
- Contract.Requires(mountedDrives != null);
- return new LinuxMountedVolumeInfoListener(ref mountedDrives!);
+ return new LinuxMountedVolumeInfoListener(ref mountedDrives);
}
}
}
diff --git a/src/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs b/src/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs
index cc7d5ef30d..b6bb69b05d 100644
--- a/src/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs
+++ b/src/Avalonia.Headless.Vnc/HeadlessVncPlatformExtensions.cs
@@ -11,11 +11,10 @@ namespace Avalonia
{
public static class HeadlessVncPlatformExtensions
{
- public static int StartWithHeadlessVncPlatform(
- this T builder,
+ public static int StartWithHeadlessVncPlatform(
+ this AppBuilder builder,
string host, int port,
string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
- where T : AppBuilderBase, new()
{
var tcpServer = new TcpListener(host == null ? IPAddress.Loopback : IPAddress.Parse(host), port);
tcpServer.Start();
diff --git a/src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs b/src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
index 8da10fa59b..e7cba13ce0 100644
--- a/src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
+++ b/src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs
@@ -94,8 +94,7 @@ namespace Avalonia.Headless
public static class AvaloniaHeadlessPlatformExtensions
{
- public static T UseHeadless(this T builder, AvaloniaHeadlessPlatformOptions opts)
- where T : AppBuilderBase, new()
+ public static AppBuilder UseHeadless(this AppBuilder builder, AvaloniaHeadlessPlatformOptions opts)
{
if(opts.UseHeadlessDrawing)
builder.UseRenderingSubsystem(HeadlessPlatformRenderInterface.Initialize, "Headless");
diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs
index a5b2ea30cc..6d5925c0ae 100644
--- a/src/Avalonia.Native/AvaloniaNativePlatform.cs
+++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs
@@ -9,23 +9,23 @@ using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
-using JetBrains.Annotations;
using MicroCom.Runtime;
+#nullable enable
namespace Avalonia.Native
{
class AvaloniaNativePlatform : IWindowingPlatform
{
private readonly IAvaloniaNativeFactory _factory;
- private AvaloniaNativePlatformOptions _options;
- private AvaloniaNativeGlPlatformGraphics _platformGl;
+ private AvaloniaNativePlatformOptions? _options;
+ private AvaloniaNativeGlPlatformGraphics? _platformGl;
[DllImport("libAvaloniaNative")]
static extern IntPtr CreateAvaloniaNative();
internal static readonly KeyboardDevice KeyboardDevice = new KeyboardDevice();
- [CanBeNull] internal static Compositor Compositor { get; private set; }
- [CanBeNull] internal static PlatformRenderInterfaceContextManager RenderInterface { get; private set; }
+ internal static Compositor? Compositor { get; private set; }
+ internal static PlatformRenderInterfaceContextManager? RenderInterface { get; private set; }
public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
{
@@ -63,7 +63,7 @@ namespace Avalonia.Native
public void SetupApplicationName()
{
- if (!string.IsNullOrWhiteSpace(Application.Current.Name))
+ if (!string.IsNullOrWhiteSpace(Application.Current!.Name))
{
_factory.MacOptions.SetApplicationTitle(Application.Current.Name);
}
@@ -118,10 +118,13 @@ namespace Avalonia.Native
AvaloniaLocator.CurrentMutable.Bind().ToConstant(renderLoop);
var hotkeys = AvaloniaLocator.Current.GetService();
- hotkeys.MoveCursorToTheStartOfLine.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers));
- hotkeys.MoveCursorToTheStartOfLineWithSelection.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers | hotkeys.SelectionModifiers));
- hotkeys.MoveCursorToTheEndOfLine.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers));
- hotkeys.MoveCursorToTheEndOfLineWithSelection.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers | hotkeys.SelectionModifiers));
+ if (hotkeys is not null)
+ {
+ hotkeys.MoveCursorToTheStartOfLine.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers));
+ hotkeys.MoveCursorToTheStartOfLineWithSelection.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers | hotkeys.SelectionModifiers));
+ hotkeys.MoveCursorToTheEndOfLine.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers));
+ hotkeys.MoveCursorToTheEndOfLineWithSelection.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers | hotkeys.SelectionModifiers));
+ }
if (_options.UseGpu)
{
diff --git a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs
index 189f45d7c8..6613fc09be 100644
--- a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs
+++ b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs
@@ -6,8 +6,7 @@ namespace Avalonia
{
public static class AvaloniaNativePlatformExtensions
{
- public static T UseAvaloniaNative(this T builder)
- where T : AppBuilderBase, new()
+ public static AppBuilder UseAvaloniaNative(this AppBuilder builder)
{
builder.UseWindowingSubsystem(() =>
{
diff --git a/src/Avalonia.Native/Helpers.cs b/src/Avalonia.Native/Helpers.cs
index 764ff789dc..6270cd30a0 100644
--- a/src/Avalonia.Native/Helpers.cs
+++ b/src/Avalonia.Native/Helpers.cs
@@ -1,5 +1,4 @@
using Avalonia.Native.Interop;
-using JetBrains.Annotations;
namespace Avalonia.Native
{
diff --git a/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs b/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs
index 92b2915e2e..1907a3d129 100644
--- a/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs
+++ b/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs
@@ -72,7 +72,6 @@ namespace Avalonia.Native
{
public IDisposable Listen(ObservableCollection mountedDrives)
{
- Contract.Requires(mountedDrives != null);
return new MacOSMountedVolumeInfoListener(mountedDrives);
}
}
diff --git a/src/Avalonia.OpenGL/Egl/EglInterface.cs b/src/Avalonia.OpenGL/Egl/EglInterface.cs
index ad4b55a686..a913c05996 100644
--- a/src/Avalonia.OpenGL/Egl/EglInterface.cs
+++ b/src/Avalonia.OpenGL/Egl/EglInterface.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
+using Avalonia.Compatibility;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
using Avalonia.SourceGenerator;
@@ -24,10 +25,9 @@ namespace Avalonia.OpenGL.Egl
static Func Load()
{
- var os = AvaloniaLocator.Current.GetService().GetRuntimeInfo().OperatingSystem;
- if(os == OperatingSystemType.Linux)
+ if(OperatingSystemEx.IsLinux())
return Load("libEGL.so.1");
- if (os == OperatingSystemType.Android)
+ if (OperatingSystemEx.IsAndroid())
return Load("libEGL.so");
throw new PlatformNotSupportedException();
diff --git a/src/Avalonia.ReactiveUI/AppBuilderExtensions.cs b/src/Avalonia.ReactiveUI/AppBuilderExtensions.cs
index 359da3d7c2..3fde580160 100644
--- a/src/Avalonia.ReactiveUI/AppBuilderExtensions.cs
+++ b/src/Avalonia.ReactiveUI/AppBuilderExtensions.cs
@@ -12,8 +12,7 @@ namespace Avalonia.ReactiveUI
/// scheduler, an activation for view fetcher, a template binding hook. Remember
/// to call this method if you are using ReactiveUI in your application.
///
- public static TAppBuilder UseReactiveUI(this TAppBuilder builder)
- where TAppBuilder : AppBuilderBase, new() =>
+ public static AppBuilder UseReactiveUI(this AppBuilder builder) =>
builder.AfterPlatformServicesSetup(_ => Locator.RegisterResolverCallbackChanged(() =>
{
if (Locator.CurrentMutable is null)
diff --git a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
index 9abcf5d32b..28f8649e2d 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
@@ -50,7 +50,8 @@
Opacity="0"
Fill="{DynamicResource CheckBoxCheckGlyphForegroundUnchecked}"
Stretch="Uniform"
- VerticalAlignment="Center" />
+ VerticalAlignment="Center"
+ FlowDirection="LeftToRight" />
@@ -146,7 +147,6 @@
-
diff --git a/src/Avalonia.X11/Avalonia.X11.csproj b/src/Avalonia.X11/Avalonia.X11.csproj
index 812010a3c3..061c516ef6 100644
--- a/src/Avalonia.X11/Avalonia.X11.csproj
+++ b/src/Avalonia.X11/Avalonia.X11.csproj
@@ -10,10 +10,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.X11/NativeDialogs/Gtk.cs b/src/Avalonia.X11/NativeDialogs/Gtk.cs
index d5eae037a9..4e56ae73cf 100644
--- a/src/Avalonia.X11/NativeDialogs/Gtk.cs
+++ b/src/Avalonia.X11/NativeDialogs/Gtk.cs
@@ -3,7 +3,6 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Platform.Interop;
-using JetBrains.Annotations;
// ReSharper disable IdentifierTypo
namespace Avalonia.X11.NativeDialogs
diff --git a/src/Avalonia.X11/X11Info.cs b/src/Avalonia.X11/X11Info.cs
index 13dc460f45..72f3bf3137 100644
--- a/src/Avalonia.X11/X11Info.cs
+++ b/src/Avalonia.X11/X11Info.cs
@@ -2,7 +2,6 @@ using System;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
-using JetBrains.Annotations;
using static Avalonia.X11.XLib;
// ReSharper disable UnusedAutoPropertyAccessor.Local
namespace Avalonia.X11
diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs
index 36b5740a17..ff1f8a9074 100644
--- a/src/Avalonia.X11/X11Platform.cs
+++ b/src/Avalonia.X11/X11Platform.cs
@@ -317,7 +317,7 @@ namespace Avalonia
}
public static class AvaloniaX11PlatformExtensions
{
- public static T UseX11(this T builder) where T : AppBuilderBase, new()
+ public static AppBuilder UseX11(this AppBuilder builder)
{
builder.UseWindowingSubsystem(() =>
new AvaloniaX11Platform().Initialize(AvaloniaLocator.Current.GetService() ??
diff --git a/src/Avalonia.X11/X11Screens.cs b/src/Avalonia.X11/X11Screens.cs
index ba6029b350..87899b11ed 100644
--- a/src/Avalonia.X11/X11Screens.cs
+++ b/src/Avalonia.X11/X11Screens.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Platform;
using static Avalonia.X11.XLib;
-using JetBrains.Annotations;
namespace Avalonia.X11
{
diff --git a/src/Avalonia.X11/X11Window.Ime.cs b/src/Avalonia.X11/X11Window.Ime.cs
index 257580a5ec..e6066c7964 100644
--- a/src/Avalonia.X11/X11Window.Ime.cs
+++ b/src/Avalonia.X11/X11Window.Ime.cs
@@ -7,7 +7,6 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Platform.Interop;
-using JetBrains.Annotations;
using static Avalonia.X11.XLib;
namespace Avalonia.X11
@@ -206,7 +205,7 @@ namespace Avalonia.X11
// This class is used to attach the text value of the key to an asynchronously dispatched KeyDown event
class RawKeyEventArgsWithText : RawKeyEventArgs
{
- public RawKeyEventArgsWithText([NotNull] IKeyboardDevice device, ulong timestamp, [NotNull] IInputRoot root,
+ public RawKeyEventArgsWithText(IKeyboardDevice device, ulong timestamp, IInputRoot root,
RawKeyEventType type, Key key, RawInputModifiers modifiers, string text) :
base(device, timestamp, root, type, key, modifiers)
{
diff --git a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
index 2432dc29a3..5e101f7f17 100644
--- a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
@@ -8,14 +8,13 @@ namespace Avalonia.Browser.Blazor;
[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
- public static T SetupWithSingleViewLifetime(
- this T builder)
- where T : AppBuilderBase, new()
+ public static AppBuilder SetupWithSingleViewLifetime(
+ this AppBuilder builder)
{
return builder.SetupWithLifetime(new BlazorSingleViewLifetime());
}
- public static T UseBlazor(this T builder) where T : AppBuilderBase, new()
+ public static AppBuilder UseBlazor(this AppBuilder builder)
{
return builder
.UseBrowser()
diff --git a/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs b/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs
index 0abc7703da..67bb040410 100644
--- a/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs
+++ b/src/Browser/Avalonia.Browser/BrowserRuntimePlatform.cs
@@ -11,12 +11,11 @@ internal class BrowserRuntimePlatform : StandardRuntimePlatform
{
private static readonly Lazy Info = new(() =>
{
+ var isMobile = AvaloniaModule.IsMobile();
var result = new RuntimePlatformInfo
{
- IsCoreClr = true, // WASM browser is always CoreCLR
- IsBrowser = true, // BrowserRuntimePlatform only runs on Browser.
- OperatingSystem = OperatingSystemType.Browser,
- IsMobile = AvaloniaModule.IsMobile()
+ IsMobile = isMobile,
+ IsDesktop = !isMobile
};
return result;
diff --git a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
index b6c766b2a5..3adcb8e539 100644
--- a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
@@ -2,8 +2,6 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using System.Runtime.Versioning;
-using Avalonia.Browser.Skia;
-using Avalonia.Platform;
namespace Avalonia.Browser;
@@ -27,9 +25,8 @@ public class BrowserPlatformOptions
[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
- public static T SetupBrowserApp(
- this T builder, string mainDivId)
- where T : AppBuilderBase, new()
+ public static AppBuilder SetupBrowserApp(
+ this AppBuilder builder, string mainDivId)
{
var lifetime = new BrowserSingleViewLifetime();
@@ -42,9 +39,8 @@ public static class WebAppBuilder
.SetupWithLifetime(lifetime);
}
- public static T UseBrowser(
- this T builder)
- where T : AppBuilderBase, new()
+ public static AppBuilder UseBrowser(
+ this AppBuilder builder)
{
return builder
.UseWindowingSubsystem(BrowserWindowingPlatform.Register)
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs b/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
index ce843952e7..3439f0edae 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
@@ -1,6 +1,5 @@
using Avalonia.LinuxFramebuffer.Output;
using Avalonia.Media;
-using JetBrains.Annotations;
namespace Avalonia.LinuxFramebuffer
{
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
index 38498951f8..4202ba821f 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Threading;
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Embedding;
@@ -12,12 +13,10 @@ using Avalonia.LinuxFramebuffer.Input;
using Avalonia.LinuxFramebuffer.Input.EvDev;
using Avalonia.LinuxFramebuffer.Input.LibInput;
using Avalonia.LinuxFramebuffer.Output;
-using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
-using Avalonia.Threading;
-using JetBrains.Annotations;
+#nullable enable
namespace Avalonia.LinuxFramebuffer
{
@@ -26,9 +25,9 @@ namespace Avalonia.LinuxFramebuffer
IOutputBackend _fb;
private static readonly Stopwatch St = Stopwatch.StartNew();
internal static uint Timestamp => (uint)St.ElapsedTicks;
- public static InternalPlatformThreadingInterface Threading;
+ public static InternalPlatformThreadingInterface? Threading;
- internal static Compositor Compositor { get; private set; }
+ internal static Compositor? Compositor { get; private set; }
LinuxFramebufferPlatform(IOutputBackend backend)
@@ -60,7 +59,7 @@ namespace Avalonia.LinuxFramebuffer
}
- internal static LinuxFramebufferLifetime Initialize(T builder, IOutputBackend outputBackend, IInputBackend inputBackend) where T : AppBuilderBase, new()
+ internal static LinuxFramebufferLifetime Initialize(AppBuilder builder, IOutputBackend outputBackend, IInputBackend? inputBackend)
{
var platform = new LinuxFramebufferPlatform(outputBackend);
builder.UseSkia().UseWindowingSubsystem(platform.Initialize, "fbdev");
@@ -71,8 +70,8 @@ namespace Avalonia.LinuxFramebuffer
class LinuxFramebufferLifetime : IControlledApplicationLifetime, ISingleViewApplicationLifetime
{
private readonly IOutputBackend _fb;
- [CanBeNull] private readonly IInputBackend _inputBackend;
- private TopLevel _topLevel;
+ private readonly IInputBackend? _inputBackend;
+ private TopLevel? _topLevel;
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
public CancellationToken Token => _cts.Token;
@@ -81,15 +80,15 @@ namespace Avalonia.LinuxFramebuffer
_fb = fb;
}
- public LinuxFramebufferLifetime(IOutputBackend fb, IInputBackend input)
+ public LinuxFramebufferLifetime(IOutputBackend fb, IInputBackend? input)
{
_fb = fb;
_inputBackend = input;
}
- public Control MainView
+ public Control? MainView
{
- get => (Control)_topLevel?.Content;
+ get => (Control?)_topLevel?.Content;
set
{
if (_topLevel == null)
@@ -119,8 +118,8 @@ namespace Avalonia.LinuxFramebuffer
}
public int ExitCode { get; private set; }
- public event EventHandler Startup;
- public event EventHandler Exit;
+ public event EventHandler? Startup;
+ public event EventHandler? Exit;
public void Start(string[] args)
{
@@ -140,20 +139,17 @@ namespace Avalonia.LinuxFramebuffer
public static class LinuxFramebufferPlatformExtensions
{
- public static int StartLinuxFbDev(this T builder, string[] args, string fbdev = null, double scaling = 1, IInputBackend inputBackend = default)
- where T : AppBuilderBase, new() =>
- StartLinuxDirect(builder, args, new FbdevOutput(fileName: fbdev, format: null) { Scaling = scaling }, inputBackend);
- public static int StartLinuxFbDev(this T builder, string[] args, string fbdev, PixelFormat? format, double scaling, IInputBackend inputBackend = default)
- where T : AppBuilderBase, new() =>
- StartLinuxDirect(builder, args, new FbdevOutput(fileName: fbdev, format: format) { Scaling = scaling }, inputBackend);
-
- public static int StartLinuxDrm(this T builder, string[] args, string card = null, double scaling = 1, IInputBackend inputBackend = default)
- where T : AppBuilderBase, new() => StartLinuxDirect(builder, args, new DrmOutput(card) { Scaling = scaling }, inputBackend);
- public static int StartLinuxDrm(this T builder, string[] args, string card = null, bool connectorsForceProbe = false, [CanBeNull] DrmOutputOptions options = null, IInputBackend inputBackend = default)
- where T : AppBuilderBase, new() => StartLinuxDirect(builder, args, new DrmOutput(card, connectorsForceProbe, options), inputBackend);
-
- public static int StartLinuxDirect(this T builder, string[] args, IOutputBackend outputBackend, IInputBackend inputBackend = default)
- where T : AppBuilderBase, new()
+ public static int StartLinuxFbDev(this AppBuilder builder, string[] args, string? fbdev = null, double scaling = 1, IInputBackend? inputBackend = default)
+ => StartLinuxDirect(builder, args, new FbdevOutput(fileName: fbdev, format: null) { Scaling = scaling }, inputBackend);
+ public static int StartLinuxFbDev(this AppBuilder builder, string[] args, string fbdev, PixelFormat? format, double scaling, IInputBackend? inputBackend = default)
+ => StartLinuxDirect(builder, args, new FbdevOutput(fileName: fbdev, format: format) { Scaling = scaling }, inputBackend);
+
+ public static int StartLinuxDrm(this AppBuilder builder, string[] args, string? card = null, double scaling = 1, IInputBackend? inputBackend = default)
+ => StartLinuxDirect(builder, args, new DrmOutput(card) { Scaling = scaling }, inputBackend);
+ public static int StartLinuxDrm(this AppBuilder builder, string[] args, string? card = null, bool connectorsForceProbe = false, DrmOutputOptions? options = null, IInputBackend? inputBackend = default)
+ => StartLinuxDirect(builder, args, new DrmOutput(card, connectorsForceProbe, options), inputBackend);
+
+ public static int StartLinuxDirect(this AppBuilder builder, string[] args, IOutputBackend outputBackend, IInputBackend? inputBackend = default)
{
var lifetime = LinuxFramebufferPlatform.Initialize(builder, outputBackend, inputBackend);
builder.SetupWithLifetime(lifetime);
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index 22dd407791..d61dcd4f91 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -8,7 +8,6 @@ using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
-using JetBrains.Annotations;
using static Avalonia.LinuxFramebuffer.NativeUnsafeMethods;
using static Avalonia.LinuxFramebuffer.Output.LibDrm;
using static Avalonia.LinuxFramebuffer.Output.LibDrm.GbmColorFormats;
@@ -50,7 +49,7 @@ namespace Avalonia.LinuxFramebuffer.Output
_outputOptions = options;
Init(card, resources, connector, modeInfo);
}
- public DrmOutput(string path = null, bool connectorsForceProbe = false, [CanBeNull] DrmOutputOptions options = null)
+ public DrmOutput(string path = null, bool connectorsForceProbe = false, DrmOutputOptions? options = null)
{
if(options != null)
_outputOptions = options;
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
index 5004e594f7..13de455b96 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
@@ -366,6 +366,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
foreach (var branch in ExtensionNodeContainer.Branches)
{
var next = codeGen.DefineLabel();
+ codeGen.Emit(OpCodes.Nop);
if (branch.HasContext)
{
codeGen.Ldloc(context.ContextLocal);
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
index 3084964d44..4478a79d27 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
@@ -44,9 +44,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public CommandAccessor(WeakReference reference, Action execute, Func canExecute, ISet dependsOnProperties)
{
- Contract.Requires(reference != null);
-
- _reference = reference;
+ _reference = reference ?? throw new ArgumentNullException(nameof(reference));
_dependsOnProperties = dependsOnProperties;
_command = new Command(reference, execute, canExecute);
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
index ef11b06369..81f1224650 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorFactory.cs
@@ -28,11 +28,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public AvaloniaPropertyAccessor(WeakReference reference, AvaloniaProperty property)
{
- Contract.Requires(reference != null);
- Contract.Requires(property != null);
-
- _reference = reference;
- _property = property;
+ _reference = reference ?? throw new ArgumentNullException(nameof(reference));;
+ _property = property ?? throw new ArgumentNullException(nameof(property));;
}
public AvaloniaObject Instance
@@ -77,11 +74,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
public InpcPropertyAccessor(WeakReference reference, IPropertyInfo property)
{
- Contract.Requires(reference != null);
- Contract.Requires(property != null);
-
- _reference = reference;
- _property = property;
+ _reference = reference ?? throw new ArgumentNullException(nameof(reference));
+ _property = property ?? throw new ArgumentNullException(nameof(property));
}
public override Type PropertyType => _property.PropertyType;
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs
index 51e09eef71..c2f1100eff 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnFormFactorExtension.cs
@@ -6,7 +6,7 @@ using Avalonia.Platform;
namespace Avalonia.Markup.Xaml.MarkupExtensions;
-public class OnFormFactorExtension : OnFormFactorExtensionBase
+public sealed class OnFormFactorExtension : OnFormFactorExtensionBase
{
public OnFormFactorExtension()
{
@@ -24,7 +24,7 @@ public class OnFormFactorExtension : OnFormFactorExtensionBase
}
}
-public class OnFormFactorExtension : OnFormFactorExtensionBase>
+public sealed class OnFormFactorExtension : OnFormFactorExtensionBase>
{
public OnFormFactorExtension()
{
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs
index 1ac7a522f1..1c20020978 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs
@@ -1,11 +1,11 @@
#nullable enable
using System;
+using Avalonia.Compatibility;
using Avalonia.Metadata;
-using Avalonia.Platform;
namespace Avalonia.Markup.Xaml.MarkupExtensions;
-public class OnPlatformExtension : OnPlatformExtensionBase
+public sealed class OnPlatformExtension : OnPlatformExtensionBase
{
public OnPlatformExtension()
{
@@ -17,13 +17,13 @@ public class OnPlatformExtension : OnPlatformExtensionBase
Default = defaultValue;
}
- public static bool ShouldProvideOption(IServiceProvider serviceProvider, OperatingSystemType option)
+ public static bool ShouldProvideOption(string option)
{
- return serviceProvider.GetService().GetRuntimeInfo().OperatingSystem == option;
+ return ShouldProvideOptionInternal(option);
}
}
-public class OnPlatformExtension : OnPlatformExtensionBase>
+public sealed class OnPlatformExtension : OnPlatformExtensionBase>
{
public OnPlatformExtension()
{
@@ -35,9 +35,9 @@ public class OnPlatformExtension : OnPlatformExtensionBase().GetRuntimeInfo().OperatingSystem == option;
+ return ShouldProvideOptionInternal(option);
}
}
@@ -47,27 +47,44 @@ public abstract class OnPlatformExtensionBase : IAddChild
[MarkupExtensionDefaultOption]
public TReturn? Default { get; set; }
- [MarkupExtensionOption(OperatingSystemType.WinNT)]
+ [MarkupExtensionOption("WINDOWS")]
public TReturn? Windows { get; set; }
- [MarkupExtensionOption(OperatingSystemType.OSX)]
+ [MarkupExtensionOption("OSX")]
// ReSharper disable once InconsistentNaming
public TReturn? macOS { get; set; }
- [MarkupExtensionOption(OperatingSystemType.Linux)]
+ [MarkupExtensionOption("LINUX")]
public TReturn? Linux { get; set; }
- [MarkupExtensionOption(OperatingSystemType.Android)]
+ [MarkupExtensionOption("ANDROID")]
public TReturn? Android { get; set; }
- [MarkupExtensionOption(OperatingSystemType.iOS)]
+ [MarkupExtensionOption("IOS")]
// ReSharper disable once InconsistentNaming
public TReturn? iOS { get; set; }
- [MarkupExtensionOption(OperatingSystemType.Browser)]
+ [MarkupExtensionOption("BROWSER")]
public TReturn? Browser { get; set; }
// Required for the compiler, will be replaced with actual method compile time.
public object ProvideValue() { return this; }
void IAddChild.AddChild(TOn child) {}
+
+ private protected static bool ShouldProvideOptionInternal(string option)
+ {
+ // Instead of using OperatingSystem.IsOSPlatform(string) we use specific "Is***" methods so whole method can be trimmed by the mono linked.
+ // Keep in mind it works only with const "option" parameter.
+ // IsOSPlatform might work better with trimming in the future, so it should be re-visited after .NET 8/9.
+ return option switch
+ {
+ "WINDOWS" => OperatingSystemEx.IsWindows(),
+ "OSX" => OperatingSystemEx.IsMacOS(),
+ "LINUX" => OperatingSystemEx.IsLinux(),
+ "ANDROID" => OperatingSystemEx.IsAndroid(),
+ "IOS" => OperatingSystemEx.IsIOS(),
+ "BROWSER" => OperatingSystemEx.IsBrowser(),
+ _ => OperatingSystemEx.IsOSPlatform(option)
+ };
+ }
}
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index a7bec62366..48e8c761eb 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -10,7 +10,6 @@ using Avalonia.Rendering.SceneGraph;
using Avalonia.Rendering.Utilities;
using Avalonia.Utilities;
using Avalonia.Media.Imaging;
-using JetBrains.Annotations;
using SkiaSharp;
namespace Avalonia.Skia
@@ -675,13 +674,14 @@ namespace Avalonia.Skia
}
}
- [CanBeNull]
- public object GetFeature(Type t)
+#nullable enable
+ public object? GetFeature(Type t)
{
if (t == typeof(ISkiaSharpApiLeaseFeature))
return new SkiaLeaseFeature(this);
return null;
}
+#nullable restore
///
/// Configure paint wrapper for using gradient brush.
diff --git a/src/Skia/Avalonia.Skia/GlyphRunImpl.cs b/src/Skia/Avalonia.Skia/GlyphRunImpl.cs
index bdc3d075cf..484fd9f219 100644
--- a/src/Skia/Avalonia.Skia/GlyphRunImpl.cs
+++ b/src/Skia/Avalonia.Skia/GlyphRunImpl.cs
@@ -1,8 +1,8 @@
using System;
using Avalonia.Metadata;
using Avalonia.Platform;
-using JetBrains.Annotations;
using SkiaSharp;
+#nullable enable
namespace Avalonia.Skia
{
@@ -10,7 +10,7 @@ namespace Avalonia.Skia
[Unstable]
public class GlyphRunImpl : IGlyphRunImpl
{
- public GlyphRunImpl([NotNull] SKTextBlob textBlob)
+ public GlyphRunImpl(SKTextBlob textBlob)
{
TextBlob = textBlob ?? throw new ArgumentNullException (nameof (textBlob));
}
diff --git a/src/Skia/Avalonia.Skia/Helpers/PixelFormatHelper.cs b/src/Skia/Avalonia.Skia/Helpers/PixelFormatHelper.cs
index 9236bdee8d..84a1972e01 100644
--- a/src/Skia/Avalonia.Skia/Helpers/PixelFormatHelper.cs
+++ b/src/Skia/Avalonia.Skia/Helpers/PixelFormatHelper.cs
@@ -1,4 +1,5 @@
-using Avalonia.Platform;
+using Avalonia.Compatibility;
+using Avalonia.Platform;
using SkiaSharp;
namespace Avalonia.Skia.Helpers
@@ -18,10 +19,7 @@ namespace Avalonia.Skia.Helpers
var colorType = format?.ToSkColorType() ?? SKImageInfo.PlatformColorType;
// TODO: This looks like some leftover hack
- var runtimePlatform = AvaloniaLocator.Current?.GetService();
- var runtime = runtimePlatform?.GetRuntimeInfo();
-
- if (runtime?.IsDesktop == true && runtime.Value.OperatingSystem == OperatingSystemType.Linux)
+ if (OperatingSystemEx.IsLinux())
{
colorType = SKColorType.Bgra8888;
}
diff --git a/src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs b/src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs
index 014298ce83..3e4fd7b385 100644
--- a/src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs
+++ b/src/Skia/Avalonia.Skia/SkiaApplicationExtensions.cs
@@ -12,10 +12,9 @@ namespace Avalonia
///
/// Enable Skia renderer.
///
- /// Builder type.
/// Builder.
/// Configure builder.
- public static T UseSkia(this T builder) where T : AppBuilderBase, new()
+ public static AppBuilder UseSkia(this AppBuilder builder)
{
return builder.UseRenderingSubsystem(() => SkiaPlatform.Initialize(
AvaloniaLocator.Current.GetService() ?? new SkiaOptions()),
diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
index fb7831415d..5fecaef100 100644
--- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
+++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
@@ -17,7 +17,6 @@
-
diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
index a5f77230b7..5887ba2172 100644
--- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
+++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
@@ -16,7 +16,7 @@ namespace Avalonia
{
public static class Direct2DApplicationExtensions
{
- public static T UseDirect2D1(this T builder) where T : AppBuilderBase, new()
+ public static AppBuilder UseDirect2D1(this AppBuilder builder)
{
builder.UseRenderingSubsystem(Direct2D1.Direct2D1Platform.Initialize, "Direct2D1");
return builder;
diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
index f828b156da..672f3a781a 100644
--- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
+++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
@@ -820,6 +820,14 @@ namespace Avalonia.Win32.Interop
DWMWA_LAST
};
+ public enum DwmWindowCornerPreference : uint
+ {
+ DWMWCP_DEFAULT = 0,
+ DWMWCP_DONOTROUND,
+ DWMWCP_ROUND,
+ DWMWCP_ROUNDSMALL
+ }
+
public enum MapVirtualKeyMapTypes : uint
{
MAPVK_VK_TO_VSC = 0x00,
diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs
index f3b07cd50e..887bdb422f 100644
--- a/src/Windows/Avalonia.Win32/Win32Platform.cs
+++ b/src/Windows/Avalonia.Win32/Win32Platform.cs
@@ -19,16 +19,14 @@ using Avalonia.Threading;
using Avalonia.Utilities;
using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
-using JetBrains.Annotations;
using static Avalonia.Win32.Interop.UnmanagedMethods;
namespace Avalonia
{
+#nullable enable
public static class Win32ApplicationExtensions
{
- public static T UseWin32(
- this T builder)
- where T : AppBuilderBase, new()
+ public static AppBuilder UseWin32(this AppBuilder builder)
{
return builder.UseWindowingSubsystem(
() => Win32.Win32Platform.Initialize(
@@ -111,9 +109,10 @@ namespace Avalonia
///
/// Provides a way to use a custom-implemented graphics context such as a custom ISkiaGpu
///
- [CanBeNull] public IPlatformGraphics CustomPlatformGraphics { get; set; }
+ public IPlatformGraphics? CustomPlatformGraphics { get; set; }
}
}
+#nullable restore
namespace Avalonia.Win32
{
@@ -264,6 +263,8 @@ namespace Avalonia.Win32
public bool CurrentThreadIsLoopThread => _uiThread == Thread.CurrentThread;
+ public TimeSpan HoldWaitDuration { get; set; } = TimeSpan.FromMilliseconds(300);
+
public event Action Signaled;
public event EventHandler ShutdownRequested;
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index 8edfd71903..702fe89cda 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.cs
@@ -1030,6 +1030,12 @@ namespace Avalonia.Win32
{
var margins = UpdateExtendMargins();
DwmExtendFrameIntoClientArea(_hwnd, ref margins);
+
+ unsafe
+ {
+ int cornerPreference = (int)DwmWindowCornerPreference.DWMWCP_ROUND;
+ DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(int));
+ }
}
else
{
@@ -1040,6 +1046,12 @@ namespace Avalonia.Win32
_extendedMargins = new Thickness();
Resize(new Size(rcWindow.Width / RenderScaling, rcWindow.Height / RenderScaling), PlatformResizeReason.Layout);
+
+ unsafe
+ {
+ int cornerPreference = (int)DwmWindowCornerPreference.DWMWCP_DEFAULT;
+ DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(int));
+ }
}
if (!_isClientAreaExtended || (_extendChromeHints.HasAllFlags(ExtendClientAreaChromeHints.SystemChrome) &&
diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs
index e1b5f5a3a0..4f4e0b9293 100644
--- a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs
+++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs
@@ -8,7 +8,6 @@ namespace Avalonia.Win32
{
public IDisposable Listen(ObservableCollection mountedDrives)
{
- Contract.Requires(mountedDrives != null);
return new WindowsMountedVolumeInfoListener(mountedDrives);
}
}
diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs b/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs
index fb0857e472..a1836f3ce4 100644
--- a/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs
+++ b/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs
@@ -1,6 +1,5 @@
#nullable enable
using Avalonia.Input.TextInput;
-using JetBrains.Annotations;
using UIKit;
namespace Avalonia.iOS;
diff --git a/src/iOS/Avalonia.iOS/Platform.cs b/src/iOS/Avalonia.iOS/Platform.cs
index eb0a55734a..63025f7f0a 100644
--- a/src/iOS/Avalonia.iOS/Platform.cs
+++ b/src/iOS/Avalonia.iOS/Platform.cs
@@ -12,7 +12,7 @@ namespace Avalonia
{
public static class IOSApplicationExtensions
{
- public static T UseiOS(this T builder) where T : AppBuilderBase, new()
+ public static AppBuilder UseiOS(this AppBuilder builder)
{
return builder
.UseWindowingSubsystem(iOS.Platform.Register, "iOS")
diff --git a/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs b/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
index 508eff5f9d..84ee35ba61 100644
--- a/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
@@ -1,7 +1,13 @@
+using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Input;
+using Avalonia.Input.GestureRecognizers;
+using Avalonia.Media;
+using Avalonia.Platform;
+using Avalonia.Threading;
using Avalonia.UnitTests;
+using Moq;
using Xunit;
namespace Avalonia.Base.UnitTests.Input
@@ -167,6 +173,242 @@ namespace Avalonia.Base.UnitTests.Input
Assert.False(raised);
}
+ [Fact]
+ public void Hold_Should_Be_Raised_After_Hold_Duration()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ HoldingState holding = HoldingState.Cancelled;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => holding = e.HoldingState);
+
+ _mouse.Down(border);
+ Assert.False(holding != HoldingState.Cancelled);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ Assert.True(holding == HoldingState.Started);
+
+ _mouse.Up(border);
+
+ Assert.True(holding == HoldingState.Completed);
+ }
+
+ [Fact]
+ public void Hold_Should_Not_Raised_When_Pointer_Released_Before_Timer()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => raised = e.HoldingState == HoldingState.Started);
+
+ _mouse.Down(border);
+ Assert.False(raised);
+
+ _mouse.Up(border);
+ Assert.False(raised);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void Hold_Should_Not_Raised_When_Pointer_Is_Moved_Before_Timer()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => raised = e.HoldingState == HoldingState.Completed);
+
+ _mouse.Down(border);
+ Assert.False(raised);
+
+ _mouse.Move(border, position: new Point(20, 20));
+ Assert.False(raised);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void Hold_Should_Be_Cancelled_When_Second_Contact_Is_Detected()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var cancelled = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => cancelled = e.HoldingState == HoldingState.Cancelled);
+
+ _mouse.Down(border);
+ Assert.False(cancelled);
+
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ var secondMouse = new MouseTestHelper();
+
+ secondMouse.Down(border);
+
+ Assert.True(cancelled);
+ }
+
+ [Fact]
+ public void Hold_Should_Be_Cancelled_When_Pointer_Moves_Too_Far()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var cancelled = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => cancelled = e.HoldingState == HoldingState.Cancelled);
+
+ _mouse.Down(border);
+
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ _mouse.Move(border, position: new Point(3, 3));
+
+ Assert.False(cancelled);
+
+ _mouse.Move(border, position: new Point(20, 20));
+
+ Assert.True(cancelled);
+ }
+
+ [Fact]
+ public void Hold_Should_Not_Be_Raised_For_Multiple_Contacts()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => raised = e.HoldingState == HoldingState.Completed);
+
+ var secondMouse = new MouseTestHelper();
+
+ _mouse.Down(border, MouseButton.Left);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ secondMouse.Down(border, MouseButton.Left);
+
+ Assert.False(raised);
+ }
+
+ private static IPlatformThreadingInterface CreatePlatformThreadingInterface(Action<(TimeSpan, Action)> callback)
+ {
+ var threadingInterface = new Mock();
+ threadingInterface.SetupGet(p => p.CurrentThreadIsLoopThread).Returns(true);
+ threadingInterface.Setup(p => p
+ .StartTimer(It.IsAny(), It.IsAny(), It.IsAny()))
+ .Callback((_, t, a) => callback((t, a)));
+ return threadingInterface.Object;
+ }
+
private static void AddHandlers(
Decorator decorator,
Border border,
@@ -201,5 +443,101 @@ namespace Avalonia.Base.UnitTests.Input
border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt"));
border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt"));
}
+
+ [Fact]
+ public void Pinched_Should_Not_Be_Raised_For_Same_Pointer()
+ {
+ var touch = new TouchTestHelper();
+
+ Border border = new Border()
+ {
+ Width = 100,
+ Height = 100,
+ Background = new SolidColorBrush(Colors.Red)
+ };
+ border.GestureRecognizers.Add(new PinchGestureRecognizer());
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.PinchEvent, (s, e) => raised = true);
+
+ var firstPoint = new Point(5, 5);
+ var secondPoint = new Point(10, 10);
+
+ touch.Down(border, position: firstPoint);
+ touch.Down(border, position: secondPoint);
+ touch.Down(border, position: new Point(20, 20));
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void Pinched_Should_Be_Raised_For_Two_Pointers_Moving()
+ {
+ Border border = new Border()
+ {
+ Width = 100,
+ Height = 100,
+ Background = new SolidColorBrush(Colors.Red)
+ };
+ border.GestureRecognizers.Add(new PinchGestureRecognizer());
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.PinchEvent, (s, e) => raised = true);
+
+ var firstPoint = new Point(5, 5);
+ var secondPoint = new Point(10, 10);
+
+ var firstTouch = new TouchTestHelper();
+ var secondTouch = new TouchTestHelper();
+
+ firstTouch.Down(border, position: firstPoint);
+ secondTouch.Down(border, position: secondPoint);
+ secondTouch.Move(border, position: new Point(20, 20));
+
+ Assert.True(raised);
+ }
+
+ [Fact]
+ public void Scrolling_Should_Start_After_Start_Distance_Is_Exceded()
+ {
+ Border border = new Border()
+ {
+ Width = 100,
+ Height = 100,
+ Background = new SolidColorBrush(Colors.Red)
+ };
+ border.GestureRecognizers.Add(new ScrollGestureRecognizer()
+ {
+ CanHorizontallyScroll = true,
+ CanVerticallyScroll = true,
+ ScrollStartDistance = 50
+ });
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.ScrollGestureEvent, (s, e) => raised = true);
+
+ var firstTouch = new TouchTestHelper();
+
+ firstTouch.Down(border, position: new Point(5, 5));
+ firstTouch.Move(border, position: new Point(20, 20));
+
+ Assert.False(raised);
+
+ firstTouch.Move(border, position: new Point(70, 20));
+
+ Assert.True(raised);
+ }
}
}
diff --git a/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs b/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs
index c0c0182622..36587ea222 100644
--- a/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs
@@ -207,7 +207,7 @@ namespace Avalonia.Input.UnitTests
private IDisposable UnitTestApp(TimeSpan doubleClickTime = new TimeSpan())
{
var unitTestApp = UnitTestApplication.Start(
- new TestServices(inputManager: new InputManager()));
+ new TestServices(inputManager: new InputManager(), threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true)));
var iSettingsMock = new Mock();
iSettingsMock.Setup(x => x.GetDoubleTapTime(It.IsAny())).Returns(doubleClickTime);
iSettingsMock.Setup(x => x.GetDoubleTapSize(It.IsAny())).Returns(new Size(16, 16));
diff --git a/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs b/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs
index 1bb2300724..aa042ffec8 100644
--- a/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs
@@ -117,7 +117,7 @@ namespace Avalonia.Base.UnitTests.Media.Fonts
private static IDisposable StartWithResources(params (string, string)[] assets)
{
var assetLoader = new MockAssetLoader(assets);
- var services = new TestServices(assetLoader: assetLoader, platform: new AppBuilder().RuntimePlatform);
+ var services = new TestServices(assetLoader: assetLoader, platform: new StandardRuntimePlatform());
return UnitTestApplication.Start(services);
}
}
diff --git a/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs b/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs
index 27faf1e13c..3d8369faeb 100644
--- a/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs
+++ b/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()
{
diff --git a/tests/Avalonia.Base.UnitTests/Rendering/CompositorTestsBase.cs b/tests/Avalonia.Base.UnitTests/Rendering/CompositorTestsBase.cs
index d407a09b06..7f4e160000 100644
--- a/tests/Avalonia.Base.UnitTests/Rendering/CompositorTestsBase.cs
+++ b/tests/Avalonia.Base.UnitTests/Rendering/CompositorTestsBase.cs
@@ -18,7 +18,6 @@ using Avalonia.Rendering.Composition;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
-using JetBrains.Annotations;
using Xunit;
namespace Avalonia.Base.UnitTests.Rendering;
diff --git a/tests/Avalonia.Benchmarks/Data/AccessorTestObject.cs b/tests/Avalonia.Benchmarks/Data/AccessorTestObject.cs
index 0039f5670c..cd323ededb 100644
--- a/tests/Avalonia.Benchmarks/Data/AccessorTestObject.cs
+++ b/tests/Avalonia.Benchmarks/Data/AccessorTestObject.cs
@@ -1,6 +1,5 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
-using JetBrains.Annotations;
namespace Avalonia.Benchmarks.Data
{
@@ -38,7 +37,6 @@ namespace Avalonia.Benchmarks.Data
{
}
- [NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
diff --git a/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs b/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs
index d43d6bd48b..e160c8dfa8 100644
--- a/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs
+++ b/tests/Avalonia.Benchmarks/Utilities/AvaloniaPropertyDictionaryBenchmarks.cs
@@ -172,7 +172,7 @@ internal sealed class AvaloniaPropertyValueStoreOld
internal class MockProperty : StyledProperty
{
- public MockProperty([JetBrains.Annotations.NotNull] string name) : base(name, typeof(object), new StyledPropertyMetadata())
+ public MockProperty(string name) : base(name, typeof(object), new StyledPropertyMetadata())
{
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/TransitioningContentControlTests.cs b/tests/Avalonia.Controls.UnitTests/TransitioningContentControlTests.cs
new file mode 100644
index 0000000000..aaa1de4da4
--- /dev/null
+++ b/tests/Avalonia.Controls.UnitTests/TransitioningContentControlTests.cs
@@ -0,0 +1,66 @@
+using System;
+using Avalonia.LogicalTree;
+using Avalonia.UnitTests;
+using Xunit;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Animation;
+
+namespace Avalonia.Controls.UnitTests
+{
+ public class TransitioningContentControlTests
+ {
+ [Fact]
+ public void Old_Content_Shuold_Be_Removed__From_Logical_Tree_After_Out_Animation()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var testTransition = new TestTransition();
+
+ var target = new TransitioningContentControl();
+ target.PageTransition = testTransition;
+
+ var root = new TestRoot() { Child = target };
+
+ var oldControl = new Control();
+ var newControl = new Control();
+
+ target.Content = oldControl;
+ Threading.Dispatcher.UIThread.RunJobs();
+
+ Assert.Equal(target, oldControl.GetLogicalParent());
+ Assert.Equal(null, newControl.GetLogicalParent());
+
+ testTransition.BeginTransition += isFrom =>
+ {
+ // Old out
+ if (isFrom)
+ {
+ Assert.Equal(target, oldControl.GetLogicalParent());
+ Assert.Equal(null, newControl.GetLogicalParent());
+ }
+ // New in
+ else
+ {
+ Assert.Equal(null, oldControl.GetLogicalParent());
+ Assert.Equal(target, newControl.GetLogicalParent());
+ }
+ };
+
+ target.Content = newControl;
+ Threading.Dispatcher.UIThread.RunJobs();
+ }
+ }
+ }
+ public class TestTransition : IPageTransition
+ {
+ public event Action BeginTransition;
+
+ public Task Start(Visual from, Visual to, bool forward, CancellationToken cancellationToken)
+ {
+ bool isFrom = from != null && to == null;
+ BeginTransition?.Invoke(isFrom);
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
index cd38bf556a..81936711ef 100644
--- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
@@ -17,7 +17,6 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Styling;
using Avalonia.UnitTests;
-using JetBrains.Annotations;
using Moq;
using Xunit;
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
index eb57cfb8da..0c0857b680 100644
--- a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
@@ -389,9 +389,9 @@
"dev": true
},
"ansi-regex": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
- "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
@@ -405,9 +405,9 @@
}
},
"anymatch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
- "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
@@ -444,18 +444,6 @@
"sprintf-js": "~1.0.2"
}
},
- "array.prototype.map": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz",
- "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "es-array-method-boxes-properly": "^1.0.0",
- "is-string": "^1.0.4"
- }
- },
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -469,9 +457,9 @@
"dev": true
},
"binary-extensions": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
- "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"brace-expansion": {
@@ -538,9 +526,9 @@
}
},
"chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
@@ -554,19 +542,19 @@
"dev": true
},
"chokidar": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
- "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"requires": {
- "anymatch": "~3.1.1",
+ "anymatch": "~3.1.2",
"braces": "~3.0.2",
- "fsevents": "~2.1.2",
- "glob-parent": "~5.1.0",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
- "readdirp": "~3.4.0"
+ "readdirp": "~3.6.0"
}
},
"clean-stack": {
@@ -576,42 +564,14 @@
"dev": true
},
"cliui": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
- "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": {
- "string-width": "^3.1.0",
- "strip-ansi": "^5.2.0",
- "wrap-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
}
},
"color-convert": {
@@ -708,15 +668,6 @@
"strip-bom": "^4.0.0"
}
},
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@@ -724,68 +675,23 @@
"dev": true
},
"emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
- },
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- },
- "es-array-method-boxes-properly": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
- "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
- "es-get-iterator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz",
- "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==",
- "dev": true,
- "requires": {
- "es-abstract": "^1.17.4",
- "has-symbols": "^1.0.1",
- "is-arguments": "^1.0.4",
- "is-map": "^2.0.1",
- "is-set": "^2.0.1",
- "is-string": "^1.0.5",
- "isarray": "^2.0.5"
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
"es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"dev": true
},
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -829,13 +735,10 @@
}
},
"flat": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
- "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
- "dev": true,
- "requires": {
- "is-buffer": "~2.0.3"
- }
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true
},
"foreground-child": {
"version": "2.0.0",
@@ -860,18 +763,12 @@
"dev": true
},
"fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
"gensync": {
"version": "1.0.0-beta.1",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
@@ -911,9 +808,9 @@
}
},
"glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
@@ -931,33 +828,12 @@
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
- "growl": {
- "version": "1.10.5",
- "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
- "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
- "dev": true
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
"hasha": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz",
@@ -1008,12 +884,6 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
- "is-arguments": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
- "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
- "dev": true
- },
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -1023,51 +893,27 @@
"binary-extensions": "^2.0.0"
}
},
- "is-buffer": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
- "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
- "dev": true
- },
- "is-callable": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz",
- "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==",
- "dev": true
- },
- "is-date-object": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
- "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
- "dev": true
- },
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true
},
"is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
- "is-map": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz",
- "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==",
- "dev": true
- },
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -1075,24 +921,9 @@
"dev": true
},
"is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
- "dev": true
- },
- "is-regex": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
- "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "is-set": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz",
- "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true
},
"is-stream": {
@@ -1101,39 +932,24 @@
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
"dev": true
},
- "is-string": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
- "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
- "dev": true
- },
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
- "isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
- },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -1222,22 +1038,6 @@
"istanbul-lib-report": "^3.0.0"
}
},
- "iterate-iterator": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz",
- "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==",
- "dev": true
- },
- "iterate-value": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz",
- "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==",
- "dev": true,
- "requires": {
- "es-get-iterator": "^1.0.2",
- "iterate-iterator": "^1.0.1"
- }
- },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1261,13 +1061,10 @@
"dev": true
},
"json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz",
+ "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==",
+ "dev": true
},
"locate-path": {
"version": "6.0.0",
@@ -1291,12 +1088,13 @@
"dev": true
},
"log-symbols": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
- "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dev": true,
"requires": {
- "chalk": "^4.0.0"
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
}
},
"loose-envify": {
@@ -1332,43 +1130,133 @@
"brace-expansion": "^1.1.7"
}
},
- "minimist": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
- "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
- "dev": true
- },
"mocha": {
- "version": "8.1.3",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz",
- "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+ "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
"dev": true,
"requires": {
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
- "chokidar": "3.4.2",
- "debug": "4.1.1",
- "diff": "4.0.2",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
- "glob": "7.1.6",
- "growl": "1.10.5",
+ "glob": "7.2.0",
"he": "1.2.0",
- "js-yaml": "3.14.0",
- "log-symbols": "4.0.0",
- "minimatch": "3.0.4",
- "ms": "2.1.2",
- "object.assign": "4.1.0",
- "promise.allsettled": "1.0.2",
- "serialize-javascript": "4.0.0",
- "strip-json-comments": "3.0.1",
- "supports-color": "7.1.0",
- "which": "2.0.2",
- "wide-align": "1.1.3",
- "workerpool": "6.0.0",
- "yargs": "13.3.2",
- "yargs-parser": "13.1.2",
- "yargs-unparser": "1.6.1"
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
}
},
"moq.ts": {
@@ -1386,6 +1274,12 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
+ "nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true
+ },
"node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
@@ -1570,30 +1464,6 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true
},
- "object-inspect": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
- "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
- "dev": true
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- },
- "object.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "function-bind": "^1.1.1",
- "has-symbols": "^1.0.0",
- "object-keys": "^1.0.11"
- }
- },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1604,12 +1474,12 @@
}
},
"p-limit": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz",
- "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"requires": {
- "p-try": "^2.0.0"
+ "yocto-queue": "^0.1.0"
}
},
"p-locate": {
@@ -1679,9 +1549,9 @@
"dev": true
},
"picomatch": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
- "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"pkg-dir": {
@@ -1741,19 +1611,6 @@
"fromentries": "^1.2.0"
}
},
- "promise.allsettled": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz",
- "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==",
- "dev": true,
- "requires": {
- "array.prototype.map": "^1.0.1",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
- "iterate-value": "^1.0.0"
- }
- },
"prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
@@ -1792,9 +1649,9 @@
"dev": true
},
"readdirp": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
- "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
@@ -1858,9 +1715,9 @@
"dev": true
},
"serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
- "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
@@ -1938,42 +1795,23 @@
"dev": true
},
"string-width": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
- "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
- "dev": true,
- "requires": {
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^4.0.0"
- }
- },
- "string.prototype.trimend": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
- "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- }
- },
- "string.prototype.trimstart": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
- "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
}
},
"strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
- "ansi-regex": "^3.0.0"
+ "ansi-regex": "^5.0.1"
}
},
"strip-bom": {
@@ -1983,9 +1821,9 @@
"dev": true
},
"strip-json-comments": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
- "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"supports-color": {
@@ -2090,82 +1928,21 @@
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
- "wide-align": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
- "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
- "dev": true,
- "requires": {
- "string-width": "^1.0.2 || 2"
- }
- },
"workerpool": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz",
- "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
"dev": true
},
"wrap-ansi": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
- "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": {
- "ansi-styles": "^3.2.0",
- "string-width": "^3.0.0",
- "strip-ansi": "^5.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
}
},
"wrappy": {
@@ -2193,214 +1970,57 @@
"dev": true
},
"yargs": {
- "version": "13.3.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
- "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
- "cliui": "^5.0.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^13.1.2"
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
},
"dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
}
}
},
"yargs-parser": {
- "version": "13.1.2",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
- "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true
},
"yargs-unparser": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz",
- "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
"requires": {
- "camelcase": "^5.3.1",
- "decamelize": "^1.2.0",
- "flat": "^4.1.0",
- "is-plain-obj": "^1.1.0",
- "yargs": "^14.2.3"
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
},
"dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true
},
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- },
- "yargs": {
- "version": "14.2.3",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
- "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
- "dev": true,
- "requires": {
- "cliui": "^5.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^15.0.1"
- }
- },
- "yargs-parser": {
- "version": "15.0.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
- "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
}
}
},
@@ -2409,6 +2029,12 @@
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
}
}
}
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
index dbb12e192a..580c4059ba 100644
--- a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
@@ -16,7 +16,7 @@
"@types/mocha": "8.0.3",
"@types/react": "^16.3.14",
"chai": "^4.2.0",
- "mocha": "^8.1.3",
+ "mocha": "^10.2.0",
"moq.ts": "^6.4.0",
"nyc": "^15.1.0",
"react": "^16.3.2",
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OnPlatformExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OnPlatformExtensionTests.cs
deleted file mode 100644
index 1d37378010..0000000000
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OnPlatformExtensionTests.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Platform;
-using Xunit;
-
-namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;
-
-public class OnPlatformExtensionTests : XamlTestBase
-{
- [Fact]
- public void Should_Resolve_Default_Value()
- {
- using (AvaloniaLocator.EnterScope())
- {
- AvaloniaLocator.CurrentMutable.Bind()
- .ToConstant(new TestRuntimePlatform(OperatingSystemType.Unknown));
-
- var xaml = @"
-
-
-";
-
- var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
- var textBlock = (TextBlock)userControl.Content!;
-
- Assert.Equal("Hello World", textBlock.Text);
- }
- }
-
- [Theory]
- [InlineData(OperatingSystemType.WinNT, "Im Windows")]
- [InlineData(OperatingSystemType.OSX, "Im macOS")]
- [InlineData(OperatingSystemType.Linux, "Im Linux")]
- [InlineData(OperatingSystemType.Android, "Im Android")]
- [InlineData(OperatingSystemType.iOS, "Im iOS")]
- [InlineData(OperatingSystemType.Browser, "Im Browser")]
- [InlineData(OperatingSystemType.Unknown, "Default value")]
- public void Should_Resolve_Expected_Value_Per_Platform(OperatingSystemType currentPlatform, string expectedResult)
- {
- using (AvaloniaLocator.EnterScope())
- {
- AvaloniaLocator.CurrentMutable.Bind()
- .ToConstant(new TestRuntimePlatform(currentPlatform));
-
- var xaml = @"
-
-
-";
-
- var userControl = (UserControl)AvaloniaRuntimeXamlLoader.Load(xaml);
- var textBlock = (TextBlock)userControl.Content!;
-
- Assert.Equal(expectedResult, textBlock.Text);
- }
- }
-
- private class TestRuntimePlatform : StandardRuntimePlatform
- {
- private readonly OperatingSystemType _operatingSystemType;
-
- public TestRuntimePlatform(OperatingSystemType operatingSystemType)
- {
- _operatingSystemType = operatingSystemType;
- }
-
- public override RuntimePlatformInfo GetRuntimeInfo()
- {
- return new RuntimePlatformInfo() { OperatingSystem = _operatingSystemType };
- }
- }
-}
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OptionsMarkupExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OptionsMarkupExtensionTests.cs
index 2d1f961743..0c67f385e1 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OptionsMarkupExtensionTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/OptionsMarkupExtensionTests.cs
@@ -434,7 +434,7 @@ public class OptionsMarkupExtensionTests : XamlTestBase
";
+ Text='{local:OptionsMarkupExtensionNoServiceProvider OptionB=""Im Option 2"", OptionA=""Im Option 1""}' />";
var textBlock = (TextBlock)AvaloniaRuntimeXamlLoader.Load(xaml);
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
index 4b32a8cdca..f42f787117 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
@@ -15,7 +15,6 @@ using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
-using JetBrains.Annotations;
using Xunit;
namespace Avalonia.Markup.Xaml.UnitTests
@@ -389,7 +388,6 @@ namespace Avalonia.Markup.Xaml.UnitTests
public bool IsPressed { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
- [NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
diff --git a/tests/Avalonia.RenderTests/Controls/AdornerTests.cs b/tests/Avalonia.RenderTests/Controls/AdornerTests.cs
new file mode 100644
index 0000000000..c833017212
--- /dev/null
+++ b/tests/Avalonia.RenderTests/Controls/AdornerTests.cs
@@ -0,0 +1,73 @@
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Layout;
+using Avalonia.Media;
+using Xunit;
+
+#if AVALONIA_SKIA
+namespace Avalonia.Skia.RenderTests;
+#else
+namespace Avalonia.Direct2D1.RenderTests.Controls;
+#endif
+
+public class AdornerTests : TestBase
+{
+ public AdornerTests()
+ : base(@"Controls\Adorner")
+ {
+ }
+
+ [Fact]
+ public async Task Focus_Adorner_Is_Properly_Clipped()
+ {
+ 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
+ }
+ }
+ }
+ },
+ Width = 200,
+ Height = 200
+ };
+ var adorner = new Border
+ {
+ BorderThickness = new Thickness(2),
+ BorderBrush = Brushes.Black
+ };
+
+ 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, skipDeferred: true);
+ }
+}
\ No newline at end of file
diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs
index 8a127897d7..313281d6c6 100644
--- a/tests/Avalonia.RenderTests/TestBase.cs
+++ b/tests/Avalonia.RenderTests/TestBase.cs
@@ -156,7 +156,8 @@ namespace Avalonia.Direct2D1.RenderTests
public ILockedFramebuffer Lock() => _bitmap.Lock();
}
- protected void CompareImages([CallerMemberName] string testName = "")
+ protected void CompareImages([CallerMemberName] string testName = "",
+ bool skipImmediate = false, bool skipDeferred = false, bool skipCompositor = false)
{
var expectedPath = Path.Combine(OutputPath, testName + ".expected.png");
var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png");
@@ -172,17 +173,17 @@ namespace Avalonia.Direct2D1.RenderTests
var deferredError = CompareImages(deferred, expected);
var compositedError = CompareImages(composited, expected);
- if (immediateError > 0.022)
+ if (immediateError > 0.022 && !skipImmediate)
{
Assert.True(false, immediatePath + ": Error = " + immediateError);
}
- if (deferredError > 0.022)
+ if (deferredError > 0.022 && !skipDeferred)
{
Assert.True(false, deferredPath + ": Error = " + deferredError);
}
- if (compositedError > 0.022)
+ if (compositedError > 0.022 && !skipCompositor)
{
Assert.True(false, compositedPath + ": Error = " + compositedError);
}
diff --git a/tests/Avalonia.UnitTests/TestServices.cs b/tests/Avalonia.UnitTests/TestServices.cs
index c421adaf21..8f132433ec 100644
--- a/tests/Avalonia.UnitTests/TestServices.cs
+++ b/tests/Avalonia.UnitTests/TestServices.cs
@@ -20,7 +20,7 @@ namespace Avalonia.UnitTests
{
public static readonly TestServices StyledWindow = new TestServices(
assetLoader: new AssetLoader(),
- platform: new AppBuilder().RuntimePlatform,
+ platform: new StandardRuntimePlatform(),
renderInterface: new MockPlatformRenderInterface(),
standardCursorFactory: Mock.Of(),
theme: () => CreateSimpleTheme(),
@@ -169,16 +169,4 @@ namespace Avalonia.UnitTests
y => y.Open() == Mock.Of()));
}
}
-
- public class AppBuilder : AppBuilderBase
- {
- public AppBuilder()
- : base(new StandardRuntimePlatform(),
- builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()
- ?.GetTypeInfo().Assembly))
- {
- }
-
- protected override bool CheckSetup => false;
- }
}
diff --git a/tests/Avalonia.UnitTests/TouchTestHelper.cs b/tests/Avalonia.UnitTests/TouchTestHelper.cs
new file mode 100644
index 0000000000..db70f570a2
--- /dev/null
+++ b/tests/Avalonia.UnitTests/TouchTestHelper.cs
@@ -0,0 +1,53 @@
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.VisualTree;
+
+namespace Avalonia.UnitTests
+{
+ public class TouchTestHelper
+ {
+ private readonly Pointer _pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Touch, true);
+ private ulong _nextStamp = 1;
+ private ulong Timestamp() => _nextStamp++;
+ public IInputElement Captured => _pointer.Captured;
+
+ public void Down(Interactive target, Point position = default, KeyModifiers modifiers = default)
+ {
+ Down(target, target, position, modifiers);
+ }
+
+ public void Down(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default)
+ {
+ _pointer.Capture((IInputElement)target);
+ source.RaiseEvent(new PointerPressedEventArgs(source, _pointer, (Visual)source, position, Timestamp(), PointerPointProperties.None,
+ modifiers));
+ }
+
+ public void Move(Interactive target, in Point position, KeyModifiers modifiers = default) => Move(target, target, position, modifiers);
+
+ public void Move(Interactive target, Interactive source, in Point position, KeyModifiers modifiers = default)
+ {
+ target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)target, position,
+ Timestamp(), PointerPointProperties.None, modifiers));
+ }
+
+ public void Up(Interactive target, Point position = default, KeyModifiers modifiers = default)
+ => Up(target, target, position, modifiers);
+
+ public void Up(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default)
+ {
+ source.RaiseEvent(new PointerReleasedEventArgs(source, _pointer, (Visual)target, position, Timestamp(), PointerPointProperties.None,
+ modifiers, MouseButton.None));
+ _pointer.Capture(null);
+ }
+
+ public void Tap(Interactive target, Point position = default, KeyModifiers modifiers = default)
+ => Tap(target, target, position, modifiers);
+
+ public void Tap(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default)
+ {
+ Down(target, source, position, modifiers);
+ Up(target, source, position, modifiers);
+ }
+ }
+}
diff --git a/tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png b/tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png
new file mode 100644
index 0000000000..6a67087d41
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png differ
diff --git a/tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png b/tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png
new file mode 100644
index 0000000000..6a67087d41
Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png differ