diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml index 74c736b471..ee11551c5a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml @@ -31,6 +31,6 @@ TintIntensity="{x:Bind ViewModel.BackgroundImageTintIntensity, Mode=OneWay}" Visibility="{x:Bind ViewModel.ShowBackgroundImage, Mode=OneWay}" /> - + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 10139a94d1..76d85794ba 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -54,7 +54,8 @@ public sealed partial class MainWindow : WindowEx, IRecipient, IRecipient, IRecipient, - IDisposable + IDisposable, + IHostWindow { [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Stylistically, window messages are WM_")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Stylistically, window messages are WM_")] @@ -92,6 +93,8 @@ public sealed partial class MainWindow : WindowEx, private MainWindowViewModel ViewModel { get; } + public bool IsVisibleToUser { get; private set; } = true; + public MainWindow() { InitializeComponent(); @@ -700,17 +703,14 @@ public sealed partial class MainWindow : WindowEx, { Logger.LogWarning($"DWM cloaking of the main window failed. HRESULT: {hr.Value}."); } + else + { + IsVisibleToUser = false; + } wasCloaked = hr.Succeeded; } - if (wasCloaked) - { - // Because we're only cloaking the window, bury it at the bottom in case something can - // see it - e.g. some accessibility helper (note: this also removes the top-most status). - PInvoke.SetWindowPos(_hwnd, HWND.HWND_BOTTOM, 0, 0, 0, 0, SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE); - } - return wasCloaked; } @@ -720,6 +720,7 @@ public sealed partial class MainWindow : WindowEx, { BOOL value = false; PInvoke.DwmSetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAK, &value, (uint)sizeof(BOOL)); + IsVisibleToUser = true; } } 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 9dd7b77b0e..210592c1ac 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -13,6 +13,7 @@ using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.UI.Events; using Microsoft.CmdPal.UI.Helpers; using Microsoft.CmdPal.UI.Messages; +using Microsoft.CmdPal.UI.Services; using Microsoft.CmdPal.UI.Settings; using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CommandPalette.Extensions; @@ -72,6 +73,8 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, public event PropertyChangedEventHandler? PropertyChanged; + public IHostWindow? HostWindow { get; set; } + public ShellPage() { this.InitializeComponent(); @@ -435,7 +438,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, if (!RootFrame.CanGoBack) { - ViewModel.GoHome(); + ViewModel.GoHome(withAnimation, focusSearch); } if (focusSearch) @@ -531,6 +534,11 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, if (shouldSearchBoxBeVisible || page is not ContentPage) { + if (HostWindow?.IsVisibleToUser != true) + { + return; + } + ViewModel.IsSearchBoxVisible = shouldSearchBoxBeVisible; SearchBox.Focus(FocusState.Programmatic); SearchBox.SelectSearch(); @@ -547,6 +555,11 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, try { + if (HostWindow?.IsVisibleToUser != true) + { + return; + } + await page.DispatcherQueue.EnqueueAsync( async () => { @@ -556,6 +569,11 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, { token.ThrowIfCancellationRequested(); + if (HostWindow?.IsVisibleToUser != true) + { + break; + } + if (FocusManager.FindFirstFocusableElement(page) is FrameworkElement frameworkElement) { var set = frameworkElement.Focus(FocusState.Programmatic); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Services/IHostWindow.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Services/IHostWindow.cs new file mode 100644 index 0000000000..59e5f8f95a --- /dev/null +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Services/IHostWindow.cs @@ -0,0 +1,16 @@ +// 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.Services; + +/// +/// Represents abstract host window functionality. +/// +public interface IHostWindow +{ + /// + /// Gets a value indicating whether the window is visible to the user, taking account not only window visibility but also cloaking. + /// + bool IsVisibleToUser { get; } +}