From 49339cc2b9f756a1ab6884353723dfb54255f386 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 08:50:45 +0000 Subject: [PATCH 1/3] Initial plan From 2bb9c66ae556185057f188921104c4944e584332 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:25:29 +0000 Subject: [PATCH 2/3] Fix ZoomIt Record hotkey not capturing Alt modifier key When Alt is the only modifier in the Record toggle hotkey, XOR-ing it away for the RECORD_WINDOW_HOTKEY results in a zero modifier, causing any unmodified key press to trigger window recording. Fix: Skip registering RECORD_CROP_HOTKEY and RECORD_WINDOW_HOTKEY when the XOR operation would produce zero modifiers (i.e., when the single modifier matches the toggled one). Apply this check in all 4 hotkey registration locations in Zoomit.cpp. Also update ZoomItViewModel.cs to return null for RecordToggleKeyCrop and RecordToggleKeyWindow when the derived hotkey would have no modifier keys, preventing display of an invalid shortcut in settings UI. Agent-Logs-Url: https://github.com/microsoft/PowerToys/sessions/70c535fc-8c23-4415-bbbb-029432a5eeb3 Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com> --- src/modules/ZoomIt/ZoomIt/Zoomit.cpp | 20 +++++++++++-------- .../Settings.UI/ViewModels/ZoomItViewModel.cs | 16 +++++++++++++-- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/modules/ZoomIt/ZoomIt/Zoomit.cpp b/src/modules/ZoomIt/ZoomIt/Zoomit.cpp index 475e434d03bb..9fad516c6faf 100644 --- a/src/modules/ZoomIt/ZoomIt/Zoomit.cpp +++ b/src/modules/ZoomIt/ZoomIt/Zoomit.cpp @@ -3310,8 +3310,12 @@ void RegisterAllHotkeys(HWND hWnd) } if (g_RecordToggleKey) { registerHotkey( RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); - registerHotkey( RECORD_CROP_HOTKEY, ( g_RecordToggleMod ^ MOD_SHIFT ) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); - registerHotkey( RECORD_WINDOW_HOTKEY, ( g_RecordToggleMod ^ MOD_ALT ) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); + if ( g_RecordToggleMod ^ MOD_SHIFT ) { + registerHotkey( RECORD_CROP_HOTKEY, ( g_RecordToggleMod ^ MOD_SHIFT ) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); + } + if ( g_RecordToggleMod ^ MOD_ALT ) { + registerHotkey( RECORD_WINDOW_HOTKEY, ( g_RecordToggleMod ^ MOD_ALT ) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); + } } // Note: COPY_IMAGE_HOTKEY, COPY_CROP_HOTKEY (Ctrl+C, Ctrl+Shift+C) and @@ -5309,8 +5313,8 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message, } else if( newRecordToggleKey && (!RegisterHotKey(GetParent(hDlg), RECORD_HOTKEY, newRecordToggleMod | MOD_NOREPEAT, newRecordToggleKey & 0xFF) || - !RegisterHotKey(GetParent(hDlg), RECORD_CROP_HOTKEY, (newRecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, newRecordToggleKey & 0xFF) || - !RegisterHotKey(GetParent(hDlg), RECORD_WINDOW_HOTKEY, (newRecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, newRecordToggleKey & 0xFF))) { + ((newRecordToggleMod ^ MOD_SHIFT) && !RegisterHotKey(GetParent(hDlg), RECORD_CROP_HOTKEY, (newRecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, newRecordToggleKey & 0xFF)) || + ((newRecordToggleMod ^ MOD_ALT) && !RegisterHotKey(GetParent(hDlg), RECORD_WINDOW_HOTKEY, (newRecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, newRecordToggleKey & 0xFF)))) { MessageBox(hDlg, L"The specified record hotkey is already in use.\nSelect a different record hotkey.", APPNAME, MB_ICONERROR); @@ -7299,8 +7303,8 @@ LRESULT APIENTRY MainWndProc( } else if (g_RecordToggleKey && (!RegisterHotKey(hWnd, RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || - !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, (g_RecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || - !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, (g_RecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF))) { + ((g_RecordToggleMod ^ MOD_SHIFT) && !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, (g_RecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) || + ((g_RecordToggleMod ^ MOD_ALT) && !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, (g_RecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)))) { MessageBox(hWnd, L"The specified record hotkey is already in use.\nSelect a different record hotkey.", APPNAME, MB_ICONERROR); @@ -9876,8 +9880,8 @@ LRESULT APIENTRY MainWndProc( if (g_RecordToggleKey) { if (!RegisterHotKey(hWnd, RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || - !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, (g_RecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || - !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, (g_RecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) + ((g_RecordToggleMod ^ MOD_SHIFT) && !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, (g_RecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) || + ((g_RecordToggleMod ^ MOD_ALT) && !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, (g_RecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF))) { if(!g_StartedByPowerToys) { diff --git a/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs index 946daf6fb77b..aaf74fe3a96e 100644 --- a/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs @@ -303,7 +303,13 @@ public HotkeySettings RecordToggleKeyCrop return null; } - // XOR with Shift: if Shift is present, remove it; if absent, add it + // XOR with Shift: if Shift is present, remove it; if absent, add it. + // If the result would have no modifier keys, return null to avoid registering a key-only hotkey. + if (baseKey.Shift && !baseKey.Win && !baseKey.Ctrl && !baseKey.Alt) + { + return null; + } + return new HotkeySettings( baseKey.Win, baseKey.Ctrl, @@ -323,7 +329,13 @@ public HotkeySettings RecordToggleKeyWindow return null; } - // XOR with Alt: if Alt is present, remove it; if absent, add it + // XOR with Alt: if Alt is present, remove it; if absent, add it. + // If the result would have no modifier keys, return null to avoid registering a key-only hotkey. + if (baseKey.Alt && !baseKey.Win && !baseKey.Ctrl && !baseKey.Shift) + { + return null; + } + return new HotkeySettings( baseKey.Win, baseKey.Ctrl, From c7a62d6ead6f0996686e3685a175a1cbd9e1e1d8 Mon Sep 17 00:00:00 2001 From: "Muyuan Li (from Dev Box)" Date: Fri, 8 May 2026 11:30:01 +0800 Subject: [PATCH 3/3] Address Copilot review comments (PR #47388) - Reword C# comments: clarify null return prevents UI display, not hotkey registration - Extract XOR expressions into named locals (cropMod/windowMod) with explicit != 0 checks across all 4 hotkey registration sites in Zoomit.cpp for readability Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/modules/ZoomIt/ZoomIt/Zoomit.cpp | 53 +++++++++++-------- .../Settings.UI/ViewModels/ZoomItViewModel.cs | 4 +- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/modules/ZoomIt/ZoomIt/Zoomit.cpp b/src/modules/ZoomIt/ZoomIt/Zoomit.cpp index 9fad516c6faf..75964b2eac4f 100644 --- a/src/modules/ZoomIt/ZoomIt/Zoomit.cpp +++ b/src/modules/ZoomIt/ZoomIt/Zoomit.cpp @@ -3310,11 +3310,13 @@ void RegisterAllHotkeys(HWND hWnd) } if (g_RecordToggleKey) { registerHotkey( RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); - if ( g_RecordToggleMod ^ MOD_SHIFT ) { - registerHotkey( RECORD_CROP_HOTKEY, ( g_RecordToggleMod ^ MOD_SHIFT ) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); + UINT cropMod = g_RecordToggleMod ^ MOD_SHIFT; + UINT windowMod = g_RecordToggleMod ^ MOD_ALT; + if ( cropMod != 0 ) { + registerHotkey( RECORD_CROP_HOTKEY, cropMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); } - if ( g_RecordToggleMod ^ MOD_ALT ) { - registerHotkey( RECORD_WINDOW_HOTKEY, ( g_RecordToggleMod ^ MOD_ALT ) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); + if ( windowMod != 0 ) { + registerHotkey( RECORD_WINDOW_HOTKEY, windowMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF ); } } @@ -5311,16 +5313,18 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message, break; } - else if( newRecordToggleKey && - (!RegisterHotKey(GetParent(hDlg), RECORD_HOTKEY, newRecordToggleMod | MOD_NOREPEAT, newRecordToggleKey & 0xFF) || - ((newRecordToggleMod ^ MOD_SHIFT) && !RegisterHotKey(GetParent(hDlg), RECORD_CROP_HOTKEY, (newRecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, newRecordToggleKey & 0xFF)) || - ((newRecordToggleMod ^ MOD_ALT) && !RegisterHotKey(GetParent(hDlg), RECORD_WINDOW_HOTKEY, (newRecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, newRecordToggleKey & 0xFF)))) { - - MessageBox(hDlg, L"The specified record hotkey is already in use.\nSelect a different record hotkey.", - APPNAME, MB_ICONERROR); - UnregisterAllHotkeys(GetParent(hDlg)); - break; + else if( newRecordToggleKey ) { + UINT cropMod = newRecordToggleMod ^ MOD_SHIFT; + UINT windowMod = newRecordToggleMod ^ MOD_ALT; + if (!RegisterHotKey(GetParent(hDlg), RECORD_HOTKEY, newRecordToggleMod | MOD_NOREPEAT, newRecordToggleKey & 0xFF) || + (cropMod != 0 && !RegisterHotKey(GetParent(hDlg), RECORD_CROP_HOTKEY, cropMod | MOD_NOREPEAT, newRecordToggleKey & 0xFF)) || + (windowMod != 0 && !RegisterHotKey(GetParent(hDlg), RECORD_WINDOW_HOTKEY, windowMod | MOD_NOREPEAT, newRecordToggleKey & 0xFF))) { + MessageBox(hDlg, L"The specified record hotkey is already in use.\nSelect a different record hotkey.", + APPNAME, MB_ICONERROR); + UnregisterAllHotkeys(GetParent(hDlg)); + break; + } } else { g_BreakTimeout = newTimeout; @@ -7301,14 +7305,17 @@ LRESULT APIENTRY MainWndProc( showOptions = TRUE; } - else if (g_RecordToggleKey && - (!RegisterHotKey(hWnd, RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || - ((g_RecordToggleMod ^ MOD_SHIFT) && !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, (g_RecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) || - ((g_RecordToggleMod ^ MOD_ALT) && !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, (g_RecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)))) { + else if (g_RecordToggleKey) { + UINT cropMod = g_RecordToggleMod ^ MOD_SHIFT; + UINT windowMod = g_RecordToggleMod ^ MOD_ALT; + if (!RegisterHotKey(hWnd, RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || + (cropMod != 0 && !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, cropMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) || + (windowMod != 0 && !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, windowMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF))) { - MessageBox(hWnd, L"The specified record hotkey is already in use.\nSelect a different record hotkey.", - APPNAME, MB_ICONERROR); - showOptions = TRUE; + MessageBox(hWnd, L"The specified record hotkey is already in use.\nSelect a different record hotkey.", + APPNAME, MB_ICONERROR); + showOptions = TRUE; + } } if( showOptions ) { @@ -9879,9 +9886,11 @@ LRESULT APIENTRY MainWndProc( } if (g_RecordToggleKey) { + UINT cropMod = g_RecordToggleMod ^ MOD_SHIFT; + UINT windowMod = g_RecordToggleMod ^ MOD_ALT; if (!RegisterHotKey(hWnd, RECORD_HOTKEY, g_RecordToggleMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF) || - ((g_RecordToggleMod ^ MOD_SHIFT) && !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, (g_RecordToggleMod ^ MOD_SHIFT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) || - ((g_RecordToggleMod ^ MOD_ALT) && !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, (g_RecordToggleMod ^ MOD_ALT) | MOD_NOREPEAT, g_RecordToggleKey & 0xFF))) + (cropMod != 0 && !RegisterHotKey(hWnd, RECORD_CROP_HOTKEY, cropMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF)) || + (windowMod != 0 && !RegisterHotKey(hWnd, RECORD_WINDOW_HOTKEY, windowMod | MOD_NOREPEAT, g_RecordToggleKey & 0xFF))) { if(!g_StartedByPowerToys) { diff --git a/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs index aaf74fe3a96e..dabd312dfb9c 100644 --- a/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/ZoomItViewModel.cs @@ -304,7 +304,7 @@ public HotkeySettings RecordToggleKeyCrop } // XOR with Shift: if Shift is present, remove it; if absent, add it. - // If the result would have no modifier keys, return null to avoid registering a key-only hotkey. + // If the result would have no modifier keys, return null to avoid displaying a bare-key shortcut label. if (baseKey.Shift && !baseKey.Win && !baseKey.Ctrl && !baseKey.Alt) { return null; @@ -330,7 +330,7 @@ public HotkeySettings RecordToggleKeyWindow } // XOR with Alt: if Alt is present, remove it; if absent, add it. - // If the result would have no modifier keys, return null to avoid registering a key-only hotkey. + // If the result would have no modifier keys, return null to avoid displaying a bare-key shortcut label. if (baseKey.Alt && !baseKey.Win && !baseKey.Ctrl && !baseKey.Shift) { return null;