From 0b7d780980ce342dc76ea81977b2c705f056628c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pol=C3=A1=C5=A1ek?= Date: Mon, 30 Mar 2026 04:39:11 +0200 Subject: [PATCH] CmdPal: improve full-screen detection (#45891) ## Summary of the Pull Request This PR improves fullscreen detection for the Command Palette activation shortcut, adds a separate "busy state" guard, surfaces live notification state diagnostics in Settings, and provides an opt-in rapid-press breakthrough to bypass suppression. The existing fullscreen guard lumped D3D fullscreen, presentation mode, and the heuristic QUNS_BUSY state into a single check. This made it impossible to opt into guarding against only true fullscreen while ignoring false positives from apps like NVIDIA overlay. This PR splits those concerns, adds diagnostic visibility, and gives users an escape hatch. The problem with the detection is that QUNS_RUNNING_D3D_FULL_SCREEN is intended for exclusive D3D full-screen apps (some games), but it overlaps with QUNS_BUSY for other games and apps. - Splits the fullscreen guard into two separate settings - IsWindowFullscreen() now only checks QUNS_RUNNING_D3D_FULL_SCREEN and QUNS_PRESENTATION_MODE - New IsAppBusy() handles the heuristic QUNS_BUSY state separately - New IgnoreShortcutWhenBusy setting (off by default) so users aren't silently blocked by false positives - Migrates from hand-written P/Invoke (NativeMethods.cs, deleted) to CsWin32-generated bindings - Adds a live InfoBar in Activation settings when the shortcut is limited - Polls SHQueryUserNotificationState every 2 seconds via DispatcherTimer - Displays a warning describing which state is active (D3D fullscreen, presentation mode, or busy) - New GetUserNotificationState() in WindowHelper exposes the raw state for the UI - Attributes QUNS_BUSY to known trigger apps - New FindVisibleTriggerApps() enumerates windows by class name and process name against a known-app list - When NVIDIA Overlay (or other known apps) are detected, the InfoBar message names the likely culprit - Adds an opt-in rapid-press breakthrough to bypass suppression - New AllowBreakthroughShortcut setting (off by default) - Pressing the activation shortcut 3 times within 2 seconds overrides the guard - The suppression is automatically bypassed when the Command Palette is visible - to allow dismissal ## Pictures? Pictures! image ## PR Checklist - [x] Closes: #45548 - [x] Closes: #41225 - [x] Closes: #42716 - [x] Closes: #45875 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --- .github/actions/spell-check/allow/names.txt | 1 + .../SettingsModel.cs | 6 +- .../SettingsViewModel.cs | 18 +++ .../Helpers/NativeMethods.cs | 26 ---- .../Helpers/WindowHelper.cs | 117 ++++++++++++++-- .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 64 +++++++-- .../Microsoft.CmdPal.UI/NativeMethods.txt | 4 + .../Settings/GeneralPage.xaml | 13 ++ .../Settings/GeneralPage.xaml.cs | 129 +++++++++++++++++- .../Strings/en-us/Resources.resw | 29 +++- 10 files changed, 353 insertions(+), 54 deletions(-) delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/NativeMethods.cs diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt index bea601b3d1..45bdbcd04a 100644 --- a/.github/actions/spell-check/allow/names.txt +++ b/.github/actions/spell-check/allow/names.txt @@ -223,6 +223,7 @@ Moq mozilla mspaint Newtonsoft +NVIDIA onenote openai Quickime diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs index cb08a22dee..8e43235240 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs @@ -31,7 +31,11 @@ public record SettingsModel public bool ShowSystemTrayIcon { get; init; } = true; - public bool IgnoreShortcutWhenFullscreen { get; init; } + public bool IgnoreShortcutWhenFullscreen { get; init; } = true; + + public bool IgnoreShortcutWhenBusy { get; init; } + + public bool AllowBreakthroughShortcut { get; init; } public bool AllowExternalReload { get; init; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs index 60baa76750..4c43cc7173 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs @@ -137,6 +137,24 @@ public partial class SettingsViewModel : INotifyPropertyChanged } } + public bool IgnoreShortcutWhenBusy + { + get => _settingsService.Settings.IgnoreShortcutWhenBusy; + set + { + _settingsService.UpdateSettings(s => s with { IgnoreShortcutWhenBusy = value }); + } + } + + public bool AllowBreakthroughShortcut + { + get => _settingsService.Settings.AllowBreakthroughShortcut; + set + { + _settingsService.UpdateSettings(s => s with { AllowBreakthroughShortcut = value }); + } + } + public bool DisableAnimations { get => _settingsService.Settings.DisableAnimations; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/NativeMethods.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/NativeMethods.cs deleted file mode 100644 index a3227ca77c..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/NativeMethods.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -using System.Runtime.InteropServices; -using System.Security; - -namespace Microsoft.CmdPal.UI.Helpers; - -[SuppressUnmanagedCodeSecurity] -internal static class NativeMethods -{ - [DllImport("shell32.dll")] - public static extern int SHQueryUserNotificationState(out UserNotificationState state); -} - -internal enum UserNotificationState : int -{ - QUNS_NOT_PRESENT = 1, - QUNS_BUSY, - QUNS_RUNNING_D3D_FULL_SCREEN, - QUNS_PRESENTATION_MODE, - QUNS_ACCEPTS_NOTIFICATIONS, - QUNS_QUIET_TIME, - QUNS_APP, -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs index deddf13d5d..c36282f6df 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/WindowHelper.cs @@ -1,28 +1,115 @@ -// Copyright (c) Microsoft Corporation +// 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. -using System.Runtime.InteropServices; +using System.Diagnostics; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.UI.Shell; namespace Microsoft.CmdPal.UI.Helpers; internal sealed partial class WindowHelper { - public static bool IsWindowFullscreen() + /// + /// Known applications whose visible windows can trigger a QUNS_BUSY state + /// even when the user is not actually in a fullscreen/presentation scenario. + /// + internal sealed record KnownTriggerApp(string ProcessName, string WindowClassName, string DisplayName); + + internal static readonly KnownTriggerApp[] KnownTriggerWindowClasses = + [ + new("NVIDIA overlay", "CEF-OSC-WIDGET", "NVIDIA Overlay"), + ]; + + public static QUERY_USER_NOTIFICATION_STATE? GetUserNotificationState() { - UserNotificationState state; - // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ne-shellapi-query_user_notification_state - if (Marshal.GetExceptionForHR(NativeMethods.SHQueryUserNotificationState(out state)) is null) - { - if (state == UserNotificationState.QUNS_RUNNING_D3D_FULL_SCREEN || - state == UserNotificationState.QUNS_BUSY || - state == UserNotificationState.QUNS_PRESENTATION_MODE) - { - return true; - } - } + return PInvoke.SHQueryUserNotificationState(out var state).Succeeded ? state : null; + } - return false; + internal static UserNotificationFlags GetUserNotificationFlags() + { + return GetUserNotificationFlags(GetUserNotificationState()); + } + + internal static UserNotificationFlags GetUserNotificationFlags(QUERY_USER_NOTIFICATION_STATE? state) + { + return new UserNotificationFlags( + IsRunningD3DFullScreen: state is QUERY_USER_NOTIFICATION_STATE.QUNS_RUNNING_D3D_FULL_SCREEN, + IsPresentationMode: state is QUERY_USER_NOTIFICATION_STATE.QUNS_PRESENTATION_MODE, + IsBusy: state is QUERY_USER_NOTIFICATION_STATE.QUNS_BUSY); + } + + /// + /// Returns the display names of known trigger apps that currently have visible + /// windows matching their expected window class and process name. + /// + public static unsafe List FindVisibleTriggerApps() + { + var detected = new HashSet(StringComparer.Ordinal); + + PInvoke.EnumWindows( + (HWND hWnd, LPARAM lParam) => + { + if (!PInvoke.IsWindowVisible(hWnd)) + { + return true; // continue + } + + var className = GetWindowClassName(hWnd); + if (className is null) + { + return true; + } + + foreach (var app in KnownTriggerWindowClasses) + { + if (!string.Equals(className, app.WindowClassName, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + // Window class matches — verify the process name. + uint pid; + if (PInvoke.GetWindowThreadProcessId(hWnd, &pid) == 0) + { + continue; + } + + try + { + using var process = Process.GetProcessById((int)pid); + if (string.Equals(process.ProcessName, app.ProcessName, StringComparison.OrdinalIgnoreCase)) + { + detected.Add(app.DisplayName); + } + } + catch + { + // Process may have exited between enumeration and lookup. + } + } + + return true; + }, + 0); + + return [.. detected]; + } + + private static unsafe string? GetWindowClassName(HWND hWnd) + { + const int maxLength = 256; + fixed (char* buffer = new char[maxLength]) + { + var length = PInvoke.GetClassName(hWnd, buffer, maxLength); + return length > 0 ? new string(buffer, 0, length) : null; + } + } + + internal readonly record struct UserNotificationFlags(bool IsRunningD3DFullScreen, bool IsPresentationMode, bool IsBusy) + { + public bool IsFullscreenState => IsRunningD3DFullScreen || IsPresentationMode; } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 780c6ca846..0ebe003d62 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -73,7 +73,11 @@ public sealed partial class MainWindow : WindowEx, private readonly HiddenOwnerWindowBehavior _hiddenOwnerBehavior = new(); private readonly IThemeService _themeService; private readonly WindowThemeSynchronizer _windowThemeSynchronizer; + private readonly List _breakthroughTimestamps = []; + private bool _ignoreHotKeyWhenFullScreen = true; + private bool _ignoreHotKeyWhenBusy; + private bool _allowBreakthroughShortcut; private bool _suppressDpiChange; private bool _themeServiceInitialized; @@ -369,6 +373,8 @@ public sealed partial class MainWindow : WindowEx, App.Current.Services.GetService()!.SetupTrayIcon(settings.ShowSystemTrayIcon); _ignoreHotKeyWhenFullScreen = settings.IgnoreShortcutWhenFullscreen; + _ignoreHotKeyWhenBusy = settings.IgnoreShortcutWhenBusy; + _allowBreakthroughShortcut = settings.AllowBreakthroughShortcut; _autoGoHomeInterval = settings.AutoGoHomeInterval; _autoGoHomeTimer.Interval = _autoGoHomeInterval; @@ -1208,10 +1214,25 @@ public sealed partial class MainWindow : WindowEx, private void HandleSummon(string commandId) { - if (_ignoreHotKeyWhenFullScreen) + var isRootHotkey = string.IsNullOrEmpty(commandId); + if (isRootHotkey && IsPaletteVisibleToUser()) { - // If we're in full screen mode, ignore the hotkey - if (WindowHelper.IsWindowFullscreen()) + HandleSummonCore(commandId); + return; + } + + var notificationFlags = WindowHelper.GetUserNotificationFlags(); + var shouldSuppress = + (_ignoreHotKeyWhenFullScreen && notificationFlags.IsFullscreenState) || + (_ignoreHotKeyWhenBusy && notificationFlags.IsBusy); + + if (shouldSuppress) + { + if (_allowBreakthroughShortcut && IsBreakthroughTriggered()) + { + // Rapid-press breakthrough: let it through + } + else { return; } @@ -1220,12 +1241,9 @@ public sealed partial class MainWindow : WindowEx, HandleSummonCore(commandId); } - private void HandleSummonCore(string commandId) + private bool IsPaletteVisibleToUser() { - var isRootHotkey = string.IsNullOrEmpty(commandId); - PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey)); - - var isVisible = this.Visible; + var isVisible = Visible; unsafe { @@ -1240,6 +1258,36 @@ public sealed partial class MainWindow : WindowEx, } } + return isVisible; + } + + private bool IsBreakthroughTriggered() + { + const int requiredPresses = 3; + var windowTicks = 2 * Stopwatch.Frequency; // 2 seconds + var now = Stopwatch.GetTimestamp(); + + _breakthroughTimestamps.Add(now); + + // Prune timestamps outside the window + _breakthroughTimestamps.RemoveAll(t => now - t > windowTicks); + + if (_breakthroughTimestamps.Count >= requiredPresses) + { + _breakthroughTimestamps.Clear(); + return true; + } + + return false; + } + + private void HandleSummonCore(string commandId) + { + var isRootHotkey = string.IsNullOrEmpty(commandId); + PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey)); + + var isVisible = IsPaletteVisibleToUser(); + // Note to future us: the wParam will have the index of the hotkey we registered. // We can use that in the future to differentiate the hotkeys we've pressed // so that we can bind hotkeys to individual commands diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt b/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt index 7d0a2c71f3..426d9a2ffb 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt @@ -112,3 +112,7 @@ AttachThreadInput GetWindowPlacement WINDOWPLACEMENT WM_DPICHANGED + +QUERY_USER_NOTIFICATION_STATE +EnumWindows +IsWindowVisible diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml index 04d9c9003f..5e6ccd70fd 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml @@ -55,7 +55,20 @@ + + + + + + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml.cs index cc78a00f56..a14e8573b2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml.cs @@ -2,22 +2,32 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.ComponentModel; using System.Globalization; using Microsoft.CmdPal.Common.Services; using Microsoft.CmdPal.UI.Helpers; using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels.Services; using Microsoft.Extensions.DependencyInjection; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Windows.Win32.UI.Shell; namespace Microsoft.CmdPal.UI.Settings; -public sealed partial class GeneralPage : Page +public sealed partial class GeneralPage : Page, INotifyPropertyChanged { private readonly TaskScheduler _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); private readonly SettingsViewModel? viewModel; private readonly IApplicationInfoService _appInfoService; + private readonly ISettingsService _settingsService; + private readonly DispatcherTimer _notificationStateTimer; + + private bool _isNotificationStateSuppressing; + private string _notificationStateMessage = string.Empty; + + public event PropertyChangedEventHandler? PropertyChanged; public GeneralPage() { @@ -25,9 +35,41 @@ public sealed partial class GeneralPage : Page var topLevelCommandManager = App.Current.Services.GetService()!; var themeService = App.Current.Services.GetService()!; - var settingsService = App.Current.Services.GetRequiredService(); + _settingsService = App.Current.Services.GetRequiredService(); _appInfoService = App.Current.Services.GetRequiredService(); - viewModel = new SettingsViewModel(topLevelCommandManager, _mainTaskScheduler, themeService, settingsService); + viewModel = new SettingsViewModel(topLevelCommandManager, _mainTaskScheduler, themeService, _settingsService); + + _notificationStateTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) }; + _notificationStateTimer.Tick += NotificationStateTimer_Tick; + + Loaded += GeneralPage_Loaded; + Unloaded += GeneralPage_Unloaded; + } + + public bool IsNotificationStateSuppressing + { + get => _isNotificationStateSuppressing; + private set + { + if (_isNotificationStateSuppressing != value) + { + _isNotificationStateSuppressing = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsNotificationStateSuppressing))); + } + } + } + + public string NotificationStateMessage + { + get => _notificationStateMessage; + private set + { + if (_notificationStateMessage != value) + { + _notificationStateMessage = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NotificationStateMessage))); + } + } } public string ApplicationVersion @@ -39,4 +81,85 @@ public sealed partial class GeneralPage : Page return string.Format(CultureInfo.CurrentCulture, versionNo, version); } } + + private void GeneralPage_Loaded(object sender, RoutedEventArgs e) + { + _settingsService.SettingsChanged += SettingsService_SettingsChanged; + UpdateNotificationState(); + _notificationStateTimer.Start(); + } + + private void GeneralPage_Unloaded(object sender, RoutedEventArgs e) + { + _notificationStateTimer.Stop(); + _settingsService.SettingsChanged -= SettingsService_SettingsChanged; + } + + private void NotificationStateTimer_Tick(object? sender, object e) + { + UpdateNotificationState(); + } + + private void SettingsService_SettingsChanged(ISettingsService sender, SettingsModel settings) + { + if (DispatcherQueue.HasThreadAccess) + { + UpdateNotificationState(); + return; + } + + DispatcherQueue.TryEnqueue(UpdateNotificationState); + } + + private void UpdateNotificationState() + { + var state = WindowHelper.GetUserNotificationState(); + var notificationFlags = WindowHelper.GetUserNotificationFlags(state); + + if (IsActivationShortcutSuppressed( + notificationFlags.IsFullscreenState, + notificationFlags.IsBusy, + viewModel?.IgnoreShortcutWhenFullscreen == true, + viewModel?.IgnoreShortcutWhenBusy == true)) + { + var stateDescription = state switch + { + QUERY_USER_NOTIFICATION_STATE.QUNS_RUNNING_D3D_FULL_SCREEN => ResourceLoaderInstance.GetString("NotificationState_D3DFullScreen"), + QUERY_USER_NOTIFICATION_STATE.QUNS_PRESENTATION_MODE => ResourceLoaderInstance.GetString("NotificationState_PresentationMode"), + QUERY_USER_NOTIFICATION_STATE.QUNS_BUSY => ResourceLoaderInstance.GetString("NotificationState_Busy"), + _ => string.Empty, + }; + + var messageFormat = ResourceLoaderInstance.GetString("Settings_GeneralPage_NotificationState_InfoBar"); + var message = string.Format(CultureInfo.CurrentCulture, messageFormat, stateDescription); + + if (state is QUERY_USER_NOTIFICATION_STATE.QUNS_BUSY) + { + var triggerApps = WindowHelper.FindVisibleTriggerApps(); + if (triggerApps.Count > 0) + { + var triggerFormat = ResourceLoaderInstance.GetString("NotificationState_TriggerApps"); + message += " " + string.Format(CultureInfo.CurrentCulture, triggerFormat, string.Join(", ", triggerApps)); + } + } + + NotificationStateMessage = message; + IsNotificationStateSuppressing = true; + } + else + { + NotificationStateMessage = string.Empty; + IsNotificationStateSuppressing = false; + } + } + + private static bool IsActivationShortcutSuppressed( + bool isFullscreenState, + bool isBusyState, + bool ignoreShortcutWhenFullscreen, + bool ignoreShortcutWhenBusy) + { + return (ignoreShortcutWhenFullscreen && isFullscreenState) || + (ignoreShortcutWhenBusy && isBusyState); + } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw index 447e0502af..57df03fb19 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw @@ -347,6 +347,33 @@ Right-click to remove the key combination, thereby deactivating the shortcut. Preventing disruption of the program running in fullscreen by unintentional activation of shortcut + + Ignore shortcut when the system heuristically detects fullscreen + + + Windows may detect that a fullscreen application is running or Presentation Settings are applied. Some applications (such as NVIDIA overlay) can trigger this incorrectly, preventing the shortcut from working + + + Allow breakthrough with rapid shortcut presses + + + Press the activation shortcut 3 times within 2 seconds to bypass the fullscreen or busy state guard + + + Your activation shortcut might not work right now because {0}. + + + a full-screen app is running + + + presentation mode is on + + + Windows thinks a full-screen app or presentation is active + + + Likely caused by: {0}. + Highlight search on activate @@ -1125,4 +1152,4 @@ Right-click to remove the key combination, thereby deactivating the shortcut.Right Right section label in pin to dock dialog (code access, horizontal end) - \ No newline at end of file +