Browse Source

Merge branch 'master' into fix/ButtonSpinnerPointerWheel

pull/7252/head
Max Katz 4 years ago
committed by GitHub
parent
commit
7199cc2fce
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/Avalonia/Avalonia.csproj
  2. 33
      samples/ControlCatalog/App.xaml.cs
  3. 42
      samples/ControlCatalog/MainView.xaml.cs
  4. 2
      src/Avalonia.Animation/Avalonia.Animation.csproj
  5. 2
      src/Avalonia.Base/Avalonia.Base.csproj
  6. 2
      src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs
  7. 2
      src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
  8. 2
      src/Avalonia.Controls/Avalonia.Controls.csproj
  9. 2
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  10. 2
      src/Avalonia.Desktop/Avalonia.Desktop.csproj
  11. 2
      src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
  12. 2
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  13. 2
      src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
  14. 2
      src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
  15. 2
      src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj
  16. 2
      src/Avalonia.Headless/Avalonia.Headless.csproj
  17. 2
      src/Avalonia.Input/Avalonia.Input.csproj
  18. 2
      src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs
  19. 2
      src/Avalonia.Input/TouchDevice.cs
  20. 2
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  21. 2
      src/Avalonia.Layout/Avalonia.Layout.csproj
  22. 2
      src/Avalonia.Native/Avalonia.Native.csproj
  23. 2
      src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
  24. 2
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  25. 2
      src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
  26. 2
      src/Avalonia.Styling/Avalonia.Styling.csproj
  27. 2
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  28. 2
      src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
  29. 96
      src/Avalonia.Themes.Fluent/FluentTheme.cs
  30. 2
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  31. 4
      src/Avalonia.Visuals/Media/TextFormatting/Unicode/LineBreakEnumerator.cs
  32. 2
      src/Avalonia.X11/Avalonia.X11.csproj
  33. 2
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  34. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  35. 2
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  36. 2
      src/Markup/Avalonia.Markup/Avalonia.Markup.csproj
  37. 2
      src/Skia/Avalonia.Skia/Avalonia.Skia.csproj
  38. 2
      src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
  39. 2
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  40. 346
      tests/Avalonia.Input.UnitTests/TouchDeviceTests.cs

2
packages/Avalonia/Avalonia.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461;netcoreapp2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0;net461;netcoreapp2.0</TargetFrameworks>
<PackageId>Avalonia</PackageId>
</PropertyGroup>

33
samples/ControlCatalog/App.xaml.cs

@ -5,6 +5,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
using Avalonia.Themes.Fluent;
using ControlCatalog.ViewModels;
namespace ControlCatalog
@ -16,33 +17,17 @@ namespace ControlCatalog
DataContext = new ApplicationViewModel();
}
private static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
public static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml")
};
private static readonly StyleInclude DataGridDefault = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
public static readonly StyleInclude DataGridDefault = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Default.xaml")
};
public static Styles FluentDark = new Styles
{
new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml")
},
DataGridFluent
};
public static Styles FluentLight = new Styles
{
new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml")
},
DataGridFluent
};
public static FluentTheme Fluent = new FluentTheme(new Uri("avares://ControlCatalog/Styles"));
public static Styles DefaultLight = new Styles
{
@ -65,8 +50,7 @@ namespace ControlCatalog
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
},
DataGridDefault
}
};
public static Styles DefaultDark = new Styles
@ -90,14 +74,13 @@ namespace ControlCatalog
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
},
DataGridDefault
}
};
public override void Initialize()
{
Styles.Insert(0, FluentLight);
Styles.Insert(0, Fluent);
Styles.Insert(1, DataGridFluent);
AvaloniaXamlLoader.Load(this);
}

42
samples/ControlCatalog/MainView.xaml.cs

