Browse Source

Merge branch 'master' into feature/FormattedTextPort

pull/4893/head
Benedikt Stebner 4 years ago
committed by GitHub
parent
commit
a91c86977f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 41
      Avalonia.sln
  2. 22
      samples/ControlCatalog/Pages/ViewboxPage.xaml
  3. 19
      samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
  4. 54
      samples/RenderDemo/Pages/ClippingPage.xaml
  5. 17
      samples/RenderDemo/Pages/ClippingPage.xaml.cs
  6. 5
      src/Android/Avalonia.Android/AndroidPlatform.cs
  7. 2
      src/Android/Avalonia.Android/AppBuilder.cs
  8. 4
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  9. 18
      src/Android/Avalonia.Android/RuntimeInfo.cs
  10. 5
      src/Avalonia.Base/Platform/IRuntimePlatform.cs
  11. 3
      src/Avalonia.DesktopRuntime/ApiCompatBaseline.txt
  12. 2
      src/Avalonia.DesktopRuntime/AppBuilder.cs
  13. 2
      src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
  14. 40
      src/Avalonia.DesktopRuntime/RuntimeInfo.cs
  15. 2
      src/Avalonia.Input/ICloseable.cs
  16. 22
      src/Avalonia.Input/IInputElement.cs
  17. 2
      src/Avalonia.Input/IMainMenu.cs
  18. 2
      src/Avalonia.Input/INavigableContainer.cs
  19. 32
      src/Avalonia.Input/InputElement.cs
  20. 10
      src/Avalonia.Input/TextInput/ITextInputMethodClient.cs
  21. 2
      src/Avalonia.Input/TextInput/ITextInputMethodImpl.cs
  22. 11
      src/Avalonia.Interactivity/Interactive.cs
  23. 2
      src/Avalonia.Layout/ElementManager.cs
  24. 2
      src/Avalonia.Layout/FlowLayoutAlgorithm.cs
  25. 8
      src/Avalonia.Layout/LayoutHelper.cs
  26. 2
      src/Avalonia.Layout/StackLayout.cs
  27. 2
      src/Avalonia.Layout/UniformGridLayout.cs
  28. 4
      src/Avalonia.Layout/VirtualizingLayout.cs
  29. 2
      src/Avalonia.Layout/WrapLayout/WrapLayout.cs
  30. 17
      src/Avalonia.PlatformSupport/AssetLoader.cs
  31. 18
      src/Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj
  32. 65
      src/Avalonia.PlatformSupport/DynLoader.cs
  33. 79
      src/Avalonia.PlatformSupport/StandardRuntimePlatform.cs
  34. 31
      src/Avalonia.PlatformSupport/StandardRuntimePlatformServices.cs
  35. 2
      src/Avalonia.Styling/Controls/IResourceHost.cs
  36. 2
      src/Avalonia.Styling/Controls/IResourceProvider.cs
  37. 4
      src/Avalonia.Styling/LogicalTree/LogicalTreeAttachmentEventArgs.cs
  38. 4
      src/Avalonia.Styling/Styling/IGlobalStyles.cs
  39. 48
      src/Avalonia.Themes.Fluent/FluentTheme.cs
  40. 4
      src/Avalonia.Visuals/Media/DrawingContext.cs
  41. 4
      src/Avalonia.Visuals/Platform/LockedFramebuffer.cs
  42. 2
      src/Avalonia.Visuals/VisualTree/IHostedVisualTreeRoot.cs
  43. 2
      src/Avalonia.Visuals/VisualTree/IVisualTreeHost.cs
  44. 17
      src/Shared/PlatformSupport/PlatformSupport.projitems
  45. 11
      src/Shared/PlatformSupport/PlatformSupport.shproj
  46. 28
      src/Shared/PlatformSupport/StandardRuntimePlatformServices.cs
  47. 13
      src/Shared/RenderHelpers/QuadBezierHelper.cs
  48. 14
      src/Shared/RenderHelpers/RenderHelpers.projitems
  49. 13
      src/Shared/RenderHelpers/RenderHelpers.shproj
  50. 84
      src/Shared/WindowResizeDragHelper.cs
  51. 3
      src/Skia/Avalonia.Skia/Avalonia.Skia.csproj
  52. 3
      src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj
  53. 5
      src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs
  54. 61
      src/Web/Avalonia.Web.Blazor/BlazorRuntimePlatform.cs
  55. 1
      src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
  56. 11
      src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
  57. 5
      src/iOS/Avalonia.iOS/Boilerplate/AppBuilder.cs
  58. 19
      src/iOS/Avalonia.iOS/Boilerplate/RuntimePlatform.cs
  59. 595
      src/iOS/Avalonia.iOS/Boilerplate/Shared.cs
  60. 4
      tests/Avalonia.Benchmarks/Themes/FluentBenchmark.cs
  61. 2
      tests/Avalonia.Benchmarks/Themes/ThemeBenchmark.cs
  62. 2
      tests/Avalonia.RenderTests/TestBase.cs
  63. 2
      tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
  64. 16
      tests/Avalonia.UnitTests/RuntimeInfo.cs
  65. 2
      tests/Avalonia.UnitTests/TestServices.cs
  66. 2
      tests/Avalonia.UnitTests/UnitTestApplication.cs

41
Avalonia.sln

@ -60,20 +60,17 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlatformSupport", "src\Shared\PlatformSupport\PlatformSupport.shproj", "{E4D9629C-F168-4224-3F51-A5E482FFBC42}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Markup\Avalonia.Markup\Avalonia.Markup.csproj", "{6417E941-21BC-467B-A771-0DE389353CE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingDemo", "samples\BindingDemo\BindingDemo.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skia", "Skia", "{3743B0F2-CC41-4F14-A8C8-267F579BF91E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}"
@ -235,15 +232,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "sampl
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 5
src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 5
src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 5
src\Shared\PlatformSupport\PlatformSupport.projitems*{88060192-33d5-4932-b0f9-8bd2763e857d}*SharedItemsImports = 5
src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|iPhone = Ad-Hoc|iPhone
@ -2169,6 +2160,30 @@ Global
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhone.Build.0 = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.Build.0 = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.ActiveCfg = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.Build.0 = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2187,11 +2202,9 @@ Global
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{E4D9629C-F168-4224-3F51-A5E482FFBC42} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{3C4C0CB4-0C0F-4450-A37B-148C84FF905F} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}

22
samples/ControlCatalog/Pages/ViewboxPage.xaml

