-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Introduced "forced" CSD mode without app opting in #20976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
2593a33
9b75f50
5b8d6dc
437fadd
acc4e3d
0851768
47b715c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -98,6 +98,7 @@ public class Window : WindowBase, IFocusScope | |
| private Thickness _offScreenMargin; | ||
| private bool _canHandleResized = false; | ||
| private Size _arrangeBounds; | ||
| private bool _isForcedDecorationMode; | ||
|
|
||
| /// <summary> | ||
| /// Defines the <see cref="SizeToContent"/> property. | ||
|
|
@@ -249,7 +250,10 @@ public Window(IWindowImpl impl) | |
| impl.WindowStateChanged = HandleWindowStateChanged; | ||
| _maxPlatformClientSize = PlatformImpl?.MaxAutoSizeHint ?? default(Size); | ||
| impl.ExtendClientAreaToDecorationsChanged = ExtendClientAreaToDecorationsChanged; | ||
| this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x, WindowResizeReason.Application)); | ||
| this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => | ||
| { | ||
| ResizePlatformImpl(x, WindowResizeReason.Application); | ||
| }); | ||
|
|
||
| CreatePlatformImplBinding(TitleProperty, title => PlatformImpl!.SetTitle(title)); | ||
| CreatePlatformImplBinding(IconProperty, SetEffectiveIcon); | ||
|
|
@@ -668,7 +672,7 @@ private void HandleWindowStateChanged(WindowState state) | |
| UpdateDrawnDecorationParts(); | ||
| } | ||
|
|
||
| protected virtual void ExtendClientAreaToDecorationsChanged(bool isExtended) | ||
| private void ExtendClientAreaToDecorationsChanged(bool isExtended) | ||
| { | ||
| IsExtendedIntoWindowDecorations = isExtended; | ||
| OffScreenMargin = PlatformImpl?.OffScreenMargin ?? default; | ||
|
|
@@ -679,6 +683,10 @@ protected virtual void ExtendClientAreaToDecorationsChanged(bool isExtended) | |
| private void UpdateDrawnDecorations() | ||
| { | ||
| var parts = ComputeDecorationParts(); | ||
|
|
||
| // Detect forced mode: platform needs managed decorations but app hasn't opted in | ||
| _isForcedDecorationMode = parts != null && !IsExtendedIntoWindowDecorations; | ||
|
|
||
| TopLevelHost.UpdateDrawnDecorations(parts, WindowState); | ||
|
|
||
| if (parts != null) | ||
|
|
@@ -753,7 +761,9 @@ private void UpdateDrawnDecorationMargins() | |
| var decorations = TopLevelHost.Decorations; | ||
| if (decorations == null) | ||
| { | ||
| // Only use platform margins if drawn decorations are not active | ||
| WindowDecorationMargin = PlatformImpl?.ExtendedMargins ?? default; | ||
| TopLevelHost.DecorationInset = default; | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -764,11 +774,25 @@ private void UpdateDrawnDecorationMargins() | |
| ? decorations.FrameThickness : default; | ||
| var shadow = parts.HasFlag(Chrome.DrawnWindowDecorationParts.Shadow) | ||
| ? decorations.ShadowThickness : default; | ||
| WindowDecorationMargin = new Thickness( | ||
| var margin = new Thickness( | ||
| frame.Left + shadow.Left, | ||
| titleBarHeight + frame.Top + shadow.Top, | ||
| frame.Right + shadow.Right, | ||
| frame.Bottom + shadow.Bottom); | ||
|
|
||
| if (_isForcedDecorationMode) | ||
| { | ||
| // In forced mode, app is unaware of decorations. | ||
| // TopLevelHost insets the Window child; WindowDecorationMargin stays zero. | ||
| WindowDecorationMargin = default; | ||
| TopLevelHost.DecorationInset = margin; | ||
| } | ||
| else | ||
| { | ||
| // In extended mode, app handles the margin itself. | ||
| WindowDecorationMargin = margin; | ||
| TopLevelHost.DecorationInset = default; | ||
| } | ||
|
Comment on lines
+793
to
+805
|
||
| } | ||
|
|
||
| private void OnTitleBarHeightHintChanged() | ||
|
|
@@ -933,6 +957,15 @@ private void EnsureParentStateBeforeShow(Window owner) | |
| // Enable drawn decorations before layout so margins are computed | ||
| UpdateDrawnDecorations(); | ||
|
|
||
| // In forced mode, adjust ClientSize to reflect usable content area | ||
| if (_isForcedDecorationMode) | ||
| { | ||
| var inset = TopLevelHost.DecorationInset; | ||
| ClientSize = new Size( | ||
| Math.Max(0, ClientSize.Width - inset.Left - inset.Right), | ||
| Math.Max(0, ClientSize.Height - inset.Top - inset.Bottom)); | ||
| } | ||
|
|
||
| _shown = true; | ||
| IsVisible = true; | ||
|
|
||
|
|
@@ -978,10 +1011,18 @@ private void EnsureParentStateBeforeShow(Window owner) | |
|
|
||
| DesktopScalingOverride = null; | ||
|
|
||
| if (clientSizeChanged || ClientSize != PlatformImpl?.ClientSize) | ||
| // In forced mode, compare against adjusted platform size | ||
| var platformClientSize = PlatformImpl?.ClientSize ?? default; | ||
| var comparableClientSize = _isForcedDecorationMode | ||
| ? new Size( | ||
| Math.Max(0, platformClientSize.Width - TopLevelHost.DecorationInset.Left - TopLevelHost.DecorationInset.Right), | ||
| Math.Max(0, platformClientSize.Height - TopLevelHost.DecorationInset.Top - TopLevelHost.DecorationInset.Bottom)) | ||
| : platformClientSize; | ||
|
|
||
| if (clientSizeChanged || ClientSize != comparableClientSize) | ||
| { | ||
| // Previously it was called before ExecuteInitialLayoutPass | ||
| PlatformImpl?.Resize(ClientSize, WindowResizeReason.Layout); | ||
| ResizePlatformImpl(ClientSize, WindowResizeReason.Layout); | ||
|
|
||
| // we do not want PlatformImpl?.Resize to trigger HandleResized yet because it will set Width and Height. | ||
| // So perform some important actions from HandleResized | ||
|
|
@@ -1037,6 +1078,22 @@ private void EnsureParentStateBeforeShow(Window owner) | |
| } | ||
| } | ||
|
|
||
| private void ResizePlatformImpl(Size size, WindowResizeReason reason) | ||
| { | ||
| // In forced mode, add decoration inset so platform gets full frame size | ||
| if (_isForcedDecorationMode) | ||
| { | ||
| var inset = TopLevelHost.DecorationInset; | ||
| size = new Size( | ||
| size.Width + inset.Left + inset.Right, | ||
| size.Height + inset.Top + inset.Bottom); | ||
| if (PlatformImpl?.ClientSize != size) | ||
| PlatformImpl?.Resize(size, reason); | ||
| } | ||
| else | ||
| PlatformImpl?.Resize(size, reason); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Shows the window as a dialog. | ||
| /// </summary> | ||
|
|
@@ -1272,6 +1329,14 @@ protected override Size MeasureOverride(Size availableSize) | |
| { | ||
| var sizeToContent = SizeToContent; | ||
| var clientSize = ClientSize; | ||
| if (_isForcedDecorationMode) | ||
| { | ||
| clientSize = PlatformImpl?.ClientSize ?? clientSize; | ||
| var inset = TopLevelHost.DecorationInset; | ||
| clientSize = new Size( | ||
| Math.Max(0, clientSize.Width - inset.Left - inset.Right), | ||
| Math.Max(0, clientSize.Height - inset.Top - inset.Bottom)); | ||
| } | ||
| var maxAutoSize = PlatformImpl?.MaxAutoSizeHint ?? Size.Infinity; | ||
| var useAutoWidth = sizeToContent.HasAllFlags(SizeToContent.Width); | ||
| var useAutoHeight = sizeToContent.HasAllFlags(SizeToContent.Height); | ||
|
|
@@ -1332,7 +1397,9 @@ private protected sealed override Size ArrangeSetBounds(Size size) | |
| { | ||
| _arrangeBounds = size; | ||
| if (_canHandleResized) | ||
| PlatformImpl?.Resize(size, WindowResizeReason.Layout); | ||
| { | ||
| ResizePlatformImpl(size, WindowResizeReason.Layout); | ||
| } | ||
| return ClientSize; | ||
| } | ||
|
|
||
|
|
@@ -1350,6 +1417,16 @@ private protected sealed override void HandleClosed() | |
| /// <inheritdoc/> | ||
| internal override void HandleResized(Size clientSize, WindowResizeReason reason) | ||
| { | ||
| // In forced decoration mode, the platform's clientSize includes decoration area. | ||
| // Subtract the decoration inset so Window.ClientSize reflects the usable content area. | ||
| if (_isForcedDecorationMode) | ||
| { | ||
| var inset = TopLevelHost.DecorationInset; | ||
| clientSize = new Size( | ||
| Math.Max(0, clientSize.Width - inset.Left - inset.Right), | ||
| Math.Max(0, clientSize.Height - inset.Top - inset.Bottom)); | ||
| } | ||
|
|
||
| if (_canHandleResized && (ClientSize != clientSize || double.IsNaN(Width) || double.IsNaN(Height))) | ||
| { | ||
| var sizeToContent = SizeToContent; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.