@ -3,14 +3,12 @@ using System.Collections;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Markup.Xaml.XamlIl;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
using ControlCatalog.Pages;
using Avalonia.Themes.Fluent;
using ControlCatalog.Models;
using ControlCatalog.Pages;
namespace ControlCatalog
{
@ -43,14 +41,36 @@ namespace ControlCatalog
{
if (themes.SelectedItem is CatalogTheme theme)
{
Application.Current.Styles[0] = theme switch
var themeStyle = Application.Current.Styles[0];
if (theme == CatalogTheme.FluentLight)
{
if (App.Fluent.Mode != FluentThemeMode.Light)
{
App.Fluent.Mode = FluentThemeMode.Light;
}
Application.Current.Styles[0] = App.Fluent;
Application.Current.Styles[1] = App.DataGridFluent;
}
else if (theme == CatalogTheme.FluentDark)
{
if (App.Fluent.Mode != FluentThemeMode.Dark)
{
App.Fluent.Mode = FluentThemeMode.Dark;
}
Application.Current.Styles[0] = App.Fluent;
Application.Current.Styles[1] = App.DataGridFluent;
}
else if (theme == CatalogTheme.DefaultLight)
{
Application.Current.Styles[0] = App.DefaultLight;
Application.Current.Styles[1] = App.DataGridDefault;
}
else if (theme == CatalogTheme.DefaultDark)
{
CatalogTheme.FluentLight => App.FluentLight,
CatalogTheme.FluentDark => App.FluentDark,
CatalogTheme.DefaultLight => App.DefaultLight,
CatalogTheme.DefaultDark => App.DefaultDark,
_ => Application.Current.Styles[0]
};
Application.Current.Styles[0] = App.DefaultDark;
Application.Current.Styles[1] = App.DataGridDefault;
}
}
};

2
src/Avalonia.Animation/Avalonia.Animation.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />

2
src/Avalonia.Base/Avalonia.Base.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AssemblyName>Avalonia.Base</AssemblyName>
<RootNamespace>Avalonia</RootNamespace>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>

2
src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs

@ -180,7 +180,7 @@ namespace Avalonia.Utilities
{
var r = _data[c];
if (r?.TryGetTarget(out var sub) == true)
sub.OnEvent(sender, eventArgs);
sub!.OnEvent(sender, eventArgs);
else
needCompact = true;
}

2
src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<PackageId>Avalonia.Controls.DataGrid</PackageId>
</PropertyGroup>
<ItemGroup>

2
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />

2
src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<!-- WARNING! The designer support version number needs to be frozen
To allow projects that implement designer functionality to still
work with newer versions of Avalonia. This version number only

2
src/Avalonia.Desktop/Avalonia.Desktop.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<PackageId>Avalonia.Desktop</PackageId>
</PropertyGroup>

2
src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;net461;netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>

2
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<RootNamespace>Avalonia</RootNamespace>
<PackageId>Avalonia.Diagnostics</PackageId>
</PropertyGroup>

2
src/Avalonia.Dialogs/Avalonia.Dialogs.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>

2
src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>

2
src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>

2
src/Avalonia.Headless/Avalonia.Headless.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>

2
src/Avalonia.Input/Avalonia.Input.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />

2
src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -71,7 +71,7 @@ namespace Avalonia.Input.GestureRecognizers
EndGesture();
_tracking = e.Pointer;
_gestureId = ScrollGestureEventArgs.GetNextFreeId();;
_trackedRootPoint = e.GetPosition(null);
_trackedRootPoint = e.GetPosition(_target);
}
}

2
src/Avalonia.Input/TouchDevice.cs

@ -61,7 +61,7 @@ namespace Avalonia.Input
var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
if (settings == null)
{
throw new Exception("IPlatformSettings can not be null");
throw new Exception("IPlatformSettings can not be null.");
}
if (!_lastClickRect.Contains(args.Position)
|| ev.Timestamp - _lastClickTime > settings.DoubleClickTime.TotalMilliseconds)

2
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />

2
src/Avalonia.Layout/Avalonia.Layout.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />

2
src/Avalonia.Native/Avalonia.Native.csproj

@ -4,7 +4,7 @@
<PackAvaloniaNative Condition="'$(PackAvaloniaNative)' == ''">$([MSBuild]::IsOSPlatform(OSX))</PackAvaloniaNative>
<IsPackable>$(PackAvaloniaNative)</IsPackable>
<IsPackable Condition="'$([MSBuild]::IsOSPlatform(OSX))' == 'True'">true</IsPackable>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

2
src/Avalonia.OpenGL/Avalonia.OpenGL.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

2
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<PackageId>Avalonia.ReactiveUI</PackageId>
<SignAssembly>false</SignAssembly>
</PropertyGroup>

