Browse Source

Use TemplatePart

pull/10882/head
Benedikt Stebner 3 years ago
parent
commit
384e090d10
  1. 5
      .ncrunch/AppWithoutLifetime.v3.ncrunchproject
  2. 5
      .ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject
  3. 5
      .ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject
  4. 11
      Avalonia.Desktop.slnf
  5. 3
      Avalonia.sln
  6. 2
      build/SharedVersion.props
  7. 6
      dirs.proj
  8. 2
      nukebuild/Build.cs
  9. 101
      nukebuild/RefAssemblyGenerator.cs
  10. 6
      nukebuild/_build.csproj
  11. 2
      packages/Avalonia/Avalonia.csproj
  12. 1
      packages/Avalonia/Avalonia.targets
  13. 26
      packages/Avalonia/AvaloniaPrivateApis.targets
  14. 7
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  15. 11
      samples/ControlCatalog.Desktop/Program.cs
  16. 1
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  17. 5
      samples/ControlCatalog/MainView.xaml.cs
  18. 3
      samples/ControlCatalog/Pages/ColorPickerPage.xaml
  19. 4
      samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
  20. 2
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  21. 5
      samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
  22. 3
      samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs
  23. 29
      samples/ControlCatalog/Pages/TabControlPage.xaml
  24. 2
      samples/ControlCatalog/Pages/TabControlPage.xaml.cs
  25. 2
      samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs
  26. 2
      samples/GpuInterop/MainWindow.axaml.cs
  27. 2
      samples/GpuInterop/VulkanDemo/VulkanContext.cs
  28. 3
      samples/IntegrationTestApp/MainWindow.axaml
  29. 2
      samples/IntegrationTestApp/MainWindow.axaml.cs
  30. 21
      samples/MobileSandbox.Desktop/MobileSandbox.Desktop.csproj
  31. 15
      samples/MobileSandbox/MobileSandbox.csproj
  32. 2
      samples/RenderDemo/MainWindow.xaml.cs
  33. 4
      samples/RenderDemo/Pages/AnimationsPage.xaml
  34. 15
      samples/RenderDemo/Pages/AnimationsPage.xaml.cs
  35. 12
      samples/RenderDemo/Pages/CustomAnimatorPage.xaml
  36. 6
      samples/RenderDemo/Pages/CustomSkiaPage.cs
  37. 5
      samples/RenderDemo/Pages/CustomStringAnimator.cs
  38. 8
      samples/RenderDemo/Pages/PathMeasurementPage.cs
  39. 3
      samples/RenderDemo/Pages/Transform3DPage.axaml
  40. 4
      samples/RenderDemo/Pages/TransitionsPage.xaml
  41. 15
      samples/RenderDemo/Pages/TransitionsPage.xaml.cs
  42. 1
      samples/Sandbox/Sandbox.csproj
  43. 6
      samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs
  44. 4
      samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs
  45. 23
      samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs
  46. 33
      samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml
  47. 52
      samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs
  48. 9
      samples/interop/WindowsInteropTest/Program.cs
  49. 76
      samples/interop/WindowsInteropTest/SelectorForm.Designer.cs
  50. 30
      samples/interop/WindowsInteropTest/SelectorForm.cs
  51. 120
      samples/interop/WindowsInteropTest/SelectorForm.resx
  52. 6
      samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
  53. 7
      src/Android/Avalonia.Android/AndroidPlatform.cs
  54. 4
      src/Android/Avalonia.Android/AvaloniaView.cs
  55. 112
      src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs
  56. 2
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  57. 173
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  58. 8
      src/Avalonia.Base/Animation/Animatable.cs
  59. 27
      src/Avalonia.Base/Animation/Animation.cs
  60. 9
      src/Avalonia.Base/Animation/AnimatorDrivenTransition.cs
  61. 4
      src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
  62. 6
      src/Avalonia.Base/Animation/AnimatorTransitionObservable.cs
  63. 2
      src/Avalonia.Base/Animation/Animators/Animator`1.cs
  64. 2
      src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs
  65. 2
      src/Avalonia.Base/Animation/Animators/BoolAnimator.cs
  66. 2
      src/Avalonia.Base/Animation/Animators/BoxShadowAnimator.cs
  67. 2
      src/Avalonia.Base/Animation/Animators/BoxShadowsAnimator.cs
  68. 2
      src/Avalonia.Base/Animation/Animators/ByteAnimator.cs
  69. 2
      src/Avalonia.Base/Animation/Animators/ColorAnimator.cs
  70. 2
      src/Avalonia.Base/Animation/Animators/CornerRadiusAnimator.cs
  71. 2
      src/Avalonia.Base/Animation/Animators/DecimalAnimator.cs
  72. 2
      src/Avalonia.Base/Animation/Animators/DoubleAnimator.cs
  73. 2
      src/Avalonia.Base/Animation/Animators/FloatAnimator.cs
  74. 2
      src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs
  75. 2
      src/Avalonia.Base/Animation/Animators/Int16Animator.cs
  76. 2
      src/Avalonia.Base/Animation/Animators/Int32Animator.cs
  77. 2
      src/Avalonia.Base/Animation/Animators/Int64Animator.cs
  78. 2
      src/Avalonia.Base/Animation/Animators/PointAnimator.cs
  79. 2
      src/Avalonia.Base/Animation/Animators/RectAnimator.cs
  80. 2
      src/Avalonia.Base/Animation/Animators/RelativePointAnimator.cs
  81. 2
      src/Avalonia.Base/Animation/Animators/SizeAnimator.cs
  82. 2
      src/Avalonia.Base/Animation/Animators/SolidColorBrushAnimator.cs
  83. 2
      src/Avalonia.Base/Animation/Animators/ThicknessAnimator.cs
  84. 2
      src/Avalonia.Base/Animation/Animators/TransformAnimator.cs
  85. 2
      src/Avalonia.Base/Animation/Animators/TransformOperationsAnimator.cs
  86. 2
      src/Avalonia.Base/Animation/Animators/UInt16Animator.cs
  87. 2
      src/Avalonia.Base/Animation/Animators/UInt32Animator.cs
  88. 2
      src/Avalonia.Base/Animation/Animators/UInt64Animator.cs
  89. 2
      src/Avalonia.Base/Animation/Animators/VectorAnimator.cs
  90. 5
      src/Avalonia.Base/Animation/Clock.cs
  91. 2
      src/Avalonia.Base/Animation/ClockBase.cs
  92. 3
      src/Avalonia.Base/Animation/Easings/IEasing.cs
  93. 5
      src/Avalonia.Base/Animation/Easings/SpringEasing.cs
  94. 4
      src/Avalonia.Base/Animation/IAnimation.cs
  95. 2
      src/Avalonia.Base/Animation/IAnimationSetter.cs
  96. 3
      src/Avalonia.Base/Animation/IAnimator.cs
  97. 3
      src/Avalonia.Base/Animation/IClock.cs
  98. 30
      src/Avalonia.Base/Animation/ICustomAnimator.cs
  99. 3
      src/Avalonia.Base/Animation/IGlobalClock.cs
  100. 4
      src/Avalonia.Base/Animation/ITransition.cs

5
.ncrunch/AppWithoutLifetime.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

11
Avalonia.Desktop.slnf

@ -39,14 +39,13 @@
"src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj", "src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj",
"src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj", "src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj",
"src\\Skia\\Avalonia.Skia\\Avalonia.Skia.csproj", "src\\Skia\\Avalonia.Skia\\Avalonia.Skia.csproj",
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
"src\\tools\\DevGenerators\\DevGenerators.csproj",
"src\\tools\\PublicAnalyzers\\Avalonia.Analyzers.csproj",
"src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj", "src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj",
"src\\Windows\\Avalonia.Win32.Interop\\Avalonia.Win32.Interop.csproj", "src\\Windows\\Avalonia.Win32.Interop\\Avalonia.Win32.Interop.csproj",
"src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj", "src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
"src\\tools\\Avalonia.Analyzers\\Avalonia.Analyzers.csproj",
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
"src\\tools\\DevGenerators\\DevGenerators.csproj",
"tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj", "tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj",
"tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj", "tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj",
"tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj", "tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj",
@ -66,4 +65,4 @@
"tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj" "tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj"
] ]
} }
} }

3
Avalonia.sln

@ -135,7 +135,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interoperability", "src\Windows\Avalonia.Win32.Interoperability\Avalonia.Win32.Interoperability.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}"
EndProject EndProject
@ -251,6 +251,7 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generators.Sandbox", "samples\Generators.Sandbox\Generators.Sandbox.csproj", "{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generators.Sandbox", "samples\Generators.Sandbox\Generators.Sandbox.csproj", "{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppWithoutLifetime", "samples\AppWithoutLifetime\AppWithoutLifetime.csproj", "{F8928267-688E-4A51-989C-612A72446D33}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppWithoutLifetime", "samples\AppWithoutLifetime\AppWithoutLifetime.csproj", "{F8928267-688E-4A51-989C-612A72446D33}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo", "samples\SafeAreaDemo\SafeAreaDemo.csproj", "{6B60A970-D5D2-49C2-8BAB-F9C7973B74B6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo", "samples\SafeAreaDemo\SafeAreaDemo.csproj", "{6B60A970-D5D2-49C2-8BAB-F9C7973B74B6}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.Android", "samples\SafeAreaDemo.Android\SafeAreaDemo.Android.csproj", "{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.Android", "samples\SafeAreaDemo.Android\SafeAreaDemo.Android.csproj", "{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D}"

2
build/SharedVersion.props

@ -4,7 +4,7 @@
<Product>Avalonia</Product> <Product>Avalonia</Product>
<Version>11.0.999</Version> <Version>11.0.999</Version>
<Authors>Avalonia Team</Authors> <Authors>Avalonia Team</Authors>
<Copyright>Copyright 2022 &#169; The AvaloniaUI Project</Copyright> <Copyright>Copyright 2013-$([System.DateTime]::Now.ToString(`yyyy`)) &#169; The AvaloniaUI Project</Copyright>
<PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl> <PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl>
<RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl> <RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>

6
dirs.proj

@ -14,11 +14,11 @@
<ProjectReference Remove="samples/*.Android/*.csproj" /> <ProjectReference Remove="samples/*.Android/*.csproj" />
<ProjectReference Remove="samples/*.Browser/*.csproj" /> <ProjectReference Remove="samples/*.Browser/*.csproj" />
<ProjectReference Remove="samples/*.Blazor/*.csproj" /> <ProjectReference Remove="samples/*.Blazor/*.csproj" />
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows')) OR '$(MSBuildRuntimeType)' != 'Full'"> <ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))">
<ProjectReference Remove="src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj" /> <ProjectReference Remove="src/Windows/Avalonia.Win32.Interoperability/Avalonia.Win32.Interoperability.csproj" />
<ProjectReference Remove="samples/interop/**/*.*proj" /> <ProjectReference Remove="samples/interop/**/*.*proj" />
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup> </ItemGroup>
<!-- Build android and iOS projects only on Windows, where we have installed android workload --> <!-- Build android and iOS projects only on Windows, where we have installed android workload -->

2
nukebuild/Build.cs

@ -312,7 +312,7 @@ partial class Build : NukeBuild
public static int Main() => public static int Main() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Execute<Build>(x => x.RunToolsTests) ? Execute<Build>(x => x.Package)
: Execute<Build>(x => x.RunTests); : Execute<Build>(x => x.RunTests);
} }

101
nukebuild/RefAssemblyGenerator.cs

@ -63,52 +63,89 @@ public class RefAssemblyGenerator
}); });
} }
static bool HasPrivateApi(IEnumerable<CustomAttribute> attrs) => attrs.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute");
static void ProcessType(TypeDefinition type, MethodReference obsoleteCtor) static void ProcessType(TypeDefinition type, MethodReference obsoleteCtor)
{ {
foreach (var nested in type.NestedTypes) foreach (var nested in type.NestedTypes)
ProcessType(nested, obsoleteCtor); ProcessType(nested, obsoleteCtor);
if (type.IsInterface)
var hideMembers = (type.IsInterface && type.Name.EndsWith("Impl"))
|| HasPrivateApi(type.CustomAttributes);
var injectMethod = hideMembers
|| type.CustomAttributes.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute");
if (injectMethod)
{ {
var hideMethods = type.Name.EndsWith("Impl") type.Methods.Add(new MethodDefinition(
|| (type.HasCustomAttributes && type.CustomAttributes.Any(a => "(This interface or abstract class is -not- implementable by user code !)",
a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute")); MethodAttributes.Assembly
| MethodAttributes.Abstract
| MethodAttributes.NewSlot
| MethodAttributes.HideBySig, type.Module.TypeSystem.Void));
}
var injectMethod = hideMethods var forceUnstable = type.CustomAttributes.FirstOrDefault(a =>
|| type.CustomAttributes.Any(a => a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute");
a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute");
foreach (var m in type.Methods)
if (hideMethods) {
if (hideMembers || HasPrivateApi(m.CustomAttributes))
{ {
foreach (var m in type.Methods) HideMethod(m);
{
var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem |
MethodAttributes.FamANDAssem | MethodAttributes.Assembly;
m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
}
} }
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
if(injectMethod) }
foreach (var p in type.Properties)
{
if (HasPrivateApi(p.CustomAttributes))
{ {
type.Methods.Add(new MethodDefinition("NotClientImplementable", if (p.SetMethod != null)
MethodAttributes.Assembly HideMethod(p.SetMethod);
| MethodAttributes.Abstract if (p.GetMethod != null)
| MethodAttributes.NewSlot HideMethod(p.GetMethod);
| MethodAttributes.HideBySig, type.Module.TypeSystem.Void));
} }
}
var forceUnstable = type.CustomAttributes.FirstOrDefault(a => foreach (var f in type.Fields)
a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute"); {
if (hideMembers || HasPrivateApi(f.CustomAttributes))
foreach (var m in type.Methods) {
MarkAsUnstable(m, obsoleteCtor, forceUnstable); var dflags = FieldAttributes.Public | FieldAttributes.Family | FieldAttributes.FamORAssem |
foreach (var m in type.Properties) FieldAttributes.FamANDAssem | FieldAttributes.Assembly;
MarkAsUnstable(m, obsoleteCtor, forceUnstable); f.Attributes = ((f.Attributes | dflags) ^ dflags) | FieldAttributes.Assembly;
foreach (var m in type.Events) }
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
} }
foreach (var cl in type.NestedTypes)
{
ProcessType(cl, obsoleteCtor);
if (hideMembers)
{
var dflags = TypeAttributes.Public;
cl.Attributes = ((cl.Attributes | dflags) ^ dflags) | TypeAttributes.NotPublic;
}
}
foreach (var m in type.Properties)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
foreach (var m in type.Events)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
} }
static void HideMethod(MethodDefinition m)
{
var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem |
MethodAttributes.FamANDAssem | MethodAttributes.Assembly;
m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
}
static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor, ICustomAttribute unstableAttribute) static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor, ICustomAttribute unstableAttribute)
{ {
if (def.CustomAttributes.Any(a => a.AttributeType.FullName == "System.ObsoleteAttribute")) if (def.CustomAttributes.Any(a => a.AttributeType.FullName == "System.ObsoleteAttribute"))

6
nukebuild/_build.csproj

@ -35,6 +35,12 @@
<EmbeddedResource Include="../build/avalonia.snk"></EmbeddedResource> <EmbeddedResource Include="../build/avalonia.snk"></EmbeddedResource>
<Compile Remove="il-repack\ILRepack\Application.cs" /> <Compile Remove="il-repack\ILRepack\Application.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="..\dirs.proj">
<Link>dirs.proj</Link>
</Content>
</ItemGroup>

2
packages/Avalonia/Avalonia.csproj

@ -5,7 +5,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.BuildServices" Version="0.0.12" /> <PackageReference Include="Avalonia.BuildServices" Version="0.0.19" />
<ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj" /> <ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj" />
<ProjectReference Include="../../src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj"> <ProjectReference Include="../../src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

1
packages/Avalonia/Avalonia.targets

@ -1,3 +1,4 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildThisFileDirectory)\AvaloniaBuildTasks.targets"/> <Import Project="$(MSBuildThisFileDirectory)\AvaloniaBuildTasks.targets"/>
<Import Project="$(MSBuildThisFileDirectory)\AvaloniaPrivateApis.targets" />
</Project> </Project>

26
packages/Avalonia/AvaloniaPrivateApis.targets

@ -0,0 +1,26 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="RemoveAvaloniaRefAssemblies" AfterTargets="ResolveTargetingPackAssets" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'">
<ItemGroup>
<ReferencesToRemove Include="@(Reference)" Condition="'%(Reference.NuGetPackageId)' == 'Avalonia'" />
</ItemGroup>
<ItemGroup>
<Reference Remove="@(ReferencesToRemove)" />
</ItemGroup>
</Target>
<Target Name="PreventPackingAvaloniaUnstableApis" BeforeTargets="Pack">
<Error Condition="'$(IsPackable.ToLowerInvariant())' == 'true' and '$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())' == 'true' and '$(Avalonia_I_Want_To_Use_Private_Apis_In_Nuget_Package_And_Promise_To_Pin_The_Exact_Avalonia_Version_In_Package_Dependency)' != 'true'"
Text="It seems that you are using private APIs in a nuget package, please follow this guide https://github.com/AvaloniaUI/Avalonia/wiki/Using-private-apis-in-nuget-packages" />
</Target>
<Target Name="AddReferencePathsToRealAvaloniaAssemblies" BeforeTargets="CoreCompile" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'">
<PropertyGroup>
<AvaloniaUnstableApiFrameworkToUse>net6.0</AvaloniaUnstableApiFrameworkToUse>
<AvaloniaUnstableApiFrameworkToUse Condition="$(TargetFramework.StartsWith('net4')) == 'true' or $(TargetFramework.StartsWith('net5')) == 'true' or $(TargetFramework.StartsWith('netsta')) == 'true' or $(TargetFramework.StartsWith('netcore')) == 'true'">netstandard2.0</AvaloniaUnstableApiFrameworkToUse>
</PropertyGroup>
<ItemGroup>
<Reference Include="$(MSBuildThisFileDirectory)/../lib/$(AvaloniaUnstableApiFrameworkToUse)/*.dll"/>
<ReferencePath Include="$(MSBuildThisFileDirectory)/../lib/$(AvaloniaUnstableApiFrameworkToUse)/*.dll"/>
<ReferencePathWithRefAssemblies Include="$(MSBuildThisFileDirectory)/../lib/$(AvaloniaUnstableApiFrameworkToUse)/*.dll"/>
</ItemGroup>
<Warning Text="AvaloniaAccessUnstablePrivateApis is Enabled: This means you are using unstable internal APIs, and your code may be depending on APIs which may change or be removed in future versions of Avalonia. Set AvaloniaAccessUnstablePrivateApis to 'False' to disable this warning." />
</Target>
</Project>

7
samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj

@ -4,10 +4,17 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net461</TargetFramework> <TargetFramework>net461</TargetFramework>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>../ControlCatalog.NetCore/app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> <ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\ControlCatalog.NetCore\NativeControls\Win\*.cs" Link="NativeControls\*" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\SampleApp.props" /> <Import Project="..\..\build\SampleApp.props" />

11
samples/ControlCatalog.Desktop/Program.cs

@ -3,6 +3,8 @@ using System.Linq;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Platform; using Avalonia.Platform;
using ControlCatalog.NetCore;
using ControlCatalog.Pages;
namespace ControlCatalog namespace ControlCatalog
{ {
@ -18,6 +20,15 @@ namespace ControlCatalog
public static AppBuilder BuildAvaloniaApp() public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>() => AppBuilder.Configure<App>()
.LogToTrace() .LogToTrace()
.AfterSetup(builder =>
{
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
{
StartupScreenIndex = 1,
});
EmbedSample.Implementation = new EmbedSampleWin();
})
.UsePlatformDetect(); .UsePlatformDetect();
private static void ConfigureAssetAssembly(AppBuilder builder) private static void ConfigureAssetAssembly(AppBuilder builder)

1
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" /> <Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" />
<Compile Include="..\..\src\Avalonia.Base\Platform\Interop\Utf8Buffer.cs" Link="NativeControls\Utf8Buffer.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

5
samples/ControlCatalog/MainView.xaml.cs

@ -83,9 +83,10 @@ namespace ControlCatalog
if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected) if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected)
{ {
var topLevel = (TopLevel)this.GetVisualRoot()!; var topLevel = (TopLevel)this.GetVisualRoot()!;
topLevel.TransparencyLevelHint = selected; topLevel.TransparencyLevelHint = new[] { selected };
if (selected != WindowTransparencyLevel.None) if (topLevel.ActualTransparencyLevel != WindowTransparencyLevel.None &&
topLevel.ActualTransparencyLevel == selected)
{ {
var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0); var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0);
var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2); var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2);

3
samples/ControlCatalog/Pages/ColorPickerPage.xaml

@ -103,7 +103,8 @@
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" />--> HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" />-->
<ColorPreviewer Grid.Row="8" <ColorPreviewer Grid.Row="8"
IsAccentColorsVisible="False" IsAccentColorsVisible="False"
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" /> HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}"
Margin="0,2,0,0" />
</Grid> </Grid>
</Grid> </Grid>
</UserControl> </UserControl>

4
samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs

@ -19,8 +19,8 @@ namespace ControlCatalog.Pages
customContextRequestedBorder.AddHandler(ContextRequestedEvent, CustomContextRequested, RoutingStrategies.Tunnel); customContextRequestedBorder.AddHandler(ContextRequestedEvent, CustomContextRequested, RoutingStrategies.Tunnel);
var cancellableContextBorder = this.Get<Border>("CancellableContextBorder"); var cancellableContextBorder = this.Get<Border>("CancellableContextBorder");
cancellableContextBorder.ContextMenu!.ContextMenuClosing += ContextFlyoutPage_Closing; cancellableContextBorder.ContextMenu!.Closing += ContextFlyoutPage_Closing;
cancellableContextBorder.ContextMenu!.ContextMenuOpening += ContextFlyoutPage_Opening; cancellableContextBorder.ContextMenu!.Opening += ContextFlyoutPage_Opening;
} }
private ContextPageViewModel? _model; private ContextPageViewModel? _model;

2
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -307,7 +307,7 @@ namespace ControlCatalog.Pages
Content: Content:
"; ";
resultText += await ReadTextFromFile(file, 10000); resultText += await ReadTextFromFile(file, 500);
} }
openedFileContent.Text = resultText; openedFileContent.Text = resultText;

5
samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs

@ -1,5 +1,4 @@
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Avalonia.Controls; using Avalonia.Controls;
@ -23,7 +22,7 @@ namespace ControlCatalog.Pages
$"Text was dragged {++textCount} times"), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link); $"Text was dragged {++textCount} times"), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link);
SetupDnd("Custom", d => d.Set(CustomFormat, "Test123"), DragDropEffects.Move); SetupDnd("Custom", d => d.Set(CustomFormat, "Test123"), DragDropEffects.Move);
SetupDnd("Files", d => d.Set(DataFormats.Files, new[] { Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName }), DragDropEffects.Copy); SetupDnd("Files", async d => d.Set(DataFormats.Files, new[] { await (VisualRoot as TopLevel)!.StorageProvider.TryGetFileFromPathAsync(Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName) }), DragDropEffects.Copy);
} }
void SetupDnd(string suffix, Action<DataObject> factory, DragDropEffects effects) void SetupDnd(string suffix, Action<DataObject> factory, DragDropEffects effects)
@ -99,7 +98,7 @@ namespace ControlCatalog.Pages
{ {
if (item is IStorageFile file) if (item is IStorageFile file)
{ {
var content = await DialogsPage.ReadTextFromFile(file, 1000); var content = await DialogsPage.ReadTextFromFile(file, 500);
contentStr += $"File {item.Name}:{Environment.NewLine}{content}{Environment.NewLine}{Environment.NewLine}"; contentStr += $"File {item.Name}:{Environment.NewLine}{content}{Environment.NewLine}{Environment.NewLine}";
} }
else if (item is IStorageFolder folder) else if (item is IStorageFolder folder)

3
samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs

@ -117,9 +117,8 @@ namespace ControlCatalog.Pages
private void ScrollTo(int index) private void ScrollTo(int index)
{ {
System.Diagnostics.Debug.WriteLine("Scroll to " + index); System.Diagnostics.Debug.WriteLine("Scroll to " + index);
var layoutManager = ((TopLevel)VisualRoot!).LayoutManager;
var element = _repeater.GetOrCreateElement(index); var element = _repeater.GetOrCreateElement(index);
layoutManager.ExecuteLayoutPass(); ((TopLevel)VisualRoot!).UpdateLayout();
element.BringIntoView(); element.BringIntoView();
} }

29
samples/ControlCatalog/Pages/TabControlPage.xaml

@ -4,7 +4,27 @@
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:viewModels="using:ControlCatalog.ViewModels" xmlns:viewModels="using:ControlCatalog.ViewModels"
x:DataType="viewModels:TabControlPageViewModel"> x:DataType="viewModels:TabControlPageViewModel">
<DockPanel> <DockPanel Classes.WithContentTemplates="{Binding IsChecked, ElementName=UseContentTemplates}">
<DockPanel.Styles>
<Style Selector="DockPanel.WithContentTemplates">
<Style Selector="^ TabItem">
<Setter Property="ContentTemplate">
<DataTemplate x:CompileBindings="False">
<Border BorderBrush="Red" BorderThickness="10">
<ContentPresenter Content="{Binding}"/>
</Border>
</DataTemplate>
</Setter>
</Style>
<Style Selector="^ TabControl">
<Setter Property="ContentTemplate">
<DataTemplate>
<TextBlock Text="This template should be overriden by each TabItem's template."/>
</DataTemplate>
</Setter>
</Style>
</Style>
</DockPanel.Styles>
<TextBlock <TextBlock
DockPanel.Dock="Top" DockPanel.Dock="Top"
Classes="h2" Classes="h2"
@ -55,14 +75,14 @@
Margin="0 16" Margin="0 16"
DisplayMemberBinding="{Binding Header, x:DataType=viewModels:TabControlPageViewModelItem}" DisplayMemberBinding="{Binding Header, x:DataType=viewModels:TabControlPageViewModelItem}"
TabStripPlacement="{Binding TabPlacement}"> TabStripPlacement="{Binding TabPlacement}">
<TabControl.ContentTemplate> <TabControl.DataTemplates>
<DataTemplate x:DataType="viewModels:TabControlPageViewModelItem"> <DataTemplate x:DataType="viewModels:TabControlPageViewModelItem">
<StackPanel Orientation="Vertical" Spacing="8"> <StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Text="{Binding Text}"/> <TextBlock Text="{Binding Text}"/>
<Image Source="{Binding Image}" Width="300"/> <Image Source="{Binding Image}" Width="300"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</TabControl.ContentTemplate> </TabControl.DataTemplates>
<TabControl.Styles> <TabControl.Styles>
<Style Selector="TabItem" x:DataType="viewModels:TabControlPageViewModelItem"> <Style Selector="TabItem" x:DataType="viewModels:TabControlPageViewModelItem">
<Setter Property="IsEnabled" Value="{Binding IsEnabled}"/> <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
@ -78,12 +98,13 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center"> VerticalAlignment="Center">
<TextBlock VerticalAlignment="Center">Tab Placement:</TextBlock> <TextBlock VerticalAlignment="Center">Tab Placement:</TextBlock>
<ComboBox SelectedIndex="{Binding TabPlacement, Mode=TwoWay}"> <ComboBox SelectedIndex="{Binding TabPlacement, Mode=TwoWay}" Width="100">
<ComboBoxItem>Left</ComboBoxItem> <ComboBoxItem>Left</ComboBoxItem>
<ComboBoxItem>Bottom</ComboBoxItem> <ComboBoxItem>Bottom</ComboBoxItem>
<ComboBoxItem>Right</ComboBoxItem> <ComboBoxItem>Right</ComboBoxItem>
<ComboBoxItem>Top</ComboBoxItem> <ComboBoxItem>Top</ComboBoxItem>
</ComboBox> </ComboBox>
<CheckBox Name="UseContentTemplates">Set TabItem.ContentTemplate</CheckBox>
</StackPanel> </StackPanel>
</Grid> </Grid>
</DockPanel> </DockPanel>

2
samples/ControlCatalog/Pages/TabControlPage.xaml.cs

@ -49,7 +49,7 @@ namespace ControlCatalog.Pages
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
private static IBitmap LoadBitmap(string uri) private static Bitmap LoadBitmap(string uri)
{ {
var assets = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>(); var assets = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
return new Bitmap(assets.Open(new Uri(uri))); return new Bitmap(assets.Open(new Uri(uri)));

2
samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs

@ -21,6 +21,6 @@ public class TabControlPageViewModelItem
{ {
public string? Header { get; set; } public string? Header { get; set; }
public string? Text { get; set; } public string? Text { get; set; }
public IBitmap? Image { get; set; } public Bitmap? Image { get; set; }
public bool IsEnabled { get; set; } = true; public bool IsEnabled { get; set; } = true;
} }

2
samples/GpuInterop/MainWindow.axaml.cs

@ -11,7 +11,7 @@ namespace GpuInterop
{ {
InitializeComponent(); InitializeComponent();
this.AttachDevTools(); this.AttachDevTools();
Renderer.Diagnostics.DebugOverlays = RendererDebugOverlays.Fps; RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
} }
private void InitializeComponent() private void InitializeComponent()

2
samples/GpuInterop/VulkanDemo/VulkanContext.cs

@ -174,7 +174,7 @@ public unsafe class VulkanContext : IDisposable
for (uint queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++) for (uint queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++)
{ {
var family = familyProperties[queueFamilyIndex]; var family = familyProperties[queueFamilyIndex];
if (!family.QueueFlags.HasAllFlags(QueueFlags.GraphicsBit)) if (!family.QueueFlags.HasFlag(QueueFlags.GraphicsBit))
continue; continue;

3
samples/IntegrationTestApp/MainWindow.axaml

@ -47,6 +47,9 @@
<Button Name="DisabledButton" IsEnabled="False"> <Button Name="DisabledButton" IsEnabled="False">
Disabled Button Disabled Button
</Button> </Button>
<Button Name="EffectivelyDisabledButton" Command="{ReflectionBinding DoesntExist}">
Effectively Disabled Button
</Button>
<Button Name="BasicButton"> <Button Name="BasicButton">
Basic Button Basic Button
</Button> </Button>

2
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -136,7 +136,7 @@ namespace IntegrationTestApp
Name = "TransparentWindow", Name = "TransparentWindow",
SystemDecorations = SystemDecorations.None, SystemDecorations = SystemDecorations.None,
Background = Brushes.Transparent, Background = Brushes.Transparent,
TransparencyLevelHint = WindowTransparencyLevel.Transparent, TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent },
WindowStartupLocation = WindowStartupLocation.CenterOwner, WindowStartupLocation = WindowStartupLocation.CenterOwner,
Width = 200, Width = 200,
Height = 200, Height = 200,

21
samples/MobileSandbox.Desktop/MobileSandbox.Desktop.csproj

@ -4,37 +4,16 @@
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(RunNativeAotCompilation)' == 'true'">
<IlcTrimMetadata>true</IlcTrimMetadata>
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json</RestoreAdditionalProjectSources>
<NativeAotCompilerVersion>7.0.0-*</NativeAotCompilerVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Headless\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\MobileSandbox\MobileSandbox.csproj" /> <ProjectReference Include="..\MobileSandbox\MobileSandbox.csproj" />
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
<!-- For native controls test --> <!-- For native controls test -->
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" /> <PackageReference Include="MonoMac.NetStandard" Version="0.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(RunNativeAotCompilation)' == 'true'">
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="$(NativeAotCompilerVersion)" />
<!-- Cross-compilation for Windows x64-arm64 and Linux x64-arm64 -->
<PackageReference Condition="'$(RuntimeIdentifier)'=='win-arm64'" Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="$(NativeAotCompilerVersion)" />
<PackageReference Condition="'$(RuntimeIdentifier)'=='linux-arm64'" Include="runtime.linux-x64.Microsoft.DotNet.ILCompiler" Version="$(NativeAotCompilerVersion)" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<!-- For Microsoft.CodeAnalysis --> <!-- For Microsoft.CodeAnalysis -->
<SatelliteResourceLanguages>en</SatelliteResourceLanguages> <SatelliteResourceLanguages>en</SatelliteResourceLanguages>

15
samples/MobileSandbox/MobileSandbox.csproj

@ -14,9 +14,6 @@
<AvaloniaResource Include="Assets\*" /> <AvaloniaResource Include="Assets\*" />
<AvaloniaResource Include="Assets\Fonts\*" /> <AvaloniaResource Include="Assets\Fonts\*" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Remove="Pages\NativeEmbedPage.xaml" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Assets\Fonts\SourceSansPro-Bold.ttf" /> <EmbeddedResource Include="Assets\Fonts\SourceSansPro-Bold.ttf" />
<EmbeddedResource Include="Assets\Fonts\SourceSansPro-BoldItalic.ttf" /> <EmbeddedResource Include="Assets\Fonts\SourceSansPro-BoldItalic.ttf" />
@ -34,17 +31,5 @@
<ProjectReference Include="..\SampleControls\ControlSamples.csproj" /> <ProjectReference Include="..\SampleControls\ControlSamples.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<AvaloniaResource Update="Pages\NativeEmbedPage.xaml">
<Generator>MSBuild:Compile</Generator>
</AvaloniaResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Pages\NativeEmbedPage.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
</Project> </Project>

2
samples/RenderDemo/MainWindow.xaml.cs

@ -21,7 +21,7 @@ namespace RenderDemo
void BindOverlay(Expression<Func<MainWindowViewModel, bool>> expr, RendererDebugOverlays overlay) void BindOverlay(Expression<Func<MainWindowViewModel, bool>> expr, RendererDebugOverlays overlay)
=> vm.WhenAnyValue(expr).Subscribe(x => => vm.WhenAnyValue(expr).Subscribe(x =>
{ {
var diagnostics = Renderer.Diagnostics; var diagnostics = RendererDiagnostics;
diagnostics.DebugOverlays = x ? diagnostics.DebugOverlays = x ?
diagnostics.DebugOverlays | overlay : diagnostics.DebugOverlays | overlay :
diagnostics.DebugOverlays & ~overlay; diagnostics.DebugOverlays & ~overlay;

4
samples/RenderDemo/Pages/AnimationsPage.xaml

@ -347,12 +347,8 @@
</UserControl.Styles> </UserControl.Styles>
<Grid> <Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="False"> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="False">
<StackPanel.Clock>
<Clock />
</StackPanel.Clock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20">
<TextBlock VerticalAlignment="Center">Hover to activate Keyframe Animations.</TextBlock> <TextBlock VerticalAlignment="Center">Hover to activate Keyframe Animations.</TextBlock>
<Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" />
</StackPanel> </StackPanel>
<WrapPanel ClipToBounds="False"> <WrapPanel ClipToBounds="False">
<Border Classes="Test Rect1" Background="DarkRed"/> <Border Classes="Test Rect1" Background="DarkRed"/>

15
samples/RenderDemo/Pages/AnimationsPage.xaml.cs

@ -24,20 +24,5 @@ namespace RenderDemo.Pages
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
private void ToggleClock(object sender, RoutedEventArgs args)
{
var button = sender as Button;
var clock = button.Clock;
if (clock.PlayState == PlayState.Run)
{
clock.PlayState = PlayState.Pause;
}
else if (clock.PlayState == PlayState.Pause)
{
clock.PlayState = PlayState.Run;
}
}
} }
} }

12
samples/RenderDemo/Pages/CustomAnimatorPage.xaml

@ -11,10 +11,18 @@
<Style.Animations> <Style.Animations>
<Animation Duration="0:0:1" IterationCount="Infinite"> <Animation Duration="0:0:1" IterationCount="Infinite">
<KeyFrame Cue="0%"> <KeyFrame Cue="0%">
<Setter Property="Text" Value="" Animation.Animator="{x:Type pages:CustomStringAnimator}"/> <Setter Property="Text" Value="">
<Animation.Animator>
<pages:CustomStringAnimator/>
</Animation.Animator>
</Setter>
</KeyFrame> </KeyFrame>
<KeyFrame Cue="100%"> <KeyFrame Cue="100%">
<Setter Property="Text" Value="0123456789" Animation.Animator="{x:Type pages:CustomStringAnimator}"/> <Setter Property="Text" Value="0123456789" >
<Animation.Animator>
<pages:CustomStringAnimator/>
</Animation.Animator>
</Setter>
</KeyFrame> </KeyFrame>
</Animation> </Animation>
</Style.Animations> </Style.Animations>

6
samples/RenderDemo/Pages/CustomSkiaPage.cs

@ -27,11 +27,11 @@ namespace RenderDemo.Pages
class CustomDrawOp : ICustomDrawOperation class CustomDrawOp : ICustomDrawOperation
{ {
private readonly GlyphRun _noSkia; private readonly IImmutableGlyphRunReference _noSkia;
public CustomDrawOp(Rect bounds, GlyphRun noSkia) public CustomDrawOp(Rect bounds, GlyphRun noSkia)
{ {
_noSkia = noSkia; _noSkia = noSkia.TryCreateImmutableGlyphRunReference();
Bounds = bounds; Bounds = bounds;
} }
@ -48,7 +48,7 @@ namespace RenderDemo.Pages
{ {
var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>(); var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
if (leaseFeature == null) if (leaseFeature == null)
context.DrawGlyphRun(Brushes.Black, _noSkia.PlatformImpl); context.DrawGlyphRun(Brushes.Black, _noSkia);
else else
{ {
using var lease = leaseFeature.Lease(); using var lease = leaseFeature.Lease();

5
samples/RenderDemo/Pages/CustomStringAnimator.cs

@ -1,8 +1,9 @@
using Avalonia.Animation.Animators; using Avalonia.Animation;
using Avalonia.Animation.Animators;
namespace RenderDemo.Pages namespace RenderDemo.Pages
{ {
public class CustomStringAnimator : Animator<string> public class CustomStringAnimator : CustomAnimatorBase<string>
{ {
public override string Interpolate(double progress, string oldValue, string newValue) public override string Interpolate(double progress, string oldValue, string newValue)
{ {

8
samples/RenderDemo/Pages/PathMeasurementPage.cs

@ -53,15 +53,15 @@ namespace RenderDemo.Pages
bitmapCtx.DrawGeometry(null, strokePen, basePath); bitmapCtx.DrawGeometry(null, strokePen, basePath);
var length = basePath.PlatformImpl.ContourLength; var length = basePath.ContourLength;
if (basePath.PlatformImpl.TryGetSegment(length * 0.05, length * 0.2, true, out var dst1)) if (basePath.TryGetSegment(length * 0.05, length * 0.2, true, out var dst1))
bitmapCtx.DrawGeometry(null, strokePen1, dst1); bitmapCtx.DrawGeometry(null, strokePen1, dst1);
if (basePath.PlatformImpl.TryGetSegment(length * 0.2, length * 0.8, true, out var dst2)) if (basePath.TryGetSegment(length * 0.2, length * 0.8, true, out var dst2))
bitmapCtx.DrawGeometry(null, strokePen2, dst2); bitmapCtx.DrawGeometry(null, strokePen2, dst2);
if (basePath.PlatformImpl.TryGetSegment(length * 0.8, length * 0.95, true, out var dst3)) if (basePath.TryGetSegment(length * 0.8, length * 0.95, true, out var dst3))
bitmapCtx.DrawGeometry(null, strokePen3, dst3); bitmapCtx.DrawGeometry(null, strokePen3, dst3);
var pathBounds = basePath.GetRenderBounds(strokePen); var pathBounds = basePath.GetRenderBounds(strokePen);

3
samples/RenderDemo/Pages/Transform3DPage.axaml

@ -134,9 +134,6 @@
</UserControl.Styles> </UserControl.Styles>
<Grid ColumnDefinitions="Auto,*,Auto,*" RowDefinitions="*, Auto, Auto, Auto, Auto, Auto, Auto, Auto"> <Grid ColumnDefinitions="Auto,*,Auto,*" RowDefinitions="*, Auto, Auto, Auto, Auto, Auto, Auto, Auto">
<Grid.Clock>
<Clock />
</Grid.Clock>
<Border Name="B1" Background="DarkRed" Classes="Test"> <Border Name="B1" Background="DarkRed" Classes="Test">
<Border.RenderTransform> <Border.RenderTransform>
<Rotate3DTransform CenterZ="-100" <Rotate3DTransform CenterZ="-100"

4
samples/RenderDemo/Pages/TransitionsPage.xaml

@ -248,12 +248,8 @@
<Grid> <Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="False"> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="False">
<StackPanel.Clock>
<Clock />
</StackPanel.Clock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20">
<TextBlock VerticalAlignment="Center">Hover to activate Transitions.</TextBlock> <TextBlock VerticalAlignment="Center">Hover to activate Transitions.</TextBlock>
<Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" />
</StackPanel> </StackPanel>
<WrapPanel ClipToBounds="False"> <WrapPanel ClipToBounds="False">
<Border Classes="Test Rect1" Background="DarkRed"/> <Border Classes="Test Rect1" Background="DarkRed"/>

15
samples/RenderDemo/Pages/TransitionsPage.xaml.cs

@ -18,20 +18,5 @@ namespace RenderDemo.Pages
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
private void ToggleClock(object sender, RoutedEventArgs args)
{
var button = sender as Button;
var clock = button.Clock;
if (clock.PlayState == PlayState.Run)
{
clock.PlayState = PlayState.Pause;
}
else if (clock.PlayState == PlayState.Pause)
{
clock.PlayState = PlayState.Run;
}
}
} }
} }

1
samples/Sandbox/Sandbox.csproj

@ -5,6 +5,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators> <IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators>
<!-- <AvaloniaXamlIlDebuggerLaunch>true</AvaloniaXamlIlDebuggerLaunch>-->
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

6
samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs

@ -24,19 +24,19 @@ public class PlaygroundPageViewModel : ViewModelBase
public bool Multiple public bool Multiple
{ {
get => _selectionMode.HasAnyFlag(SelectionMode.Multiple); get => _selectionMode.HasFlag(SelectionMode.Multiple);
set => SetSelectionMode(SelectionMode.Multiple, value); set => SetSelectionMode(SelectionMode.Multiple, value);
} }
public bool Toggle public bool Toggle
{ {
get => _selectionMode.HasAnyFlag(SelectionMode.Toggle); get => _selectionMode.HasFlag(SelectionMode.Toggle);
set => SetSelectionMode(SelectionMode.Toggle, value); set => SetSelectionMode(SelectionMode.Toggle, value);
} }
public bool AlwaysSelected public bool AlwaysSelected
{ {
get => _selectionMode.HasAnyFlag(SelectionMode.AlwaysSelected); get => _selectionMode.HasFlag(SelectionMode.AlwaysSelected);
set => SetSelectionMode(SelectionMode.AlwaysSelected, value); set => SetSelectionMode(SelectionMode.AlwaysSelected, value);
} }

4
samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs

@ -1,4 +1,4 @@
using Avalonia.Win32.Embedding; using Avalonia.Win32.Interoperability;
namespace WindowsInteropTest namespace WindowsInteropTest
{ {
@ -116,4 +116,4 @@ namespace WindowsInteropTest
private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.GroupBox groupBox2;
private WinFormsAvaloniaControlHost avaloniaHost; private WinFormsAvaloniaControlHost avaloniaHost;
} }
} }

23
samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs

@ -1,35 +1,14 @@
using System; using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Avalonia.Controls;
using Avalonia.Rendering;
using Avalonia.VisualTree;
using ControlCatalog; using ControlCatalog;
namespace WindowsInteropTest namespace WindowsInteropTest
{ {
public partial class EmbedToWinFormsDemo : Form public partial class EmbedToWinFormsDemo : Form
{ {
private readonly IRenderer _renderer;
public EmbedToWinFormsDemo() public EmbedToWinFormsDemo()
{ {
InitializeComponent(); InitializeComponent();
avaloniaHost.Content = new MainView(); avaloniaHost.Content = new MainView();
_renderer = ((TopLevel)avaloniaHost.Content.GetVisualRoot()).Renderer;
_renderer.Start();
}
protected override void OnClosed(EventArgs e)
{
_renderer.Stop();
base.OnClosed(e);
} }
} }
} }

33
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml

@ -1,33 +0,0 @@
<Window x:Class="WindowsInteropTest.EmbedToWpfDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:av="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WindowsInteropTest"
xmlns:embedding="clr-namespace:Avalonia.Win32.Embedding;assembly=Avalonia.Win32"
xmlns:wpf="clr-namespace:Avalonia.Win32.Interop.Wpf;assembly=Avalonia.Win32.Interop"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400" MinWidth="500" MinHeight="400">
<DockPanel>
<GroupBox DockPanel.Dock="Left" Header="WPF">
<StackPanel>
<Slider/>
<Calendar/>
</StackPanel>
</GroupBox>
<GroupBox Header="Avalonia button" DockPanel.Dock="Bottom">
<wpf:WpfAvaloniaHost >
<av:Button Content="Avalonia button"/>
</wpf:WpfAvaloniaHost>
</GroupBox>
<GroupBox Header="AvBtn" DockPanel.Dock="Right">
<wpf:WpfAvaloniaHost x:Name="RightBtn">
<av:Button Content="Avalonia button 2"/>
</wpf:WpfAvaloniaHost>
</GroupBox>
<GroupBox Header="Avalonia">
<wpf:WpfAvaloniaHost x:Name="Host"/>
</GroupBox>
</DockPanel>
</Window>

52
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs

@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Rendering;
using Avalonia.VisualTree;
using ControlCatalog;
using Window = System.Windows.Window;
namespace WindowsInteropTest
{
/// <summary>
/// Interaction logic for EmbedToWpfDemo.xaml
/// </summary>
public partial class EmbedToWpfDemo : Window
{
private IRenderer _renderer;
public EmbedToWpfDemo()
{
InitializeComponent();
var view = new MainView();
Host.Content = view;
var tl = (TopLevel)view.GetVisualRoot();
tl.AttachDevTools();
_renderer = tl.Renderer;
_renderer.Start();
var btn = (Avalonia.Controls.Button) RightBtn.Content;
btn.Click += delegate
{
btn.Content += "!";
};
}
protected override void OnClosed(EventArgs e)
{
_renderer.Stop();
base.OnClosed(e);
}
}
}

9
samples/interop/WindowsInteropTest/Program.cs

@ -16,14 +16,9 @@ namespace WindowsInteropTest
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false); System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
AppBuilder.Configure<App>() AppBuilder.Configure<App>()
.UseWin32() .UseWin32()
.UseDirect2D1() .UseSkia()
.With(new Win32PlatformOptions
{
UseWindowsUIComposition = false,
ShouldRenderOnUIThread = true // necessary for WPF
})
.SetupWithoutStarting(); .SetupWithoutStarting();
System.Windows.Forms.Application.Run(new SelectorForm()); System.Windows.Forms.Application.Run(new EmbedToWinFormsDemo());
} }
} }
} }

76
samples/interop/WindowsInteropTest/SelectorForm.Designer.cs

@ -1,76 +0,0 @@
namespace WindowsInteropTest
{
partial class SelectorForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnEmbedToWinForms = new System.Windows.Forms.Button();
this.btnEmbedToWpf = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnEmbedToWinForms
//
this.btnEmbedToWinForms.Location = new System.Drawing.Point(12, 12);
this.btnEmbedToWinForms.Name = "btnEmbedToWinForms";
this.btnEmbedToWinForms.Size = new System.Drawing.Size(201, 86);
this.btnEmbedToWinForms.TabIndex = 0;
this.btnEmbedToWinForms.Text = "Embed to WinForms";
this.btnEmbedToWinForms.UseVisualStyleBackColor = true;
this.btnEmbedToWinForms.Click += new System.EventHandler(this.btnEmbedToWinForms_Click);
//
// btnEmbedToWpf
//
this.btnEmbedToWpf.Location = new System.Drawing.Point(219, 12);
this.btnEmbedToWpf.Name = "btnEmbedToWpf";
this.btnEmbedToWpf.Size = new System.Drawing.Size(201, 86);
this.btnEmbedToWpf.TabIndex = 1;
this.btnEmbedToWpf.Text = "Embed to WPF";
this.btnEmbedToWpf.UseVisualStyleBackColor = true;
this.btnEmbedToWpf.Click += new System.EventHandler(this.btnEmbedToWpf_Click);
//
// SelectorForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(432, 284);
this.Controls.Add(this.btnEmbedToWpf);
this.Controls.Add(this.btnEmbedToWinForms);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Name = "SelectorForm";
this.Text = "Interop";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnEmbedToWinForms;
private System.Windows.Forms.Button btnEmbedToWpf;
}
}

30
samples/interop/WindowsInteropTest/SelectorForm.cs

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsInteropTest
{
public partial class SelectorForm : Form
{
public SelectorForm()
{
InitializeComponent();
}
private void btnEmbedToWinForms_Click(object sender, EventArgs e)
{
new EmbedToWinFormsDemo().ShowDialog(this);
}
private void btnEmbedToWpf_Click(object sender, EventArgs e)
{
new EmbedToWpfDemo().ShowDialog();
}
}
}

120
samples/interop/WindowsInteropTest/SelectorForm.resx

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

6
samples/interop/WindowsInteropTest/WindowsInteropTest.csproj

@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net461</TargetFramework> <TargetFrameworks>net461;net6.0-windows</TargetFrameworks>
<PlatformTarget>x64</PlatformTarget>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj" /> <ProjectReference Include="..\..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32.Interoperability\Avalonia.Win32.Interoperability.csproj" />
<ProjectReference Include="..\..\ControlCatalog\ControlCatalog.csproj" /> <ProjectReference Include="..\..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

7
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -45,7 +45,6 @@ namespace Avalonia.Android
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface()) .Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoaderStub>() .Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoaderStub>()
.Bind<IRenderTimer>().ToConstant(new ChoreographerTimer()) .Bind<IRenderTimer>().ToConstant(new ChoreographerTimer())
.Bind<IRenderLoop>().ToConstant(new RenderLoop())
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>(); .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
if (Options.UseGpu) if (Options.UseGpu)
@ -53,11 +52,7 @@ namespace Avalonia.Android
EglPlatformGraphics.TryInitialize(); EglPlatformGraphics.TryInitialize();
} }
Compositor = new Compositor( Compositor = new Compositor(AvaloniaLocator.Current.GetService<IPlatformGraphics>());
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(),
AvaloniaLocator.Current.GetService<IPlatformGraphics>());
} }
} }

4
src/Android/Avalonia.Android/AvaloniaView.cs

@ -67,7 +67,7 @@ namespace Avalonia.Android
_timerSubscription = timer.SubscribeView(this); _timerSubscription = timer.SubscribeView(this);
} }
_root.Renderer.Start(); _root.StartRendering();
if (_view.TryGetFeature<IInsetsManager>(out var insetsManager) == true) if (_view.TryGetFeature<IInsetsManager>(out var insetsManager) == true)
{ {
@ -76,7 +76,7 @@ namespace Avalonia.Android
} }
else else
{ {
_root.Renderer.Stop(); _root.StopRendering();
_timerSubscription?.Dispose(); _timerSubscription?.Dispose();
} }
} }

112
src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs

@ -5,8 +5,9 @@ using Avalonia.Input;
namespace Avalonia.Android.Platform.Input namespace Avalonia.Android.Platform.Input
{ {
internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice { internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice
private static readonly Dictionary<Keycode, Key> KeyDic = new Dictionary<Keycode, Key> {
private static readonly Dictionary<Keycode, Key> KeyDic = new Dictionary<Keycode, Key>
{ {
// { Keycode.Cancel?, Key.Cancel }, // { Keycode.Cancel?, Key.Cancel },
{ Keycode.Del, Key.Back }, { Keycode.Del, Key.Back },
@ -15,7 +16,7 @@ namespace Avalonia.Android.Platform.Input
{ Keycode.Clear, Key.Clear }, { Keycode.Clear, Key.Clear },
{ Keycode.Enter, Key.Return }, { Keycode.Enter, Key.Return },
{ Keycode.MediaPause, Key.Pause }, { Keycode.MediaPause, Key.Pause },
//{ Keycode.?, Key.CapsLock } { Keycode.CapsLock, Key.CapsLock },
//{ Keycode.?, Key.HangulMode } //{ Keycode.?, Key.HangulMode }
//{ Keycode.?, Key.JunjaMode } //{ Keycode.?, Key.JunjaMode }
//{ Keycode.?, Key.FinalMode } //{ Keycode.?, Key.FinalMode }
@ -28,8 +29,8 @@ namespace Avalonia.Android.Platform.Input
{ Keycode.Space, Key.Space }, { Keycode.Space, Key.Space },
{ Keycode.PageUp, Key.Prior }, { Keycode.PageUp, Key.Prior },
{ Keycode.PageDown, Key.PageDown }, { Keycode.PageDown, Key.PageDown },
// { Keycode.end?, Key.End }, { Keycode.MoveEnd, Key.End },
{ Keycode.Home, Key.Home }, { Keycode.MoveHome, Key.Home },
{ Keycode.DpadLeft, Key.Left }, { Keycode.DpadLeft, Key.Left },
{ Keycode.DpadUp, Key.Up }, { Keycode.DpadUp, Key.Up },
{ Keycode.DpadRight, Key.Right }, { Keycode.DpadRight, Key.Right },
@ -37,20 +38,20 @@ namespace Avalonia.Android.Platform.Input
// { Keycode.ButtonSelect?, Key.Select }, // { Keycode.ButtonSelect?, Key.Select },
// { Keycode.print?, Key.Print }, // { Keycode.print?, Key.Print },
//{ Keycode.execute?, Key.Execute }, //{ Keycode.execute?, Key.Execute },
// { Keycode.snap, Key.Snapshot } //{ Keycode.snap?, Key.Snapshot }
{ Keycode.Insert, Key.Insert }, { Keycode.Insert, Key.Insert },
{ Keycode.ForwardDel, Key.Delete }, { Keycode.ForwardDel, Key.Delete },
//{ Keycode.help, Key.Help }, { Keycode.Help, Key.Help },
//{ Keycode.?, Key.D0 } { Keycode.Num0, Key.D0 },
//{ Keycode.?, Key.D1 } { Keycode.Num1, Key.D1 },
//{ Keycode.?, Key.D2 } { Keycode.Num2, Key.D2 },
//{ Keycode.?, Key.D3 } { Keycode.Num3, Key.D3 },
//{ Keycode.?, Key.D4 } { Keycode.Num4, Key.D4 },
//{ Keycode.?, Key.D5 } { Keycode.Num5, Key.D5 },
//{ Keycode.?, Key.D6 } { Keycode.Num6, Key.D6 },
//{ Keycode.?, Key.D7 } { Keycode.Num7, Key.D7 },
//{ Keycode.?, Key.D8 } { Keycode.Num8, Key.D8 },
//{ Keycode.?, Key.D9 } { Keycode.Num9, Key.D9 },
{ Keycode.A, Key.A }, { Keycode.A, Key.A },
{ Keycode.B, Key.B }, { Keycode.B, Key.B },
{ Keycode.C, Key.C }, { Keycode.C, Key.C },
@ -106,22 +107,22 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.LWin } //{ Keycode.?, Key.LWin }
//{ Keycode.?, Key.RWin } //{ Keycode.?, Key.RWin }
//{ Keycode.?, Key.Apps } //{ Keycode.?, Key.Apps }
//{ Keycode.?, Key.Sleep } { Keycode.Sleep, Key.Sleep },
//{ Keycode.?, Key.NumPad0 } { Keycode.Numpad0, Key.NumPad0 },
//{ Keycode.?, Key.NumPad1 } { Keycode.Numpad1, Key.NumPad1 },
//{ Keycode.?, Key.NumPad2 } { Keycode.Numpad2, Key.NumPad2 },
//{ Keycode.?, Key.NumPad3 } { Keycode.Numpad3, Key.NumPad3 },
//{ Keycode.?, Key.NumPad4 } { Keycode.Numpad4, Key.NumPad4 },
//{ Keycode.?, Key.NumPad5 } { Keycode.Numpad5, Key.NumPad5 },
//{ Keycode.?, Key.NumPad6 } { Keycode.Numpad6, Key.NumPad6 },
//{ Keycode.?, Key.NumPad7 } { Keycode.Numpad7, Key.NumPad7 },
//{ Keycode.?, Key.NumPad8 } { Keycode.Numpad8, Key.NumPad8 },
//{ Keycode.?, Key.NumPad9 } { Keycode.Numpad9, Key.NumPad9 },
{ Keycode.NumpadMultiply, Key.Multiply }, { Keycode.NumpadMultiply, Key.Multiply },
{ Keycode.NumpadAdd, Key.Add }, { Keycode.NumpadAdd, Key.Add },
{ Keycode.NumpadComma, Key.Separator }, { Keycode.NumpadComma, Key.Separator },
{ Keycode.NumpadSubtract, Key.Subtract }, { Keycode.NumpadSubtract, Key.Subtract },
//{ Keycode.numpaddecimal?, Key.Decimal } { Keycode.NumpadDot, Key.Decimal },
{ Keycode.NumpadDivide, Key.Divide }, { Keycode.NumpadDivide, Key.Divide },
{ Keycode.F1, Key.F1 }, { Keycode.F1, Key.F1 },
{ Keycode.F2, Key.F2 }, { Keycode.F2, Key.F2 },
@ -147,14 +148,14 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.R2, Key.F22 }, //{ Keycode.R2, Key.F22 },
//{ Keycode.F23, Key.F23 }, //{ Keycode.F23, Key.F23 },
//{ Keycode.R4, Key.F24 }, //{ Keycode.R4, Key.F24 },
// { Keycode.numpad, Key.NumLock } { Keycode.NumLock, Key.NumLock },
{ Keycode.ScrollLock, Key.Scroll }, { Keycode.ScrollLock, Key.Scroll },
{ Keycode.ShiftLeft, Key.LeftShift }, { Keycode.ShiftLeft, Key.LeftShift },
//{ Keycode.?, Key.RightShift } { Keycode.ShiftRight, Key.RightShift },
//{ Keycode.?, Key.LeftCtrl } { Keycode.CtrlLeft, Key.LeftCtrl },
//{ Keycode.?, Key.RightCtrl } { Keycode.CtrlRight, Key.RightCtrl },
//{ Keycode.?, Key.LeftAlt } { Keycode.AltLeft, Key.LeftAlt },
//{ Keycode.?, Key.RightAlt } { Keycode.AltRight, Key.RightAlt },
//{ Keycode.?, Key.BrowserBack } //{ Keycode.?, Key.BrowserBack }
//{ Keycode.?, Key.BrowserForward } //{ Keycode.?, Key.BrowserForward }
//{ Keycode.?, Key.BrowserRefresh } //{ Keycode.?, Key.BrowserRefresh }
@ -163,28 +164,30 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.BrowserFavorites } //{ Keycode.?, Key.BrowserFavorites }
//{ Keycode.?, Key.BrowserHome } //{ Keycode.?, Key.BrowserHome }
//{ Keycode.?, Key.VolumeMute } //{ Keycode.?, Key.VolumeMute }
//{ Keycode.?, Key.VolumeDown } { Keycode.VolumeDown, Key.VolumeDown },
//{ Keycode.?, Key.VolumeUp } { Keycode.VolumeUp, Key.VolumeUp },
//{ Keycode.?, Key.MediaNextTrack } { Keycode.MediaNext, Key.MediaNextTrack },
//{ Keycode.?, Key.MediaPreviousTrack } { Keycode.MediaPrevious, Key.MediaPreviousTrack },
//{ Keycode.?, Key.MediaStop } { Keycode.MediaStop, Key.MediaStop },
//{ Keycode.?, Key.MediaPlayPause } { Keycode.MediaPlayPause, Key.MediaPlayPause },
//{ Keycode.?, Key.LaunchMail } //{ Keycode.?, Key.LaunchMail }
//{ Keycode.?, Key.SelectMedia } //{ Keycode.?, Key.SelectMedia }
//{ Keycode.?, Key.LaunchApplication1 } //{ Keycode.?, Key.LaunchApplication1 }
//{ Keycode.?, Key.LaunchApplication2 } //{ Keycode.?, Key.LaunchApplication2 }
//{ Keycode.?, Key.OemSemicolon } { Keycode.Semicolon, Key.OemSemicolon },
//{ Keycode.?, Key.OemPlus } { Keycode.Plus, Key.OemPlus },
//{ Keycode.?, Key.OemComma } { Keycode.Comma, Key.OemComma },
//{ Keycode.?, Key.OemMinus } { Keycode.Minus, Key.OemMinus },
//{ Keycode.?, Key.OemPeriod } { Keycode.Period, Key.OemPeriod },
//{ Keycode.?, Key.Oem2 } //{ Keycode.?, Key.Oem2 }
//{ Keycode.?, Key.OemTilde } { Keycode.Grave, Key.OemTilde },
//{ Keycode.?, Key.AbntC1 } //{ Keycode.?, Key.AbntC1 }
//{ Keycode.?, Key.AbntC2 } //{ Keycode.?, Key.AbntC2 }
//{ Keycode.?, Key.Oem4 }
//{ Keycode.?, Key.OemPipe } //{ Keycode.?, Key.OemPipe }
//{ Keycode.?, Key.OemCloseBrackets } { Keycode.Apostrophe, Key.OemQuotes },
{ Keycode.Slash, Key.OemQuestion },
{ Keycode.LeftBracket, Key.OemOpenBrackets },
{ Keycode.RightBracket, Key.OemCloseBrackets },
//{ Keycode.?, Key.Oem7 } //{ Keycode.?, Key.Oem7 }
//{ Keycode.?, Key.Oem8 } //{ Keycode.?, Key.Oem8 }
//{ Keycode.?, Key.Oem102 } //{ Keycode.?, Key.Oem102 }
@ -200,17 +203,18 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.DbeEnterWordRegisterMode } //{ Keycode.?, Key.DbeEnterWordRegisterMode }
//{ Keycode.?, Key.DbeEnterImeConfigureMode } //{ Keycode.?, Key.DbeEnterImeConfigureMode }
//{ Keycode.?, Key.EraseEof } //{ Keycode.?, Key.EraseEof }
//{ Keycode.?, Key.Play } { Keycode.MediaPlay, Key.Play },
//{ Keycode.?, Key.Zoom } //{ Keycode.?, Key.Zoom }
//{ Keycode.?, Key.NoName } //{ Keycode.?, Key.NoName }
//{ Keycode.?, Key.DbeEnterDialogConversionMode } //{ Keycode.?, Key.DbeEnterDialogConversionMode }
//{ Keycode.?, Key.OemClear } //{ Keycode.?, Key.OemClear }
//{ Keycode.?, Key.DeadCharProcessed } //{ Keycode.?, Key.DeadCharProcessed }
{ Keycode.Backslash, Key.OemBackslash }
}; };
internal static Key ConvertKey(Keycode key) { internal static Key ConvertKey(Keycode key)
Key result; {
return KeyDic.TryGetValue(key, out result) ? result : Key.None; return KeyDic.TryGetValue(key, out var result) ? result : Key.None;
}
} }
}
} }

2
src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs

@ -10,7 +10,7 @@ using Avalonia.Platform;
namespace Avalonia.Android namespace Avalonia.Android
{ {
internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformNativeSurfaceHandle internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, INativePlatformHandleSurface
{ {
bool _invalidateQueued; bool _invalidateQueued;
readonly object _lock = new object(); readonly object _lock = new object();

173
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Versioning;
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Graphics; using Android.Graphics;
@ -45,6 +46,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
private readonly AndroidInsetsManager _insetsManager; private readonly AndroidInsetsManager _insetsManager;
private readonly ClipboardImpl _clipboard; private readonly ClipboardImpl _clipboard;
private ViewImpl _view; private ViewImpl _view;
private WindowTransparencyLevel _transparencyLevel;
public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false) public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false)
{ {
@ -68,6 +70,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView); _nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView);
_storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context); _storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context);
_transparencyLevel = WindowTransparencyLevel.None;
_systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService); _systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService);
} }
@ -103,9 +106,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IEnumerable<object> Surfaces => new object[] { _gl, _framebuffer, Handle }; public IEnumerable<object> Surfaces => new object[] { _gl, _framebuffer, Handle };
public IRenderer CreateRenderer(IRenderRoot root) => public Compositor Compositor => AndroidPlatform.Compositor;
new CompositingRenderer(root, AndroidPlatform.Compositor, () => Surfaces);
public virtual void Hide() public virtual void Hide()
{ {
_view.Visibility = ViewStates.Invisible; _view.Visibility = ViewStates.Invisible;
@ -274,7 +276,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public Action LostFocus { get; set; } public Action LostFocus { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; } public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
public WindowTransparencyLevel TransparencyLevel { get; private set; } public WindowTransparencyLevel TransparencyLevel
{
get => _transparencyLevel;
private set
{
if (_transparencyLevel != value)
{
_transparencyLevel = value;
TransparencyLevelChanged?.Invoke(value);
}
}
}
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) public void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
{ {
@ -299,91 +312,64 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public double Scaling => RenderScaling; public double Scaling => RenderScaling;
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels)
{ {
if (TransparencyLevel != transparencyLevel) if (_view.Context is not AvaloniaMainActivity activity)
return;
foreach (var level in transparencyLevels)
{ {
bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; if (!IsSupported(level))
bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; {
if (_view.Context is AvaloniaMainActivity activity) continue;
}
if (level == TransparencyLevel)
{
return;
}
if (level == WindowTransparencyLevel.None)
{
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
activity.SetTranslucent(false);
}
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White));
}
else if (level == WindowTransparencyLevel.Transparent)
{
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
activity.SetTranslucent(true);
SetBlurBehind(activity, 0);
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
}
}
else if (level == WindowTransparencyLevel.Blur)
{ {
switch (transparencyLevel) if (OperatingSystem.IsAndroidVersionAtLeast(31))
{ {
case WindowTransparencyLevel.AcrylicBlur: activity.SetTranslucent(true);
case WindowTransparencyLevel.ForceAcrylicBlur: SetBlurBehind(activity, 120);
case WindowTransparencyLevel.Mica: activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
case WindowTransparencyLevel.None:
if (!isBelowR)
{
activity.SetTranslucent(false);
}
if (isAboveR)
{
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
var attr = activity.Window?.Attributes;
if (attr != null)
{
attr.BlurBehindRadius = 0;
activity.Window.Attributes = attr;
}
}
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
if(transparencyLevel != WindowTransparencyLevel.None)
{
return;
}
break;
case WindowTransparencyLevel.Transparent:
if (!isBelowR)
{
activity.SetTranslucent(true);
}
if (isAboveR)
{
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
var attr = activity.Window?.Attributes;
if (attr != null)
{
attr.BlurBehindRadius = 0;
activity.Window.Attributes = attr;
}
}
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
break;
case WindowTransparencyLevel.Blur:
if (isAboveR)
{
activity.SetTranslucent(true);
activity.Window?.AddFlags(WindowManagerFlags.BlurBehind);
var attr = activity.Window?.Attributes;
if (attr != null)
{
attr.BlurBehindRadius = 120;
activity.Window.Attributes = attr;
}
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
}
else
{
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
return;
}
break;
} }
TransparencyLevel = transparencyLevel;
} }
TransparencyLevel = level;
return;
} }
// If we get here, we didn't find a supported level. Use the default of None.
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
activity.SetTranslucent(false);
}
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White));
} }
public virtual object TryGetFeature(Type featureType) public virtual object TryGetFeature(Type featureType)
{ {
if (featureType == typeof(IStorageProvider)) if (featureType == typeof(IStorageProvider))
@ -418,6 +404,31 @@ namespace Avalonia.Android.Platform.SkiaPlatform
return null; return null;
} }
private static bool IsSupported(WindowTransparencyLevel level)
{
if (level == WindowTransparencyLevel.None)
return true;
if (level == WindowTransparencyLevel.Transparent)
return OperatingSystem.IsAndroidVersionAtLeast(30);
if (level == WindowTransparencyLevel.Blur)
return OperatingSystem.IsAndroidVersionAtLeast(31);
return false;
}
private static void SetBlurBehind(AvaloniaMainActivity activity, int radius)
{
if (radius == 0)
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
else
activity.Window?.AddFlags(WindowManagerFlags.BlurBehind);
if (OperatingSystem.IsAndroidVersionAtLeast(31) && activity.Window?.Attributes is { } attr)
{
attr.BlurBehindRadius = radius;
activity.Window.Attributes = attr;
}
}
} }
internal class AvaloniaInputConnection : BaseInputConnection internal class AvaloniaInputConnection : BaseInputConnection

8
src/Avalonia.Base/Animation/Animatable.cs

@ -17,7 +17,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Defines the <see cref="Clock"/> property. /// Defines the <see cref="Clock"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<IClock> ClockProperty = internal static readonly StyledProperty<IClock> ClockProperty =
AvaloniaProperty.Register<Animatable, IClock>(nameof(Clock), inherits: true); AvaloniaProperty.Register<Animatable, IClock>(nameof(Clock), inherits: true);
/// <summary> /// <summary>
@ -36,7 +36,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Gets or sets the clock which controls the animations on the control. /// Gets or sets the clock which controls the animations on the control.
/// </summary> /// </summary>
public IClock Clock internal IClock Clock
{ {
get => GetValue(ClockProperty); get => GetValue(ClockProperty);
set => SetValue(ClockProperty, value); set => SetValue(ClockProperty, value);
@ -58,7 +58,7 @@ namespace Avalonia.Animation
/// This method should not be called from user code, it will be called automatically by the framework /// This method should not be called from user code, it will be called automatically by the framework
/// when a control is added to the visual tree. /// when a control is added to the visual tree.
/// </remarks> /// </remarks>
protected void EnableTransitions() internal void EnableTransitions()
{ {
if (!_transitionsEnabled) if (!_transitionsEnabled)
{ {
@ -83,7 +83,7 @@ namespace Avalonia.Animation
/// This method should not be called from user code, it will be called automatically by the framework /// This method should not be called from user code, it will be called automatically by the framework
/// when a control is removed from the visual tree. /// when a control is removed from the visual tree.
/// </remarks> /// </remarks>
protected void DisableTransitions() internal void DisableTransitions()
{ {
if (_transitionsEnabled) if (_transitionsEnabled)
{ {

27
src/Avalonia.Base/Animation/Animation.cs

@ -16,7 +16,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Tracks the progress of an animation. /// Tracks the progress of an animation.
/// </summary> /// </summary>
public class Animation : AvaloniaObject, IAnimation public sealed class Animation : AvaloniaObject, IAnimation
{ {
/// <summary> /// <summary>
/// Defines the <see cref="Duration"/> property. /// Defines the <see cref="Duration"/> property.
@ -186,7 +186,7 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <param name="setter">The animation setter.</param> /// <param name="setter">The animation setter.</param>
/// <returns>The property animator type.</returns> /// <returns>The property animator type.</returns>
public static (Type Type, Func<IAnimator> Factory)? GetAnimator(IAnimationSetter setter) internal static (Type Type, Func<IAnimator> Factory)? GetAnimator(IAnimationSetter setter)
{ {
if (s_animators.TryGetValue(setter, out var type)) if (s_animators.TryGetValue(setter, out var type))
{ {
@ -200,11 +200,9 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <param name="setter">The animation setter.</param> /// <param name="setter">The animation setter.</param>
/// <param name="value">The property animator value.</param> /// <param name="value">The property animator value.</param>
public static void SetAnimator(IAnimationSetter setter, public static void SetAnimator(IAnimationSetter setter, CustomAnimatorBase value)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicMethods)]
Type value)
{ {
s_animators[setter] = (value, () => (IAnimator)Activator.CreateInstance(value)!); s_animators[setter] = (value.WrapperType, value.CreateWrapper);
} }
private readonly static List<(Func<AvaloniaProperty, bool> Condition, Type Animator, Func<IAnimator> Factory)> Animators = new() private readonly static List<(Func<AvaloniaProperty, bool> Condition, Type Animator, Func<IAnimator> Factory)> Animators = new()
@ -233,7 +231,7 @@ namespace Avalonia.Animation
/// <typeparam name="TAnimator"> /// <typeparam name="TAnimator">
/// The type of the animator to instantiate. /// The type of the animator to instantiate.
/// </typeparam> /// </typeparam>
public static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition) internal static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition)
where TAnimator : IAnimator, new() where TAnimator : IAnimator, new()
{ {
Animators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator())); Animators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator()));
@ -312,8 +310,11 @@ namespace Avalonia.Animation
return (newAnimatorInstances, subscriptions); return (newAnimatorInstances, subscriptions);
} }
IDisposable IAnimation.Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
=> Apply(control, clock, match, onComplete);
/// <inheritdoc/> /// <inheritdoc/>
public IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete) internal IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
{ {
var (animators, subscriptions) = InterpretKeyframes(control); var (animators, subscriptions) = InterpretKeyframes(control);
if (animators.Count == 1) if (animators.Count == 1)
@ -358,14 +359,20 @@ namespace Avalonia.Animation
return new CompositeDisposable(subscriptions); return new CompositeDisposable(subscriptions);
} }
public Task RunAsync(Animatable control, CancellationToken cancellationToken = default) =>
RunAsync(control, null, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task RunAsync(Animatable control, IClock? clock = null) internal Task RunAsync(Animatable control, IClock? clock)
{ {
return RunAsync(control, clock, default); return RunAsync(control, clock, default);
} }
Task IAnimation.RunAsync(Animatable control, IClock? clock, CancellationToken cancellationToken)
=> RunAsync(control, clock, cancellationToken);
/// <inheritdoc/> /// <inheritdoc/>
public Task RunAsync(Animatable control, IClock? clock = null, CancellationToken cancellationToken = default) internal Task RunAsync(Animatable control, IClock? clock, CancellationToken cancellationToken)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {

9
src/Avalonia.Base/Animation/AnimatorDrivenTransition.cs

@ -1,5 +1,6 @@
using System; using System;
using Avalonia.Animation.Animators; using Avalonia.Animation.Animators;
using Avalonia.Animation.Easings;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
@ -8,13 +9,11 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <typeparam name="T">Type of the transitioned value.</typeparam> /// <typeparam name="T">Type of the transitioned value.</typeparam>
/// <typeparam name="TAnimator">Type of the animator.</typeparam> /// <typeparam name="TAnimator">Type of the animator.</typeparam>
public abstract class AnimatorDrivenTransition<T, TAnimator> : Transition<T> where TAnimator : Animator<T>, new() internal static class AnimatorDrivenTransition<T, TAnimator> where TAnimator : Animator<T>, new()
{ {
private static readonly TAnimator s_animator = new TAnimator(); private static readonly TAnimator s_animator = new TAnimator();
public override IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue) public static IObservable<T> Transition(IEasing easing, IObservable<double> progress, T oldValue, T newValue) =>
{ new AnimatorTransitionObservable<T, TAnimator>(s_animator, progress, easing, oldValue, newValue);
return new AnimatorTransitionObservable<T, TAnimator>(s_animator, progress, Easing, oldValue, newValue);
}
} }
} }

4
src/Avalonia.Base/Animation/AnimatorKeyFrame.cs

@ -11,7 +11,7 @@ namespace Avalonia.Animation
/// Defines a KeyFrame that is used for /// Defines a KeyFrame that is used for
/// <see cref="Animator{T}"/> objects. /// <see cref="Animator{T}"/> objects.
/// </summary> /// </summary>
public class AnimatorKeyFrame : AvaloniaObject internal class AnimatorKeyFrame : AvaloniaObject
{ {
public static readonly DirectProperty<AnimatorKeyFrame, object?> ValueProperty = public static readonly DirectProperty<AnimatorKeyFrame, object?> ValueProperty =
AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object?>(nameof(Value), k => k.Value, (k, v) => k.Value = v); AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object?>(nameof(Value), k => k.Value, (k, v) => k.Value = v);
@ -67,7 +67,7 @@ namespace Avalonia.Animation
} }
} }
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>() public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{ {
var typeConv = TypeDescriptor.GetConverter(typeof(T)); var typeConv = TypeDescriptor.GetConverter(typeof(T));

6
src/Avalonia.Base/Animation/AnimatorTransitionObservable.cs

@ -9,17 +9,15 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <typeparam name="T">Type of the transitioned value.</typeparam> /// <typeparam name="T">Type of the transitioned value.</typeparam>
/// <typeparam name="TAnimator">Type of the animator.</typeparam> /// <typeparam name="TAnimator">Type of the animator.</typeparam>
public class AnimatorTransitionObservable<T, TAnimator> : TransitionObservableBase<T> where TAnimator : Animator<T> internal class AnimatorTransitionObservable<T, TAnimator> : TransitionObservableBase<T> where TAnimator : Animator<T>
{ {
private readonly TAnimator _animator; private readonly TAnimator _animator;
private readonly Easing _easing;
private readonly T _oldValue; private readonly T _oldValue;
private readonly T _newValue; private readonly T _newValue;
public AnimatorTransitionObservable(TAnimator animator, IObservable<double> progress, Easing easing, T oldValue, T newValue) : base(progress, easing) public AnimatorTransitionObservable(TAnimator animator, IObservable<double> progress, IEasing easing, T oldValue, T newValue) : base(progress, easing)
{ {
_animator = animator; _animator = animator;
_easing = easing;
_oldValue = oldValue; _oldValue = oldValue;
_newValue = newValue; _newValue = newValue;
} }

2
src/Avalonia.Base/Animation/Animators/Animator`1.cs