@ -1,5 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:collections="clr-namespace:System.Collections;assembly=netstandard"
x:Class="ControlCatalog.Pages.ViewboxPage">
<Grid RowDefinitions="Auto,*,*">
@ -12,8 +13,8 @@
<Border HorizontalAlignment="Center" Grid.Column="0" BorderThickness="1" BorderBrush="Orange" Width="200" Height="200">
<Border VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0" BorderThickness="1" BorderBrush="CornflowerBlue" Width="{Binding #WidthSlider.Value}" Height="{Binding #HeightSlider.Value}" >
<Viewbox
Stretch="{Binding #StretchSelector.SelectedItem}"
StretchDirection="{Binding #StretchDirectionSelector.SelectedItem}">
Stretch="{Binding #StretchSelector.SelectedItem, FallbackValue={x:Static Stretch.Uniform}}"
StretchDirection="{Binding #StretchDirectionSelector.SelectedItem, FallbackValue={x:Static StretchDirection.Both}}">
<Ellipse Width="50" Height="50" Fill="CornflowerBlue" />
</Viewbox>
</Border>
@ -25,9 +26,22 @@
<TextBlock Text="Height" />
<Slider Minimum="10" Maximum="200" Value="100" x:Name="HeightSlider" TickFrequency="25" TickPlacement="TopLeft" />
<TextBlock Text="Stretch" />
<ComboBox x:Name="StretchSelector" HorizontalAlignment="Stretch" Margin="0,0,0,2" />
<ComboBox x:Name="StretchSelector" HorizontalAlignment="Stretch" SelectedIndex="0" Margin="0,0,0,2">
<collections:ArrayList>
<Stretch>Uniform</Stretch>
<Stretch>UniformToFill</Stretch>
<Stretch>Fill</Stretch>
<Stretch>None</Stretch>
</collections:ArrayList>
</ComboBox>
<TextBlock Text="Stretch Direction" />
<ComboBox x:Name="StretchDirectionSelector" HorizontalAlignment="Stretch" />
<ComboBox x:Name="StretchDirectionSelector" SelectedIndex="0" HorizontalAlignment="Stretch">
<collections:ArrayList>
<StretchDirection>Both</StretchDirection>
<StretchDirection>DownOnly</StretchDirection>
<StretchDirection>UpOnly</StretchDirection>
</collections:ArrayList>
</ComboBox>
</StackPanel>
</Grid>

19
samples/ControlCatalog/Pages/ViewboxPage.xaml.cs

@ -1,6 +1,5 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
namespace ControlCatalog.Pages
{
@ -9,24 +8,6 @@ namespace ControlCatalog.Pages
public ViewboxPage()
{
InitializeComponent();
var stretchSelector = this.FindControl<ComboBox>("StretchSelector");
stretchSelector.Items = new[]
{
Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None
};
stretchSelector.SelectedIndex = 0;
var stretchDirectionSelector = this.FindControl<ComboBox>("StretchDirectionSelector");
stretchDirectionSelector.Items = new[]
{
StretchDirection.Both, StretchDirection.DownOnly, StretchDirection.UpOnly
};
stretchDirectionSelector.SelectedIndex = 0;
}
private void InitializeComponent()

54
samples/RenderDemo/Pages/ClippingPage.xaml

@ -19,30 +19,36 @@
</Style>
</Styles>
</Grid.Styles>
<Border Name="clipped"
Background="Yellow"
Width="100"
Height="100"
Clip="M 58.625 0.07421875
C 50.305778 0.26687364 42.411858 7.0346526 41.806641 15.595703
C 42.446442 22.063923 39.707425 13.710754 36.982422 12.683594
C 29.348395 6.1821635 16.419398 8.4359222 11.480469 17.195312
C 6.0935256 25.476803 9.8118851 37.71125 18.8125 41.6875
C 9.1554771 40.62945 -0.070876925 49.146842 0.21679688 58.857422
C 0.21545578 60.872512 0.56758794 62.88911 1.2617188 64.78125
C 4.3821886 74.16708 16.298268 78.921772 25.03125 74.326172
C 28.266843 72.062552 26.298191 74.214838 25.414062 76.398438
C 21.407348 85.589198 27.295992 97.294293 37.097656 99.501953
C 46.864883 102.3541 57.82177 94.726518 58.539062 84.580078
C 58.142158 79.498998 59.307538 83.392694 61.207031 85.433594
C 67.532324 93.056874 80.440232 93.192029 86.882812 85.630859
C 93.836392 78.456939 92.396838 65.538666 84.115234 60.009766
C 79.783641 57.904836 83.569793 58.802369 86.375 58.193359
C 96.383335 56.457569 102.87506 44.824101 99.083984 35.394531
C 95.963498 26.008711 84.047451 21.254079 75.314453 25.849609
C 72.078834 28.113269 74.047517 25.960974 74.931641 23.777344
C 78.93827 14.586564 73.049722 2.8815081 63.248047 0.67382812
C 61.721916 0.22817968 60.165597 0.038541919 58.625 0.07421875 z ">
<Border Name="clipped"
Background="Yellow"
Width="100"
Height="100"
Classes.clip="{Binding #useMask.IsChecked}">
<Border.Styles>
<Style Selector="Border.clip">
<Setter Property="Clip"
Value="M 58.625 0.07421875
C 50.305778 0.26687364 42.411858 7.0346526 41.806641 15.595703
C 42.446442 22.063923 39.707425 13.710754 36.982422 12.683594
C 29.348395 6.1821635 16.419398 8.4359222 11.480469 17.195312
C 6.0935256 25.476803 9.8118851 37.71125 18.8125 41.6875
C 9.1554771 40.62945 -0.070876925 49.146842 0.21679688 58.857422
C 0.21545578 60.872512 0.56758794 62.88911 1.2617188 64.78125
C 4.3821886 74.16708 16.298268 78.921772 25.03125 74.326172
C 28.266843 72.062552 26.298191 74.214838 25.414062 76.398438
C 21.407348 85.589198 27.295992 97.294293 37.097656 99.501953
C 46.864883 102.3541 57.82177 94.726518 58.539062 84.580078
C 58.142158 79.498998 59.307538 83.392694 61.207031 85.433594
C 67.532324 93.056874 80.440232 93.192029 86.882812 85.630859
C 93.836392 78.456939 92.396838 65.538666 84.115234 60.009766
C 79.783641 57.904836 83.569793 58.802369 86.375 58.193359
C 96.383335 56.457569 102.87506 44.824101 99.083984 35.394531
C 95.963498 26.008711 84.047451 21.254079 75.314453 25.849609
C 72.078834 28.113269 74.047517 25.960974 74.931641 23.777344
C 78.93827 14.586564 73.049722 2.8815081 63.248047 0.67382812
C 61.721916 0.22817968 60.165597 0.038541919 58.625 0.07421875 z " />
</Style>
</Border.Styles>
<Border Name="clipChild" Background="Red" Margin="4">
<!-- Setting opacity puts the TextBox on a new layer -->
<TextBox Text="Avalonia" Opacity="0.9" VerticalAlignment="Center"/>

17
samples/RenderDemo/Pages/ClippingPage.xaml.cs

@ -1,35 +1,18 @@
using System;
using System.Reactive.Linq;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
namespace RenderDemo.Pages
{
public class ClippingPage : UserControl
{
private Geometry _clip;
public ClippingPage()
{
InitializeComponent();
WireUpCheckbox();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void WireUpCheckbox()
{
var useMask = this.FindControl<CheckBox>("useMask");
var clipped = this.FindControl<Border>("clipped");
_clip = clipped.Clip;
useMask.Click += (s, e) => clipped.Clip = clipped.Clip == null ? _clip : null;
}
}
}

5
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -10,7 +10,7 @@ using Avalonia.Input.Platform;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
using Avalonia.Skia;
namespace Avalonia
@ -59,8 +59,7 @@ namespace Avalonia.Android
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoaderStub>()
.Bind<IRenderTimer>().ToConstant(new ChoreographerTimer())
.Bind<IRenderLoop>().ToConstant(new RenderLoop())
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
.Bind<IAssetLoader>().ToConstant(new AssetLoader(appType.Assembly));
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
SkiaPlatform.Initialize();

2
src/Android/Avalonia.Android/AppBuilder.cs

@ -1,5 +1,5 @@
using Avalonia.Controls;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
namespace Avalonia
{

4
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -5,9 +5,11 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
<ProjectReference Include="..\..\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj">
<SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
</ProjectReference>
<ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
</ItemGroup>
<Import Project="..\..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
<Import Project="..\..\..\build\Rx.props" />
<Import Project="..\..\..\build\AndroidWorkarounds.props" />
</Project>

18
src/Android/Avalonia.Android/RuntimeInfo.cs

@ -1,18 +0,0 @@
using Avalonia.Platform;
namespace Avalonia.Shared.PlatformSupport
{
internal partial class StandardRuntimePlatform
{
public RuntimePlatformInfo GetRuntimeInfo() => new RuntimePlatformInfo
{
IsCoreClr = false,
IsDesktop = false,
IsMobile = true,
IsDotNetFramework = false,
IsMono = true,
IsUnix = true,
OperatingSystem = OperatingSystemType.Android
};
}
}

5
src/Avalonia.Base/Platform/IRuntimePlatform.cs

@ -1,5 +1,4 @@
using System;
using System.Reflection;
namespace Avalonia.Platform
{
@ -23,6 +22,7 @@ namespace Avalonia.Platform
public OperatingSystemType OperatingSystem { get; set; }
public bool IsDesktop { get; set; }
public bool IsMobile { get; set; }
public bool IsBrowser { get; set; }
public bool IsCoreClr { get; set; }
public bool IsMono { get; set; }
public bool IsDotNetFramework { get; set; }
@ -36,6 +36,7 @@ namespace Avalonia.Platform
Linux,
OSX,
Android,
iOS
iOS,
Browser
}
}

3
src/Avalonia.DesktopRuntime/ApiCompatBaseline.txt

@ -0,0 +1,3 @@
Compat issues with assembly Avalonia.DesktopRuntime:
TypesMustExist : Type 'Avalonia.Shared.PlatformSupport.AssetLoader' does not exist in the implementation but it does exist in the contract.
Total Issues: 1

2
src/Avalonia.DesktopRuntime/AppBuilder.cs

@ -4,7 +4,7 @@ using System.Linq;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
namespace Avalonia
{

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

@ -8,6 +8,7 @@
<ProjectReference Include="../Avalonia.Base/Avalonia.Base.csproj" />
<ProjectReference Include="../Avalonia.Visuals/Avalonia.Visuals.csproj" />
<ProjectReference Include="../Avalonia.Controls/Avalonia.Controls.csproj" />
<ProjectReference Include="../Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj" />
</ItemGroup>
<ItemGroup>
@ -16,6 +17,5 @@
<Import Project="..\..\build\NetCore.props" />
<Import Project="..\..\build\NetFX.props" />
<Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" />
<Import Project="..\..\build\ApiDiff.props" />
</Project>

40
src/Avalonia.DesktopRuntime/RuntimeInfo.cs

@ -1,40 +0,0 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Platform;
namespace Avalonia.Shared.PlatformSupport
{
internal partial class StandardRuntimePlatform
{
private static readonly Lazy<RuntimePlatformInfo> Info = new Lazy<RuntimePlatformInfo>(() =>
{
OperatingSystemType os;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
os = OperatingSystemType.OSX;
else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
os = OperatingSystemType.Linux;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
os = OperatingSystemType.WinNT;
else
throw new Exception("Unknown OS platform " + RuntimeInformation.OSDescription);
return new RuntimePlatformInfo
{
#if NETCOREAPP2_0
IsCoreClr = true,
#elif NET461
IsDotNetFramework = false,
#endif
IsDesktop = true,
IsMono = false,
IsMobile = false,
IsUnix = os != OperatingSystemType.WinNT,
OperatingSystem = os,
};
});
public RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
}
}

2
src/Avalonia.Input/ICloseable.cs

@ -4,6 +4,6 @@ namespace Avalonia.Input
{
public interface ICloseable
{
event EventHandler Closed;
event EventHandler? Closed;
}
}

22
src/Avalonia.Input/IInputElement.cs

@ -15,57 +15,57 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the control receives focus.
/// </summary>
event EventHandler<GotFocusEventArgs> GotFocus;
event EventHandler<GotFocusEventArgs>? GotFocus;
/// <summary>
/// Occurs when the control loses focus.
/// </summary>
event EventHandler<RoutedEventArgs> LostFocus;
event EventHandler<RoutedEventArgs>? LostFocus;
/// <summary>
/// Occurs when a key is pressed while the control has focus.
/// </summary>
event EventHandler<KeyEventArgs> KeyDown;
event EventHandler<KeyEventArgs>? KeyDown;
/// <summary>
/// Occurs when a key is released while the control has focus.
/// </summary>
event EventHandler<KeyEventArgs> KeyUp;
event EventHandler<KeyEventArgs>? KeyUp;
/// <summary>
/// Occurs when a user typed some text while the control has focus.
/// </summary>
event EventHandler<TextInputEventArgs> TextInput;
event EventHandler<TextInputEventArgs>? TextInput;
/// <summary>
/// Occurs when the pointer enters the control.
/// </summary>
event EventHandler<PointerEventArgs> PointerEnter;
event EventHandler<PointerEventArgs>? PointerEnter;
/// <summary>
/// Occurs when the pointer leaves the control.
/// </summary>
event EventHandler<PointerEventArgs> PointerLeave;
event EventHandler<PointerEventArgs>? PointerLeave;
/// <summary>
/// Occurs when the pointer is pressed over the control.
/// </summary>
event EventHandler<PointerPressedEventArgs> PointerPressed;
event EventHandler<PointerPressedEventArgs>? PointerPressed;
/// <summary>
/// Occurs when the pointer moves over the control.
/// </summary>
event EventHandler<PointerEventArgs> PointerMoved;
event EventHandler<PointerEventArgs>? PointerMoved;
/// <summary>
/// Occurs when the pointer is released over the control.
/// </summary>
event EventHandler<PointerReleasedEventArgs> PointerReleased;
event EventHandler<PointerReleasedEventArgs>? PointerReleased;
/// <summary>
/// Occurs when the mouse wheel is scrolled over the control.
/// </summary>
event EventHandler<PointerWheelEventArgs> PointerWheelChanged;
event EventHandler<PointerWheelEventArgs>? PointerWheelChanged;
/// <summary>
/// Gets or sets a value indicating whether the control can receive keyboard focus.

2
src/Avalonia.Input/IMainMenu.cs

@ -27,6 +27,6 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the main menu closes.
/// </summary>
event EventHandler<RoutedEventArgs> MenuClosed;
event EventHandler<RoutedEventArgs>? MenuClosed;
}
}

2
src/Avalonia.Input/INavigableContainer.cs

@ -12,6 +12,6 @@ namespace Avalonia.Input
/// <param name="from">The control from which movement begins.</param>
/// <param name="wrap">Whether to wrap around when the first or last item is reached.</param>
/// <returns>The control.</returns>
IInputElement GetControl(NavigationDirection direction, IInputElement from, bool wrap);
IInputElement? GetControl(NavigationDirection direction, IInputElement? from, bool wrap);
}
}

