diff --git a/src/Avalonia.Controls/TopLevelHost.Decorations.cs b/src/Avalonia.Controls/TopLevelHost.Decorations.cs
index f9cb20f511..11f3dc3ada 100644
--- a/src/Avalonia.Controls/TopLevelHost.Decorations.cs
+++ b/src/Avalonia.Controls/TopLevelHost.Decorations.cs
@@ -48,64 +48,76 @@ internal partial class TopLevelHost
internal WindowDrawnDecorations? Decorations => _decorations;
///
- /// Enables drawn window decorations with the specified parts.
- /// Creates the decorations instance, applies the template, and inserts layers into the visual tree.
+ /// Updates drawn window decorations with the specified parts and window state.
+ /// When is null, decorations are removed entirely.
+ /// When non-null (including ), the decoration
+ /// infrastructure is kept alive and parts/fullscreen state are updated.
///
- internal void EnableDecorations(DrawnWindowDecorationParts parts)
+ internal void UpdateDrawnDecorations(DrawnWindowDecorationParts? parts, WindowState windowState)
{
+ if (parts == null)
+ {
+ RemoveDecorations();
+ return;
+ }
+
+ var enabledParts = parts.Value;
+
if (_decorations != null)
{
// Layers persist across part changes; pseudo-classes driven by EnabledParts
// control visibility of individual decoration elements in the theme.
- _decorations.EnabledParts = parts;
+ _decorations.EnabledParts = enabledParts;
if (_resizeGrips != null)
- _resizeGrips.IsVisible = parts.HasFlag(DrawnWindowDecorationParts.ResizeGrips);
- return;
+ _resizeGrips.IsVisible = enabledParts.HasFlag(DrawnWindowDecorationParts.ResizeGrips);
}
-
- _decorations = new WindowDrawnDecorations();
- _decorations.EnabledParts = parts;
-
- // Set up logical parenting
- LogicalChildren.Add(_decorations);
-
- // Create layer wrappers
- _underlay = new LayerWrapper() { [AutomationProperties.AutomationIdProperty] = "WindowChromeUnderlay" };
- _overlay = new LayerWrapper() { [AutomationProperties.AutomationIdProperty] = "WindowChromeOverlay" };
- _fullscreenPopover = new LayerWrapper()
+ else
{
- IsVisible = false, [AutomationProperties.AutomationIdProperty] = "PopoverWindowChrome"
- };
-
- // Insert layers: underlay below TopLevel, overlay and popover above
- // Visual order: underlay(0), TopLevel(1), overlay(2), fullscreenPopover(3), resizeGrips(4)
- VisualChildren.Insert(0, _underlay);
- VisualChildren.Add(_overlay);
- VisualChildren.Add(_fullscreenPopover);
-
- // Always create resize grips; visibility is controlled by EnabledParts
- _resizeGrips = new ResizeGripLayer();
- _resizeGrips.IsVisible = parts.HasFlag(DrawnWindowDecorationParts.ResizeGrips);
- VisualChildren.Add(_resizeGrips);
+ _decorations = new WindowDrawnDecorations();
+ _decorations.EnabledParts = enabledParts;
- // Attach to window if available
- if (_topLevel is Window window)
- _decorations.Attach(window);
+ // Set up logical parenting
+ LogicalChildren.Add(_decorations);
- // Subscribe to template changes to re-apply and geometry changes for resize grips
- _decorations.EffectiveGeometryChanged += OnDecorationsGeometryChanged;
- _decorationsSubscriptions = _decorations.GetObservable(WindowDrawnDecorations.TemplateProperty)
- .Subscribe(_ => ApplyDecorationsTemplate());
+ // Create layer wrappers
+ _underlay = new LayerWrapper() { [AutomationProperties.AutomationIdProperty] = "WindowChromeUnderlay" };
+ _overlay = new LayerWrapper() { [AutomationProperties.AutomationIdProperty] = "WindowChromeOverlay" };
+ _fullscreenPopover = new LayerWrapper()
+ {
+ IsVisible = false, [AutomationProperties.AutomationIdProperty] = "PopoverWindowChrome"
+ };
+
+ // Insert layers: underlay below TopLevel, overlay and popover above
+ // Visual order: underlay(0), TopLevel(1), overlay(2), fullscreenPopover(3), resizeGrips(4)
+ VisualChildren.Insert(0, _underlay);
+ VisualChildren.Add(_overlay);
+ VisualChildren.Add(_fullscreenPopover);
+
+ // Always create resize grips; visibility is controlled by EnabledParts
+ _resizeGrips = new ResizeGripLayer();
+ _resizeGrips.IsVisible = enabledParts.HasFlag(DrawnWindowDecorationParts.ResizeGrips);
+ VisualChildren.Add(_resizeGrips);
+
+ // Attach to window if available
+ if (_topLevel is Window window)
+ _decorations.Attach(window);
+
+ // Subscribe to template changes to re-apply and geometry changes for resize grips
+ _decorations.EffectiveGeometryChanged += OnDecorationsGeometryChanged;
+ _decorationsSubscriptions = _decorations.GetObservable(WindowDrawnDecorations.TemplateProperty)
+ .Subscribe(_ => ApplyDecorationsTemplate());
+
+ ApplyDecorationsTemplate();
+ InvalidateMeasure();
+ }
- ApplyDecorationsTemplate();
- InvalidateMeasure();
- _decorationsOverlayPeer?.InvalidateChildren();
+ ApplyFullscreenState(windowState == WindowState.FullScreen);
}
///
- /// Disables drawn window decorations and removes all layers.
+ /// Removes drawn window decorations and all associated layers.
///
- internal void DisableDecorations()
+ private void RemoveDecorations()
{
if (_decorations == null)
return;
@@ -192,15 +204,15 @@ internal partial class TopLevelHost
}
///
- /// Shows or hides the fullscreen popover based on the window state.
- /// Called by Window when window state changes.
+ /// Applies fullscreen-specific layer visibility: hides overlay/underlay and enables
+ /// popover hover detection, or restores normal state.
///
- internal void SetFullscreenPopoverEnabled(bool enabled)
+ private void ApplyFullscreenState(bool isFullscreen)
{
if (_fullscreenPopover == null)
return;
- if (enabled)
+ if (isFullscreen)
{
// In fullscreen mode, hide overlay and underlay, enable popover hover detection
if (_overlay != null)
diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs
index 043abb0e1b..d92a46a70a 100644
--- a/src/Avalonia.Controls/Window.cs
+++ b/src/Avalonia.Controls/Window.cs
@@ -626,10 +626,7 @@ namespace Avalonia.Controls
StartRendering();
}
- // Update fullscreen popover visibility
- TopLevelHost.SetFullscreenPopoverEnabled(state == WindowState.FullScreen);
-
- // Update decoration parts for the new window state
+ // Update decoration parts and fullscreen popover state for the new window state
UpdateDrawnDecorationParts();
}
@@ -643,13 +640,11 @@ namespace Avalonia.Controls
private void UpdateDrawnDecorations()
{
- var needsDrawnDecorations = PlatformImpl?.NeedsManagedDecorations ?? false;
+ var parts = ComputeDecorationParts();
+ TopLevelHost.UpdateDrawnDecorations(parts, WindowState);
- var parts = needsDrawnDecorations ? ComputeDecorationParts() : DrawnWindowDecorationParts.None;
- if (parts != DrawnWindowDecorationParts.None)
+ if (parts != null)
{
- TopLevelHost.EnableDecorations(parts);
-
// Forward ExtendClientAreaTitleBarHeightHint to decoration TitleBarHeight
var decorations = TopLevelHost.Decorations;
if (decorations != null)
@@ -659,10 +654,6 @@ namespace Avalonia.Controls
decorations.TitleBarHeightOverride = hint;
}
}
- else
- {
- TopLevelHost.DisableDecorations();
- }
UpdateDrawnDecorationMargins();
}
@@ -676,11 +667,14 @@ namespace Avalonia.Controls
if (TopLevelHost.Decorations == null)
return;
- TopLevelHost.EnableDecorations(ComputeDecorationParts());
+ TopLevelHost.UpdateDrawnDecorations(ComputeDecorationParts(), WindowState);
}
- private Chrome.DrawnWindowDecorationParts ComputeDecorationParts()
+ private Chrome.DrawnWindowDecorationParts? ComputeDecorationParts()
{
+ if (!(PlatformImpl?.NeedsManagedDecorations ?? false))
+ return null;
+
var platformNeeds = PlatformImpl?.RequestedDrawnDecorations ?? PlatformRequestedDrawnDecoration.None;
var parts = Chrome.DrawnWindowDecorationParts.None;
if (WindowDecorations != WindowDecorations.None)