@ -11,7 +11,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Base class for <see cref="Animator{T}"/> objects /// Base class for <see cref="Animator{T}"/> objects
/// </summary> /// </summary>
public abstract class Animator<T> : AvaloniaList<AnimatorKeyFrame>, IAnimator internal abstract class Animator<T> : AvaloniaList<AnimatorKeyFrame>, IAnimator
{ {
/// <summary> /// <summary>
/// List of type-converted keyframes. /// List of type-converted keyframes.

2
src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs

@ -15,7 +15,7 @@ namespace Avalonia.Animation.Animators
/// redirect them to the properly registered /// redirect them to the properly registered
/// animators in this class. /// animators in this class.
/// </summary> /// </summary>
public class BaseBrushAnimator : Animator<IBrush?> internal class BaseBrushAnimator : Animator<IBrush?>
{ {
private static readonly List<(Func<Type, bool> Match, Type AnimatorType, Func<IAnimator> AnimatorFactory)> _brushAnimators = new(); private static readonly List<(Func<Type, bool> Match, Type AnimatorType, Func<IAnimator> AnimatorFactory)> _brushAnimators = new();

2
src/Avalonia.Base/Animation/Animators/BoolAnimator.cs

@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// Animator that handles <see cref="bool"/> properties. /// Animator that handles <see cref="bool"/> properties.
/// </summary> /// </summary>
public class BoolAnimator : Animator<bool> internal class BoolAnimator : Animator<bool>
{ {
/// <inheritdocs/> /// <inheritdocs/>
public override bool Interpolate(double progress, bool oldValue, bool newValue) public override bool Interpolate(double progress, bool oldValue, bool newValue)

2
src/Avalonia.Base/Animation/Animators/BoxShadowAnimator.cs

@ -2,7 +2,7 @@ using Avalonia.Media;
namespace Avalonia.Animation.Animators namespace Avalonia.Animation.Animators
{ {
public class BoxShadowAnimator : Animator<BoxShadow> internal class BoxShadowAnimator : Animator<BoxShadow>
{ {
static ColorAnimator s_colorAnimator = new ColorAnimator(); static ColorAnimator s_colorAnimator = new ColorAnimator();
static DoubleAnimator s_doubleAnimator = new DoubleAnimator(); static DoubleAnimator s_doubleAnimator = new DoubleAnimator();

2
src/Avalonia.Base/Animation/Animators/BoxShadowsAnimator.cs

@ -2,7 +2,7 @@ using Avalonia.Media;
namespace Avalonia.Animation.Animators namespace Avalonia.Animation.Animators
{ {
public class BoxShadowsAnimator : Animator<BoxShadows> internal class BoxShadowsAnimator : Animator<BoxShadows>
{ {
private static readonly BoxShadowAnimator s_boxShadowAnimator = new BoxShadowAnimator(); private static readonly BoxShadowAnimator s_boxShadowAnimator = new BoxShadowAnimator();
public override BoxShadows Interpolate(double progress, BoxShadows oldValue, BoxShadows newValue) public override BoxShadows Interpolate(double progress, BoxShadows oldValue, BoxShadows newValue)

2
src/Avalonia.Base/Animation/Animators/ByteAnimator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="byte"/> properties. /// Animator that handles <see cref="byte"/> properties.
/// </summary> /// </summary>
public class ByteAnimator : Animator<byte> internal class ByteAnimator : Animator<byte>
{ {
const double maxVal = (double)byte.MaxValue; const double maxVal = (double)byte.MaxValue;

2
src/Avalonia.Base/Animation/Animators/ColorAnimator.cs

@ -12,7 +12,7 @@ namespace Avalonia.Animation.Animators
/// Animator that interpolates <see cref="Color"/> through /// Animator that interpolates <see cref="Color"/> through
/// gamma sRGB color space for better visual result. /// gamma sRGB color space for better visual result.
/// </summary> /// </summary>
public class ColorAnimator : Animator<Color> internal class ColorAnimator : Animator<Color>
{ {
/// <summary> /// <summary>
/// Opto-electronic conversion function for the sRGB color space. /// Opto-electronic conversion function for the sRGB color space.

2
src/Avalonia.Base/Animation/Animators/CornerRadiusAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="CornerRadius"/> properties. /// Animator that handles <see cref="CornerRadius"/> properties.
/// </summary> /// </summary>
public class CornerRadiusAnimator : Animator<CornerRadius> internal class CornerRadiusAnimator : Animator<CornerRadius>
{ {
public override CornerRadius Interpolate(double progress, CornerRadius oldValue, CornerRadius newValue) public override CornerRadius Interpolate(double progress, CornerRadius oldValue, CornerRadius newValue)
{ {

2
src/Avalonia.Base/Animation/Animators/DecimalAnimator.cs

@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// Animator that handles <see cref="decimal"/> properties. /// Animator that handles <see cref="decimal"/> properties.
/// </summary> /// </summary>
public class DecimalAnimator : Animator<decimal> internal class DecimalAnimator : Animator<decimal>
{ {
/// <inheritdocs/> /// <inheritdocs/>
public override decimal Interpolate(double progress, decimal oldValue, decimal newValue) public override decimal Interpolate(double progress, decimal oldValue, decimal newValue)

2
src/Avalonia.Base/Animation/Animators/DoubleAnimator.cs

@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// Animator that handles <see cref="double"/> properties. /// Animator that handles <see cref="double"/> properties.
/// </summary> /// </summary>
public class DoubleAnimator : Animator<double> internal class DoubleAnimator : Animator<double>
{ {
/// <inheritdocs/> /// <inheritdocs/>
public override double Interpolate(double progress, double oldValue, double newValue) public override double Interpolate(double progress, double oldValue, double newValue)

2
src/Avalonia.Base/Animation/Animators/FloatAnimator.cs

@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// Animator that handles <see cref="float"/> properties. /// Animator that handles <see cref="float"/> properties.
/// </summary> /// </summary>
public class FloatAnimator : Animator<float> internal class FloatAnimator : Animator<float>
{ {
/// <inheritdocs/> /// <inheritdocs/>
public override float Interpolate(double progress, float oldValue, float newValue) public override float Interpolate(double progress, float oldValue, float newValue)

2
src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs

@ -13,7 +13,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="SolidColorBrush"/> values. /// Animator that handles <see cref="SolidColorBrush"/> values.
/// </summary> /// </summary>
public class GradientBrushAnimator : Animator<IGradientBrush?> internal class GradientBrushAnimator : Animator<IGradientBrush?>
{ {
private static readonly RelativePointAnimator s_relativePointAnimator = new RelativePointAnimator(); private static readonly RelativePointAnimator s_relativePointAnimator = new RelativePointAnimator();
private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator(); private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator();

2
src/Avalonia.Base/Animation/Animators/Int16Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Int16"/> properties. /// Animator that handles <see cref="Int16"/> properties.
/// </summary> /// </summary>
public class Int16Animator : Animator<Int16> internal class Int16Animator : Animator<Int16>
{ {
const double maxVal = (double)Int16.MaxValue; const double maxVal = (double)Int16.MaxValue;

2
src/Avalonia.Base/Animation/Animators/Int32Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Int32"/> properties. /// Animator that handles <see cref="Int32"/> properties.
/// </summary> /// </summary>
public class Int32Animator : Animator<Int32> internal class Int32Animator : Animator<Int32>
{ {
const double maxVal = (double)Int32.MaxValue; const double maxVal = (double)Int32.MaxValue;

2
src/Avalonia.Base/Animation/Animators/Int64Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Int64"/> properties. /// Animator that handles <see cref="Int64"/> properties.
/// </summary> /// </summary>
public class Int64Animator : Animator<Int64> internal class Int64Animator : Animator<Int64>
{ {
const double maxVal = (double)Int64.MaxValue; const double maxVal = (double)Int64.MaxValue;

2
src/Avalonia.Base/Animation/Animators/PointAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Point"/> properties. /// Animator that handles <see cref="Point"/> properties.
/// </summary> /// </summary>
public class PointAnimator : Animator<Point> internal class PointAnimator : Animator<Point>
{ {
public override Point Interpolate(double progress, Point oldValue, Point newValue) public override Point Interpolate(double progress, Point oldValue, Point newValue)
{ {

2
src/Avalonia.Base/Animation/Animators/RectAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Rect"/> properties. /// Animator that handles <see cref="Rect"/> properties.
/// </summary> /// </summary>
public class RectAnimator : Animator<Rect> internal class RectAnimator : Animator<Rect>
{ {
public override Rect Interpolate(double progress, Rect oldValue, Rect newValue) public override Rect Interpolate(double progress, Rect oldValue, Rect newValue)
{ {

2
src/Avalonia.Base/Animation/Animators/RelativePointAnimator.cs

@ -3,7 +3,7 @@
/// <summary> /// <summary>
/// Animator that handles <see cref="RelativePoint"/> properties. /// Animator that handles <see cref="RelativePoint"/> properties.
/// </summary> /// </summary>
public class RelativePointAnimator : Animator<RelativePoint> internal class RelativePointAnimator : Animator<RelativePoint>
{ {
private static readonly PointAnimator s_pointAnimator = new PointAnimator(); private static readonly PointAnimator s_pointAnimator = new PointAnimator();

2
src/Avalonia.Base/Animation/Animators/SizeAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Size"/> properties. /// Animator that handles <see cref="Size"/> properties.
/// </summary> /// </summary>
public class SizeAnimator : Animator<Size> internal class SizeAnimator : Animator<Size>
{ {
public override Size Interpolate(double progress, Size oldValue, Size newValue) public override Size Interpolate(double progress, Size oldValue, Size newValue)
{ {

2
src/Avalonia.Base/Animation/Animators/SolidColorBrushAnimator.cs

@ -10,7 +10,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="SolidColorBrush"/> values. /// Animator that handles <see cref="SolidColorBrush"/> values.
/// </summary> /// </summary>
public class ISolidColorBrushAnimator : Animator<ISolidColorBrush?> internal class ISolidColorBrushAnimator : Animator<ISolidColorBrush?>
{ {
private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator(); private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator();

2
src/Avalonia.Base/Animation/Animators/ThicknessAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Thickness"/> properties. /// Animator that handles <see cref="Thickness"/> properties.
/// </summary> /// </summary>
public class ThicknessAnimator : Animator<Thickness> internal class ThicknessAnimator : Animator<Thickness>
{ {
public override Thickness Interpolate(double progress, Thickness oldValue, Thickness newValue) public override Thickness Interpolate(double progress, Thickness oldValue, Thickness newValue)
{ {

2
src/Avalonia.Base/Animation/Animators/TransformAnimator.cs

@ -9,7 +9,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Transform"/> properties. /// Animator that handles <see cref="Transform"/> properties.
/// </summary> /// </summary>
public class TransformAnimator : Animator<double> internal class TransformAnimator : Animator<double>
{ {
DoubleAnimator? _doubleAnimator; DoubleAnimator? _doubleAnimator;

2
src/Avalonia.Base/Animation/Animators/TransformOperationsAnimator.cs

@ -4,7 +4,7 @@ using Avalonia.Media.Transformation;
namespace Avalonia.Animation.Animators namespace Avalonia.Animation.Animators
{ {
public class TransformOperationsAnimator : Animator<TransformOperations> internal class TransformOperationsAnimator : Animator<TransformOperations>
{ {
public TransformOperationsAnimator() public TransformOperationsAnimator()
{ {

2
src/Avalonia.Base/Animation/Animators/UInt16Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="UInt16"/> properties. /// Animator that handles <see cref="UInt16"/> properties.
/// </summary> /// </summary>
public class UInt16Animator : Animator<UInt16> internal class UInt16Animator : Animator<UInt16>
{ {
const double maxVal = (double)UInt16.MaxValue; const double maxVal = (double)UInt16.MaxValue;

2
src/Avalonia.Base/Animation/Animators/UInt32Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="UInt32"/> properties. /// Animator that handles <see cref="UInt32"/> properties.
/// </summary> /// </summary>
public class UInt32Animator : Animator<UInt32> internal class UInt32Animator : Animator<UInt32>
{ {
const double maxVal = (double)UInt32.MaxValue; const double maxVal = (double)UInt32.MaxValue;

2
src/Avalonia.Base/Animation/Animators/UInt64Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="UInt64"/> properties. /// Animator that handles <see cref="UInt64"/> properties.
/// </summary> /// </summary>
public class UInt64Animator : Animator<UInt64> internal class UInt64Animator : Animator<UInt64>
{ {
const double maxVal = (double)UInt64.MaxValue; const double maxVal = (double)UInt64.MaxValue;

2
src/Avalonia.Base/Animation/Animators/VectorAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Animator that handles <see cref="Vector"/> properties. /// Animator that handles <see cref="Vector"/> properties.
/// </summary> /// </summary>
public class VectorAnimator : Animator<Vector> internal class VectorAnimator : Animator<Vector>
{ {
public override Vector Interpolate(double progress, Vector oldValue, Vector newValue) public override Vector Interpolate(double progress, Vector oldValue, Vector newValue)
{ {

5
src/Avalonia.Base/Animation/Clock.cs

@ -3,7 +3,10 @@ using Avalonia.Reactive;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
public class Clock : ClockBase // Note: this class was always broken: it subscribes to the global clock immediately even it if
// doesn't actually have subscriptions
internal class Clock : ClockBase
{ {
public static IClock GlobalClock => AvaloniaLocator.Current.GetRequiredService<IGlobalClock>(); public static IClock GlobalClock => AvaloniaLocator.Current.GetRequiredService<IGlobalClock>();

2
src/Avalonia.Base/Animation/ClockBase.cs

@ -3,7 +3,7 @@ using Avalonia.Reactive;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
public class ClockBase : IClock internal class ClockBase : IClock
{ {
private readonly ClockObservable _observable; private readonly ClockObservable _observable;

3
src/Avalonia.Base/Animation/Easings/IEasing.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Animation.Easings namespace Avalonia.Animation.Easings
{ {
/// <summary> /// <summary>
/// Defines the interface for easing classes. /// Defines the interface for easing classes.
/// </summary> /// </summary>
[NotClientImplementable]
public interface IEasing public interface IEasing
{ {
/// <summary> /// <summary>

5
src/Avalonia.Base/Animation/Easings/SpringEasing.cs

@ -64,11 +64,6 @@ public class SpringEasing : Easing
Damping = damping; Damping = damping;
InitialVelocity = initialVelocity; InitialVelocity = initialVelocity;
} }
public SpringEasing(Spring keySpline)
{
_internalSpring = keySpline;
}
public SpringEasing() public SpringEasing()
{ {

4
src/Avalonia.Base/Animation/IAnimation.cs

@ -14,11 +14,11 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Apply the animation to the specified control and run it when <paramref name="match" /> produces <c>true</c>. /// Apply the animation to the specified control and run it when <paramref name="match" /> produces <c>true</c>.
/// </summary> /// </summary>
IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete = null); internal IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete = null);
/// <summary> /// <summary>
/// Run the animation on the specified control. /// Run the animation on the specified control.
/// </summary> /// </summary>
Task RunAsync(Animatable control, IClock clock, CancellationToken cancellationToken = default); internal Task RunAsync(Animatable control, IClock clock, CancellationToken cancellationToken = default);
} }
} }

2
src/Avalonia.Base/Animation/IAnimationSetter.cs

@ -2,7 +2,7 @@ using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
[NotClientImplementable] [NotClientImplementable, PrivateApi]
public interface IAnimationSetter public interface IAnimationSetter
{ {
AvaloniaProperty? Property { get; set; } AvaloniaProperty? Property { get; set; }

3
src/Avalonia.Base/Animation/IAnimator.cs

@ -7,8 +7,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Interface for Animator objects /// Interface for Animator objects
/// </summary> /// </summary>
[NotClientImplementable] internal interface IAnimator : IList<AnimatorKeyFrame>
public interface IAnimator : IList<AnimatorKeyFrame>
{ {
/// <summary> /// <summary>
/// The target property. /// The target property.

3
src/Avalonia.Base/Animation/IClock.cs

@ -3,8 +3,7 @@ using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
[NotClientImplementable] internal interface IClock : IObservable<TimeSpan>
public interface IClock : IObservable<TimeSpan>
{ {
PlayState PlayState { get; set; } PlayState PlayState { get; set; }
} }

30
src/Avalonia.Base/Animation/ICustomAnimator.cs

@ -0,0 +1,30 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation;
public abstract class CustomAnimatorBase
{
internal abstract IAnimator CreateWrapper();
internal abstract Type WrapperType { get; }
}
public abstract class CustomAnimatorBase<T> : CustomAnimatorBase
{
public abstract T Interpolate(double progress, T oldValue, T newValue);
internal override Type WrapperType => typeof(AnimatorWrapper);
internal override IAnimator CreateWrapper() => new AnimatorWrapper(this);
internal class AnimatorWrapper : Animator<T>
{
private readonly CustomAnimatorBase<T> _parent;
public AnimatorWrapper(CustomAnimatorBase<T> parent)
{
_parent = parent;
}
public override T Interpolate(double progress, T oldValue, T newValue) => _parent.Interpolate(progress, oldValue, newValue);
}
}

3
src/Avalonia.Base/Animation/IGlobalClock.cs

@ -2,8 +2,7 @@ using Avalonia.Metadata;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
[NotClientImplementable] internal interface IGlobalClock : IClock
public interface IGlobalClock : IClock
{ {
} }
} }

4
src/Avalonia.Base/Animation/ITransition.cs

@ -6,13 +6,13 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Interface for Transition objects. /// Interface for Transition objects.
/// </summary> /// </summary>
[NotClientImplementable] [NotClientImplementable, PrivateApi]
public interface ITransition public interface ITransition
{ {
/// <summary> /// <summary>
/// Applies the transition to the specified <see cref="Animatable"/>. /// Applies the transition to the specified <see cref="Animatable"/>.
/// </summary> /// </summary>
IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue); internal IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue);
/// <summary> /// <summary>
/// Gets the property to be animated. /// Gets the property to be animated.

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save