32
src/Avalonia.Input/InputElement.cs

@ -233,7 +233,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the control receives focus.
/// </summary>
public event EventHandler<GotFocusEventArgs> GotFocus
public event EventHandler<GotFocusEventArgs>? GotFocus
{
add { AddHandler(GotFocusEvent, value); }
remove { RemoveHandler(GotFocusEvent, value); }
@ -242,7 +242,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the control loses focus.
/// </summary>
public event EventHandler<RoutedEventArgs> LostFocus
public event EventHandler<RoutedEventArgs>? LostFocus
{
add { AddHandler(LostFocusEvent, value); }
remove { RemoveHandler(LostFocusEvent, value); }
@ -251,7 +251,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when a key is pressed while the control has focus.
/// </summary>
public event EventHandler<KeyEventArgs> KeyDown
public event EventHandler<KeyEventArgs>? KeyDown
{
add { AddHandler(KeyDownEvent, value); }
remove { RemoveHandler(KeyDownEvent, value); }
@ -260,7 +260,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when a key is released while the control has focus.
/// </summary>
public event EventHandler<KeyEventArgs> KeyUp
public event EventHandler<KeyEventArgs>? KeyUp
{
add { AddHandler(KeyUpEvent, value); }
remove { RemoveHandler(KeyUpEvent, value); }
@ -269,7 +269,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when a user typed some text while the control has focus.
/// </summary>
public event EventHandler<TextInputEventArgs> TextInput
public event EventHandler<TextInputEventArgs>? TextInput
{
add { AddHandler(TextInputEvent, value); }
remove { RemoveHandler(TextInputEvent, value); }
@ -278,7 +278,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when an input element gains input focus and input method is looking for the corresponding client
/// </summary>
public event EventHandler<TextInputMethodClientRequestedEventArgs> TextInputMethodClientRequested
public event EventHandler<TextInputMethodClientRequestedEventArgs>? TextInputMethodClientRequested
{
add { AddHandler(TextInputMethodClientRequestedEvent, value); }
remove { RemoveHandler(TextInputMethodClientRequestedEvent, value); }
@ -287,7 +287,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when an input element gains input focus and input method is asking for required content options
/// </summary>
public event EventHandler<TextInputOptionsQueryEventArgs> TextInputOptionsQuery
public event EventHandler<TextInputOptionsQueryEventArgs>? TextInputOptionsQuery
{
add { AddHandler(TextInputOptionsQueryEvent, value); }
remove { RemoveHandler(TextInputOptionsQueryEvent, value); }
@ -296,7 +296,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the pointer enters the control.
/// </summary>
public event EventHandler<PointerEventArgs> PointerEnter
public event EventHandler<PointerEventArgs>? PointerEnter
{
add { AddHandler(PointerEnterEvent, value); }
remove { RemoveHandler(PointerEnterEvent, value); }
@ -305,7 +305,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the pointer leaves the control.
/// </summary>
public event EventHandler<PointerEventArgs> PointerLeave
public event EventHandler<PointerEventArgs>? PointerLeave
{
add { AddHandler(PointerLeaveEvent, value); }
remove { RemoveHandler(PointerLeaveEvent, value); }
@ -314,7 +314,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the pointer moves over the control.
/// </summary>
public event EventHandler<PointerEventArgs> PointerMoved
public event EventHandler<PointerEventArgs>? PointerMoved
{
add { AddHandler(PointerMovedEvent, value); }
remove { RemoveHandler(PointerMovedEvent, value); }
@ -323,7 +323,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the pointer is pressed over the control.
/// </summary>
public event EventHandler<PointerPressedEventArgs> PointerPressed
public event EventHandler<PointerPressedEventArgs>? PointerPressed
{
add { AddHandler(PointerPressedEvent, value); }
remove { RemoveHandler(PointerPressedEvent, value); }
@ -332,7 +332,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the pointer is released over the control.
/// </summary>
public event EventHandler<PointerReleasedEventArgs> PointerReleased
public event EventHandler<PointerReleasedEventArgs>? PointerReleased
{
add { AddHandler(PointerReleasedEvent, value); }
remove { RemoveHandler(PointerReleasedEvent, value); }
@ -342,7 +342,7 @@ namespace Avalonia.Input
/// Occurs when the control or its child control loses the pointer capture for any reason,
/// event will not be triggered for a parent control if capture was transferred to another child of that parent control
/// </summary>
public event EventHandler<PointerCaptureLostEventArgs> PointerCaptureLost
public event EventHandler<PointerCaptureLostEventArgs>? PointerCaptureLost
{
add => AddHandler(PointerCaptureLostEvent, value);
remove => RemoveHandler(PointerCaptureLostEvent, value);
@ -351,7 +351,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the mouse is scrolled over the control.
/// </summary>
public event EventHandler<PointerWheelEventArgs> PointerWheelChanged
public event EventHandler<PointerWheelEventArgs>? PointerWheelChanged
{
add { AddHandler(PointerWheelChangedEvent, value); }
remove { RemoveHandler(PointerWheelChangedEvent, value); }
@ -360,7 +360,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when a tap gesture occurs on the control.
/// </summary>
public event EventHandler<TappedEventArgs> Tapped
public event EventHandler<TappedEventArgs>? Tapped
{
add { AddHandler(TappedEvent, value); }
remove { RemoveHandler(TappedEvent, value); }
@ -369,7 +369,7 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when a double-tap gesture occurs on the control.
/// </summary>
public event EventHandler<TappedEventArgs> DoubleTapped
public event EventHandler<TappedEventArgs>? DoubleTapped
{
add { AddHandler(DoubleTappedEvent, value); }
remove { RemoveHandler(DoubleTappedEvent, value); }

10
src/Avalonia.Input/TextInput/ITextInputMethodClient.cs

@ -12,7 +12,7 @@ namespace Avalonia.Input.TextInput
/// <summary>
/// Should be fired when cursor rectangle is changed inside the TextViewVisual
/// </summary>
event EventHandler CursorRectangleChanged;
event EventHandler? CursorRectangleChanged;
/// <summary>
/// The visual that's showing the text
/// </summary>
@ -20,7 +20,7 @@ namespace Avalonia.Input.TextInput
/// <summary>
/// Should be fired when text-hosting visual is changed
/// </summary>
event EventHandler TextViewVisualChanged;
event EventHandler? TextViewVisualChanged;
/// <summary>
/// Indicates if TextViewVisual is capable of displaying non-committed input on the cursor position
/// </summary>
@ -40,15 +40,15 @@ namespace Avalonia.Input.TextInput
/// <summary>
/// Should be fired when surrounding text changed
/// </summary>
event EventHandler SurroundingTextChanged;
event EventHandler? SurroundingTextChanged;
/// <summary>
/// Returns the text before the cursor. Must return a non-empty string if cursor is not at the beginning of the text entry
/// </summary>
string TextBeforeCursor { get; }
string? TextBeforeCursor { get; }
/// <summary>
/// Returns the text before the cursor. Must return a non-empty string if cursor is not at the end of the text entry
/// </summary>
string TextAfterCursor { get; }
string? TextAfterCursor { get; }
}
public struct TextInputMethodSurroundingText

2
src/Avalonia.Input/TextInput/ITextInputMethodImpl.cs

@ -10,6 +10,6 @@ namespace Avalonia.Input.TextInput
public interface ITextInputMethodRoot : IInputRoot
{
ITextInputMethodImpl InputMethod { get; }
ITextInputMethodImpl? InputMethod { get; }
}
}

11
src/Avalonia.Interactivity/Interactive.cs

@ -50,12 +50,14 @@ namespace Avalonia.Interactivity
/// <param name="handledEventsToo">Whether handled events should also be listened for.</param>
public void AddHandler<TEventArgs>(
RoutedEvent<TEventArgs> routedEvent,
EventHandler<TEventArgs> handler,
EventHandler<TEventArgs>? handler,
RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble,
bool handledEventsToo = false) where TEventArgs : RoutedEventArgs
{
routedEvent = routedEvent ?? throw new ArgumentNullException(nameof(routedEvent));
handler = handler ?? throw new ArgumentNullException(nameof(handler));
if (handler is null)
return;
static void InvokeAdapter(Delegate baseHandler, object sender, RoutedEventArgs args)
{
@ -99,10 +101,11 @@ namespace Avalonia.Interactivity
/// <typeparam name="TEventArgs">The type of the event's args.</typeparam>
/// <param name="routedEvent">The routed event.</param>
/// <param name="handler">The handler.</param>
public void RemoveHandler<TEventArgs>(RoutedEvent<TEventArgs> routedEvent, EventHandler<TEventArgs> handler)
public void RemoveHandler<TEventArgs>(RoutedEvent<TEventArgs> routedEvent, EventHandler<TEventArgs>? handler)
where TEventArgs : RoutedEventArgs
{
RemoveHandler(routedEvent, (Delegate)handler);
if (handler is not null)
RemoveHandler(routedEvent, (Delegate)handler);
}
/// <summary>

2
src/Avalonia.Layout/ElementManager.cs

@ -263,7 +263,7 @@ namespace Avalonia.Layout
return intersects;
}
public void DataSourceChanged(object source, NotifyCollectionChangedEventArgs args)
public void DataSourceChanged(object? source, NotifyCollectionChangedEventArgs args)
{
if (_realizedElements.Count > 0)
{

2
src/Avalonia.Layout/FlowLayoutAlgorithm.cs

@ -135,7 +135,7 @@ namespace Avalonia.Layout
}
public void OnItemsSourceChanged(
object source,
object? source,
NotifyCollectionChangedEventArgs args,
VirtualizingLayoutContext context)
{

8
src/Avalonia.Layout/LayoutHelper.cs

@ -33,13 +33,13 @@ namespace Avalonia.Layout
MathUtilities.Clamp(constraints.Height, minmax.MinHeight, minmax.MaxHeight));
}
public static Size MeasureChild(ILayoutable control, Size availableSize, Thickness padding,
public static Size MeasureChild(ILayoutable? control, Size availableSize, Thickness padding,
Thickness borderThickness)
{
return MeasureChild(control, availableSize, padding + borderThickness);
}
public static Size MeasureChild(ILayoutable control, Size availableSize, Thickness padding)
public static Size MeasureChild(ILayoutable? control, Size availableSize, Thickness padding)
{
if (control != null)
{
@ -50,12 +50,12 @@ namespace Avalonia.Layout
return new Size(padding.Left + padding.Right, padding.Bottom + padding.Top);
}
public static Size ArrangeChild(ILayoutable child, Size availableSize, Thickness padding, Thickness borderThickness)
public static Size ArrangeChild(ILayoutable? child, Size availableSize, Thickness padding, Thickness borderThickness)
{
return ArrangeChild(child, availableSize, padding + borderThickness);
}
public static Size ArrangeChild(ILayoutable child, Size availableSize, Thickness padding)
public static Size ArrangeChild(ILayoutable? child, Size availableSize, Thickness padding)
{
child?.Arrange(new Rect(availableSize).Deflate(padding));

2
src/Avalonia.Layout/StackLayout.cs

@ -313,7 +313,7 @@ namespace Avalonia.Layout
return new Size(value.Width, value.Height);
}
protected internal override void OnItemsChangedCore(VirtualizingLayoutContext context, object source, NotifyCollectionChangedEventArgs args)
protected internal override void OnItemsChangedCore(VirtualizingLayoutContext context, object? source, NotifyCollectionChangedEventArgs args)
{
GetFlowAlgorithm(context).OnItemsSourceChanged(source, args, context);
// Always invalidate layout to keep the view accurate.

2
src/Avalonia.Layout/UniformGridLayout.cs

@ -461,7 +461,7 @@ namespace Avalonia.Layout
return new Size(value.Width, value.Height);
}
protected internal override void OnItemsChangedCore(VirtualizingLayoutContext context, object source, NotifyCollectionChangedEventArgs args)
protected internal override void OnItemsChangedCore(VirtualizingLayoutContext context, object? source, NotifyCollectionChangedEventArgs args)
{
GetFlowAlgorithm(context).OnItemsSourceChanged(source, args, context);
// Always invalidate layout to keep the view accurate.

4
src/Avalonia.Layout/VirtualizingLayout.cs

@ -35,7 +35,7 @@ namespace Avalonia.Layout
/// </remarks>
public void OnItemsChanged(
VirtualizingLayoutContext context,
object source,
object? source,
NotifyCollectionChangedEventArgs args) => OnItemsChangedCore(context, source, args);
/// <summary>
@ -113,7 +113,7 @@ namespace Avalonia.Layout
/// <param name="args">Data about the collection change.</param>
protected internal virtual void OnItemsChangedCore(
VirtualizingLayoutContext context,
object source,
object? source,
NotifyCollectionChangedEventArgs args) => InvalidateMeasure();
}
}

2
src/Avalonia.Layout/WrapLayout/WrapLayout.cs

@ -86,7 +86,7 @@ namespace Avalonia.Layout
}
/// <inheritdoc />
protected internal override void OnItemsChangedCore(VirtualizingLayoutContext context, object source, NotifyCollectionChangedEventArgs args)
protected internal override void OnItemsChangedCore(VirtualizingLayoutContext context, object? source, NotifyCollectionChangedEventArgs args)
{
var state = (WrapLayoutState)context.LayoutState!;

17
src/Shared/PlatformSupport/AssetLoader.cs → src/Avalonia.PlatformSupport/AssetLoader.cs

@ -6,9 +6,7 @@ using System.Reflection;
using Avalonia.Platform;
using Avalonia.Utilities;
#nullable enable
namespace Avalonia.Shared.PlatformSupport
namespace Avalonia.PlatformSupport
{
/// <summary>
/// Loads assets compiled into the application binary.
@ -233,14 +231,15 @@ namespace Avalonia.Shared.PlatformSupport
else
{
// iOS does not support loading assemblies dynamically!
//
#if __IOS__
throw new InvalidOperationException(
$"Assembly {name} needs to be referenced and explicitly loaded before loading resources");
#else
#if NET6_0_OR_GREATER
if (OperatingSystem.IsIOS())
{
throw new InvalidOperationException(
$"Assembly {name} needs to be referenced and explicitly loaded before loading resources");
}
#endif
name = Uri.UnescapeDataString(name);
AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name));
#endif
}
}

18
src/Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net461;netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Avalonia.Base/Avalonia.Base.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" Condition="'$(TargetFramework)' == 'net461'" />
</ItemGroup>
<Import Project="..\..\build\NetCore.props" />
<Import Project="..\..\build\NetFX.props" />
<Import Project="..\..\build\NullableEnable.props" />
</Project>

65
src/Shared/PlatformSupport/DynLoader.cs → src/Avalonia.PlatformSupport/DynLoader.cs

@ -1,35 +1,40 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Shared.PlatformSupport
// ReSharper disable InconsistentNaming
namespace Avalonia.PlatformSupport
{
#if !__IOS__
class UnixLoader : IDynamicLibraryLoader
{
// ReSharper disable InconsistentNaming
static class LinuxImports
{
#if __ANDROID__
[DllImport("libdl.so")]
#else
[DllImport("libdl.so.2")]
#endif
private static extern IntPtr dlopen(string path, int flags);
#if __ANDROID__
[DllImport("libdl.so")]
#else
[DllImport("libdl.so.2")]
#endif
private static extern IntPtr dlsym(IntPtr handle, string symbol);
#if __ANDROID__
[DllImport("libdl.so")]
#else
[DllImport("libdl.so.2")]
#endif
private static extern IntPtr dlerror();
public static void Init()
{
DlOpen = dlopen;
DlSym = dlsym;
DlError = dlerror;
}
}
static class AndroidImports
{
[DllImport("libdl.so")]
private static extern IntPtr dlopen(string path, int flags);
[DllImport("libdl.so")]
private static extern IntPtr dlsym(IntPtr handle, string symbol);
[DllImport("libdl.so")]
private static extern IntPtr dlerror();
public static void Init()
@ -42,8 +47,6 @@ namespace Avalonia.Shared.PlatformSupport
static class OsXImports
{
[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlopen(string path, int flags);
@ -72,32 +75,36 @@ namespace Avalonia.Shared.PlatformSupport
uname(buffer);
var unixName = Marshal.PtrToStringAnsi(buffer);
Marshal.FreeHGlobal(buffer);
if(unixName == "Darwin")
if (unixName == "Darwin")
OsXImports.Init();
#if NET6_0_OR_GREATER
else if (OperatingSystem.IsAndroid())
AndroidImports.Init();
#endif
else
LinuxImports.Init();
}
private static Func<string, int, IntPtr> DlOpen;
private static Func<IntPtr, string, IntPtr> DlSym;
private static Func<IntPtr> DlError;
private static Func<string, int, IntPtr>? DlOpen;
private static Func<IntPtr, string, IntPtr>? DlSym;
private static Func<IntPtr>? DlError;
// ReSharper restore InconsistentNaming
static string DlErrorString() => Marshal.PtrToStringAnsi(DlError());
static string? DlErrorString() => Marshal.PtrToStringAnsi(DlError!.Invoke());
public IntPtr LoadLibrary(string dll)
{
var handle = DlOpen(dll, 1);
var handle = DlOpen!.Invoke(dll, 1);
if (handle == IntPtr.Zero)
throw new DynamicLibraryLoaderException(DlErrorString());
throw new DynamicLibraryLoaderException(DlErrorString()!);
return handle;
}
public IntPtr GetProcAddress(IntPtr dll, string proc, bool optional)
{
var ptr = DlSym(dll, proc);
var ptr = DlSym!.Invoke(dll, proc);
if (ptr == IntPtr.Zero && !optional)
throw new DynamicLibraryLoaderException(DlErrorString());
throw new DynamicLibraryLoaderException(DlErrorString()!);
return ptr;
}
}
@ -129,8 +136,7 @@ namespace Avalonia.Shared.PlatformSupport
}
}
#else
internal class IOSLoader : IDynamicLibraryLoader
internal class NotSupportedLoader : IDynamicLibraryLoader
{
IntPtr IDynamicLibraryLoader.LoadLibrary(string dll)
{
@ -142,5 +148,4 @@ namespace Avalonia.Shared.PlatformSupport
throw new PlatformNotSupportedException();
}
}
#endif
}

79
src/Shared/PlatformSupport/StandardRuntimePlatform.cs → src/Avalonia.PlatformSupport/StandardRuntimePlatform.cs

@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Platform;
namespace Avalonia.Shared.PlatformSupport
namespace Avalonia.PlatformSupport
{
internal partial class StandardRuntimePlatform : IRuntimePlatform
public class StandardRuntimePlatform : IRuntimePlatform
{
public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
{
@ -16,15 +15,15 @@ namespace Avalonia.Shared.PlatformSupport
}
public IUnmanagedBlob AllocBlob(int size) => new UnmanagedBlob(this, size);
class UnmanagedBlob : IUnmanagedBlob
private class UnmanagedBlob : IUnmanagedBlob
{
private readonly StandardRuntimePlatform _plat;
private IntPtr _address;
private readonly object _lock = new object();
#if DEBUG
private static readonly List<string> Backtraces = new List<string>();
private static Thread GCThread;
private static Thread? GCThread;
private readonly string _backtrace;
private static readonly object _btlock = new object();
@ -38,15 +37,14 @@ namespace Avalonia.Shared.PlatformSupport
[MethodImpl(MethodImplOptions.NoInlining)]
static void Spawn() => new GCThreadDetector();
static UnmanagedBlob()
{
Spawn();
GC.WaitForPendingFinalizers();
}
#endif
public UnmanagedBlob(StandardRuntimePlatform plat, int size)
{
try
@ -117,14 +115,12 @@ namespace Avalonia.Shared.PlatformSupport
DoDispose();
}
public IntPtr Address => IsDisposed ? throw new ObjectDisposedException("UnmanagedBlob") : _address;
public IntPtr Address => IsDisposed ? throw new ObjectDisposedException("UnmanagedBlob") : _address;
public int Size { get; private set; }
public bool IsDisposed { get; private set; }
}
#if NET461 || NETCOREAPP2_0
#if NET461 || NETCOREAPP2_0_OR_GREATER
[DllImport("libc", SetLastError = true)]
private static extern IntPtr mmap(IntPtr addr, IntPtr length, int prot, int flags, int fd, IntPtr offset);
[DllImport("libc", SetLastError = true)]
@ -133,15 +129,15 @@ namespace Avalonia.Shared.PlatformSupport
private static extern long sysconf(int name);
private bool? _useMmap;
private bool UseMmap
private bool UseMmap
=> _useMmap ?? ((_useMmap = GetRuntimeInfo().OperatingSystem == OperatingSystemType.Linux)).Value;
IntPtr Alloc(int size)
{
if (UseMmap)
{
var rv = mmap(IntPtr.Zero, new IntPtr(size), 3, 0x22, -1, IntPtr.Zero);
if (rv.ToInt64() == -1 || (ulong) rv.ToInt64() == 0xffffffff)
if (rv.ToInt64() == -1 || (ulong)rv.ToInt64() == 0xffffffff)
{
var errno = Marshal.GetLastWin32Error();
throw new Exception("Unable to allocate memory: " + errno);
@ -169,5 +165,54 @@ namespace Avalonia.Shared.PlatformSupport
IntPtr Alloc(int size) => Marshal.AllocHGlobal(size);
void Free(IntPtr ptr, int len) => Marshal.FreeHGlobal(ptr);
#endif
private static readonly Lazy<RuntimePlatformInfo> Info = new Lazy<RuntimePlatformInfo>(() =>
{
OperatingSystemType os;
#if NET5_0_OR_GREATER
if (OperatingSystem.IsWindows())
os = OperatingSystemType.WinNT;
else if (OperatingSystem.IsMacOS())
os = OperatingSystemType.OSX;
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
os = OperatingSystemType.Linux;
else if (OperatingSystem.IsAndroid())
os = OperatingSystemType.Android;
else if (OperatingSystem.IsIOS())
os = OperatingSystemType.iOS;
else if (OperatingSystem.IsBrowser())
os = OperatingSystemType.Browser;
else
throw new Exception("Unknown OS platform " + RuntimeInformation.OSDescription);
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
os = OperatingSystemType.OSX;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
os = OperatingSystemType.Linux;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
os = OperatingSystemType.WinNT;
else
throw new Exception("Unknown OS platform " + RuntimeInformation.OSDescription);
#endif
return new RuntimePlatformInfo
{
#if NETCOREAPP
IsCoreClr = true,
#elif NETFRAMEWORK
IsDotNetFramework = false,
#endif
IsDesktop = os == OperatingSystemType.Linux || os == OperatingSystemType.OSX || os == OperatingSystemType.WinNT,
IsMono = os == OperatingSystemType.Android || os == OperatingSystemType.iOS || os == OperatingSystemType.Browser,
IsMobile = os == OperatingSystemType.Android || os == OperatingSystemType.iOS,
IsUnix = os == OperatingSystemType.Linux || os == OperatingSystemType.OSX || os == OperatingSystemType.Android,
IsBrowser = os == OperatingSystemType.Browser,
OperatingSystem = os,
};
});
public virtual RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
}
}

31
src/Avalonia.PlatformSupport/StandardRuntimePlatformServices.cs

@ -0,0 +1,31 @@
using System.Reflection;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.PlatformSupport
{
public static class StandardRuntimePlatformServices
{
public static void Register(Assembly? assembly = null)
{
var standardPlatform = new StandardRuntimePlatform();
var os = standardPlatform.GetRuntimeInfo().OperatingSystem;
AssetLoader.RegisterResUriParsers();
AvaloniaLocator.CurrentMutable
.Bind<IRuntimePlatform>().ToConstant(standardPlatform)
.Bind<IAssetLoader>().ToConstant(new AssetLoader(assembly))
.Bind<IDynamicLibraryLoader>().ToConstant(
os switch
{
OperatingSystemType.WinNT => new Win32Loader(),
OperatingSystemType.OSX => new UnixLoader(),
OperatingSystemType.Linux => new UnixLoader(),
OperatingSystemType.Android => new UnixLoader(),
// iOS, WASM, ...
_ => (IDynamicLibraryLoader)new NotSupportedLoader()
}
);
}
}
}

2
src/Avalonia.Styling/Controls/IResourceHost.cs

@ -15,7 +15,7 @@ namespace Avalonia.Controls
/// <summary>
/// Raised when the resources change on the element or an ancestor of the element.
/// </summary>
event EventHandler<ResourcesChangedEventArgs> ResourcesChanged;
event EventHandler<ResourcesChangedEventArgs>? ResourcesChanged;
/// <summary>
/// Notifies the resource host that one or more of its hosted resources has changed.

2
src/Avalonia.Styling/Controls/IResourceProvider.cs

@ -25,7 +25,7 @@ namespace Avalonia.Controls
/// <summary>
/// Raised when the <see cref="Owner"/> of the resource provider changes.
/// </summary>
event EventHandler OwnerChanged;
event EventHandler? OwnerChanged;
/// <summary>
/// Adds an owner to the resource provider.

4
src/Avalonia.Styling/LogicalTree/LogicalTreeAttachmentEventArgs.cs

@ -17,7 +17,7 @@ namespace Avalonia.LogicalTree
public LogicalTreeAttachmentEventArgs(
ILogicalRoot root,
ILogical source,
ILogical parent)
ILogical? parent)
{
Root = root ?? throw new ArgumentNullException(nameof(root));
Source = source ?? throw new ArgumentNullException(nameof(source));
@ -47,6 +47,6 @@ namespace Avalonia.LogicalTree
/// detachment, holds the old logical parent of <see cref="Source"/>. If the detachment event
/// was caused by a top-level control being closed, then this property will be null.
/// </remarks>
public ILogical Parent { get; }
public ILogical? Parent { get; }
}
}

4
src/Avalonia.Styling/Styling/IGlobalStyles.cs

@ -13,11 +13,11 @@ namespace Avalonia.Styling
/// <summary>
/// Raised when styles are added to <see cref="Styles"/> or a nested styles collection.
/// </summary>
public event Action<IReadOnlyList<IStyle>> GlobalStylesAdded;
public event Action<IReadOnlyList<IStyle>>? GlobalStylesAdded;
/// <summary>
/// Raised when styles are removed from <see cref="Styles"/> or a nested styles collection.
/// </summary>
public event Action<IReadOnlyList<IStyle>> GlobalStylesRemoved;
public event Action<IReadOnlyList<IStyle>>? GlobalStylesRemoved;
}
}

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

@ -15,6 +15,12 @@ namespace Avalonia.Themes.Fluent
Dark,
}
public enum DensityStyle
{
Normal,
Compact
}
/// <summary>
/// Includes the fluent theme in an application.
/// </summary>
@ -24,6 +30,7 @@ namespace Avalonia.Themes.Fluent
private Styles _fluentDark = new();
private Styles _fluentLight = new();
private Styles _sharedStyles = new();
private Styles _densityStyles = new();
private bool _isLoading;
private IStyle? _loaded;
@ -47,9 +54,12 @@ namespace Avalonia.Themes.Fluent
InitStyles(_baseUri);
}
public static readonly StyledProperty<FluentThemeMode> ModeProperty =
AvaloniaProperty.Register<FluentTheme, FluentThemeMode>(nameof(Mode));
public static readonly StyledProperty<DensityStyle> DensityStyleProperty =
AvaloniaProperty.Register<FluentTheme, DensityStyle>(nameof(DensityStyle));
/// <summary>
/// Gets or sets the mode of the fluent theme (light, dark).
/// </summary>
@ -58,6 +68,16 @@ namespace Avalonia.Themes.Fluent
get => GetValue(ModeProperty);
set => SetValue(ModeProperty, value);
}
/// <summary>
/// Gets or sets the density style of the fluent theme (normal, compact).
/// </summary>
public DensityStyle DensityStyle
{
get => GetValue(DensityStyleProperty);
set => SetValue(DensityStyleProperty, value);
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
@ -74,6 +94,18 @@ namespace Avalonia.Themes.Fluent
(Loaded as Styles)![2] = _fluentLight[1];
}
}
if (change.Property == DensityStyleProperty)
{
if (DensityStyle == DensityStyle.Compact)
{
(Loaded as Styles)!.Add(_densityStyles[0]);
}
else if (DensityStyle == DensityStyle.Normal)
{
(Loaded as Styles)!.Remove(_densityStyles[0]);
}
}
}
public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner;
@ -97,6 +129,12 @@ namespace Avalonia.Themes.Fluent
{
_loaded = new Styles() { _sharedStyles, _fluentDark[0], _fluentDark[1] };
}
if (DensityStyle == DensityStyle.Compact)
{
(_loaded as Styles)!.Add(_densityStyles[0]);
}
_isLoading = false;
}
@ -183,6 +221,14 @@ namespace Avalonia.Themes.Fluent
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml")
}
};
_densityStyles = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Fluent/DensityStyles/Compact.xaml")
}
};
}
}
}

