diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp index 50f5166940..46958bfc14 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp @@ -139,6 +139,14 @@ namespace KeyboardEventHandlers if (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, it->first, target); + + // If a Ctrl/Alt/Shift key is remapped to a non-modifier key, reset the modifier state to prevent the injected key from being delivered as WM_SYSKEYDOWN instead of WM_KEYDOWN + if (Helpers::IsModifierKey(it->first) && !Helpers::IsModifierKey(target) && target != VK_CAPITAL && !(it->first == VK_LWIN || it->first == VK_RWIN || it->first == CommonSharedConstants::VK_WIN_BOTH)) + { + std::vector suppressList; + Helpers::SetKeyEvent(suppressList, INPUT_KEYBOARD, static_cast(it->first), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); + ii.SendVirtualInput(suppressList); + } } if (remapToKey) diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp index de6597ae5c..efb03aae2e 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp @@ -226,6 +226,27 @@ namespace RemappingLogicTests Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); } + // Test if SendVirtualInput is sent exactly once with the suppress flag when a Ctrl/Alt/Shift key is remapped to a non-modifier key + TEST_METHOD (HandleSingleKeyRemapEvent_ShouldSendVirtualInputWithSuppressFlagExactlyOnce_WhenCtrlAltShiftIsMappedToNonModifierKey) + { + mockedInputHandler.SetSendVirtualInputTestHandler([](LowlevelKeyboardEvent* data) { + if (data->lParam->dwExtraInfo == KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG) + return true; + else + return false; + }); + + testState.AddSingleKeyRemap(VK_LMENU, (DWORD)VK_BACK); + + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LMENU } }, + }; + + mockedInputHandler.SendVirtualInput(inputs); + + Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); + } + // Test if correct keyboard states are set for a single key to two key shortcut remap TEST_METHOD (RemappedKeyToTwoKeyShortcut_ShouldSetTargetKeyState_OnKeyEvent) {