From f2796b74a506bf76c0b090a514cdea58fc67a431 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Sat, 8 Aug 2026 10:34:53 -0500 Subject: [PATCH] CmdPal: make dialogs prevent compact mode from being collapsed (#49451) ContentDialogs we present for CommandResult.Confirm need to be visible. When the window is clipped for compact mode, the dialog is predictably also collapsed. This makes sure that content dialogs are always visible, by forcing us out of compact mode when dialogs are shown. Closes: quite sure it was filed somewhere, right? --- .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 33 +++++++++++++++++-- .../Messages/MaximizeForDialogMessage.cs | 14 ++++++++ .../Pages/ShellPage.xaml.cs | 21 +++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/MaximizeForDialogMessage.cs diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 363cb1aada..1931a7f2b2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -57,6 +57,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient, IRecipient, IRecipient, + IRecipient, IDisposable, IHostWindow { @@ -112,6 +113,15 @@ public sealed partial class MainWindow : WindowEx, private bool _preventHideWhenDeactivated; private bool _isLoadedFromDock; + // While a modal dialog (e.g. a confirmation) is showing, the card is forced to fill the + // whole window so the dialog — which renders in the window's popup layer and is clipped to + // the card's HWND region — isn't cut off. Cleared when the dialog closes. + private bool _dialogFullExpandActive; + + // The most recent expand/collapse request, remembered so the correct compact layout can be + // restored once a dialog-driven full expansion ends. + private bool _lastExpandRequested; + private DevRibbon? _devRibbon; private MainWindowViewModel ViewModel { get; } @@ -184,6 +194,7 @@ public sealed partial class MainWindow : WindowEx, WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); + WeakReferenceMessenger.Default.Register(this); // Hide our titlebar. // We need to both ExtendsContentIntoTitleBar, then set the height to Collapsed @@ -1918,16 +1929,32 @@ public sealed partial class MainWindow : WindowEx, this.DispatcherQueue.TryEnqueue(() => HandleExpandCompactOnUiThread(message.Expanded)); } + public void Receive(MaximizeForDialogMessage message) + { + this.DispatcherQueue.TryEnqueue(() => + { + _dialogFullExpandActive = message.Maximize; + + // Re-run with the last requested state: when maximizing this fills the window; when + // the dialog closes it restores the normal compact/expanded layout. + HandleExpandCompactOnUiThread(_lastExpandRequested); + }); + } + // The HWND is already as large as it will ever need to be (and it's transparent), so // instead of resizing the window we simply shrink or grow the visible card inside it. private void HandleExpandCompactOnUiThread(bool expanded) { + _lastExpandRequested = expanded; + var settings = App.Current.Services.GetRequiredService().Settings; - if (!settings.CompactMode) + var preventCompactMode = _dialogFullExpandActive || !settings.CompactMode; + if (preventCompactMode) { - // When compact mode is off the card is always static and fills the entire window, - // regardless of how much content is currently displayed. + // When compact mode is off, or a dialog is active, the card is + // always static and fills the entire window, regardless of how much + // content is currently displayed. RootElement.SetCardStretch(true); RootElement.SetCardMaxHeight(double.PositiveInfinity); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/MaximizeForDialogMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/MaximizeForDialogMessage.cs new file mode 100644 index 0000000000..f1cf35ec54 --- /dev/null +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Messages/MaximizeForDialogMessage.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.CmdPal.UI.Messages; + +/// +/// Asks the host window to temporarily make the visible card fill the entire window, +/// ignoring the compact-mode clamps, so a modal dialog (e.g. a confirmation) isn't clipped +/// by the card's HWND region. Sent with = while +/// the dialog is showing and once it closes to restore the normal +/// compact/expanded behavior. +/// +public record MaximizeForDialogMessage(bool Maximize); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index 1a02cd964a..822667d61e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -361,7 +361,26 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, // }; } - var result = await dialog.ShowAsync(); + // In compact mode the palette may be collapsed to just the search box. The confirmation + // dialog renders in the host window's popup layer, which is clipped to the card's HWND + // region, so merely expanding our own content isn't enough - the card must fill the whole + // window or the dialog is clipped. Ask the host window to maximize the card while the + // dialog is up (and expand our own content to match), then restore the normal compact + // behavior once it closes. + WeakReferenceMessenger.Default.Send(new MaximizeForDialogMessage(true)); + HandleExpandCompactOnUiThread(true); + + ContentDialogResult result; + try + { + result = await dialog.ShowAsync(); + } + finally + { + WeakReferenceMessenger.Default.Send(new MaximizeForDialogMessage(false)); + UpdateCompactModeForCurrentPage(); + } + if (result == ContentDialogResult.Primary) { var performMessage = new PerformCommandMessage(vm);