4
src/Avalonia.Visuals/Media/DrawingContext.cs

@ -119,7 +119,7 @@ namespace Avalonia.Media
/// <param name="brush">The fill brush.</param>
/// <param name="pen">The stroke pen.</param>
/// <param name="geometry">The geometry.</param>
public void DrawGeometry(IBrush brush, IPen pen, Geometry geometry)
public void DrawGeometry(IBrush? brush, IPen? pen, Geometry geometry)
{
if (geometry.PlatformImpl is not null)
DrawGeometry(brush, pen, geometry.PlatformImpl);
@ -131,7 +131,7 @@ namespace Avalonia.Media
/// <param name="brush">The fill brush.</param>
/// <param name="pen">The stroke pen.</param>
/// <param name="geometry">The geometry.</param>
public void DrawGeometry(IBrush brush, IPen pen, IGeometryImpl geometry)
public void DrawGeometry(IBrush? brush, IPen? pen, IGeometryImpl geometry)
{
_ = geometry ?? throw new ArgumentNullException(nameof(geometry));

4
src/Avalonia.Visuals/Platform/LockedFramebuffer.cs

@ -4,10 +4,10 @@ namespace Avalonia.Platform
{
public class LockedFramebuffer : ILockedFramebuffer
{
private readonly Action _onDispose;
private readonly Action? _onDispose;
public LockedFramebuffer(IntPtr address, PixelSize size, int rowBytes, Vector dpi, PixelFormat format,
Action onDispose)
Action? onDispose)
{
_onDispose = onDispose;
Address = address;

2
src/Avalonia.Visuals/VisualTree/IHostedVisualTreeRoot.cs

@ -11,6 +11,6 @@ namespace Avalonia.VisualTree
/// <value>
/// The visual tree host.
/// </value>
IVisual Host { get; }
IVisual? Host { get; }
}
}

2
src/Avalonia.Visuals/VisualTree/IVisualTreeHost.cs

@ -14,6 +14,6 @@ namespace Avalonia.VisualTree
/// <value>
/// The root of the hosted visual tree.
/// </value>
IVisual Root { get; }
IVisual? Root { get; }
}
}

