mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 17:42:45 +08:00
Add workaround for IME Caps Lock issue (#4123)
* Add workaround for Japanese IME Caps Lock issue * Changed tweak to reset modifier key rather than Caps Lock * added tests * Fixed test comment * Moved environment initialization in KBM tests to TEST_METHOD_INITIALIZE
This commit is contained in:
parent
f8cc129f04
commit
49cbcf01c6
@ -32,6 +32,12 @@ namespace KeyboardEventHandlers
|
||||
target = VK_LWIN;
|
||||
}
|
||||
|
||||
// If Ctrl/Alt/Shift is being remapped to Caps Lock, then reset the modifier key state to fix issues in certain IME keyboards where the IME shortcut gets invoked since it detects that the modifier and Caps Lock is pressed even though it is suppressed by the hook - More information at the GitHub issue https://github.com/microsoft/PowerToys/issues/3397
|
||||
if (target == VK_CAPITAL && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
|
||||
{
|
||||
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, it->first);
|
||||
}
|
||||
|
||||
if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
|
||||
{
|
||||
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)target, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
||||
@ -44,6 +50,13 @@ namespace KeyboardEventHandlers
|
||||
lock.unlock();
|
||||
UINT res = ii.SendVirtualInput(key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
|
||||
// If Caps Lock is being remapped to Ctrl/Alt/Shift, then reset the modifier key state to fix issues in certain IME keyboards where the IME shortcut gets invoked since it detects that the modifier and Caps Lock is pressed even though it is suppressed by the hook - More information at the GitHub issue https://github.com/microsoft/PowerToys/issues/3397
|
||||
if (it->first == VK_CAPITAL && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
|
||||
{
|
||||
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, target);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -611,10 +624,27 @@ namespace KeyboardEventHandlers
|
||||
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
|
||||
// Use the shortcut flag to ensure these are not intercepted by any remapped keys or shortcuts
|
||||
// Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts
|
||||
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, VK_NUMLOCK, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG);
|
||||
KeyboardManagerHelper::SetKeyEvent(keyEventList, 1, INPUT_KEYBOARD, VK_NUMLOCK, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG);
|
||||
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
}
|
||||
|
||||
// Function to ensure Ctrl/Shift/Alt modifier key state is not detected as pressed down by applications which detect keys at a lower level than hooks when it is remapped
|
||||
void ResetIfModifierKeyForLowerLevelKeyHandlers(InputInterface& ii, DWORD key)
|
||||
{
|
||||
// If the argument is either of the Ctrl/Shift/Alt modifier key codes
|
||||
if (KeyboardManagerHelper::IsModifierKey(key) && !(key == VK_LWIN || key == VK_RWIN || key == CommonSharedConstants::VK_WIN_BOTH))
|
||||
{
|
||||
int key_count = 1;
|
||||
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
|
||||
// Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts
|
||||
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)key, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG);
|
||||
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,4 +22,7 @@ namespace KeyboardEventHandlers
|
||||
|
||||
// Function to ensure Num Lock state does not change when it is suppressed by the low level hook
|
||||
void SetNumLockToPreviousState(InputInterface& ii);
|
||||
|
||||
// Function to ensure Ctrl/Shift/Alt modifier key state is not detected as pressed down by applications which detect keys at a lower level than hooks when it is remapped
|
||||
void ResetIfModifierKeyForLowerLevelKeyHandlers(InputInterface& ii, DWORD key);
|
||||
};
|
||||
|
@ -15,12 +15,15 @@ namespace KeyboardManagerRemapLogicTests
|
||||
TEST_CLASS (MockedInputSanityTests)
|
||||
{
|
||||
public:
|
||||
// Test if mocked input is working
|
||||
TEST_METHOD (MockedInput_ShouldSetKeyboardState_OnKeyEvent)
|
||||
TEST_METHOD_INITIALIZE(InitializeTestEnv)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
}
|
||||
|
||||
// Test if mocked input is working
|
||||
TEST_METHOD (MockedInput_ShouldSetKeyboardState_OnKeyEvent)
|
||||
{
|
||||
// Send key down and key up for A key (0x41) and check keyboard state both times
|
||||
const int nInputs = 1;
|
||||
INPUT input[nInputs] = {};
|
||||
@ -45,8 +48,7 @@ namespace KeyboardManagerRemapLogicTests
|
||||
TEST_CLASS (SingleKeyRemappingTests)
|
||||
{
|
||||
public:
|
||||
// Test if correct keyboard states are set for a single key remap
|
||||
TEST_METHOD (RemappedKey_ShouldSetTargetKeyState_OnKeyEvent)
|
||||
TEST_METHOD_INITIALIZE(InitializeTestEnv)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
@ -54,7 +56,11 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Set HandleSingleKeyRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleSingleKeyRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
}
|
||||
|
||||
// Test if correct keyboard states are set for a single key remap
|
||||
TEST_METHOD (RemappedKey_ShouldSetTargetKeyState_OnKeyEvent)
|
||||
{
|
||||
// Remap A to B
|
||||
testState.AddSingleKeyRemap(0x41, 0x42);
|
||||
const int nInputs = 1;
|
||||
@ -82,13 +88,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if key is suppressed if a key is disabled by single key remap
|
||||
TEST_METHOD (RemappedKeyDisabled_ShouldNotChangeKeyState_OnKeyEvent)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleSingleKeyRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleSingleKeyRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap A to 0x0 (disabled)
|
||||
testState.AddSingleKeyRemap(0x41, 0x0);
|
||||
const int nInputs = 1;
|
||||
@ -114,13 +113,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a remap to Win (Both) key
|
||||
TEST_METHOD (RemappedKeyToWinBoth_ShouldSetWinLeftKeyState_OnKeyEvent)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleSingleKeyRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleSingleKeyRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap A to Common Win key
|
||||
testState.AddSingleKeyRemap(0x41, CommonSharedConstants::VK_WIN_BOTH);
|
||||
const int nInputs = 1;
|
||||
@ -144,13 +136,64 @@ namespace KeyboardManagerRemapLogicTests
|
||||
Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false);
|
||||
Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false);
|
||||
}
|
||||
|
||||
// Test if SendVirtualInput is sent exactly once with the suppress flag when Caps Lock is remapped to Ctrl
|
||||
TEST_METHOD (HandleSingleKeyRemapEvent_ShouldSendVirutalInputWithSuppressFlagExactlyOnce_WhenCapsLockIsMappedToCtrlAltShift)
|
||||
{
|
||||
// Set sendvirtualinput call count condition to return true if the key event was sent with the suppress flag
|
||||
mockedInputHandler.SetSendVirtualInputTestHandler([](LowlevelKeyboardEvent* data) {
|
||||
if (data->lParam->dwExtraInfo == KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
});
|
||||
|
||||
// Remap Caps Lock to Ctrl
|
||||
testState.AddSingleKeyRemap(VK_CAPITAL, VK_CONTROL);
|
||||
const int nInputs = 1;
|
||||
|
||||
INPUT input[nInputs] = {};
|
||||
input[0].type = INPUT_KEYBOARD;
|
||||
input[0].ki.wVk = VK_CAPITAL;
|
||||
|
||||
// Send Caps Lock keydown
|
||||
mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT));
|
||||
|
||||
// SendVirtualInput should be called exactly once with the above condition
|
||||
Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount());
|
||||
}
|
||||
|
||||
// Test if SendVirtualInput is sent exactly once with the suppress flag when Ctrl is remapped to Caps Lock
|
||||
TEST_METHOD (HandleSingleKeyRemapEvent_ShouldSendVirutalInputWithSuppressFlagExactlyOnce_WhenCtrlAltShiftIsMappedToCapsLock)
|
||||
{
|
||||
// Set sendvirtualinput call count condition to return true if the key event was sent with the suppress flag
|
||||
mockedInputHandler.SetSendVirtualInputTestHandler([](LowlevelKeyboardEvent* data) {
|
||||
if (data->lParam->dwExtraInfo == KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
});
|
||||
|
||||
// Remap Ctrl to Caps Lock
|
||||
testState.AddSingleKeyRemap(VK_CONTROL, VK_CAPITAL);
|
||||
const int nInputs = 1;
|
||||
|
||||
INPUT input[nInputs] = {};
|
||||
input[0].type = INPUT_KEYBOARD;
|
||||
input[0].ki.wVk = VK_CONTROL;
|
||||
|
||||
// Send Ctrl keydown
|
||||
mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT));
|
||||
|
||||
// SendVirtualInput should be called exactly once with the above condition
|
||||
Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS (OSLevelShortcutRemappingTests)
|
||||
{
|
||||
public:
|
||||
// Test if correct keyboard states are set for a 2 key shortcut remap wih different modifiers key down
|
||||
TEST_METHOD (RemappedTwoKeyShortcutWithDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
TEST_METHOD_INITIALIZE(InitializeTestEnv)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
@ -158,7 +201,11 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
}
|
||||
|
||||
// Test if correct keyboard states are set for a 2 key shortcut remap wih different modifiers key down
|
||||
TEST_METHOD (RemappedTwoKeyShortcutWithDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Remap Ctrl+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -188,13 +235,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key shortcut remap with same modifiers key down
|
||||
TEST_METHOD (RemappedTwoKeyShortcutWithSameModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Ctrl+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -223,13 +263,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key shortcut remap with different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedTwoKeyShortcutWithDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -265,13 +298,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key shortcut remap with same modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedTwoKeyShortcutWithSameModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Ctrl+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -306,13 +332,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set when a 2 key shortcut is remapped, and a 3 key shortcut containing those keys is invoked - Ex: Ctrl+A remapped, but user presses Ctrl+Shift+A
|
||||
TEST_METHOD (RemappedTwoKeyShortcutInvokingAShortcutContainingThoseKeys_ShouldNotBeRemapped_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -345,13 +364,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key shortcut remap wih different modifiers key down
|
||||
TEST_METHOD (RemappedThreeKeyShortcutWithDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+LWin+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -387,13 +399,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key shortcut remap wih partially different modifiers key down
|
||||
TEST_METHOD (RemappedThreeKeyShortcutWithPartiallyDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+Ctrl+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -428,13 +433,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key shortcut remap with same modifiers key down
|
||||
TEST_METHOD (RemappedThreeKeyShortcutWithSameModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Ctrl+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -468,13 +466,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key shortcut remap with different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedThreeKeyShortcutWithDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+LWin+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -519,13 +510,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key shortcut remap with partially different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedThreeKeyShortcutWithPartiallyDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+Ctrl+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -569,13 +553,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key shortcut remap with same modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedThreeKeyShortcutWithSameModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Ctrl+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -618,13 +595,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set when a 3 key shortcut is remapped, and a 2 key shortcut which is a subset of those keys is invoked - Ex: Ctrl+Shift+A remapped, but user presses Ctrl+A
|
||||
TEST_METHOD (RemappedThreeKeyShortcutInvokingAShortcutSubsetOfThoseKeys_ShouldNotBeRemapped_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -655,13 +625,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key to 2 key shortcut remap with different modifiers key down
|
||||
TEST_METHOD (RemappedThreeKeyToTwoKeyShortcutWithDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -695,13 +658,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key to 2 key shortcut remap with partially different modifiers key down
|
||||
TEST_METHOD (RemappedThreeKeyToTwoKeyShortcutWithPartiallyDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Ctrl+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -734,13 +690,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key to 2 key shortcut remap with different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedThreeKeyToTwoKeyShortcutWithDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -783,13 +732,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 3 key to 2 key shortcut remap with partially different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedThreeKeyToTwoKeyShortcutWithPartiallyDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+Shift+A to Ctrl+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -831,13 +773,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key to 3 key shortcut remap with different modifiers key down
|
||||
TEST_METHOD (RemappedTwoKeyToThreeKeyShortcutWithDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Alt+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -869,13 +804,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key to 3 key shortcut remap with partially different modifiers key down
|
||||
TEST_METHOD (RemappedTwoKeyToThreeKeyShortcutWithPartiallyDiffModifiers_ShouldSetTargetShortcutDown_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Ctrl+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -906,13 +834,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key to 3 key shortcut remap with different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedTwoKeyToThreeKeyShortcutWithDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Alt+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -950,13 +871,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a 2 key to 3 key shortcut remap with partially different modifiers key down followed by key up
|
||||
TEST_METHOD (RemappedTwoKeyToThreeKeyShortcutWithPartiallyDiffModifiers_ShouldClearKeyboard_OnKeyUp)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Ctrl+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -993,13 +907,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set if a shortcut remap is pressed and then an unremapped shortcut with the same modifier is pressed - Ex: Ctrl+A is remapped. User invokes Ctrl+A then releases A and presses C (while Ctrl is held), should invoke Ctrl+C
|
||||
TEST_METHOD (InvokingUnremappedShortcutAfterRemappedShortcutWithSameModifier_ShouldSetUnremappedShortcut_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Alt+Shift+V
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
@ -1037,13 +944,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set for a shortcut remap with win both modifier
|
||||
TEST_METHOD (RemappedShortcutWithWinBothModifier_ShouldSetRemappedShortcut_OnKeyEvent)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Win+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(CommonSharedConstants::VK_WIN_BOTH);
|
||||
@ -1175,13 +1075,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set if a win both shortcut remap is pressed and then an unremapped shortcut with the LWin modifier is pressed
|
||||
TEST_METHOD (InvokingUnremappedShortcutWithLWinAfterRemappedShortcutWithWinBothModifier_ShouldSetUnremappedShortcutWithLWinKey_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Win+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(CommonSharedConstants::VK_WIN_BOTH);
|
||||
@ -1222,13 +1115,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if correct keyboard states are set if a win both shortcut remap is pressed and then an unremapped shortcut with the RWin modifier is pressed
|
||||
TEST_METHOD (InvokingUnremappedShortcutWithRWinAfterRemappedShortcutWithWinBothModifier_ShouldSetUnremappedShortcutWithRWinKey_OnKeyDown)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Win+A to Alt+V
|
||||
Shortcut src;
|
||||
src.SetKey(CommonSharedConstants::VK_WIN_BOTH);
|
||||
@ -1269,13 +1155,6 @@ namespace KeyboardManagerRemapLogicTests
|
||||
// Test if target modifier is still held down even if the action key of the original shortcut is released - required for Alt+Tab/Win+Space cases
|
||||
TEST_METHOD (RemappedShortcutModifiers_ShouldBeDetectedAsPressed_OnReleasingActionKeyButHoldingModifiers)
|
||||
{
|
||||
// Reset test environment
|
||||
TestHelpers::ResetTestEnv(mockedInputHandler, testState);
|
||||
|
||||
// Set HandleOSLevelShortcutRemapEvent as the hook procedure
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> currentHookProc = std::bind(&KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent, std::ref(mockedInputHandler), std::placeholders::_1, std::ref(testState));
|
||||
mockedInputHandler.SetHookProc(currentHookProc);
|
||||
|
||||
// Remap Ctrl+A to Alt+Tab
|
||||
Shortcut src;
|
||||
src.SetKey(VK_CONTROL);
|
||||
|
@ -45,6 +45,12 @@ UINT MockedInput::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize)
|
||||
lParam.dwExtraInfo = pInputs[i].ki.dwExtraInfo;
|
||||
keyEvent.lParam = &lParam;
|
||||
|
||||
// If the SendVirtualInput call condition is true, increment the count. If no condition is set then always increment the count
|
||||
if (sendVirtualInputCallCondition == nullptr || sendVirtualInputCallCondition(&keyEvent))
|
||||
{
|
||||
sendVirtualInputCallCount++;
|
||||
}
|
||||
|
||||
// Call low level hook handler
|
||||
intptr_t result = MockedKeyboardHook(&keyEvent);
|
||||
|
||||
@ -128,3 +134,16 @@ void MockedInput::ResetKeyboardState()
|
||||
{
|
||||
std::fill(keyboardState.begin(), keyboardState.end(), false);
|
||||
}
|
||||
|
||||
// Function to set SendVirtualInput call count condition
|
||||
void MockedInput::SetSendVirtualInputTestHandler(std::function<bool(LowlevelKeyboardEvent*)> condition)
|
||||
{
|
||||
sendVirtualInputCallCount = 0;
|
||||
sendVirtualInputCallCondition = condition;
|
||||
}
|
||||
|
||||
// Function to get SendVirtualInput call count
|
||||
int MockedInput::GetSendVirtualInputCallCount()
|
||||
{
|
||||
return sendVirtualInputCallCount;
|
||||
}
|
||||
|
@ -15,6 +15,10 @@ private:
|
||||
// Function to be executed as a low level hook. By default it is nullptr so the hook is skipped
|
||||
std::function<intptr_t(LowlevelKeyboardEvent*)> hookProc;
|
||||
|
||||
// Stores the count of sendVirtualInput calls given if the condition sendVirtualInputCallCondition is satisfied
|
||||
int sendVirtualInputCallCount = 0;
|
||||
std::function<bool(LowlevelKeyboardEvent*)> sendVirtualInputCallCondition;
|
||||
|
||||
public:
|
||||
MockedInput()
|
||||
{
|
||||
@ -35,4 +39,10 @@ public:
|
||||
|
||||
// Function to reset the mocked keyboard state
|
||||
void ResetKeyboardState();
|
||||
|
||||
// Function to set SendVirtualInput call count condition
|
||||
void SetSendVirtualInputTestHandler(std::function<bool(LowlevelKeyboardEvent*)> condition);
|
||||
|
||||
// Function to get SendVirtualInput call count
|
||||
int GetSendVirtualInputCallCount();
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ namespace TestHelpers
|
||||
{
|
||||
input.ResetKeyboardState();
|
||||
input.SetHookProc(nullptr);
|
||||
input.SetSendVirtualInputTestHandler(nullptr);
|
||||
state.ClearSingleKeyRemaps();
|
||||
state.ClearOSLevelShortcuts();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user