2
src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<DefineConstants>AVALONIA_REMOTE_PROTOCOL;$(DefineConstants)</DefineConstants>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>

2
src/Avalonia.Styling/Avalonia.Styling.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AssemblyName>Avalonia.Styling</AssemblyName>
<RootNamespace>Avalonia</RootNamespace>
</PropertyGroup>

2
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />

2
src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />

96
src/Avalonia.Themes.Fluent/FluentTheme.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
#nullable enable
@ -17,11 +18,14 @@ namespace Avalonia.Themes.Fluent
/// <summary>
/// Includes the fluent theme in an application.
/// </summary>
public class FluentTheme : IStyle, IResourceProvider
public class FluentTheme : AvaloniaObject, IStyle, IResourceProvider
{
private readonly Uri _baseUri;
private IStyle[]? _loaded;
private Styles _fluentDark = new();
private Styles _fluentLight = new();
private Styles _sharedStyles = new();
private bool _isLoading;
private IStyle? _loaded;
/// <summary>
/// Initializes a new instance of the <see cref="FluentTheme"/> class.
@ -30,6 +34,7 @@ namespace Avalonia.Themes.Fluent
public FluentTheme(Uri baseUri)
{
_baseUri = baseUri;
InitStyles(baseUri);
}
/// <summary>
@ -39,12 +44,37 @@ namespace Avalonia.Themes.Fluent
public FluentTheme(IServiceProvider serviceProvider)
{
_baseUri = ((IUriContext)serviceProvider.GetService(typeof(IUriContext))).BaseUri;
InitStyles(_baseUri);
}
public static readonly StyledProperty<FluentThemeMode> ModeProperty =
AvaloniaProperty.Register<FluentTheme, FluentThemeMode>(nameof(Mode));
/// <summary>
/// Gets or sets the mode of the fluent theme (light, dark).
/// </summary>
public FluentThemeMode Mode { get; set; }
public FluentThemeMode Mode
{
get => GetValue(ModeProperty);
set => SetValue(ModeProperty, value);
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == ModeProperty)
{
if (Mode == FluentThemeMode.Dark)
{
(Loaded as Styles)![1] = _fluentDark[0];
(Loaded as Styles)![2] = _fluentDark[1];
}
else
{
(Loaded as Styles)![1] = _fluentLight[0];
(Loaded as Styles)![2] = _fluentLight[1];
}
}
}
public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner;
@ -58,18 +88,25 @@ namespace Avalonia.Themes.Fluent
if (_loaded == null)
{
_isLoading = true;
var loaded = (IStyle)AvaloniaXamlLoader.Load(GetUri(), _baseUri);
_loaded = new[] { loaded };
if (Mode == FluentThemeMode.Light)
{
_loaded = new Styles() { _sharedStyles , _fluentLight[0], _fluentLight[1] };
}
else if (Mode == FluentThemeMode.Dark)
{
_loaded = new Styles() { _sharedStyles, _fluentDark[0], _fluentDark[1] };
}
_isLoading = false;
}
return _loaded?[0]!;
return _loaded!;
}
}
bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false;
IReadOnlyList<IStyle> IStyle.Children => _loaded ?? Array.Empty<IStyle>();
IReadOnlyList<IStyle> IStyle.Children => _loaded?.Children ?? Array.Empty<IStyle>();
public event EventHandler OwnerChanged
{
@ -105,10 +142,47 @@ namespace Avalonia.Themes.Fluent
void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner);
void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner);
private Uri GetUri() => Mode switch
private void InitStyles(Uri baseUri)
{
FluentThemeMode.Dark => new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml", UriKind.Absolute),
_ => new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml", UriKind.Absolute),
};
_sharedStyles = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Controls/FluentControls.xaml")
}
};
_fluentLight = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml")
}
};
_fluentDark = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml")
}
};
}
}
}

2
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<RootNamespace>Avalonia</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

4
src/Avalonia.Visuals/Media/TextFormatting/Unicode/LineBreakEnumerator.cs