17
src/Shared/PlatformSupport/PlatformSupport.projitems

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>{E4D9629C-F168-4224-8F51-F5E482FFEC42}</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Avalonia.Shared.PlatformSupport</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)AssetLoader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DynLoader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StandardRuntimePlatform.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StandardRuntimePlatformServices.cs" />
</ItemGroup>
</Project>

11
src/Shared/PlatformSupport/PlatformSupport.shproj

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{E4D9629C-F168-4224-3F51-A5E482FFBC42}</ProjectGuid>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<Import Project="PlatformSupport.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>

28
src/Shared/PlatformSupport/StandardRuntimePlatformServices.cs

@ -1,28 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Shared.PlatformSupport
{
static class StandardRuntimePlatformServices
{
public static void Register(Assembly assembly = null)
{
var standardPlatform = new StandardRuntimePlatform();
AssetLoader.RegisterResUriParsers();
AvaloniaLocator.CurrentMutable
.Bind<IRuntimePlatform>().ToConstant(standardPlatform)
.Bind<IAssetLoader>().ToConstant(new AssetLoader(assembly))
.Bind<IDynamicLibraryLoader>().ToConstant(
#if __IOS__
new IOSLoader()
#else
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? (IDynamicLibraryLoader)new Win32Loader()
: new UnixLoader()
#endif
);
}
}
}

