From 75b0676d058de10a8bbb736f72378d3b50dac2bb Mon Sep 17 00:00:00 2001
From: shine <106159554+shine1258@users.noreply.github.com>
Date: Mon, 30 Mar 2026 15:58:02 +0800
Subject: [PATCH 01/86] Fix Placeholder not visible (#21024)
* Add default PlaceholderForeground to AutoCompleteBox, CalendarDatePicker and NumericUpDown.
* Add PlaceholderText template binding for simple theme ComboBox PART_EditableTextBox.
---
src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml | 1 +
src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml | 1 +
src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml | 1 +
src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml | 1 +
src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml | 1 +
src/Avalonia.Themes.Simple/Controls/ComboBox.xaml | 1 +
src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml | 1 +
7 files changed, 7 insertions(+)
diff --git a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
index 92c46ecd41..bd9c84af17 100644
--- a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
@@ -25,6 +25,7 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
index 3a8db8ae36..395e2d514f 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
@@ -63,6 +63,7 @@
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml b/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml
index b6c19484e9..bcd486534d 100644
--- a/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml
@@ -52,6 +52,7 @@
+
diff --git a/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml
index ec0eccc8c4..7a1c98b598 100644
--- a/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/AutoCompleteBox.xaml
@@ -4,6 +4,7 @@
+
diff --git a/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml
index a38f6f912d..9eba0a413b 100644
--- a/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/CalendarDatePicker.xaml
@@ -12,6 +12,7 @@
+
diff --git a/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml b/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml
index 5a6266af6e..be4725d08c 100644
--- a/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/ComboBox.xaml
@@ -50,6 +50,7 @@
Foreground="{TemplateBinding Foreground}"
Background="Transparent"
Text="{TemplateBinding Text, Mode=TwoWay}"
+ PlaceholderText="{TemplateBinding PlaceholderText}"
BorderThickness="0"
IsVisible="{TemplateBinding IsEditable}">
diff --git a/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml b/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml
index 14cb0de6af..dbd01456bd 100644
--- a/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml
+++ b/src/Avalonia.Themes.Simple/Controls/NumericUpDown.xaml
@@ -4,6 +4,7 @@
+
From 775d39d9aeb1bfb5434c5e726078c8bb4e08cf8c Mon Sep 17 00:00:00 2001
From: Dong Bin <14807942+rabbitism@users.noreply.github.com>
Date: Mon, 30 Mar 2026 16:02:55 +0800
Subject: [PATCH 02/86] Revise security policy and add vulnerability reporting
(#21029)
Updated the security policy to include vulnerability reporting guidelines and removed supported versions section.
---
SECURITY.md | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 SECURITY.md
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000..fcf55a12b9
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,11 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability in any of our SDKs, tools, services, or repositories, please help us keep the community safe by reporting it responsibly.
+
+You can report security vulnerabilities by emailing **[security@avaloniaui.net](mailto:security@avaloniaui.net)**.
+
+Please avoid disclosing the issue publicly until we have had a reasonable amount of time to investigate and release a patch or mitigation. We review all legitimate reports and will work with you to quickly resolve the issue.
+
+Please note that Avalonia does not operate a bug bounty programme.
From 23baa0a0433ccda53b59d39fa0e3ab4848a85d91 Mon Sep 17 00:00:00 2001
From: Nikita Tsukanov
Date: Mon, 30 Mar 2026 13:54:32 +0500
Subject: [PATCH 03/86] Added explicit background processing support to managed
dispatcher impl (#21025)
---
.../Platform/ManagedDispatcherImpl.cs | 32 ++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/Avalonia.Base/Platform/ManagedDispatcherImpl.cs b/src/Avalonia.Base/Platform/ManagedDispatcherImpl.cs
index c8225f775b..fc1cfbf5b1 100644
--- a/src/Avalonia.Base/Platform/ManagedDispatcherImpl.cs
+++ b/src/Avalonia.Base/Platform/ManagedDispatcherImpl.cs
@@ -7,7 +7,7 @@ using Avalonia.Threading;
namespace Avalonia.Controls.Platform;
[Unstable]
-public class ManagedDispatcherImpl : IControlledDispatcherImpl
+public class ManagedDispatcherImpl : IControlledDispatcherImpl, IDispatcherImplWithExplicitBackgroundProcessing
{
private readonly IManagedDispatcherInputProvider? _inputProvider;
private readonly AutoResetEvent _wakeup = new(false);
@@ -16,6 +16,7 @@ public class ManagedDispatcherImpl : IControlledDispatcherImpl
private readonly Stopwatch _clock = Stopwatch.StartNew();
private TimeSpan? _nextTimer;
private readonly Thread _loopThread = Thread.CurrentThread;
+ private bool _backgroundProcessingRequested;
public interface IManagedDispatcherInputProvider
{
@@ -56,6 +57,22 @@ public class ManagedDispatcherImpl : IControlledDispatcherImpl
public bool CanQueryPendingInput => _inputProvider != null;
public bool HasPendingInput => _inputProvider?.HasInput ?? false;
+ private Action? ReadyForBackgroundProcessing { get; set; }
+ event Action? IDispatcherImplWithExplicitBackgroundProcessing.ReadyForBackgroundProcessing
+ {
+ add => ReadyForBackgroundProcessing += value;
+ remove => ReadyForBackgroundProcessing -= value;
+ }
+
+ void IDispatcherImplWithExplicitBackgroundProcessing.RequestBackgroundProcessing()
+ {
+ lock (_lock)
+ {
+ _backgroundProcessingRequested = true;
+ _wakeup.Set();
+ }
+ }
+
public void RunLoop(CancellationToken token)
{
CancellationTokenRegistration registration = default;
@@ -98,6 +115,19 @@ public class ManagedDispatcherImpl : IControlledDispatcherImpl
_inputProvider.DispatchNextInputEvent();
continue;
}
+
+ bool triggerBackgroundProcessing;
+ lock (_lock)
+ {
+ triggerBackgroundProcessing = _backgroundProcessingRequested;
+ _backgroundProcessingRequested = false;
+ }
+
+ if (triggerBackgroundProcessing)
+ {
+ ReadyForBackgroundProcessing?.Invoke();
+ continue;
+ }
TimeSpan? nextTimer;
lock (_lock)
From ebbf9c00fc3a1af1c957be0f52e8f1376dccced2 Mon Sep 17 00:00:00 2001
From: Nikita Tsukanov
Date: Mon, 30 Mar 2026 14:13:04 +0500
Subject: [PATCH 04/86] Combine Ready/Corrupted into a single passthrough
struct (#21028)
* Combine Ready/Corrupted into a single passthrough struct
* api diff
---
api/Avalonia.Skia.nupkg.xml | 28 ++++++++++-
api/Avalonia.Win32.nupkg.xml | 16 +++++++
api/Avalonia.nupkg.xml | 48 +++++++++++++++++++
src/Avalonia.Base/Platform/IRenderTarget.cs | 9 +---
.../Platform/RenderTargetProperties.cs | 30 ++++++++++++
.../Surfaces/IPlatformRenderSurface.cs | 2 +-
.../Server/ServerCompositionTarget.cs | 4 +-
.../AvaloniaNativeGlPlatformGraphics.cs | 2 +-
.../Egl/EglGlPlatformSurfaceBase.cs | 3 ++
.../IGlPlatformSurfaceRenderTarget.cs | 1 -
.../VulkanKhrSurfaceRenderTarget.cs | 3 ++
src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs | 2 +-
.../HeadlessPlatformRenderInterface.cs | 2 -
.../Output/DrmOutput.cs | 2 +-
.../Avalonia.Skia/FramebufferRenderTarget.cs | 9 ++--
.../Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs | 4 +-
.../Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs | 4 +-
.../Gpu/OpenGl/GlRenderTarget.cs | 4 +-
.../Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs | 5 +-
.../Gpu/Vulkan/VulkanSkiaRenderTarget.cs | 4 +-
.../DirectCompositedWindowSurface.cs | 6 +--
.../IDirect3D11TexturePlatformSurface.cs | 4 +-
.../OpenGl/Angle/AngleD3DTextureFeature.cs | 3 +-
.../OpenGl/WglGlPlatformSurface.cs | 2 +-
.../WinUiCompositedWindowSurface.cs | 5 +-
25 files changed, 154 insertions(+), 48 deletions(-)
create mode 100644 api/Avalonia.Win32.nupkg.xml
diff --git a/api/Avalonia.Skia.nupkg.xml b/api/Avalonia.Skia.nupkg.xml
index b73745af8e..7a83006bf2 100644
--- a/api/Avalonia.Skia.nupkg.xml
+++ b/api/Avalonia.Skia.nupkg.xml
@@ -1,4 +1,4 @@
-
+
@@ -61,6 +61,18 @@
baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll
current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll
+
+ CP0002
+ M:Avalonia.Skia.ISkiaGpuRenderTarget.get_IsCorrupted
+ baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll
+ current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll
+
+
+ CP0002
+ M:Avalonia.Skia.ISkiaGpuRenderTarget.get_IsReady
+ baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll
+ current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll
+
CP0002
M:Avalonia.Skia.Helpers.DrawingContextHelper.WrapSkiaCanvas(SkiaSharp.SKCanvas,Avalonia.Vector)
@@ -85,6 +97,18 @@
baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
+
+ CP0002
+ M:Avalonia.Skia.ISkiaGpuRenderTarget.get_IsCorrupted
+ baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
+ current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
+
+
+ CP0002
+ M:Avalonia.Skia.ISkiaGpuRenderTarget.get_IsReady
+ baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
+ current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
+
CP0006
M:Avalonia.Skia.ISkiaGpu.TryCreateRenderTarget(System.Collections.Generic.IEnumerable{Avalonia.Platform.Surfaces.IPlatformRenderSurface})
@@ -169,4 +193,4 @@
baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll
-
+
\ No newline at end of file
diff --git a/api/Avalonia.Win32.nupkg.xml b/api/Avalonia.Win32.nupkg.xml
new file mode 100644
index 0000000000..903595add8
--- /dev/null
+++ b/api/Avalonia.Win32.nupkg.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ CP0002
+ M:Avalonia.Win32.DirectX.IDirect3D11TextureRenderTarget.get_IsCorrupted
+ baseline/Avalonia.Win32/lib/net10.0/Avalonia.Win32.dll
+ current/Avalonia.Win32/lib/net10.0/Avalonia.Win32.dll
+
+
+ CP0002
+ M:Avalonia.Win32.DirectX.IDirect3D11TextureRenderTarget.get_IsCorrupted
+ baseline/Avalonia.Win32/lib/net8.0/Avalonia.Win32.dll
+ current/Avalonia.Win32/lib/net8.0/Avalonia.Win32.dll
+
+
\ No newline at end of file
diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index 71bdf3714d..f3a9929ca1 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -1693,12 +1693,30 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.get_IsCorrupted
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.get_IsReady
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Platform.LockedFramebuffer.#ctor(System.IntPtr,Avalonia.PixelSize,System.Int32,Avalonia.Vector,Avalonia.Platform.PixelFormat,System.Action)
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Platform.Surfaces.IPlatformRenderSurfaceRenderTarget.get_IsReady
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Rendering.Composition.ICompositionGpuImportedObject.get_ImportCompeted
@@ -2587,6 +2605,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.OpenGL.dll
current/Avalonia/lib/net10.0/Avalonia.OpenGL.dll
+
+ CP0002
+ M:Avalonia.OpenGL.Surfaces.IGlPlatformSurfaceRenderTarget.get_IsCorrupted
+ baseline/Avalonia/lib/net10.0/Avalonia.OpenGL.dll
+ current/Avalonia/lib/net10.0/Avalonia.OpenGL.dll
+
CP0002
M:Avalonia.Vulkan.IVulkanKhrSurfacePlatformSurfaceFactory.CanRenderToSurface(Avalonia.Vulkan.IVulkanPlatformGraphicsContext,System.Object)
@@ -3367,12 +3391,30 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.get_IsCorrupted
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.get_IsReady
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Platform.LockedFramebuffer.#ctor(System.IntPtr,Avalonia.PixelSize,System.Int32,Avalonia.Vector,Avalonia.Platform.PixelFormat,System.Action)
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Platform.Surfaces.IPlatformRenderSurfaceRenderTarget.get_IsReady
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Rendering.Composition.ICompositionGpuImportedObject.get_ImportCompeted
@@ -4267,6 +4309,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
current/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
+
+ CP0002
+ M:Avalonia.OpenGL.Surfaces.IGlPlatformSurfaceRenderTarget.get_IsCorrupted
+ baseline/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
+ current/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
+
CP0002
M:Avalonia.Vulkan.IVulkanKhrSurfacePlatformSurfaceFactory.CanRenderToSurface(Avalonia.Vulkan.IVulkanPlatformGraphicsContext,System.Object)
diff --git a/src/Avalonia.Base/Platform/IRenderTarget.cs b/src/Avalonia.Base/Platform/IRenderTarget.cs
index e66d14995e..2e7d56405a 100644
--- a/src/Avalonia.Base/Platform/IRenderTarget.cs
+++ b/src/Avalonia.Base/Platform/IRenderTarget.cs
@@ -12,11 +12,6 @@ namespace Avalonia.Platform
[PrivateApi]
public interface IRenderTarget : IDisposable
{
- ///
- /// Indicates if the render target is no longer usable and needs to be recreated
- ///
- bool IsCorrupted { get; }
-
///
/// Gets the properties of the render target.
///
@@ -33,9 +28,9 @@ namespace Avalonia.Platform
IDrawingContextImpl CreateDrawingContext(RenderTargetSceneInfo sceneInfo, out RenderTargetDrawingContextProperties properties);
///
- /// Indicates if the render target is currently ready to be rendered to
+ /// Gets the current readiness state of the render target.
///
- bool IsReady => true;
+ PlatformRenderTargetState PlatformRenderTargetState => PlatformRenderTargetState.Ready;
public record struct RenderTargetSceneInfo(PixelSize Size, double Scaling);
}
diff --git a/src/Avalonia.Base/Platform/RenderTargetProperties.cs b/src/Avalonia.Base/Platform/RenderTargetProperties.cs
index c4a0948180..de4f3f4345 100644
--- a/src/Avalonia.Base/Platform/RenderTargetProperties.cs
+++ b/src/Avalonia.Base/Platform/RenderTargetProperties.cs
@@ -3,6 +3,36 @@ using Avalonia.Metadata;
namespace Avalonia.Platform;
+///
+/// Describes the current readiness state of a platform render target.
+/// Flows through the entire rendering pipeline from platform to compositor.
+///
+[PrivateApi]
+[SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Private API, not meant to be compared")]
+public readonly struct PlatformRenderTargetState
+{
+ ///
+ /// Indicates if the render target is currently ready to be rendered to.
+ ///
+ public bool IsReady { get; init; }
+
+ ///
+ /// Indicates if the render target is no longer usable and needs to be recreated
+ ///
+ public bool IsCorrupted { get; init; }
+
+ ///
+ /// A readiness state indicating the target is ready to render.
+ ///
+ public static PlatformRenderTargetState Ready => new() { IsReady = true };
+
+ public static PlatformRenderTargetState NotReadyTryLater => default;
+
+ public static PlatformRenderTargetState Corrupted => new() { IsCorrupted = true, IsReady = true};
+
+ public static PlatformRenderTargetState Disposed => new() { IsCorrupted = true};
+}
+
[PrivateApi]
[SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Private API, not meant to be compared")]
public struct RenderTargetProperties
diff --git a/src/Avalonia.Base/Platform/Surfaces/IPlatformRenderSurface.cs b/src/Avalonia.Base/Platform/Surfaces/IPlatformRenderSurface.cs
index ff71a700c4..0c085c20b8 100644
--- a/src/Avalonia.Base/Platform/Surfaces/IPlatformRenderSurface.cs
+++ b/src/Avalonia.Base/Platform/Surfaces/IPlatformRenderSurface.cs
@@ -11,5 +11,5 @@ public interface IPlatformRenderSurface
[PrivateApi]
public interface IPlatformRenderSurfaceRenderTarget
{
- bool IsReady => true;
+ PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
}
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
index e8ae84eb03..fe857ac466 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
@@ -138,7 +138,7 @@ namespace Avalonia.Rendering.Composition.Server
if (Root == null)
return;
- if (_renderTarget?.IsCorrupted == true)
+ if (_renderTarget?.PlatformRenderTargetState.IsCorrupted == true)
{
_layer?.Dispose();
_layer = null;
@@ -178,7 +178,7 @@ namespace Avalonia.Rendering.Composition.Server
if (!_redrawRequested)
return;
- if (!_renderTarget.IsReady)
+ if (!_renderTarget.PlatformRenderTargetState.IsReady)
{
IsWaitingForReadyRenderTarget = IsEnabled;
return;
diff --git a/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs b/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs
index 91e4dd2680..9efe33689f 100644
--- a/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs
+++ b/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs
@@ -173,7 +173,7 @@ namespace Avalonia.Native
_context = context;
}
- public bool IsCorrupted => false;
+ public PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
public IGlPlatformSurfaceRenderingSession BeginDraw(IRenderTarget.RenderTargetSceneInfo sceneInfo)
{
diff --git a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs
index ef4ae257bd..8ee06266d8 100644
--- a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs
+++ b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs
@@ -110,6 +110,9 @@ namespace Avalonia.OpenGL.Egl
public bool IsYFlipped { get; }
}
+ public virtual PlatformRenderTargetState State =>
+ IsCorrupted ? PlatformRenderTargetState.Corrupted : PlatformRenderTargetState.Ready;
+
public virtual bool IsCorrupted => Context.IsLost;
}
}
diff --git a/src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs b/src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs
index da35de6649..86c733c5fa 100644
--- a/src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs
+++ b/src/Avalonia.OpenGL/Surfaces/IGlPlatformSurfaceRenderTarget.cs
@@ -8,7 +8,6 @@ namespace Avalonia.OpenGL.Surfaces
[PrivateApi]
public interface IGlPlatformSurfaceRenderTarget : IDisposable, IPlatformRenderSurfaceRenderTarget
{
- bool IsCorrupted { get; }
IGlPlatformSurfaceRenderingSession BeginDraw(IRenderTarget.RenderTargetSceneInfo sceneInfo);
}
}
diff --git a/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs b/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs
index a24b9eea7a..64aaa5ad30 100644
--- a/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs
+++ b/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs
@@ -1,4 +1,5 @@
using System;
+using Avalonia.Platform;
using Avalonia.Vulkan.Interop;
using Avalonia.Vulkan.UnmanagedInterop;
@@ -26,6 +27,8 @@ internal class VulkanKhrRenderTarget : IVulkanRenderTarget
Format = IsRgba ? VkFormat.VK_FORMAT_R8G8B8A8_UNORM : VkFormat.VK_FORMAT_B8G8R8A8_UNORM;
}
+ public PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
+
private void CreateImage()
{
_image = new VulkanImage(_context, _display.CommandBufferPool, Format, _display.Size);
diff --git a/src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs b/src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs
index 81d7a4e9bc..b91c7ac6c9 100644
--- a/src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs
+++ b/src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs
@@ -39,7 +39,7 @@ namespace Avalonia.X11.Glx
// No-op
}
- public bool IsCorrupted => false;
+ public PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
public IGlPlatformSurfaceRenderingSession BeginDraw(IRenderTarget.RenderTargetSceneInfo sceneInfo)
{
var size = sceneInfo.Size;
diff --git a/src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs b/src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
index b83cf8b526..1c152d0fe4 100644
--- a/src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
+++ b/src/Headless/Avalonia.Headless/HeadlessPlatformRenderInterface.cs
@@ -608,8 +608,6 @@ namespace Avalonia.Headless
properties = default;
return new HeadlessDrawingContextStub();
}
-
- public bool IsCorrupted => false;
}
public void Dispose()
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index cf0bf1e49a..dabf1b6bfd 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -407,7 +407,7 @@ namespace Avalonia.LinuxFramebuffer.Output
_parent = parent;
}
- public bool IsCorrupted => false;
+ public PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
public void Dispose()
{
diff --git a/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs b/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
index 5491df93b8..828de2843f 100644
--- a/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
@@ -47,8 +47,8 @@ namespace Avalonia.Skia
IsSuitableForDirectRendering = true
};
-
-
+ public PlatformRenderTargetState PlatformRenderTargetState =>
+ _renderTarget?.State ?? PlatformRenderTargetState.Disposed;
///
public IDrawingContextImpl CreateDrawingContext(IRenderTarget.RenderTargetSceneInfo sceneInfo,
@@ -86,10 +86,7 @@ namespace Avalonia.Skia
return new DrawingContextImpl(createInfo, _preFramebufferCopyHandler, canvas, framebuffer);
}
-
- public bool IsCorrupted => false;
-
- public bool IsReady => _renderTarget is not IPlatformRenderSurfaceRenderTarget prs || prs.IsReady;
+
///
/// Check if two images info are compatible.
diff --git a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs
index 65b6b5a8df..bd8061cf98 100644
--- a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderTarget.cs
@@ -15,8 +15,6 @@ namespace Avalonia.Skia
/// A render session instance.
ISkiaGpuRenderSession BeginRenderingSession(IRenderTarget.RenderTargetSceneInfo sceneInfo);
- bool IsCorrupted { get; }
-
- bool IsReady => true;
+ PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
}
}
diff --git a/src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs b/src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs
index 640b415d6f..402d83fd10 100644
--- a/src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/Metal/SkiaMetalGpu.cs
@@ -108,9 +108,7 @@ internal class SkiaMetalGpu : ISkiaGpu
return new SkiaMetalRenderSession(_gpu, surface, session, backendTarget);
}
- public bool IsCorrupted => false;
-
- public bool IsReady => _target?.IsReady ?? false;
+ public PlatformRenderTargetState State => _target?.State ?? PlatformRenderTargetState.Disposed;
}
internal class SkiaMetalRenderSession : ISkiaGpuRenderSession
diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
index f5c164be45..69e2f0563e 100644
--- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
@@ -21,9 +21,7 @@ namespace Avalonia.Skia
public void Dispose() => _surface.Dispose();
- public bool IsCorrupted => _surface.IsCorrupted;
-
- public bool IsReady => _surface.IsReady;
+ public PlatformRenderTargetState State => _surface.State;
class GlGpuSession : ISkiaGpuRenderSession
{
diff --git a/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs
index 13bd946b74..d748018824 100644
--- a/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs
@@ -43,9 +43,8 @@ namespace Avalonia.Skia
return new DrawingContextImpl(nfo, session);
}
-
- public bool IsCorrupted => _renderTarget.IsCorrupted;
- public bool IsReady => _renderTarget.IsReady;
+
+ public PlatformRenderTargetState PlatformRenderTargetState => _renderTarget.State;
public RenderTargetProperties Properties { get; }
diff --git a/src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaRenderTarget.cs
index 6b04fcd8c0..dc229e16e8 100644
--- a/src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/Gpu/Vulkan/VulkanSkiaRenderTarget.cs
@@ -74,9 +74,7 @@ class VulkanSkiaRenderTarget : ISkiaGpuRenderTarget
}
}
- public bool IsCorrupted => false;
-
- public bool IsReady => _target.IsReady;
+ public PlatformRenderTargetState State => _target.State;
internal class VulkanSkiaRenderSession : ISkiaGpuRenderSession
diff --git a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs
index d0651e08ee..9c6f5707bf 100644
--- a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs
+++ b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs
@@ -78,11 +78,11 @@ internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarg
_d3dDevice.Dispose();
}
- public bool IsCorrupted => _context.IsLost || _lost;
-
+ public PlatformRenderTargetState State => _context.IsLost || _lost ? PlatformRenderTargetState.Corrupted : PlatformRenderTargetState.Ready;
+
public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw()
{
- if (IsCorrupted)
+ if (State.IsCorrupted)
throw new RenderTargetCorruptedException();
var transaction = _window.BeginTransaction();
bool needsEndDraw = false;
diff --git a/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs b/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs
index fb1a6a27e7..ce077d6ce0 100644
--- a/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs
+++ b/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs
@@ -1,5 +1,6 @@
using System;
using Avalonia.OpenGL;
+using Avalonia.OpenGL.Surfaces;
using Avalonia.Platform;
using Avalonia.Platform.Surfaces;
@@ -12,9 +13,8 @@ public interface IDirect3D11TexturePlatformSurface : IPlatformRenderSurface
-public interface IDirect3D11TextureRenderTarget : IDisposable
+public interface IDirect3D11TextureRenderTarget : IPlatformRenderSurfaceRenderTarget, IDisposable
{
- bool IsCorrupted { get; }
IDirect3D11TextureRenderTargetRenderSession BeginDraw();
}
diff --git a/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs b/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs
index 0dc8ec453e..60882fb62e 100644
--- a/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs
+++ b/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs
@@ -83,7 +83,8 @@ internal class AngleD3DTextureFeature : IGlPlatformSurfaceRenderTargetFactory
base.Dispose();
}
- public override bool IsCorrupted => _target.IsCorrupted || base.IsCorrupted;
+ public override PlatformRenderTargetState State =>
+ base.IsCorrupted ? PlatformRenderTargetState.Corrupted : _target.State;
}
public IGlPlatformSurfaceRenderTarget CreateRenderTarget(IGlContext context, IPlatformRenderSurface surface)
diff --git a/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs
index f54ca9b62c..39a7da74ca 100644
--- a/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs
+++ b/src/Windows/Avalonia.Win32/OpenGl/WglGlPlatformSurface.cs
@@ -37,7 +37,7 @@ namespace Avalonia.Win32.OpenGl
_hdc = context.CreateConfiguredDeviceContext(info.Handle);
}
- public bool IsCorrupted => false;
+ public PlatformRenderTargetState State => PlatformRenderTargetState.Ready;
public void Dispose()
{
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
index 2addbc6524..96e5fae00b 100644
--- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
@@ -114,11 +114,12 @@ namespace Avalonia.Win32.WinRT.Composition
_d3dDevice.Dispose();
}
- public bool IsCorrupted => _context.IsLost || _lost;
+ public PlatformRenderTargetState State =>
+ _context.IsLost || _lost ? PlatformRenderTargetState.Corrupted : PlatformRenderTargetState.Ready;
public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw()
{
- if (IsCorrupted)
+ if (State.IsCorrupted)
throw new RenderTargetCorruptedException();
var transaction = _window.BeginTransaction();
bool needsEndDraw = false;
From b2ee6119fde635c2ca9cf179162391e9afebb4af Mon Sep 17 00:00:00 2001
From: Nikita Tsukanov
Date: Mon, 30 Mar 2026 14:26:35 +0500
Subject: [PATCH 05/86] Change XInternAtoms call force-create atoms (#21034)
---
src/tools/DevGenerators/X11AtomsGenerator.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tools/DevGenerators/X11AtomsGenerator.cs b/src/tools/DevGenerators/X11AtomsGenerator.cs
index 920b3477dc..e91016af3e 100644
--- a/src/tools/DevGenerators/X11AtomsGenerator.cs
+++ b/src/tools/DevGenerators/X11AtomsGenerator.cs
@@ -72,7 +72,7 @@ public class X11AtomsGenerator : IIncrementalGenerator
classBuilder.Pad(3).Append("\"").Append(writeableFields[c].Name).AppendLine("\",");
classBuilder.Pad(2).AppendLine("};");
- classBuilder.Pad(2).AppendLine("XInternAtoms(display, atomNames, atomNames.Length, true, atoms);");
+ classBuilder.Pad(2).AppendLine("XInternAtoms(display, atomNames, atomNames.Length, false, atoms);");
for (int c = 0; c < writeableFields.Count; c++)
classBuilder.Pad(2).Append("InitAtom(ref ").Append(writeableFields[c].Name).Append(", \"")
From 94c809f84eef0dbb08f84ce11ddbee3cffdd93dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Javier=20Su=C3=A1rez?=
Date: Mon, 30 Mar 2026 16:18:25 +0200
Subject: [PATCH 06/86] Rename AppBar controls (#21041)
* Renamed AppBar buttons and separator
* CommandBarSeparator inherit from Separator
* Added suppressions
---
api/Avalonia.nupkg.xml | 36 ++++
.../CommandBarCustomizationPage.xaml | 24 +--
.../CommandBarDynamicOverflowPage.xaml | 12 +-
.../CommandBar/CommandBarEventsPage.xaml | 10 +-
.../CommandBar/CommandBarEventsPage.xaml.cs | 18 +-
.../CommandBar/CommandBarFirstLookPage.xaml | 56 +++---
.../CommandBarFirstLookPage.xaml.cs | 4 +-
.../CommandBarLabelPositionPage.xaml | 24 +--
.../CommandBar/CommandBarOverflowPage.xaml | 10 +-
.../CommandBar/CommandBarOverflowPage.xaml.cs | 4 +-
.../CommandBar/CommandBarTogglePage.xaml | 28 +--
.../Pages/CommandBarPage.xaml.cs | 2 +-
.../ContentPageCommandBarPage.xaml.cs | 20 +-
.../NavigationPageToolbarPage.xaml.cs | 16 +-
.../CommandBar/CommandBar.cs | 12 +-
.../{AppBarButton.cs => CommandBarButton.cs} | 20 +-
...BarSeparator.cs => CommandBarSeparator.cs} | 8 +-
...gleButton.cs => CommandBarToggleButton.cs} | 20 +-
.../Controls/CommandBar.xaml | 38 ++--
.../Controls/NavigationPage.xaml | 4 +-
.../Controls/CommandBar.xaml | 28 +--
.../CommandBarTests.cs | 182 +++++++++---------
.../Controls/CommandBarTests.cs | 16 +-
.../Controls/ContentPageTests.cs | 8 +-
24 files changed, 319 insertions(+), 281 deletions(-)
rename src/Avalonia.Controls/CommandBar/{AppBarButton.cs => CommandBarButton.cs} (80%)
rename src/Avalonia.Controls/CommandBar/{AppBarSeparator.cs => CommandBarSeparator.cs} (81%)
rename src/Avalonia.Controls/CommandBar/{AppBarToggleButton.cs => CommandBarToggleButton.cs} (79%)
diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index f3a9929ca1..a63ac3baae 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -5821,4 +5821,40 @@
baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+ CP0001
+ T:Avalonia.Controls.AppBarButton
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+
+ CP0001
+ T:Avalonia.Controls.AppBarSeparator
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+
+ CP0001
+ T:Avalonia.Controls.AppBarToggleButton
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+
+ CP0001
+ T:Avalonia.Controls.AppBarButton
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+
+ CP0001
+ T:Avalonia.Controls.AppBarSeparator
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+
+ CP0001
+ T:Avalonia.Controls.AppBarToggleButton
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml
index 1ea3349129..3ce911d9f8 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml
@@ -15,9 +15,9 @@
-
-
-
+
+
+
@@ -74,7 +74,7 @@
-
@@ -89,20 +89,20 @@
-
-
+
+
-
-
+
+
-
-
+
+
@@ -111,8 +111,8 @@
BorderBrush="#CCCCCC"
BorderThickness="1"
OverflowButtonVisibility="Collapsed">
-
-
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml
index 2f771ab42e..6d66c19c96 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml
@@ -61,12 +61,12 @@
ClipToBounds="True">
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml
index 8dbc44e19b..b4728aa918 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml
@@ -64,13 +64,13 @@
-
-
-
+
+
+
-
-
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml.cs b/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml.cs
index c2f0b439f0..f82fcbddb9 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarEventsPage.xaml.cs
@@ -141,13 +141,13 @@ namespace ControlCatalog.Pages
private void OnCommandItemClick(object? sender, RoutedEventArgs e)
{
- if (sender is AppBarButton button)
+ if (sender is CommandBarButton button)
AppendLog($"Click, {button.Label}, {DescribePlacement(button)}");
}
- private AppBarButton CreateButton(string label)
+ private CommandBarButton CreateButton(string label)
{
- var button = new AppBarButton
+ var button = new CommandBarButton
{
Label = label,
Icon = new PathIcon
@@ -170,14 +170,14 @@ namespace ControlCatalog.Pages
{
foreach (var item in items)
{
- if (item is AppBarButton button)
+ if (item is CommandBarButton button)
button.Click -= OnCommandItemClick;
}
}
private void AttachItemHandler(ICommandBarElement item)
{
- if (item is not AppBarButton button)
+ if (item is not CommandBarButton button)
return;
button.Click -= OnCommandItemClick;
@@ -191,10 +191,10 @@ namespace ControlCatalog.Pages
return;
var item = items[^1];
- var label = item is AppBarButton button ? button.Label ?? "(unnamed)" : item.GetType().Name;
+ var label = item is CommandBarButton button ? button.Label ?? "(unnamed)" : item.GetType().Name;
- if (item is AppBarButton appBarButton)
- appBarButton.Click -= OnCommandItemClick;
+ if (item is CommandBarButton commandBarButton)
+ commandBarButton.Click -= OnCommandItemClick;
items.RemoveAt(items.Count - 1);
@@ -202,7 +202,7 @@ namespace ControlCatalog.Pages
RefreshState();
}
- private static string DescribePlacement(AppBarButton button)
+ private static string DescribePlacement(CommandBarButton button)
{
return button.IsInOverflow ? "overflow" : "primary";
}
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml
index b83d1c3e57..60c23d9c64 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml
@@ -36,7 +36,7 @@
-
@@ -52,35 +52,35 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml.cs b/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml.cs
index c624ffcad6..9e15c0fb6c 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml.cs
@@ -12,13 +12,13 @@ namespace ControlCatalog.Pages
private void OnButtonClick(object? sender, RoutedEventArgs e)
{
- if (sender is AppBarButton btn)
+ if (sender is CommandBarButton btn)
StatusText.Text = $"{btn.Label} clicked";
}
private void OnToggleChanged(object? sender, RoutedEventArgs e)
{
- if (sender is AppBarToggleButton btn)
+ if (sender is CommandBarToggleButton btn)
StatusText.Text = btn.IsChecked == true
? $"{btn.Label} enabled"
: $"{btn.Label} disabled";
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml
index a1dbea2db1..a4b23542d7 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml
@@ -15,10 +15,10 @@
-
-
-
-
+
+
+
+
@@ -26,10 +26,10 @@
-
-
-
-
+
+
+
+
@@ -37,10 +37,10 @@
-
-
-
-
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml
index be3371a8e8..46bcac3fac 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml
@@ -59,13 +59,13 @@
-
-
-
+
+
+
-
-
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml.cs b/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml.cs
index a0d5f24b7f..ff5ee07f2a 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml.cs
@@ -42,13 +42,13 @@ namespace ControlCatalog.Pages
private void OnAddPrimary(object? sender, RoutedEventArgs e)
{
_primaryCount++;
- DemoBar.PrimaryCommands.Add(new AppBarButton { Label = $"Cmd {_primaryCount}" });
+ DemoBar.PrimaryCommands.Add(new CommandBarButton { Label = $"Cmd {_primaryCount}" });
}
private void OnAddSecondary(object? sender, RoutedEventArgs e)
{
_secondaryCount++;
- DemoBar.SecondaryCommands.Add(new AppBarButton { Label = $"Sec {_secondaryCount}" });
+ DemoBar.SecondaryCommands.Add(new CommandBarButton { Label = $"Sec {_secondaryCount}" });
}
}
}
diff --git a/samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml b/samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml
index d2513038c0..794bd3fcd4 100644
--- a/samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml
+++ b/samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml
@@ -28,7 +28,7 @@
-
@@ -37,25 +37,25 @@
- AppBarToggleButton supports on/off states for formatting and feature toggles.
+ CommandBarToggleButton supports on/off states for formatting and feature toggles.
-
-
-
-
+
+
-
-
-
+
+
-
-
+
+
-
-
-
+
+
+
diff --git a/samples/ControlCatalog/Pages/CommandBarPage.xaml.cs b/samples/ControlCatalog/Pages/CommandBarPage.xaml.cs
index 7aaf6d22be..e76d605645 100644
--- a/samples/ControlCatalog/Pages/CommandBarPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/CommandBarPage.xaml.cs
@@ -13,7 +13,7 @@ namespace ControlCatalog.Pages
{
// Overview
("Overview", "First Look", "A CommandBar with primary commands, secondary overflow menu, and custom content area.", () => new CommandBarFirstLookPage()),
- ("Overview", "Toggle Buttons", "AppBarToggleButton for stateful actions like Bold, Italic, and Favorite.", () => new CommandBarTogglePage()),
+ ("Overview", "Toggle Buttons", "CommandBarToggleButton for stateful actions like Bold, Italic, and Favorite.", () => new CommandBarTogglePage()),
// Appearance
("Appearance", "Label Positions", "Configure label position: Bottom (default), Right, or Collapsed (icon only).", () => new CommandBarLabelPositionPage()),
diff --git a/samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml.cs b/samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml.cs
index 07bdbb52a2..3bb6b30082 100644
--- a/samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml.cs
@@ -78,7 +78,7 @@ namespace ControlCatalog.Pages
private void OnAddPrimary(object? sender, RoutedEventArgs e)
{
_itemCounter++;
- var btn = new AppBarButton { Label = $"Action {_itemCounter}" };
+ var btn = new CommandBarButton { Label = $"Action {_itemCounter}" };
if (UseIconCheck.IsChecked == true)
{
var preset = IconPresets[(_itemCounter - 1) % IconPresets.Length];
@@ -93,13 +93,13 @@ namespace ControlCatalog.Pages
private void OnAddSecondary(object? sender, RoutedEventArgs e)
{
_itemCounter++;
- _secondaryItems.Add(new AppBarButton { Label = $"Item {_itemCounter}" });
+ _secondaryItems.Add(new CommandBarButton { Label = $"Item {_itemCounter}" });
RebuildCommandBar();
}
private void OnAddSeparator(object? sender, RoutedEventArgs e)
{
- _primaryItems.Add(new AppBarSeparator());
+ _primaryItems.Add(new CommandBarSeparator());
RebuildCommandBar();
}
@@ -177,26 +177,26 @@ namespace ControlCatalog.Pages
foreach (var item in _primaryItems)
{
- if (item is AppBarButton btn)
+ if (item is CommandBarButton btn)
{
PathIcon? icon = null;
if (btn.Icon is PathIcon src)
icon = new PathIcon { Data = src.Data };
- commandBar.PrimaryCommands.Add(new AppBarButton
+ commandBar.PrimaryCommands.Add(new CommandBarButton
{
Label = btn.Label,
Icon = icon,
IsCompact = btn.IsCompact,
});
}
- else if (item is AppBarSeparator)
- commandBar.PrimaryCommands.Add(new AppBarSeparator());
+ else if (item is CommandBarSeparator)
+ commandBar.PrimaryCommands.Add(new CommandBarSeparator());
}
foreach (var item in _secondaryItems)
{
- if (item is AppBarButton btn)
- commandBar.SecondaryCommands.Add(new AppBarButton { Label = btn.Label });
+ if (item is CommandBarButton btn)
+ commandBar.SecondaryCommands.Add(new CommandBarButton { Label = btn.Label });
}
if (_position == "Top")
@@ -204,7 +204,7 @@ namespace ControlCatalog.Pages
else
NavigationPage.SetBottomCommandBar(activePage, commandBar);
- var primaryCount = _primaryItems.Count(i => i is AppBarButton);
+ var primaryCount = _primaryItems.Count(i => i is CommandBarButton);
var secondaryCount = _secondaryItems.Count;
StatusText.Text = $"{primaryCount} primary, {secondaryCount} secondary ({_position})";
}
diff --git a/samples/ControlCatalog/Pages/NavigationPage/NavigationPageToolbarPage.xaml.cs b/samples/ControlCatalog/Pages/NavigationPage/NavigationPageToolbarPage.xaml.cs
index c141f47781..724f8de84a 100644
--- a/samples/ControlCatalog/Pages/NavigationPage/NavigationPageToolbarPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/NavigationPage/NavigationPageToolbarPage.xaml.cs
@@ -49,7 +49,7 @@ namespace ControlCatalog.Pages
private void OnAddPrimary(object? sender, RoutedEventArgs e)
{
_itemCount++;
- _rootCommandBar.PrimaryCommands.Add(new AppBarButton
+ _rootCommandBar.PrimaryCommands.Add(new CommandBarButton
{
Label = $"Item {_itemCount}",
Icon = new PathIcon { Data = (Geometry)this.FindResource("AddIcon")! }
@@ -60,7 +60,7 @@ namespace ControlCatalog.Pages
private void OnAddSecondary(object? sender, RoutedEventArgs e)
{
_itemCount++;
- _rootCommandBar.SecondaryCommands.Add(new AppBarButton
+ _rootCommandBar.SecondaryCommands.Add(new CommandBarButton
{
Label = $"Secondary {_itemCount}"
});
@@ -69,13 +69,13 @@ namespace ControlCatalog.Pages
private void OnAddPrimarySeparator(object? sender, RoutedEventArgs e)
{
- _rootCommandBar.PrimaryCommands.Add(new AppBarSeparator());
+ _rootCommandBar.PrimaryCommands.Add(new CommandBarSeparator());
UpdateStatus();
}
private void OnAddSecondarySeparator(object? sender, RoutedEventArgs e)
{
- _rootCommandBar.SecondaryCommands.Add(new AppBarSeparator());
+ _rootCommandBar.SecondaryCommands.Add(new CommandBarSeparator());
UpdateStatus();
}
@@ -125,13 +125,13 @@ namespace ControlCatalog.Pages
{
PrimaryCommands =
{
- new AppBarButton { Label = "Search", Icon = new PathIcon { Data = (Geometry)this.FindResource("SearchIcon")! } },
- new AppBarButton { Label = "Share", Icon = new PathIcon { Data = (Geometry)this.FindResource("ShareIcon")! } },
- new AppBarButton { Label = "Edit", Icon = new PathIcon { Data = (Geometry)this.FindResource("EditIcon")! } },
+ new CommandBarButton { Label = "Search", Icon = new PathIcon { Data = (Geometry)this.FindResource("SearchIcon")! } },
+ new CommandBarButton { Label = "Share", Icon = new PathIcon { Data = (Geometry)this.FindResource("ShareIcon")! } },
+ new CommandBarButton { Label = "Edit", Icon = new PathIcon { Data = (Geometry)this.FindResource("EditIcon")! } },
},
SecondaryCommands =
{
- new AppBarButton { Label = "Delete", Icon = new PathIcon { Data = (Geometry)this.FindResource("DeleteIcon")! } }
+ new CommandBarButton { Label = "Delete", Icon = new PathIcon { Data = (Geometry)this.FindResource("DeleteIcon")! } }
}
};
}
diff --git a/src/Avalonia.Controls/CommandBar/CommandBar.cs b/src/Avalonia.Controls/CommandBar/CommandBar.cs
index 392ffb7ddc..d493bce304 100644
--- a/src/Avalonia.Controls/CommandBar/CommandBar.cs
+++ b/src/Avalonia.Controls/CommandBar/CommandBar.cs
@@ -516,7 +516,7 @@ namespace Avalonia.Controls
int primaryNonSepCount = 0;
foreach (var item in PrimaryCommands)
- if (item is not AppBarSeparator)
+ if (item is not CommandBarSeparator)
primaryNonSepCount++;
const double overflowButtonWidth = 48;
@@ -554,7 +554,7 @@ namespace Avalonia.Controls
for (var i = 0; i < prioritized.Count; i++)
{
var idx = prioritized[i].Index;
- if (PrimaryCommands[idx] is AppBarSeparator)
+ if (PrimaryCommands[idx] is CommandBarSeparator)
visibleIndices.Add(idx);
else if (nonSeparatorCount < maxItems)
{
@@ -596,8 +596,8 @@ namespace Avalonia.Controls
private static int GetDynamicOverflowOrder(ICommandBarElement element) => element switch
{
- AppBarButton b => b.DynamicOverflowOrder,
- AppBarToggleButton t => t.DynamicOverflowOrder,
+ CommandBarButton b => b.DynamicOverflowOrder,
+ CommandBarToggleButton t => t.DynamicOverflowOrder,
_ => 0
};
@@ -615,9 +615,9 @@ namespace Avalonia.Controls
{
element.IsCompact = DefaultLabelPosition == CommandBarDefaultLabelPosition.Collapsed;
- if (element is AppBarButton abb)
+ if (element is CommandBarButton abb)
abb.LabelPosition = DefaultLabelPosition;
- else if (element is AppBarToggleButton atb)
+ else if (element is CommandBarToggleButton atb)
atb.LabelPosition = DefaultLabelPosition;
}
diff --git a/src/Avalonia.Controls/CommandBar/AppBarButton.cs b/src/Avalonia.Controls/CommandBar/CommandBarButton.cs
similarity index 80%
rename from src/Avalonia.Controls/CommandBar/AppBarButton.cs
rename to src/Avalonia.Controls/CommandBar/CommandBarButton.cs
index 9e251f77bf..776f4edc47 100644
--- a/src/Avalonia.Controls/CommandBar/AppBarButton.cs
+++ b/src/Avalonia.Controls/CommandBar/CommandBarButton.cs
@@ -3,49 +3,49 @@ namespace Avalonia.Controls
///
/// A button for use in a .
///
- public class AppBarButton : Button, ICommandBarElement
+ public class CommandBarButton : Button, ICommandBarElement
{
- static AppBarButton()
+ static CommandBarButton()
{
- ForegroundProperty.Changed.AddClassHandler((x, _) => x.UpdateIconForeground());
- IconProperty.Changed.AddClassHandler((x, _) => x.UpdateIconForeground());
+ ForegroundProperty.Changed.AddClassHandler((x, _) => x.UpdateIconForeground());
+ IconProperty.Changed.AddClassHandler((x, _) => x.UpdateIconForeground());
}
///
/// Defines the property.
///
public static readonly StyledProperty LabelProperty =
- AvaloniaProperty.Register(nameof(Label));
+ AvaloniaProperty.Register(nameof(Label));
///
/// Defines the property.
///
public static readonly StyledProperty