@ -80,12 +80,12 @@ namespace Avalonia.Media.TextFormatting.Unicode
}
}
var shouldBreak = GetSimpleBreak() ?? (bool?)GetPairTableBreak(lastClass);
var shouldBreak = GetSimpleBreak() ?? GetPairTableBreak(lastClass);
// Rule LB8a
_lb8a = _nextClass == LineBreakClass.ZWJ;
if (shouldBreak.Value)
if (shouldBreak)
{
Current = new LineBreak(FindPriorNonWhitespace(_lastPosition), _lastPosition);
return true;

2
src/Avalonia.X11/Avalonia.X11.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.X11</PackageId>
</PropertyGroup>

2
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.LinuxFramebuffer</PackageId>
</PropertyGroup>

2
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<IsPackable>true</IsPackable>
<PackageId>Avalonia.Markup.Xaml.Loader</PackageId>
<DefineConstants>$(DefineConstants);XAMLX_INTERNAL</DefineConstants>

2
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<DefineConstants>$(DefineConstants);PCL;NETSTANDARD;NETSTANDARD2_0;HAS_TYPE_CONVERTER;HAS_CUSTOM_ATTRIBUTE_PROVIDER;XAMLX_INTERNAL</DefineConstants>
<UseCecil>false</UseCecil>
<DefineConstants Condition="$(UseCecil) == true">$(DefineConstants);RUNTIME_XAML_CECIL</DefineConstants>

2
src/Markup/Avalonia.Markup/Avalonia.Markup.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<RootNamespace>Avalonia</RootNamespace>
</PropertyGroup>
<ItemGroup>

2
src/Skia/Avalonia.Skia/Avalonia.Skia.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<RootNamespace>Avalonia.Skia</RootNamespace>
<AssemblyName>Avalonia.Skia</AssemblyName>
<PackageId>Avalonia.Skia</PackageId>

2
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.Direct2D1</PackageId>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

2
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Avalonia.Win32</PackageId>
</PropertyGroup>

346
tests/Avalonia.Input.UnitTests/TouchDeviceTests.cs

@ -12,56 +12,47 @@ namespace Avalonia.Input.UnitTests
[Fact]
public void Tapped_Event_Is_Fired_With_Touch()
{
using (UnitTestApplication.Start(
new TestServices(inputManager: new InputManager())))
using var app = UnitTestApp(new TimeSpan(200));
var root = new TestRoot();
var touchDevice = new TouchDevice();
var isTapped = false;
var executedTimes = 0;
root.Tapped += (a, e) =>
{
var root = new TestRoot();
var touchDevice = new TouchDevice();
isTapped = true;
executedTimes++;
};
TapOnce(InputManager.Instance, touchDevice, root);
Assert.True(isTapped);
Assert.Equal(1, executedTimes);
var isTapped = false;
var executedTimes = 0;
root.Tapped += (a, e) =>
{
isTapped = true;
executedTimes++;
};
TapOnce(InputManager.Instance, touchDevice, root);
Assert.True(isTapped);
Assert.Equal(1, executedTimes);
}
}
[Fact]
public void DoubleTapped_Event_Is_Fired_With_Touch()
{
var platformSettingsMock = new Mock<IPlatformSettings>();
platformSettingsMock.Setup(x => x.DoubleClickTime).Returns(new TimeSpan(200));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind<IPlatformSettings>().ToConstant(platformSettingsMock.Object);
using (UnitTestApplication.Start(
new TestServices(inputManager: new InputManager())))
using var app = UnitTestApp(new TimeSpan(200));
var root = new TestRoot();
var touchDevice = new TouchDevice();
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
var tappedExecutedTimes = 0;
root.DoubleTapped += (a, e) =>
{
var root = new TestRoot();
var touchDevice = new TouchDevice();
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
var tappedExecutedTimes = 0;
root.DoubleTapped += (a, e) =>
{
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
TapOnce(InputManager.Instance, touchDevice, root);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 1);
Assert.Equal(1, tappedExecutedTimes);
Assert.True(isDoubleTapped);
Assert.Equal(1, doubleTappedExecutedTimes);
}
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
TapOnce(InputManager.Instance, touchDevice, root);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 1);
Assert.Equal(1, tappedExecutedTimes);
Assert.True(isDoubleTapped);
Assert.Equal(1, doubleTappedExecutedTimes);
}
[Theory]
@ -72,173 +63,158 @@ namespace Avalonia.Input.UnitTests
[InlineData(5)]
public void PointerPressed_Counts_Clicks_Correctly(int clickCount)
{
var platformSettingsMock = new Mock<IPlatformSettings>();
platformSettingsMock.Setup(x => x.DoubleClickTime).Returns(new TimeSpan(200));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind<IPlatformSettings>().ToConstant(platformSettingsMock.Object);
using (UnitTestApplication.Start(
new TestServices(inputManager: new InputManager())))
{
var root = new TestRoot();
var touchDevice = new TouchDevice();
using var app = UnitTestApp(new TimeSpan(200));
var root = new TestRoot();
var touchDevice = new TouchDevice();
var pointerPressedExecutedTimes = 0;
var pointerPressedClicks = 0;
root.PointerPressed += (a, e) =>
{
pointerPressedClicks = e.ClickCount;
pointerPressedExecutedTimes++;
};
for (int i = 0; i < clickCount; i++)
{
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: i);
}
Assert.Equal(clickCount, pointerPressedExecutedTimes);
Assert.Equal(pointerPressedClicks, clickCount);
var pointerPressedExecutedTimes = 0;
var pointerPressedClicks = 0;
root.PointerPressed += (a, e) =>
{
pointerPressedClicks = e.ClickCount;
pointerPressedExecutedTimes++;
};
for (int i = 0; i < clickCount; i++)
{
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: i);
}
Assert.Equal(clickCount, pointerPressedExecutedTimes);
Assert.Equal(pointerPressedClicks, clickCount);
}
[Fact]
public void DoubleTapped_Not_Fired_When_Click_Too_Late()
{
var platformSettingsMock = new Mock<IPlatformSettings>();
platformSettingsMock.Setup(x => x.DoubleClickTime).Returns(new TimeSpan(0, 0, 0, 0, 20));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind<IPlatformSettings>().ToConstant(platformSettingsMock.Object);
using (UnitTestApplication.Start(
new TestServices(inputManager: new InputManager())))
using var app = UnitTestApp(new TimeSpan(0, 0, 0, 0, 20));
var root = new TestRoot();
var touchDevice = new TouchDevice();
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
var tappedExecutedTimes = 0;
root.DoubleTapped += (a, e) =>
{
var root = new TestRoot();
var touchDevice = new TouchDevice();
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
TapOnce(InputManager.Instance, touchDevice, root);
TapOnce(InputManager.Instance, touchDevice, root, 21, 1);
Assert.Equal(2, tappedExecutedTimes);
Assert.False(isDoubleTapped);
Assert.Equal(0, doubleTappedExecutedTimes);
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
var tappedExecutedTimes = 0;
root.DoubleTapped += (a, e) =>
{
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
TapOnce(InputManager.Instance, touchDevice, root);
TapOnce(InputManager.Instance, touchDevice, root, 21, 1);
Assert.Equal(2, tappedExecutedTimes);
Assert.False(isDoubleTapped);
Assert.Equal(0, doubleTappedExecutedTimes);
}
}
[Fact]
public void DoubleTapped_Not_Fired_When_Second_Click_Is_From_Different_Touch_Contact()
{
var tmp = new Mock<IPlatformSettings>();
tmp.Setup(x => x.DoubleClickTime).Returns(new TimeSpan(200));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind<IPlatformSettings>().ToConstant(tmp.Object);
using (UnitTestApplication.Start(
new TestServices(inputManager: new InputManager())))
using var app = UnitTestApp(new TimeSpan(200));
var root = new TestRoot();
var touchDevice = new TouchDevice();
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
var tappedExecutedTimes = 0;
root.DoubleTapped += (a, e) =>
{
var root = new TestRoot();
var touchDevice = new TouchDevice();
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
var tappedExecutedTimes = 0;
root.DoubleTapped += (a, e) =>
{
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchBegin, 0, 1);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchEnd, 0, 1);
Assert.Equal(2, tappedExecutedTimes);
Assert.False(isDoubleTapped);
Assert.Equal(0, doubleTappedExecutedTimes);
}
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchBegin, 0, 1);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchEnd, 0, 1);
Assert.Equal(2, tappedExecutedTimes);
Assert.False(isDoubleTapped);
Assert.Equal(0, doubleTappedExecutedTimes);
}
[Fact]
public void Click_Counting_Should_Work_Correctly_With_Few_Touch_Contacts()
{
var tmp = new Mock<IPlatformSettings>();
tmp.Setup(x => x.DoubleClickTime).Returns(new TimeSpan(200));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind<IPlatformSettings>().ToConstant(tmp.Object);
using (UnitTestApplication.Start(
new TestServices(inputManager: new InputManager())))
{
var root = new TestRoot();
var touchDevice = new TouchDevice();
using var app = UnitTestApp(new TimeSpan(200));
var pointerPressedExecutedTimes = 0;
var tappedExecutedTimes = 0;
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
root.PointerPressed += (a, e) =>
{
pointerPressedExecutedTimes++;
switch (pointerPressedExecutedTimes)
{
case <= 2:
Assert.True(e.ClickCount == 1);
break;
case 3:
Assert.True(e.ClickCount == 2);
break;
case 4:
Assert.True(e.ClickCount == 3);
break;
case 5:
Assert.True(e.ClickCount == 4);
break;
case 6:
Assert.True(e.ClickCount == 5);
break;
case 7:
Assert.True(e.ClickCount == 1);
break;
case 8:
Assert.True(e.ClickCount == 1);
break;
case 9:
Assert.True(e.ClickCount == 2);
break;
default:
break;
}
};
root.DoubleTapped += (a, e) =>
{
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
var root = new TestRoot();
var touchDevice = new TouchDevice();
var pointerPressedExecutedTimes = 0;
var tappedExecutedTimes = 0;
var isDoubleTapped = false;
var doubleTappedExecutedTimes = 0;
root.PointerPressed += (a, e) =>
{
pointerPressedExecutedTimes++;
switch (pointerPressedExecutedTimes)
{
tappedExecutedTimes++;
};
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchBegin, 0, 1);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchEnd, 0, 1);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 2);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 3);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 4);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchBegin, 5, 6, 7);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchEnd, 5, 6, 7);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 8);
Assert.Equal(6, tappedExecutedTimes);
Assert.Equal(9, pointerPressedExecutedTimes);
Assert.True(isDoubleTapped);
Assert.Equal(3, doubleTappedExecutedTimes);
case <= 2:
Assert.True(e.ClickCount == 1);
break;
case 3:
Assert.True(e.ClickCount == 2);
break;
case 4:
Assert.True(e.ClickCount == 3);
break;
case 5:
Assert.True(e.ClickCount == 4);
break;
case 6:
Assert.True(e.ClickCount == 5);
break;
case 7:
Assert.True(e.ClickCount == 1);
break;
case 8:
Assert.True(e.ClickCount == 1);
break;
case 9:
Assert.True(e.ClickCount == 2);
break;
default:
break;
}
};
root.DoubleTapped += (a, e) =>
{
isDoubleTapped = true;
doubleTappedExecutedTimes++;
};
root.Tapped += (a, e) =>
{
tappedExecutedTimes++;
};
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchBegin, 0, 1);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchEnd, 0, 1);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 2);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 3);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 4);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchBegin, 5, 6, 7);
SendXTouchContactsWithIds(InputManager.Instance, touchDevice, root, RawPointerEventType.TouchEnd, 5, 6, 7);
TapOnce(InputManager.Instance, touchDevice, root, touchPointId: 8);
Assert.Equal(6, tappedExecutedTimes);
Assert.Equal(9, pointerPressedExecutedTimes);
Assert.True(isDoubleTapped);
Assert.Equal(3, doubleTappedExecutedTimes);
}
}
private IDisposable UnitTestApp(TimeSpan doubleClickTime = new TimeSpan())
{
var unitTestApp = UnitTestApplication.Start(
new TestServices(inputManager: new InputManager()));
var iSettingsMock = new Mock<IPlatformSettings>();
iSettingsMock.Setup(x => x.DoubleClickTime).Returns(doubleClickTime);
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind<IPlatformSettings>().ToConstant(iSettingsMock.Object);
return unitTestApp;
}
private static void SendXTouchContactsWithIds(IInputManager inputManager, TouchDevice device, IInputRoot root, RawPointerEventType type, params long[] touchPointIds)
{
for (int i = 0; i < touchPointIds.Length; i++)

Loading…
Cancel
Save