13
src/Shared/RenderHelpers/QuadBezierHelper.cs

@ -1,13 +0,0 @@
using Avalonia.Platform;
namespace Avalonia.RenderHelpers
{
static class QuadBezierHelper
{
public static void QuadraticBezierTo(IStreamGeometryContextImpl context, Point current, Point controlPoint, Point endPoint)
{
//(s, (s + 2c)/ 3, (e + 2c)/ 3, e)
context.CubicBezierTo((current + 2*controlPoint)/3, (endPoint + 2*controlPoint)/3, endPoint);
}
}
}

14
src/Shared/RenderHelpers/RenderHelpers.projitems

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>3c4c0cb4-0c0f-4450-a37b-148c84ff905f</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Avalonia.RenderHelpers</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)QuadBezierHelper.cs" />
</ItemGroup>
</Project>

13
src/Shared/RenderHelpers/RenderHelpers.shproj

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>3c4c0cb4-0c0f-4450-a37b-148c84ff905f</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="RenderHelpers.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>

84
src/Shared/WindowResizeDragHelper.cs

@ -1,84 +0,0 @@
using System;
using Avalonia.Controls;
using Avalonia.Input.Raw;
using Avalonia.Platform;
namespace Avalonia
{
internal class ManagedWindowResizeDragHelper
{
private readonly IWindowBaseImpl _window;
private readonly Action<bool> _captureMouse;
private readonly Action<Rect> _resize;
private WindowEdge? _edge;
private Point _prevPoint;
public ManagedWindowResizeDragHelper(IWindowBaseImpl window, Action<bool> captureMouse, Action<Rect> resize = null)
{
_window = window;
_captureMouse = captureMouse;
_resize = resize;
}
public void BeginResizeDrag(WindowEdge edge, Point currentMousePosition)
{
_captureMouse(true);
_prevPoint = currentMousePosition;
_edge = edge;
}
public bool PreprocessInputEvent(ref RawInputEventArgs e)
{
if (_edge == null)
return false;
if (e is RawMouseEventArgs args)
{
if (args.Type == RawMouseEventType.LeftButtonUp)
{
_edge = null;
_captureMouse(false);
}
if (args.Type == RawMouseEventType.Move)
{
MoveWindow(args.Position);
return true;
}
_edge = null;
}
return false;
}
private void MoveWindow(Point position)
{
var diff = position - _prevPoint;
var edge = _edge.Value;
var rc = new Rect(_window.Position, _window.ClientSize);
if (edge == WindowEdge.East || edge == WindowEdge.NorthEast || edge == WindowEdge.SouthEast)
{
rc = rc.WithWidth(rc.Width + diff.X);
_prevPoint = _prevPoint.WithX(position.X);
}
if (edge == WindowEdge.West || edge == WindowEdge.NorthWest || edge == WindowEdge.SouthWest)
rc = rc.WithX(rc.X + diff.X).WithWidth(rc.Width - diff.X);
if (edge == WindowEdge.South || edge == WindowEdge.SouthWest || edge == WindowEdge.SouthEast)
{
rc = rc.WithHeight(rc.Height + diff.Y);
_prevPoint = _prevPoint.WithY(position.Y);
}
if (edge == WindowEdge.North || edge == WindowEdge.NorthWest || edge == WindowEdge.NorthEast)
rc = rc.WithY(rc.Y + diff.Y).WithHeight(rc.Height - diff.Y);
if (_resize != null)
_resize(rc);
else
{
if (_window.Position != rc.Position)
_window.Position = rc.Position;
if (_window.ClientSize != rc.Size)
_window.Resize(rc.Size);
}
}
}
}

3
src/Skia/Avalonia.Skia/Avalonia.Skia.csproj

@ -16,6 +16,5 @@
</ItemGroup>
<Import Project="..\..\..\build\SkiaSharp.props" />
<Import Project="..\..\..\build\HarfBuzzSharp.props" />
<Import Project="..\..\Shared\RenderHelpers\RenderHelpers.projitems" Label="Shared" />
<Import Project="..\..\..\build\HarfBuzzSharp.props" />
</Project>

3
src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj

@ -10,7 +10,6 @@
<ItemGroup>
<SupportedPlatform Include="browser" />
<Compile Include="..\..\Shared\PlatformSupport\AssetLoader.cs" />
</ItemGroup>
<PropertyGroup>
@ -51,7 +50,7 @@
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj" />
<ProjectReference Include="..\..\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj" />
<ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
</ItemGroup>
</Project>

5
src/Web/Avalonia.Web.Blazor/AvaloniaBlazorAppBuilder.cs

