diff --git a/.ncrunch/AppWithoutLifetime.v3.ncrunchproject b/.ncrunch/AppWithoutLifetime.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/AppWithoutLifetime.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
index 92c924f107..5e770a0170 100644
--- a/Avalonia.Desktop.slnf
+++ b/Avalonia.Desktop.slnf
@@ -39,14 +39,13 @@
"src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj",
"src\\Markup\\Avalonia.Markup\\Avalonia.Markup.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.Win32.Interop\\Avalonia.Win32.Interop.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.Benchmarks\\Avalonia.Benchmarks.csproj",
"tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj",
@@ -66,4 +65,4 @@
"tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj"
]
}
-}
+}
\ No newline at end of file
diff --git a/Avalonia.sln b/Avalonia.sln
index 9670327d67..0bae725d33 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -135,7 +135,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}"
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
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}"
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}"
EndProject
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}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.Android", "samples\SafeAreaDemo.Android\SafeAreaDemo.Android.csproj", "{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D}"
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 2849262591..3239ca830a 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -4,7 +4,7 @@
Avalonia
11.0.999
Avalonia Team
- Copyright 2022 © The AvaloniaUI Project
+ Copyright 2013-$([System.DateTime]::Now.ToString(`yyyy`)) © The AvaloniaUI Project
https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
true
diff --git a/dirs.proj b/dirs.proj
index d29aa61fcb..120212bd9f 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -14,11 +14,11 @@
+
-
-
+
+
-
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 87e1e86bf9..524c9fa4e4 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -312,7 +312,7 @@ partial class Build : NukeBuild
public static int Main() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
- ? Execute(x => x.RunToolsTests)
+ ? Execute(x => x.Package)
: Execute(x => x.RunTests);
}
diff --git a/nukebuild/RefAssemblyGenerator.cs b/nukebuild/RefAssemblyGenerator.cs
index f0d5c81a37..54e428c442 100644
--- a/nukebuild/RefAssemblyGenerator.cs
+++ b/nukebuild/RefAssemblyGenerator.cs
@@ -63,52 +63,89 @@ public class RefAssemblyGenerator
});
}
+ static bool HasPrivateApi(IEnumerable attrs) => attrs.Any(a =>
+ a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute");
+
static void ProcessType(TypeDefinition type, MethodReference obsoleteCtor)
{
foreach (var nested in type.NestedTypes)
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.HasCustomAttributes && type.CustomAttributes.Any(a =>
- a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute"));
+ type.Methods.Add(new MethodDefinition(
+ "(This interface or abstract class is -not- implementable by user code !)",
+ MethodAttributes.Assembly
+ | MethodAttributes.Abstract
+ | MethodAttributes.NewSlot
+ | MethodAttributes.HideBySig, type.Module.TypeSystem.Void));
+ }
- var injectMethod = hideMethods
- || type.CustomAttributes.Any(a =>
- a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute");
-
- if (hideMethods)
+ var forceUnstable = type.CustomAttributes.FirstOrDefault(a =>
+ a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute");
+
+ foreach (var m in type.Methods)
+ {
+ if (hideMembers || HasPrivateApi(m.CustomAttributes))
{
- foreach (var m in type.Methods)
- {
- var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem |
- MethodAttributes.FamANDAssem | MethodAttributes.Assembly;
- m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
- }
+ HideMethod(m);
}
-
- if(injectMethod)
+ MarkAsUnstable(m, obsoleteCtor, forceUnstable);
+ }
+
+ foreach (var p in type.Properties)
+ {
+ if (HasPrivateApi(p.CustomAttributes))
{
- type.Methods.Add(new MethodDefinition("NotClientImplementable",
- MethodAttributes.Assembly
- | MethodAttributes.Abstract
- | MethodAttributes.NewSlot
- | MethodAttributes.HideBySig, type.Module.TypeSystem.Void));
+ if (p.SetMethod != null)
+ HideMethod(p.SetMethod);
+ if (p.GetMethod != null)
+ HideMethod(p.GetMethod);
}
+ }
- var forceUnstable = type.CustomAttributes.FirstOrDefault(a =>
- a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute");
-
- foreach (var m in type.Methods)
- MarkAsUnstable(m, obsoleteCtor, forceUnstable);
- foreach (var m in type.Properties)
- MarkAsUnstable(m, obsoleteCtor, forceUnstable);
- foreach (var m in type.Events)
- MarkAsUnstable(m, obsoleteCtor, forceUnstable);
-
+ foreach (var f in type.Fields)
+ {
+ if (hideMembers || HasPrivateApi(f.CustomAttributes))
+ {
+ var dflags = FieldAttributes.Public | FieldAttributes.Family | FieldAttributes.FamORAssem |
+ FieldAttributes.FamANDAssem | FieldAttributes.Assembly;
+ f.Attributes = ((f.Attributes | dflags) ^ dflags) | FieldAttributes.Assembly;
+ }
}
+
+ 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)
{
if (def.CustomAttributes.Any(a => a.AttributeType.FullName == "System.ObsoleteAttribute"))
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index 8999b7ca76..30e1200220 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -35,6 +35,12 @@
+
+
+
+ dirs.proj
+
+
diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj
index 412251bc9c..3f313ead1b 100644
--- a/packages/Avalonia/Avalonia.csproj
+++ b/packages/Avalonia/Avalonia.csproj
@@ -5,7 +5,7 @@
-
+
all
diff --git a/packages/Avalonia/Avalonia.targets b/packages/Avalonia/Avalonia.targets
index 50306f2cdc..eacd287b59 100644
--- a/packages/Avalonia/Avalonia.targets
+++ b/packages/Avalonia/Avalonia.targets
@@ -1,3 +1,4 @@
+
diff --git a/packages/Avalonia/AvaloniaPrivateApis.targets b/packages/Avalonia/AvaloniaPrivateApis.targets
new file mode 100644
index 0000000000..5343559c07
--- /dev/null
+++ b/packages/Avalonia/AvaloniaPrivateApis.targets
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ net6.0
+ netstandard2.0
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
index c6405dabb6..2c47effa38 100644
--- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
+++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
@@ -4,10 +4,17 @@
Exe
net461
x64
+ true
+ ../ControlCatalog.NetCore/app.manifest
+
+
+
+
+
diff --git a/samples/ControlCatalog.Desktop/Program.cs b/samples/ControlCatalog.Desktop/Program.cs
index 4d28f15e2c..eeb2095201 100644
--- a/samples/ControlCatalog.Desktop/Program.cs
+++ b/samples/ControlCatalog.Desktop/Program.cs
@@ -3,6 +3,8 @@ using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;
+using ControlCatalog.NetCore;
+using ControlCatalog.Pages;
namespace ControlCatalog
{
@@ -18,6 +20,15 @@ namespace ControlCatalog
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure()
.LogToTrace()
+ .AfterSetup(builder =>
+ {
+ builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
+ {
+ StartupScreenIndex = 1,
+ });
+
+ EmbedSample.Implementation = new EmbedSampleWin();
+ })
.UsePlatformDetect();
private static void ConfigureAssetAssembly(AppBuilder builder)
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index 877d475fb6..37719b77d8 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -16,6 +16,7 @@
+
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index 9c511f9eb0..801844a43c 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -83,9 +83,10 @@ namespace ControlCatalog
if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected)
{
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 semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2);
diff --git a/samples/ControlCatalog/Pages/ColorPickerPage.xaml b/samples/ControlCatalog/Pages/ColorPickerPage.xaml
index b759720cf2..25fffabfd2 100644
--- a/samples/ControlCatalog/Pages/ColorPickerPage.xaml
+++ b/samples/ControlCatalog/Pages/ColorPickerPage.xaml
@@ -103,7 +103,8 @@
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" />-->
+ HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}"
+ Margin="0,2,0,0" />
diff --git a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
index 96fcb54650..664264956f 100644
--- a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
@@ -19,8 +19,8 @@ namespace ControlCatalog.Pages
customContextRequestedBorder.AddHandler(ContextRequestedEvent, CustomContextRequested, RoutingStrategies.Tunnel);
var cancellableContextBorder = this.Get("CancellableContextBorder");
- cancellableContextBorder.ContextMenu!.ContextMenuClosing += ContextFlyoutPage_Closing;
- cancellableContextBorder.ContextMenu!.ContextMenuOpening += ContextFlyoutPage_Opening;
+ cancellableContextBorder.ContextMenu!.Closing += ContextFlyoutPage_Closing;
+ cancellableContextBorder.ContextMenu!.Opening += ContextFlyoutPage_Opening;
}
private ContextPageViewModel? _model;
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
index 971a6a6718..4d617fd313 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
@@ -307,7 +307,7 @@ namespace ControlCatalog.Pages
Content:
";
- resultText += await ReadTextFromFile(file, 10000);
+ resultText += await ReadTextFromFile(file, 500);
}
openedFileContent.Text = resultText;
diff --git a/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs b/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
index 7fb5bec589..aef82768c8 100644
--- a/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
@@ -1,5 +1,4 @@
using System;
-using System.IO;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
@@ -23,7 +22,7 @@ namespace ControlCatalog.Pages
$"Text was dragged {++textCount} times"), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link);
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 factory, DragDropEffects effects)
@@ -99,7 +98,7 @@ namespace ControlCatalog.Pages
{
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}";
}
else if (item is IStorageFolder folder)
diff --git a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs
index 70ce6107ad..2219966daa 100644
--- a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs
@@ -117,9 +117,8 @@ namespace ControlCatalog.Pages
private void ScrollTo(int index)
{
System.Diagnostics.Debug.WriteLine("Scroll to " + index);
- var layoutManager = ((TopLevel)VisualRoot!).LayoutManager;
var element = _repeater.GetOrCreateElement(index);
- layoutManager.ExecuteLayoutPass();
+ ((TopLevel)VisualRoot!).UpdateLayout();
element.BringIntoView();
}
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml b/samples/ControlCatalog/Pages/TabControlPage.xaml
index 3a2464e9fd..1faa74c1ce 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml
@@ -4,7 +4,27 @@
xmlns="https://github.com/avaloniaui"
xmlns:viewModels="using:ControlCatalog.ViewModels"
x:DataType="viewModels:TabControlPageViewModel">
-
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+ -->
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml
index e05fa5a907..520e6e8db3 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml
@@ -1,6 +1,7 @@
+ xmlns:pc="using:Avalonia.Controls.Primitives.Converters"
+ x:ClassModifier="internal">
80
@@ -8,7 +9,9 @@
-
+
+
+
@@ -21,7 +24,6 @@
Height="{StaticResource ColorPreviewerAccentSectionHeight}"
Width="{StaticResource ColorPreviewerAccentSectionWidth}"
ColumnDefinitions="*,*"
- Margin="0,0,-10,0"
VerticalAlignment="Center">
+ CornerRadius="{TemplateBinding CornerRadius}">
@@ -82,8 +81,7 @@
+ VerticalAlignment="Stretch">
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml
index 789473571b..edc6246ddd 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml
index ebbb006fd1..c9972125a0 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml
@@ -1,6 +1,7 @@
+ xmlns:controls="using:Avalonia.Controls"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
index acd2c7ff15..9ca55566f3 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
@@ -4,7 +4,8 @@
xmlns:converters="using:Avalonia.Controls.Converters"
xmlns:primitives="using:Avalonia.Controls.Primitives"
xmlns:pc="using:Avalonia.Controls.Primitives.Converters"
- xmlns:globalization="using:System.Globalization">
+ xmlns:globalization="using:System.Globalization"
+ x:ClassModifier="internal">
@@ -360,8 +361,8 @@
-
+
+
+
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml
index ff4e1d93a8..c20f7935f4 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml
@@ -1,7 +1,8 @@
+ xmlns:primitives="using:Avalonia.Controls.Primitives"
+ x:ClassModifier="internal">
@@ -112,8 +113,8 @@
-
+
@@ -501,6 +502,23 @@
+
+
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml
index a39dd91f52..23f0b34ddd 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml
@@ -1,6 +1,7 @@
+ xmlns:pc="using:Avalonia.Controls.Primitives.Converters"
+ x:ClassModifier="internal">
80
@@ -8,7 +9,9 @@
-
+
+
+
@@ -21,7 +24,6 @@
Height="{StaticResource ColorPreviewerAccentSectionHeight}"
Width="{StaticResource ColorPreviewerAccentSectionWidth}"
ColumnDefinitions="*,*"
- Margin="0,0,-10,0"
VerticalAlignment="Center">
+ CornerRadius="{TemplateBinding CornerRadius}">
@@ -82,8 +81,7 @@
+ VerticalAlignment="Stretch">
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml
index 472f1ca100..6b4ad68275 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml
@@ -1,5 +1,6 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml
index a7ad56d8b4..101a06ccb9 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml
@@ -1,6 +1,7 @@
+ xmlns:controls="using:Avalonia.Controls"
+ x:ClassModifier="internal">
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml
index a26d3179b5..994a5e1bbc 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml
@@ -4,7 +4,8 @@
xmlns:converters="using:Avalonia.Controls.Converters"
xmlns:primitives="using:Avalonia.Controls.Primitives"
xmlns:pc="using:Avalonia.Controls.Primitives.Converters"
- xmlns:globalization="using:System.Globalization">
+ xmlns:globalization="using:System.Globalization"
+ x:ClassModifier="internal">
@@ -322,8 +323,8 @@
-
+
+
+
+
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index a55a47fa53..7ade9f2437 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -2660,25 +2660,25 @@ namespace Avalonia.Controls
internal bool ProcessDownKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessDownKeyInternal(shift, ctrl);
}
internal bool ProcessEndKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessEndKey(shift, ctrl);
}
internal bool ProcessEnterKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessEnterKey(shift, ctrl);
}
internal bool ProcessHomeKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessHomeKey(shift, ctrl);
}
@@ -2718,25 +2718,25 @@ namespace Avalonia.Controls
internal bool ProcessLeftKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessLeftKey(shift, ctrl);
}
internal bool ProcessNextKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessNextKey(shift, ctrl);
}
internal bool ProcessPriorKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessPriorKey(shift, ctrl);
}
internal bool ProcessRightKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessRightKey(shift, ctrl);
}
@@ -2854,7 +2854,7 @@ namespace Avalonia.Controls
internal bool ProcessUpKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessUpKey(shift, ctrl);
}
@@ -3124,13 +3124,13 @@ namespace Avalonia.Controls
//TODO: Ensure right button is checked for
internal bool UpdateStateOnMouseRightButtonDown(PointerPressedEventArgs pointerPressedEventArgs, int columnIndex, int slot, bool allowEdit)
{
- KeyboardHelper.GetMetaKeyState(pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift);
return UpdateStateOnMouseRightButtonDown(pointerPressedEventArgs, columnIndex, slot, allowEdit, shift, ctrl);
}
//TODO: Ensure left button is checked for
internal bool UpdateStateOnMouseLeftButtonDown(PointerPressedEventArgs pointerPressedEventArgs, int columnIndex, int slot, bool allowEdit)
{
- KeyboardHelper.GetMetaKeyState(pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift);
return UpdateStateOnMouseLeftButtonDown(pointerPressedEventArgs, columnIndex, slot, allowEdit, shift, ctrl);
}
@@ -3958,7 +3958,7 @@ namespace Avalonia.Controls
{
bool focusLeftDataGrid = true;
bool dataGridWillReceiveRoutedEvent = true;
- Visual focusedObject = FocusManager.Instance.Current as Visual;
+ Visual focusedObject = FocusManager.GetFocusManager(this)?.GetFocusedElement() as Visual;
DataGridColumn editingColumn = null;
while (focusedObject != null)
@@ -4654,7 +4654,7 @@ namespace Avalonia.Controls
private bool ProcessAKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift, out bool alt);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift, out bool alt);
if (ctrl && !shift && !alt && SelectionMode == DataGridSelectionMode.Extended)
{
@@ -4865,7 +4865,8 @@ namespace Avalonia.Controls
if (!ctrl)
{
// If Enter was used by a TextBox, we shouldn't handle the key
- if (FocusManager.Instance.Current is TextBox focusedTextBox && focusedTextBox.AcceptsReturn)
+ if (FocusManager.GetFocusManager(this)?.GetFocusedElement() is TextBox focusedTextBox
+ && focusedTextBox.AcceptsReturn)
{
return false;
}
@@ -4922,7 +4923,7 @@ namespace Avalonia.Controls
private bool ProcessF2Key(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
if (!shift && !ctrl &&
_editingColumnIndex == -1 && CurrentColumnIndex != -1 && GetRowSelection(CurrentSlot) &&
@@ -5279,7 +5280,7 @@ namespace Avalonia.Controls
private bool ProcessTabKey(KeyEventArgs e)
{
- KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift);
return ProcessTabKey(e, shift, ctrl);
}
@@ -6098,7 +6099,7 @@ namespace Avalonia.Controls
/// Whether or not the DataGrid handled the key press.
private bool ProcessCopyKey(KeyModifiers modifiers)
{
- KeyboardHelper.GetMetaKeyState(modifiers, out bool ctrl, out bool shift, out bool alt);
+ KeyboardHelper.GetMetaKeyState(this, modifiers, out bool ctrl, out bool shift, out bool alt);
if (ctrl && !shift && !alt && ClipboardCopyMode != DataGridClipboardCopyMode.None && SelectedItems.Count > 0)
{
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
index d1e1efdd85..96d072260c 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
@@ -703,7 +703,7 @@ namespace Avalonia.Controls
public void ClearSort()
{
//InvokeProcessSort is already validating if sorting is possible
- _headerCell?.InvokeProcessSort(KeyboardHelper.GetPlatformCtrlOrCmdKeyModifier());
+ _headerCell?.InvokeProcessSort(KeyboardHelper.GetPlatformCtrlOrCmdKeyModifier(OwningGrid));
}
///
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
index ef1e84c745..0755864c25 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
@@ -241,7 +241,7 @@ namespace Avalonia.Controls
DataGrid owningGrid = OwningGrid;
DataGridSortDescription newSort;
- KeyboardHelper.GetMetaKeyState(keyModifiers, out bool ctrl, out bool shift);
+ KeyboardHelper.GetMetaKeyState(this, keyModifiers, out bool ctrl, out bool shift);
DataGridSortDescription sort = OwningColumn.GetSortDescription();
IDataGridCollectionView collectionView = owningGrid.DataConnection.CollectionView;
diff --git a/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs b/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs
index d2b1fd4b8e..bcb30888dc 100644
--- a/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs
+++ b/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs
@@ -10,23 +10,23 @@ namespace Avalonia.Controls.Utils
{
internal static class KeyboardHelper
{
- public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift)
+ public static void GetMetaKeyState(Control target, KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift)
{
- ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier());
+ ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier(target));
shift = modifiers.HasFlag(KeyModifiers.Shift);
}
- public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift, out bool alt)
+ public static void GetMetaKeyState(Control target, KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift, out bool alt)
{
- ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier());
+ ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier(target));
shift = modifiers.HasFlag(KeyModifiers.Shift);
alt = modifiers.HasFlag(KeyModifiers.Alt);
}
- public static KeyModifiers GetPlatformCtrlOrCmdKeyModifier()
- {
- var keymap = AvaloniaLocator.Current.GetService();
- return keymap?.CommandModifiers ?? KeyModifiers.Control;
+ public static KeyModifiers GetPlatformCtrlOrCmdKeyModifier(Control target)
+ {
+ var keymap = TopLevel.GetTopLevel(target)!.PlatformSettings!.HotkeyConfiguration;
+ return keymap.CommandModifiers;
}
}
}
diff --git a/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs b/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs
index 49c8b9ff92..d03949c1c2 100644
--- a/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs
+++ b/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs
@@ -53,8 +53,8 @@ namespace Avalonia.Controls
{
return _owner.GetElementImpl(
index,
- options.HasAllFlags(ElementRealizationOptions.ForceCreate),
- options.HasAllFlags(ElementRealizationOptions.SuppressAutoRecycle));
+ options.HasFlag(ElementRealizationOptions.ForceCreate),
+ options.HasFlag(ElementRealizationOptions.SuppressAutoRecycle));
}
protected override object GetItemAtCore(int index) => _owner.ItemsSourceView!.GetAt(index)!;
diff --git a/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs b/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs
index 6b9d7934bf..674389d77c 100644
--- a/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs
+++ b/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs
@@ -695,7 +695,7 @@ namespace Avalonia.Controls
{
Control? focusedElement = null;
- if (FocusManager.Instance?.Current is Visual child)
+ if (TopLevel.GetTopLevel(_owner)?.FocusManager?.GetFocusedElement() is Visual child)
{
var parent = child.GetVisualParent();
var owner = _owner;
diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs
index e907fd5988..30791551f5 100644
--- a/src/Avalonia.Controls/Application.cs
+++ b/src/Avalonia.Controls/Application.cs
@@ -8,6 +8,7 @@ using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Input.Raw;
+using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
@@ -117,25 +118,13 @@ namespace Avalonia
///
public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
- ///
- /// Gets the application's focus manager.
- ///
- ///
- /// The application's focus manager.
- ///
- public IFocusManager? FocusManager
- {
- get;
- private set;
- }
-
///
/// Gets the application's input manager.
///
///
/// The application's input manager.
///
- public InputManager? InputManager
+ internal InputManager? InputManager
{
get;
private set;
@@ -191,6 +180,17 @@ namespace Avalonia
///
public IApplicationLifetime? ApplicationLifetime { get; set; }
+ ///
+ /// Represents a contract for accessing global platform-specific settings.
+ ///
+ ///
+ /// PlatformSettings can be null only if application wasn't initialized yet.
+ /// 's is an equivalent API
+ /// which should always be preferred over a global one,
+ /// as specific top levels might have different settings set-up.
+ ///
+ public IPlatformSettings? PlatformSettings => AvaloniaLocator.Current.GetService();
+
event Action>? IGlobalStyles.GlobalStylesAdded
{
add => _stylesAdded += value;
@@ -237,32 +237,32 @@ namespace Avalonia
public virtual void RegisterServices()
{
AvaloniaSynchronizationContext.InstallIfNeeded();
- FocusManager = new FocusManager();
+ var focusManager = new FocusManager();
InputManager = new InputManager();
- var settings = AvaloniaLocator.Current.GetRequiredService();
- settings.ColorValuesChanged += OnColorValuesChanged;
- OnColorValuesChanged(settings, settings.GetColorValues());
-
+ if (PlatformSettings is { } settings)
+ {
+ settings.ColorValuesChanged += OnColorValuesChanged;
+ OnColorValuesChanged(settings, settings.GetColorValues());
+ }
+
AvaloniaLocator.CurrentMutable
.Bind().ToTransient()
.Bind().ToConstant(this)
.Bind().ToConstant(this)
.Bind().ToConstant(this)
- .Bind().ToConstant(FocusManager)
+ .Bind().ToConstant(focusManager)
.Bind().ToConstant(InputManager)
.Bind().ToTransient()
.Bind().ToConstant(DragDropDevice.Instance);
-
+
// TODO: Fix this, for now we keep this behavior since someone might be relying on it in 0.9.x
if (AvaloniaLocator.Current.GetService() == null)
AvaloniaLocator.CurrentMutable
.Bind().ToTransient();
- var clock = new RenderLoopClock();
- AvaloniaLocator.CurrentMutable
- .Bind().ToConstant(clock)
- .GetService()?.Add(clock);
+ AvaloniaLocator.CurrentMutable.Bind()
+ .ToConstant(MediaContext.Instance.Clock);
}
public virtual void OnFrameworkInitializationCompleted()
diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
index 20711eecbc..d0b894101f 100644
--- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
@@ -762,7 +762,7 @@ namespace Avalonia.Controls
/// otherwise, false.
protected bool HasFocus()
{
- Visual? focused = FocusManager.Instance?.Current as Visual;
+ Visual? focused = FocusManager.GetFocusManager(this)?.GetFocusedElement() as Visual;
while (focused != null)
{
diff --git a/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs b/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs
index d04dfec3e8..756951667b 100644
--- a/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs
+++ b/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs
@@ -31,11 +31,31 @@ namespace Avalonia.Automation.Peers
return CreatePeerForElement(element);
}
+ ///
+ /// Gets the for a , creating it if
+ /// necessary.
+ ///
+ /// The control.
+ /// The automation peer.
+ ///
+ /// Despite the name (which comes from the analogous WPF API), this method does not create
+ /// a new peer if one already exists: instead it returns the existing peer.
+ ///
public static AutomationPeer CreatePeerForElement(Control element)
{
return element.GetOrCreateAutomationPeer();
}
+ ///
+ /// Gets an existing for a .
+ ///
+ /// The control.
+ /// The automation peer if already created; otherwise null.
+ ///
+ /// To ensure that a peer is created, use .
+ ///
+ public static AutomationPeer? FromElement(Control element) => element.GetAutomationPeer();
+
protected override void BringIntoViewCore() => Owner.BringIntoView();
protected override IReadOnlyList GetOrCreateChildrenCore()
@@ -151,7 +171,7 @@ namespace Avalonia.Automation.Peers
protected override bool HasKeyboardFocusCore() => Owner.IsFocused;
protected override bool IsContentElementCore() => true;
protected override bool IsControlElementCore() => true;
- protected override bool IsEnabledCore() => Owner.IsEnabled;
+ protected override bool IsEnabledCore() => Owner.IsEffectivelyEnabled;
protected override bool IsKeyboardFocusableCore() => Owner.Focusable;
protected override void SetFocusCore() => Owner.Focus();
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index 48761ca8b8..304454777f 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -13,7 +13,10 @@
+
+
+
@@ -22,5 +25,6 @@
+
diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs
index 78ba23c1dd..e7373a813e 100644
--- a/src/Avalonia.Controls/Border.cs
+++ b/src/Avalonia.Controls/Border.cs
@@ -47,30 +47,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty BoxShadowProperty =
AvaloniaProperty.Register(nameof(BoxShadow));
- ///
- /// Defines the property.
- ///
- public static readonly StyledProperty BorderDashOffsetProperty =
- AvaloniaProperty.Register(nameof(BorderDashOffset));
-
- ///
- /// Defines the property.
- ///
- public static readonly StyledProperty?> BorderDashArrayProperty =
- AvaloniaProperty.Register?>(nameof(BorderDashArray));
-
- ///
- /// Defines the property.
- ///
- public static readonly StyledProperty BorderLineCapProperty =
- AvaloniaProperty.Register(nameof(BorderLineCap), PenLineCap.Flat);
-
- ///
- /// Defines the property.
- ///
- public static readonly StyledProperty BorderLineJoinProperty =
- AvaloniaProperty.Register(nameof(BorderLineJoin), PenLineJoin.Miter);
-
private readonly BorderRenderHelper _borderRenderHelper = new BorderRenderHelper();
private Thickness? _layoutThickness;
private double _scale;
@@ -86,10 +62,6 @@ namespace Avalonia.Controls
BorderBrushProperty,
BorderThicknessProperty,
CornerRadiusProperty,
- BorderDashArrayProperty,
- BorderLineCapProperty,
- BorderLineJoinProperty,
- BorderDashOffsetProperty,
BoxShadowProperty);
AffectsMeasure(BorderThicknessProperty);
}
@@ -115,8 +87,8 @@ namespace Avalonia.Controls
///
public IBrush? Background
{
- get { return GetValue(BackgroundProperty); }
- set { SetValue(BackgroundProperty, value); }
+ get => GetValue(BackgroundProperty);
+ set => SetValue(BackgroundProperty, value);
}
///
@@ -124,17 +96,8 @@ namespace Avalonia.Controls
///
public IBrush? BorderBrush
{
- get { return GetValue(BorderBrushProperty); }
- set { SetValue(BorderBrushProperty, value); }
- }
-
- ///
- /// Gets or sets a collection of values that indicate the pattern of dashes and gaps that is used to outline shapes.
- ///
- public AvaloniaList? BorderDashArray
- {
- get { return GetValue(BorderDashArrayProperty); }
- set { SetValue(BorderDashArrayProperty, value); }
+ get => GetValue(BorderBrushProperty);
+ set => SetValue(BorderBrushProperty, value);
}
///
@@ -142,35 +105,8 @@ namespace Avalonia.Controls
///
public Thickness BorderThickness
{
- get { return GetValue(BorderThicknessProperty); }
- set { SetValue(BorderThicknessProperty, value); }
- }
-
- ///
- /// Gets or sets a value that specifies the distance within the dash pattern where a dash begins.
- ///
- public double BorderDashOffset
- {
- get { return GetValue(BorderDashOffsetProperty); }
- set { SetValue(BorderDashOffsetProperty, value); }
- }
-
- ///
- /// Gets or sets a enumeration value that describes the shape at the ends of a line.
- ///
- public PenLineCap BorderLineCap
- {
- get { return GetValue(BorderLineCapProperty); }
- set { SetValue(BorderLineCapProperty, value); }
- }
-
- ///
- /// Gets or sets a enumeration value that specifies the type of join that is used at the vertices of a Shape.
- ///
- public PenLineJoin BorderLineJoin
- {
- get { return GetValue(BorderLineJoinProperty); }
- set { SetValue(BorderLineJoinProperty, value); }
+ get => GetValue(BorderThicknessProperty);
+ set => SetValue(BorderThicknessProperty, value);
}
///
@@ -178,8 +114,8 @@ namespace Avalonia.Controls
///
public CornerRadius CornerRadius
{
- get { return GetValue(CornerRadiusProperty); }
- set { SetValue(CornerRadiusProperty, value); }
+ get => GetValue(CornerRadiusProperty);
+ set => SetValue(CornerRadiusProperty, value);
}
///
@@ -227,8 +163,14 @@ namespace Avalonia.Controls
/// The drawing context.
public sealed override void Render(DrawingContext context)
{
- _borderRenderHelper.Render(context, Bounds.Size, LayoutThickness, CornerRadius, Background, BorderBrush,
- BoxShadow, BorderDashOffset, BorderLineCap, BorderLineJoin, BorderDashArray);
+ _borderRenderHelper.Render(
+ context,
+ Bounds.Size,
+ LayoutThickness,
+ CornerRadius,
+ Background,
+ BorderBrush,
+ BoxShadow);
}
///
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index f48d7a7cc1..d8c31fc477 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -34,8 +34,8 @@ namespace Avalonia.Controls
[PseudoClasses(pcFlyoutOpen, pcPressed)]
public class Button : ContentControl, ICommandSource, IClickableControl
{
- protected const string pcPressed = ":pressed";
- protected const string pcFlyoutOpen = ":flyout-open";
+ private const string pcPressed = ":pressed";
+ private const string pcFlyoutOpen = ":flyout-open";
///
/// Defines the property.
diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs
index 10aadfa759..6468d0b4e8 100644
--- a/src/Avalonia.Controls/Calendar/Calendar.cs
+++ b/src/Avalonia.Controls/Calendar/Calendar.cs
@@ -1567,7 +1567,7 @@ namespace Avalonia.Controls
base.OnPointerReleased(e);
if (!HasFocusInternal && e.InitialPressMouseButton == MouseButton.Left)
{
- FocusManager.Instance?.Focus(this);
+ Focus();
}
}
diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs
index d8672cbf18..b35298b101 100644
--- a/src/Avalonia.Controls/Calendar/CalendarButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Controls.Primitives
public CalendarButton()
: base()
{
- Content = DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0];
+ SetCurrentValue(ContentProperty, DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]);
}
///
diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
index 3d0befdba7..ea3ca8e8fc 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
@@ -34,7 +34,7 @@ namespace Avalonia.Controls.Primitives
: base()
{
//Focusable = false;
- Content = DefaultContent.ToString(CultureInfo.CurrentCulture);
+ SetCurrentValue(ContentProperty, DefaultContent.ToString(CultureInfo.CurrentCulture));
}
///
diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs
index 2e3f1f96ce..e81ed8072e 100644
--- a/src/Avalonia.Controls/Calendar/CalendarItem.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs
@@ -171,7 +171,7 @@ namespace Avalonia.Controls.Primitives
var childCount = Calendar.RowsPerMonth + Calendar.RowsPerMonth * Calendar.ColumnsPerMonth;
using var children = new PooledList(childCount);
- for (int i = 0; i < Calendar.RowsPerMonth; i++)
+ for (int i = 0; i < Calendar.ColumnsPerMonth; i++)
{
if (DayTitleTemplate?.Build() is Control cell)
{
diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
index 90153d3293..679ac4a853 100644
--- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
+++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
@@ -26,8 +26,8 @@ namespace Avalonia.Controls
[PseudoClasses(pcFlyoutOpen, pcPressed)]
public partial class CalendarDatePicker : TemplatedControl
{
- protected const string pcPressed = ":pressed";
- protected const string pcFlyoutOpen = ":flyout-open";
+ private const string pcPressed = ":pressed";
+ private const string pcFlyoutOpen = ":flyout-open";
private const string ElementTextBox = "PART_TextBox";
private const string ElementButton = "PART_Button";
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index f41c00662d..bce1a3685f 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -21,8 +21,9 @@ namespace Avalonia.Controls
[PseudoClasses(pcDropdownOpen, pcPressed)]
public class ComboBox : SelectingItemsControl
{
- public const string pcDropdownOpen = ":dropdownopen";
- public const string pcPressed = ":pressed";
+ internal const string pcDropdownOpen = ":dropdownopen";
+ internal const string pcPressed = ":pressed";
+
///
/// The default value for the property.
///
@@ -164,7 +165,7 @@ namespace Avalonia.Controls
UpdateSelectionBoxItem(SelectedItem);
}
- public override void InvalidateMirrorTransform()
+ protected internal override void InvalidateMirrorTransform()
{
base.InvalidateMirrorTransform();
UpdateFlowDirection();
@@ -230,8 +231,7 @@ namespace Avalonia.Controls
var firstChild = Presenter?.Panel?.Children.FirstOrDefault(c => CanFocus(c));
if (firstChild != null)
{
- FocusManager.Instance?.Focus(firstChild, NavigationMethod.Directional);
- e.Handled = true;
+ e.Handled = firstChild.Focus(NavigationMethod.Directional);
}
}
}
@@ -361,19 +361,6 @@ namespace Avalonia.Controls
_subscriptionsOnOpen.Clear();
- var toplevel = TopLevel.GetTopLevel(this);
- if (toplevel != null)
- {
- toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) =>
- {
- //eat wheel scroll event outside dropdown popup while it's open
- if (IsDropDownOpen && (ev.Source as Visual)?.GetVisualRoot() == toplevel)
- {
- ev.Handled = true;
- }
- }, Interactivity.RoutingStrategies.Tunnel).DisposeWith(_subscriptionsOnOpen);
- }
-
this.GetObservable(IsVisibleProperty).Subscribe(IsVisibleChanged).DisposeWith(_subscriptionsOnOpen);
foreach (var parent in this.GetVisualAncestors().OfType())
diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs
index f30920ed2e..867dca2be1 100644
--- a/src/Avalonia.Controls/ContentControl.cs
+++ b/src/Avalonia.Controls/ContentControl.cs
@@ -13,7 +13,7 @@ namespace Avalonia.Controls
///
/// Displays according to an .
///
- [TemplatePart("PART_ContentPresenter", typeof(IContentPresenter))]
+ [TemplatePart("PART_ContentPresenter", typeof(ContentPresenter))]
public class ContentControl : TemplatedControl, IContentControl, IContentPresenterHost
{
///
@@ -68,7 +68,7 @@ namespace Avalonia.Controls
///
/// Gets the presenter from the control's template.
///
- public IContentPresenter? Presenter
+ public ContentPresenter? Presenter
{
get;
private set;
@@ -96,16 +96,16 @@ namespace Avalonia.Controls
IAvaloniaList IContentPresenterHost.LogicalChildren => LogicalChildren;
///
- bool IContentPresenterHost.RegisterContentPresenter(IContentPresenter presenter)
+ bool IContentPresenterHost.RegisterContentPresenter(ContentPresenter presenter)
{
return RegisterContentPresenter(presenter);
}
///
- /// Called when an is registered with the control.
+ /// Called when an is registered with the control.
///
/// The presenter.
- protected virtual bool RegisterContentPresenter(IContentPresenter presenter)
+ protected virtual bool RegisterContentPresenter(ContentPresenter presenter)
{
if (presenter.Name == "PART_ContentPresenter")
{
@@ -116,19 +116,14 @@ namespace Avalonia.Controls
return false;
}
- protected virtual void ContentChanged(AvaloniaPropertyChangedEventArgs e)
+ private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
{
- UpdateLogicalTree(e.OldValue, e.NewValue);
- }
-
- protected void UpdateLogicalTree(object? toRemove, object? toAdd)
- {
- if (toRemove is ILogical oldChild)
+ if (e.OldValue is ILogical oldChild)
{
LogicalChildren.Remove(oldChild);
}
- if (toAdd is ILogical newChild)
+ if (e.NewValue is ILogical newChild)
{
LogicalChildren.Add(newChild);
}
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index 97a8c6fe97..e3a419d7b3 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -196,14 +196,14 @@ namespace Avalonia.Controls
///
/// property is changing from false to true.
///
- public event CancelEventHandler? ContextMenuOpening;
+ public event CancelEventHandler? Opening;
///
/// Occurs when the value of the
///
/// property is changing from true to false.
///
- public event CancelEventHandler? ContextMenuClosing;
+ public event CancelEventHandler? Closing;
///
/// Called when the property changes on a control.
@@ -285,7 +285,7 @@ namespace Avalonia.Controls
}
}
- void ISetterValue.Initialize(ISetter setter)
+ void ISetterValue.Initialize(SetterBase setter)
{
// ContextMenu can be assigned to the ContextMenu property in a setter. This overrides
// the behavior defined in Control which requires controls to be wrapped in a .
@@ -353,14 +353,14 @@ namespace Avalonia.Controls
RaiseEvent(new RoutedEventArgs
{
- RoutedEvent = MenuOpenedEvent,
+ RoutedEvent = OpenedEvent,
Source = this,
});
}
private void PopupOpened(object? sender, EventArgs e)
{
- _previousFocus = FocusManager.Instance?.Current;
+ _previousFocus = FocusManager.GetFocusManager(this)?.GetFocusedElement();
Focus();
_popupHostChangedHandler?.Invoke(_popup!.Host);
@@ -390,11 +390,11 @@ namespace Avalonia.Controls
}
// HACK: Reset the focus when the popup is closed. We need to fix this so it's automatic.
- FocusManager.Instance?.Focus(_previousFocus);
+ _previousFocus?.Focus();
RaiseEvent(new RoutedEventArgs
{
- RoutedEvent = MenuClosedEvent,
+ RoutedEvent = ClosedEvent,
Source = this,
});
@@ -405,7 +405,7 @@ namespace Avalonia.Controls
{
if (IsOpen)
{
- var keymap = AvaloniaLocator.Current.GetService();
+ var keymap = Application.Current!.PlatformSettings!.HotkeyConfiguration;
if (keymap?.OpenContextMenu.Any(k => k.Matches(e)) == true
&& !CancelClosing())
@@ -446,14 +446,14 @@ namespace Avalonia.Controls
private bool CancelClosing()
{
var eventArgs = new CancelEventArgs();
- ContextMenuClosing?.Invoke(this, eventArgs);
+ Closing?.Invoke(this, eventArgs);
return eventArgs.Cancel;
}
private bool CancelOpening()
{
var eventArgs = new CancelEventArgs();
- ContextMenuOpening?.Invoke(this, eventArgs);
+ Opening?.Invoke(this, eventArgs);
return eventArgs.Cancel;
}
}
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index fcd607a707..6e0063c9ec 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -213,7 +213,7 @@ namespace Avalonia.Controls
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
///
- void ISetterValue.Initialize(ISetter setter)
+ void ISetterValue.Initialize(SetterBase setter)
{
if (setter is Setter s && s.Property == ContextFlyoutProperty)
{
@@ -440,6 +440,12 @@ namespace Avalonia.Controls
return new NoneAutomationPeer(this);
}
+ internal AutomationPeer? GetAutomationPeer()
+ {
+ VerifyAccess();
+ return _automationPeer;
+ }
+
internal AutomationPeer GetOrCreateAutomationPeer()
{
VerifyAccess();
@@ -474,7 +480,7 @@ namespace Avalonia.Controls
if (e.Source == this
&& !e.Handled)
{
- var keymap = AvaloniaLocator.Current.GetService()?.OpenContextMenu;
+ var keymap = Application.Current!.PlatformSettings?.HotkeyConfiguration.OpenContextMenu;
if (keymap is null)
{
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
index 0ae743f30a..8ff8088a34 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
@@ -323,10 +323,11 @@ namespace Avalonia.Controls
e.Handled = true;
break;
case Key.Tab:
- if (FocusManager.Instance?.Current is IInputElement focus)
+ var focusManager = FocusManager.GetFocusManager(this);
+ if (focusManager?.GetFocusedElement() is { } focus)
{
var nextFocus = KeyboardNavigationHandler.GetNext(focus, NavigationDirection.Next);
- KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
+ nextFocus?.Focus(NavigationMethod.Tab);
e.Handled = true;
}
break;
@@ -366,11 +367,11 @@ namespace Avalonia.Controls
var dt = Date;
if (DayVisible)
{
+ _daySelector.FormatDate = dt.Date;
var maxDays = _calendar.GetDaysInMonth(dt.Year, dt.Month);
_daySelector.MaximumValue = maxDays;
_daySelector.MinimumValue = 1;
_daySelector.SelectedValue = dt.Day;
- _daySelector.FormatDate = dt.Date;
}
if (MonthVisible)
@@ -449,15 +450,15 @@ namespace Avalonia.Controls
if (monthCol < dayCol && monthCol < yearCol)
{
- KeyboardDevice.Instance?.SetFocusedElement(_monthSelector, NavigationMethod.Pointer, KeyModifiers.None);
+ _monthSelector?.Focus(NavigationMethod.Pointer);
}
else if (dayCol < monthCol && dayCol < yearCol)
{
- KeyboardDevice.Instance?.SetFocusedElement(_daySelector, NavigationMethod.Pointer, KeyModifiers.None);
+ _monthSelector?.Focus(NavigationMethod.Pointer);
}
else if (yearCol < monthCol && yearCol < dayCol)
{
- KeyboardDevice.Instance?.SetFocusedElement(_yearSelector, NavigationMethod.Pointer, KeyModifiers.None);
+ _yearSelector?.Focus(NavigationMethod.Pointer);
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
index ba06e1b5e6..929ad68c24 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
@@ -161,10 +161,10 @@ namespace Avalonia.Controls
e.Handled = true;
break;
case Key.Tab:
- if (FocusManager.Instance?.Current is IInputElement focus)
+ if (FocusManager.GetFocusManager(this)?.GetFocusedElement() is { } focus)
{
var nextFocus = KeyboardNavigationHandler.GetNext(focus, NavigationDirection.Next);
- KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
+ nextFocus?.Focus(NavigationMethod.Tab);
e.Handled = true;
}
break;
@@ -216,7 +216,7 @@ namespace Avalonia.Controls
_periodSelector.SelectedValue = hr >= 12 ? 1 : 0;
SetGrid();
- KeyboardDevice.Instance?.SetFocusedElement(_hourSelector, NavigationMethod.Pointer, KeyModifiers.None);
+ _hourSelector?.Focus(NavigationMethod.Pointer);
}
private void SetGrid()
diff --git a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
index 7a0ab36050..880bbb7340 100644
--- a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
+++ b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
@@ -26,6 +26,10 @@ namespace Avalonia.Controls.Embedding
LayoutManager.ExecuteInitialLayoutPass();
}
+ public new void StartRendering() => base.StartRendering();
+
+ public new void StopRendering() => base.StopRendering();
+
private void EnsureInitialized()
{
if (!this.IsInitialized)
diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
index 387357dddd..f379120638 100644
--- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
+++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using Avalonia.Input;
using Avalonia.Input.Raw;
+using Avalonia.Media;
using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.Rendering;
@@ -34,10 +35,13 @@ namespace Avalonia.Controls.Embedding.Offscreen
public void TriggerTick() => Tick?.Invoke(St.Elapsed);
}
+ public Compositor Compositor { get; }
- public IRenderer CreateRenderer(IRenderRoot root) =>
- new CompositingRenderer(root, new Compositor(new RenderLoop(_manualRenderTimer, Dispatcher.UIThread), null),
- () => Surfaces);
+ public OffscreenTopLevelImplBase()
+ {
+ Compositor = new Compositor(new RenderLoop(_manualRenderTimer), null, false,
+ MediaContext.Instance, false);
+ }
public abstract IEnumerable