@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Platform;
using Avalonia.PlatformSupport;
namespace Avalonia.Web.Blazor
{
@ -10,7 +11,9 @@ namespace Avalonia.Web.Blazor
{
}
public AvaloniaBlazorAppBuilder() : base(BlazorRuntimePlatform.Instance, BlazorRuntimePlatform.RegisterServices)
public AvaloniaBlazorAppBuilder()
: base(new StandardRuntimePlatform(),
builder => StandardRuntimePlatformServices.Register(builder.ApplicationType.Assembly))
{
UseWindowingSubsystem(BlazorWindowingPlatform.Register);
}

61
src/Web/Avalonia.Web.Blazor/BlazorRuntimePlatform.cs

@ -1,61 +0,0 @@
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
namespace Avalonia.Web.Blazor
{
internal class BlazorRuntimePlatform : IRuntimePlatform
{
public static readonly IRuntimePlatform Instance = new BlazorRuntimePlatform();
public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
{
return new Timer(_ => tick(), null, interval, interval);
}
public RuntimePlatformInfo GetRuntimeInfo()
{
return new RuntimePlatformInfo
{
IsDesktop = false,
IsMobile = false,
IsMono = true,
IsUnix = false,
IsCoreClr = false,
IsDotNetFramework = false
};
}
private class BasicBlob : IUnmanagedBlob
{
public BasicBlob(int size)
{
Address = Marshal.AllocHGlobal(size);
Size = size;
}
public void Dispose()
{
if (Address != IntPtr.Zero)
Marshal.FreeHGlobal(Address);
Address = IntPtr.Zero;
}
public IntPtr Address { get; private set; }
public int Size { get; }
public bool IsDisposed => Address == IntPtr.Zero;
}
public IUnmanagedBlob AllocBlob(int size)
{
return new BasicBlob(size);
}
public static void RegisterServices(AvaloniaBlazorAppBuilder builder)
{
AssetLoader.RegisterResUriParsers();
AvaloniaLocator.CurrentMutable.Bind<IRuntimePlatform>().ToConstant(Instance);
AvaloniaLocator.CurrentMutable.Bind<IAssetLoader>().ToConstant(new AssetLoader());
}
}
}

1
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@ -17,6 +17,5 @@
<Import Project="..\..\..\build\Rx.props" />
<Import Project="..\..\..\build\SharpDX.props" />
<Import Project="..\..\..\build\HarfBuzzSharp.props" />
<Import Project="..\..\Shared\RenderHelpers\RenderHelpers.projitems" Label="Shared" />
<Import Project="..\..\..\build\JetBrains.Annotations.props" />
</Project>

11
src/iOS/Avalonia.iOS/Avalonia.iOS.csproj

@ -4,19 +4,14 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Compile Update="Boilerplate\Shared.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Boilerplate\RuntimePlatform.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="OpenTK-1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
<ProjectReference Include="..\..\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj">
<SetTargetFramework>TargetFramework=netstandard2.0</SetTargetFramework>
</ProjectReference>
<ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
</ItemGroup>
</Project>

5
src/iOS/Avalonia.iOS/Boilerplate/AppBuilder.cs

@ -1,6 +1,5 @@
using Avalonia.Controls;
using Avalonia.iOS;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
namespace Avalonia
{
@ -12,4 +11,4 @@ namespace Avalonia
this.UseSkia().UseWindowingSubsystem(iOS.Platform.Register);
}
}
}
}

19
src/iOS/Avalonia.iOS/Boilerplate/RuntimePlatform.cs

@ -1,19 +0,0 @@
using Avalonia.Platform;
namespace Avalonia.Shared.PlatformSupport
{
partial class StandardRuntimePlatform
{
public RuntimePlatformInfo GetRuntimeInfo()
{
return new RuntimePlatformInfo
{
IsDesktop = false,
IsMobile = true,
IsMono = true,
IsUnix = true,
OperatingSystem = OperatingSystemType.iOS
};
}
}
}

595
src/iOS/Avalonia.iOS/Boilerplate/Shared.cs

@ -1,595 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
using Avalonia.Utilities;
namespace Avalonia.Shared.PlatformSupport
{
static class StandardRuntimePlatformServices
{
public static void Register(Assembly assembly = null)
{
var standardPlatform = new StandardRuntimePlatform();
AssetLoader.RegisterResUriParsers();
AvaloniaLocator.CurrentMutable
.Bind<IRuntimePlatform>().ToConstant(standardPlatform)
.Bind<IAssetLoader>().ToConstant(new AssetLoader(assembly))
.Bind<IDynamicLibraryLoader>().ToConstant(
#if __IOS__
new IOSLoader()
#else
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? (IDynamicLibraryLoader)new Win32Loader()
: new UnixLoader()
#endif
);
}
}
internal partial class StandardRuntimePlatform : IRuntimePlatform
{
public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
{
return new Timer(_ => tick(), null, interval, interval);
}
public IUnmanagedBlob AllocBlob(int size) => new UnmanagedBlob(this, size);
class UnmanagedBlob : IUnmanagedBlob
{
private readonly StandardRuntimePlatform _plat;
private IntPtr _address;
private readonly object _lock = new object();
#if DEBUG
private static readonly List<string> Backtraces = new List<string>();
private static Thread GCThread;
private readonly string _backtrace;
private static readonly object _btlock = new object();
class GCThreadDetector
{
~GCThreadDetector()
{
GCThread = Thread.CurrentThread;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void Spawn() => new GCThreadDetector();
static UnmanagedBlob()
{
Spawn();
GC.WaitForPendingFinalizers();
}
#endif
public UnmanagedBlob(StandardRuntimePlatform plat, int size)
{
if (size <= 0)
throw new ArgumentException("Positive number required", nameof(size));
_plat = plat;
_address = plat.Alloc(size);
GC.AddMemoryPressure(size);
Size = size;
#if DEBUG
_backtrace = Environment.StackTrace;
lock (_btlock)
Backtraces.Add(_backtrace);
#endif
}
void DoDispose()
{
lock (_lock)
{
if (!IsDisposed)
{
#if DEBUG
lock (_btlock)
Backtraces.Remove(_backtrace);
#endif
_plat?.Free(_address, Size);
GC.RemoveMemoryPressure(Size);
IsDisposed = true;
_address = IntPtr.Zero;
Size = 0;
}
}
}
public void Dispose()
{
#if DEBUG
if (Thread.CurrentThread.ManagedThreadId == GCThread?.ManagedThreadId)
{
lock (_lock)
{
if (!IsDisposed)
{
Console.Error.WriteLine("Native blob disposal from finalizer thread\nBacktrace: "
+ Environment.StackTrace
+ "\n\nBlob created by " + _backtrace);
}
}
}
#endif
DoDispose();
GC.SuppressFinalize(this);
}
~UnmanagedBlob()
{
#if DEBUG
Console.Error.WriteLine("Undisposed native blob created by " + _backtrace);
#endif
DoDispose();
}
public IntPtr Address => IsDisposed ? throw new ObjectDisposedException("UnmanagedBlob") : _address;
public int Size { get; private set; }
public bool IsDisposed { get; private set; }
}
#if NET461 || NETCOREAPP2_0
[DllImport("libc", SetLastError = true)]
private static extern IntPtr mmap(IntPtr addr, IntPtr length, int prot, int flags, int fd, IntPtr offset);
[DllImport("libc", SetLastError = true)]
private static extern int munmap(IntPtr addr, IntPtr length);
[DllImport("libc", SetLastError = true)]
private static extern long sysconf(int name);
private bool? _useMmap;
private bool UseMmap
=> _useMmap ?? ((_useMmap = GetRuntimeInfo().OperatingSystem == OperatingSystemType.Linux)).Value;
IntPtr Alloc(int size)
{
if (UseMmap)
{
var rv = mmap(IntPtr.Zero, new IntPtr(size), 3, 0x22, -1, IntPtr.Zero);
if (rv.ToInt64() == -1 || (ulong) rv.ToInt64() == 0xffffffff)
{
var errno = Marshal.GetLastWin32Error();
throw new Exception("Unable to allocate memory: " + errno);
}
return rv;
}
else
return Marshal.AllocHGlobal(size);
}
void Free(IntPtr ptr, int len)
{
if (UseMmap)
{
if (munmap(ptr, new IntPtr(len)) == -1)
{
var errno = Marshal.GetLastWin32Error();
throw new Exception("Unable to free memory: " + errno);
}
}
else
Marshal.FreeHGlobal(ptr);
}
#else
IntPtr Alloc(int size) => Marshal.AllocHGlobal(size);
void Free(IntPtr ptr, int len) => Marshal.FreeHGlobal(ptr);
#endif
}
internal class IOSLoader : IDynamicLibraryLoader
{
IntPtr IDynamicLibraryLoader.LoadLibrary(string dll)
{
throw new PlatformNotSupportedException();
}
IntPtr IDynamicLibraryLoader.GetProcAddress(IntPtr dll, string proc, bool optional)
{
throw new PlatformNotSupportedException();
}
}
public class AssetLoader : IAssetLoader
{
private const string AvaloniaResourceName = "!AvaloniaResources";
private static readonly Dictionary<string, AssemblyDescriptor> AssemblyNameCache
= new Dictionary<string, AssemblyDescriptor>();
private AssemblyDescriptor _defaultResmAssembly;
/// <summary>
/// Initializes a new instance of the <see cref="AssetLoader"/> class.
/// </summary>
/// <param name="assembly">
/// The default assembly from which to load resm: assets for which no assembly is specified.
/// </param>
public AssetLoader(Assembly assembly = null)
{
if (assembly == null)
assembly = Assembly.GetEntryAssembly();
if (assembly != null)
_defaultResmAssembly = new AssemblyDescriptor(assembly);
}
/// <summary>
/// Sets the default assembly from which to load assets for which no assembly is specified.
/// </summary>
/// <param name="assembly">The default assembly.</param>
public void SetDefaultAssembly(Assembly assembly)
{
_defaultResmAssembly = new AssemblyDescriptor(assembly);
}
/// <summary>
/// Checks if an asset with the specified URI exists.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>True if the asset could be found; otherwise false.</returns>
public bool Exists(Uri uri, Uri baseUri = null)
{
return GetAsset(uri, baseUri) != null;
}
/// <summary>
/// Opens the asset with the requested URI.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>A stream containing the asset contents.</returns>
/// <exception cref="FileNotFoundException">
/// The asset could not be found.
/// </exception>
public Stream Open(Uri uri, Uri baseUri = null) => OpenAndGetAssembly(uri, baseUri).Item1;
/// <summary>
/// Opens the asset with the requested URI and returns the asset stream and the
/// assembly containing the asset.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <returns>
/// The stream containing the resource contents together with the assembly.
/// </returns>
/// <exception cref="FileNotFoundException">
/// The asset could not be found.
/// </exception>
public (Stream stream, Assembly assembly) OpenAndGetAssembly(Uri uri, Uri baseUri = null)
{
var asset = GetAsset(uri, baseUri);
if (asset == null)
{
throw new FileNotFoundException($"The resource {uri} could not be found.");
}
return (asset.GetStream(), asset.Assembly);
}
public Assembly GetAssembly(Uri uri, Uri baseUri)
{
if (!uri.IsAbsoluteUri && baseUri != null)
uri = new Uri(baseUri, uri);
return GetAssembly(uri).Assembly;
}
/// <summary>
/// Gets all assets of a folder and subfolders that match specified uri.
/// </summary>
/// <param name="uri">The URI.</param>
/// <param name="baseUri">Base URI that is used if <paramref name="uri"/> is relative.</param>
/// <returns>All matching assets as a tuple of the absolute path to the asset and the assembly containing the asset</returns>
public IEnumerable<Uri> GetAssets(Uri uri, Uri baseUri)
{
if (uri.IsAbsoluteUri && uri.Scheme == "resm")
{
var assembly = GetAssembly(uri);
return assembly?.Resources.Where(x => x.Key.Contains(uri.AbsolutePath))
.Select(x =>new Uri($"resm:{x.Key}?assembly={assembly.Name}")) ??
Enumerable.Empty<Uri>();
}
uri = EnsureAbsolute(uri, baseUri);
if (uri.Scheme == "avares")
{
var (asm, path) = GetResAsmAndPath(uri);
if (asm == null)
{
throw new ArgumentException(
"No default assembly, entry assembly or explicit assembly specified; " +
"don't know where to look up for the resource, try specifying assembly explicitly.");
}
if (asm?.AvaloniaResources == null)
return Enumerable.Empty<Uri>();
path = path.TrimEnd('/') + '/';
return asm.AvaloniaResources.Where(r => r.Key.StartsWith(path))
.Select(x => new Uri($"avares://{asm.Name}{x.Key}"));
}
return Enumerable.Empty<Uri>();
}
private Uri EnsureAbsolute(Uri uri, Uri baseUri)
{
if (uri.IsAbsoluteUri)
return uri;
if(baseUri == null)
throw new ArgumentException($"Relative uri {uri} without base url");
if (!baseUri.IsAbsoluteUri)
throw new ArgumentException($"Base uri {baseUri} is relative");
if (baseUri.Scheme == "resm")
throw new ArgumentException(
$"Relative uris for 'resm' scheme aren't supported; {baseUri} uses resm");
return new Uri(baseUri, uri);
}
private IAssetDescriptor GetAsset(Uri uri, Uri baseUri)
{
if (uri.IsAbsoluteUri && uri.Scheme == "resm")
{
var asm = GetAssembly(uri) ?? GetAssembly(baseUri) ?? _defaultResmAssembly;
if (asm == null)
{
throw new ArgumentException(
"No default assembly, entry assembly or explicit assembly specified; " +
"don't know where to look up for the resource, try specifying assembly explicitly.");
}
IAssetDescriptor rv;
var resourceKey = uri.AbsolutePath;
asm.Resources.TryGetValue(resourceKey, out rv);
return rv;
}
uri = EnsureAbsolute(uri, baseUri);
if (uri.Scheme == "avares")
{
var (asm, path) = GetResAsmAndPath(uri);
if (asm.AvaloniaResources == null)
return null;
asm.AvaloniaResources.TryGetValue(path, out var desc);
return desc;
}
throw new ArgumentException($"Unsupported url type: " + uri.Scheme, nameof(uri));
}
private (AssemblyDescriptor asm, string path) GetResAsmAndPath(Uri uri)
{
var asm = GetAssembly(uri.Authority);
return (asm, uri.AbsolutePath);
}
private AssemblyDescriptor GetAssembly(Uri uri)
{
if (uri != null)
{
if (!uri.IsAbsoluteUri)
return null;
if (uri.Scheme == "avares")
return GetResAsmAndPath(uri).asm;
if (uri.Scheme == "resm")
{
var qs = ParseQueryString(uri);
string assemblyName;
if (qs.TryGetValue("assembly", out assemblyName))
{
return GetAssembly(assemblyName);
}
}
}
return null;
}
private AssemblyDescriptor GetAssembly(string name)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
AssemblyDescriptor rv;
if (!AssemblyNameCache.TryGetValue(name, out rv))
{
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name);
if (match != null)
{
AssemblyNameCache[name] = rv = new AssemblyDescriptor(match);
}
else
{
// iOS does not support loading assemblies dynamically!
//
#if __IOS__
throw new InvalidOperationException(
$"Assembly {name} needs to be referenced and explicitly loaded before loading resources");
#else
name = Uri.UnescapeDataString(name);
AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name));
#endif
}
}
return rv;
}
private Dictionary<string, string> ParseQueryString(Uri uri)
{
return uri.Query.TrimStart('?')
.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Split('='))
.ToDictionary(p => p[0], p => p[1]);
}
private interface IAssetDescriptor
{
Stream GetStream();
Assembly Assembly { get; }
}
private class AssemblyResourceDescriptor : IAssetDescriptor
{
private readonly Assembly _asm;
private readonly string _name;
public AssemblyResourceDescriptor(Assembly asm, string name)
{
_asm = asm;
_name = name;
}
public Stream GetStream()
{
return _asm.GetManifestResourceStream(_name);
}
public Assembly Assembly => _asm;
}
private class AvaloniaResourceDescriptor : IAssetDescriptor
{
private readonly int _offset;
private readonly int _length;
public Assembly Assembly { get; }
public AvaloniaResourceDescriptor(Assembly asm, int offset, int length)
{
_offset = offset;
_length = length;
Assembly = asm;
}
public Stream GetStream()
{
return new SlicedStream(Assembly.GetManifestResourceStream(AvaloniaResourceName), _offset, _length);
}
}
class SlicedStream : Stream
{
private readonly Stream _baseStream;
private readonly int _from;
public SlicedStream(Stream baseStream, int from, int length)
{
Length = length;
_baseStream = baseStream;
_from = from;
_baseStream.Position = from;
}
public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count)
{
return _baseStream.Read(buffer, offset, (int)Math.Min(count, Length - Position));
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin == SeekOrigin.Begin)
Position = offset;
if (origin == SeekOrigin.End)
Position = _from + Length + offset;
if (origin == SeekOrigin.Current)
Position = Position + offset;
return Position;
}
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override bool CanRead => true;
public override bool CanSeek => _baseStream.CanRead;
public override bool CanWrite => false;
public override long Length { get; }
public override long Position
{
get => _baseStream.Position - _from;
set => _baseStream.Position = value + _from;
}
protected override void Dispose(bool disposing)
{
if (disposing)
_baseStream.Dispose();
}
public override void Close() => _baseStream.Close();
}
private class AssemblyDescriptor
{
public AssemblyDescriptor(Assembly assembly)
{
Assembly = assembly;
if (assembly != null)
{
Resources = assembly.GetManifestResourceNames()
.ToDictionary(n => n, n => (IAssetDescriptor)new AssemblyResourceDescriptor(assembly, n));
Name = assembly.GetName().Name;
using (var resources = assembly.GetManifestResourceStream(AvaloniaResourceName))
{
if (resources != null)
{
Resources.Remove(AvaloniaResourceName);
var indexLength = new BinaryReader(resources).ReadInt32();
var index = AvaloniaResourcesIndexReaderWriter.Read(new SlicedStream(resources, 4, indexLength));
var baseOffset = indexLength + 4;
AvaloniaResources = index.ToDictionary(r => "/" + r.Path.TrimStart('/'), r => (IAssetDescriptor)
new AvaloniaResourceDescriptor(assembly, baseOffset + r.Offset, r.Size));
}
}
}
}
public Assembly Assembly { get; }
public Dictionary<string, IAssetDescriptor> Resources { get; }
public Dictionary<string, IAssetDescriptor> AvaloniaResources { get; }
public string Name { get; }
}
public static void RegisterResUriParsers()
{
if (!UriParser.IsKnownScheme("avares"))
UriParser.Register(new GenericUriParser(
GenericUriParserOptions.GenericAuthority |
GenericUriParserOptions.NoUserInfo |
GenericUriParserOptions.NoPort |
GenericUriParserOptions.NoQuery |
GenericUriParserOptions.NoFragment), "avares", -1);
}
}
}

4
tests/Avalonia.Benchmarks/Themes/FluentBenchmark.cs

@ -1,9 +1,7 @@
using System;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
using Avalonia.Styling;
using Avalonia.UnitTests;
using BenchmarkDotNet.Attributes;

2
tests/Avalonia.Benchmarks/Themes/ThemeBenchmark.cs

@ -2,7 +2,7 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
using Avalonia.Styling;
using Avalonia.UnitTests;

2
tests/Avalonia.RenderTests/TestBase.cs

@ -24,7 +24,7 @@ namespace Avalonia.Skia.RenderTests
namespace Avalonia.Direct2D1.RenderTests
#endif
{
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
public class TestBase
{

2
tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

@ -14,6 +14,7 @@
<EmbeddedResource Include="..\Avalonia.UnitTests\Assets\*.ttf" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
<ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj" />
@ -26,7 +27,6 @@
<ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
</ItemGroup>
<Import Project="..\..\src\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
<Import Project="..\..\build\Moq.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\SharedVersion.props" />

16
tests/Avalonia.UnitTests/RuntimeInfo.cs

@ -1,16 +0,0 @@
using Avalonia.Platform;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Avalonia.Shared.PlatformSupport
{
internal partial class StandardRuntimePlatform : IRuntimePlatform
{
public RuntimePlatformInfo GetRuntimeInfo()
{
return new RuntimePlatformInfo();
}
}
}

2
tests/Avalonia.UnitTests/TestServices.cs

@ -5,7 +5,7 @@ using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
using Avalonia.Styling;
using Avalonia.Themes.Default;
using Avalonia.Rendering;

2
tests/Avalonia.UnitTests/UnitTestApplication.cs

@ -10,7 +10,7 @@ using System.Reactive.Disposables;
using System.Reactive.Concurrency;
using Avalonia.Input.Platform;
using Avalonia.Animation;
using Avalonia.Shared.PlatformSupport;
using Avalonia.PlatformSupport;
namespace Avalonia.UnitTests
{

Loading…
Cancel
Save