From 62c7b0a66dc0d8f74f06c5b93c2f6d1cd3aa21f7 Mon Sep 17 00:00:00 2001 From: Masaru Iritani <25241373+masaru-iritani@users.noreply.github.com> Date: Sat, 22 Jun 2024 06:16:41 +0900 Subject: [PATCH] [KBM][CQ]Replace LPINPUT with std::vector (#32052) --- .../keyboardmanager/keyboardeventhandlers.md | 2 +- .../KeyboardEventHandlers.cpp | 352 +---- .../AppSpecificShortcutRemappingTests.cpp | 156 +- .../KeyboardManagerEngineTest/MockedInput.cpp | 38 +- .../KeyboardManagerEngineTest/MockedInput.h | 2 +- .../MockedInputSanityTests.cpp | 16 +- .../OSLevelShortcutRemappingTests.cpp | 1393 +++++++---------- .../SetKeyEventTests.cpp | 18 +- .../SingleKeyRemappingTests.cpp | 132 +- .../keyboardmanager/common/Helpers.cpp | 66 +- src/modules/keyboardmanager/common/Helpers.h | 11 +- src/modules/keyboardmanager/common/Input.h | 15 +- .../keyboardmanager/common/InputInterface.h | 6 +- .../common/KeyboardEventHandlers.cpp | 11 +- 14 files changed, 857 insertions(+), 1361 deletions(-) diff --git a/doc/devdocs/modules/keyboardmanager/keyboardeventhandlers.md b/doc/devdocs/modules/keyboardmanager/keyboardeventhandlers.md index f8ee72ea4f..cb3d1561ce 100644 --- a/doc/devdocs/modules/keyboardmanager/keyboardeventhandlers.md +++ b/doc/devdocs/modules/keyboardmanager/keyboardeventhandlers.md @@ -72,7 +72,7 @@ In order to test the remapping logic, a mocked keyboard input handler had to be The [`MockedInput`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/MockedInput.h) class uses a 256 size `bool` vector to store the key state for each key code. Identifying the foreground process is mocked by simply setting and getting a string value for the name of the current process. [To mock the `SendInput` method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/test/MockedInput.cpp#L10-L110), the steps for processing the input are as follows. This implementation is based on public documentation for SendInput and the behavior of key messages and keyboard hooks: -- Iterate over all the inputs in the INPUT array argument +- Iterate over all the inputs in the `INPUT` vector argument. - If the event is a key up event, then it is considered [`WM_SYSKEYUP`](https://learn.microsoft.com/windows/win32/inputdev/wm-syskeyup) if Alt is held down, otherwise it is `WM_KEYUP`. - If the event is a key down event, then it is considered [`WM_SYSKEYDOWN`](https://learn.microsoft.com/windows/win32/inputdev/wm-syskeydown) if either Alt is held down or if it is F10, otherwise it is `WM_KEYDOWN`. - An optional function which can be set on the `MockedInput` handler can be used to test for the number of times a key event is received by the system with a particular condition using [`sendVirtualInputCallCondition`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/test/MockedInput.cpp#L48-L52). diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp index 5c8e4cfd19..13392bbb44 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp @@ -69,7 +69,7 @@ namespace KeyboardEventHandlers key_count = std::get(it->second).Size(); } - LPINPUT keyEventList = new INPUT[size_t(key_count)]{}; + std::vector keyEventList; // Handle remaps to VK_WIN_BOTH DWORD target; @@ -92,35 +92,31 @@ namespace KeyboardEventHandlers { if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP) { - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(target), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(target), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); } else { - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(target), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(target), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); } } else { - int i = 0; Shortcut targetShortcut = std::get(it->second); if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP) { - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); - i++; - Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); // Dummy key is not required here since SetModifierKeyEvents will only add key-up events for the modifiers here, and the action key key-up is already sent before it } else { // Dummy key is not required here since SetModifierKeyEvents will only add key-down events for the modifiers here, and the action key key-down is already sent after it - Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); - i++; + Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); } } - UINT res = ii.SendVirtualInput(key_count, keyEventList, sizeof(INPUT)); - delete[] keyEventList; + ii.SendVirtualInput(keyEventList); if (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN) { @@ -194,14 +190,12 @@ namespace KeyboardEventHandlers return 1; } } - int key_count = 2; - LPINPUT keyEventList = new INPUT[size_t(key_count)](); - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); - Helpers::SetKeyEvent(keyEventList, 1, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + std::vector keyEventList; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); lock.unlock(); - UINT res = ii.SendVirtualInput(key_count, keyEventList, sizeof(INPUT)); - delete[] keyEventList; + ii.SendVirtualInput(keyEventList); // Reset the long press flag when the key has been lifted. if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP) @@ -306,8 +300,7 @@ namespace KeyboardEventHandlers continue; } - size_t key_count = 0; - LPINPUT keyEventList = nullptr; + std::vector keyEventList; // Remember which win key was pressed initially if (ii.GetVirtualKeyState(VK_RWIN)) @@ -331,8 +324,6 @@ namespace KeyboardEventHandlers myThread.detach(); } - - Logger::trace(L"ChordKeyboardHandler:returning.."); return 1; } @@ -362,7 +353,6 @@ namespace KeyboardEventHandlers } } - auto threadFunction = [newUri]() { HINSTANCE result = ShellExecute(NULL, L"open", newUri.c_str(), NULL, NULL, SW_SHOWNORMAL); @@ -380,7 +370,6 @@ namespace KeyboardEventHandlers myThread.detach(); } - Logger::trace(L"ChordKeyboardHandler:returning.."); return 1; } @@ -394,30 +383,22 @@ namespace KeyboardEventHandlers if (commonKeys == src_size - 1) { // key down for all new shortcut keys except the common modifiers - key_count = dest_size - commonKeys; - keyEventList = new INPUT[key_count]{}; - int i = 0; - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + keyEventList = std::vector{}; + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else { // Dummy key, key up for all the original shortcut modifier keys and key down for all the new shortcut keys but common keys in each are not repeated - key_count = KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE + (src_size - 1) + (dest_size) - (2 * static_cast(commonKeys)); - keyEventList = new INPUT[key_count]{}; - // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->Ctrl+V, press Win+A, since Win will be released here we need to send a dummy event before it - int i = 0; - Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // Set new shortcut key down state - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Modifier state reset might be required for this key depending on the shortcut's action and target modifiers - ex: Win+Caps -> Ctrl+A @@ -432,31 +413,23 @@ namespace KeyboardEventHandlers } else if (remapToKey) { - // Dummy key, key up for all the original shortcut modifier keys and key down for remapped key - key_count = KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE + (src_size - 1) + dest_size; - // Do not send Disable key if (std::get(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED) { - key_count--; // Since the original shortcut's action key is pressed, set it to true it->second.isOriginalActionKeyPressed = true; } - keyEventList = new INPUT[key_count]{}; - // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->V, press Win+A, since Win will be released here we need to send a dummy event before it - int i = 0; - Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Set target key down state if (std::get(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED) { - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Modifier state reset might be required for this key depending on the shortcut's action and target modifier - ex: Win+Caps -> Ctrl @@ -468,29 +441,14 @@ namespace KeyboardEventHandlers // Remapped to text else { - key_count = KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE + src_size; + auto& remapping = std::get(it->second.targetShortcut); - auto remapping = std::get(it->second.targetShortcut); - const UINT inputEventCount = static_cast(remapping.length() * 2); - key_count += inputEventCount; - - keyEventList = new INPUT[key_count]{}; - - int i = 0; - Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - for (size_t idx = 0; idx < inputEventCount; ++idx) - { - auto& input = keyEventList[idx + i]; - input.type = INPUT_KEYBOARD; - const bool upEvent = idx & 0x1; - input.ki.dwFlags = KEYEVENTF_UNICODE | (upEvent ? KEYEVENTF_KEYUP : 0); - input.ki.dwExtraInfo = KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG; - input.ki.wScan = remapping[idx >> 1]; - } + Helpers::SetTextKeyEvents(keyEventList, remapping); } it->second.isShortcutInvoked = true; @@ -500,12 +458,9 @@ namespace KeyboardEventHandlers state.SetActivatedApp(*activatedApp); } - Logger::trace(L"ChordKeyboardHandler:key_count:{}", key_count); + Logger::trace(L"ChordKeyboardHandler:keyEventList.size:{}", keyEventList.size()); - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; - - // Send daily telemetry event for Keyboard Manager key activation. + ii.SendVirtualInput(keyEventList); if (activatedApp.has_value()) { if (remapToKey) @@ -574,84 +529,41 @@ namespace KeyboardEventHandlers if ((it->first.CheckWinKey(data->lParam->vkCode) || it->first.CheckCtrlKey(data->lParam->vkCode) || it->first.CheckAltKey(data->lParam->vkCode) || it->first.CheckShiftKey(data->lParam->vkCode)) && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)) { // Release new shortcut, and set original shortcut keys except the one released - size_t key_count = 0; - LPINPUT keyEventList = nullptr; + std::vector keyEventList; if (remapToShortcut && !isRunProgram) { - // if the released key is present in both shortcuts' modifiers (i.e part of the common modifiers) - if (std::get(it->second.targetShortcut).CheckWinKey(data->lParam->vkCode) || std::get(it->second.targetShortcut).CheckCtrlKey(data->lParam->vkCode) || std::get(it->second.targetShortcut).CheckAltKey(data->lParam->vkCode) || std::get(it->second.targetShortcut).CheckShiftKey(data->lParam->vkCode)) - { - // release all new shortcut keys and the common released modifier except the other common modifiers, and add all original shortcut modifiers except the common ones, and dummy key - key_count = (dest_size - commonKeys) + (src_size - 1 - commonKeys) + KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE; - } - else - { - // release all new shortcut keys except the common modifiers and add all original shortcut modifiers except the common ones, and dummy key - key_count = (dest_size - 1) + (src_size - 2) - (2 * static_cast(commonKeys)) + KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE; - } - // If the target shortcut's action key is pressed, then it should be released - bool isActionKeyPressed = false; - if (ii.GetVirtualKeyState((std::get(it->second.targetShortcut).GetActionKey()))) - { - isActionKeyPressed = true; - key_count += 1; - } - - keyEventList = new INPUT[key_count]{}; + bool isActionKeyPressed = ii.GetVirtualKeyState(std::get(it->second.targetShortcut).GetActionKey()); // Release new shortcut state (release in reverse order of shortcut to be accurate) - int i = 0; if (isActionKeyPressed) { - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut), data->lParam->vkCode); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut), data->lParam->vkCode); // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+Ctrl+A->Ctrl+V, press Win+Ctrl+A and release A then Ctrl, since Win will be pressed here we need to send a dummy event after it - Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else if (remapToKey) { - // 1 for releasing new key and original shortcut modifiers except the one released and dummy key - key_count = dest_size + src_size - 2 + KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE; - bool isTargetKeyPressed = false; - - // Do not send Disable key up - if (std::get(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED) - { - key_count--; - } - else if (ii.GetVirtualKeyState(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut)))) - { - isTargetKeyPressed = true; - } - else - { - isTargetKeyPressed = false; - key_count--; - } - - keyEventList = new INPUT[key_count]{}; + bool isTargetKeyPressed = (std::get(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED) && ii.GetVirtualKeyState(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))); // Release new key state - int i = 0; if (std::get(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED && isTargetKeyPressed) { - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+Ctrl+A->V, press Win+Ctrl+A and release A then Ctrl, since Win will be pressed here we need to send a dummy event after it - Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Reset the remap state @@ -665,12 +577,7 @@ namespace KeyboardEventHandlers state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp); } - // key count can be 0 if both shortcuts have same modifiers and the action key is not held down. delete will throw an error if keyEventList is empty - if (key_count > 0) - { - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; - } + ii.SendVirtualInput(keyEventList); return 1; } @@ -678,7 +585,7 @@ namespace KeyboardEventHandlers if (!remapToShortcut || (remapToShortcut && std::get(it->second.targetShortcut).CheckModifiersKeyboardState(ii))) { // Case 2: If the original shortcut is still held down the keyboard will get a key down message of the action key in the original shortcut and the new shortcut's modifiers will be held down (keys held down send repeated keydown messages) - if (((data->lParam->vkCode == it->first.GetActionKey() && !it->first.HasChord())||(data->lParam->vkCode == it->first.GetSecondKey() && it->first.HasChord())) && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN)) + if (((data->lParam->vkCode == it->first.GetActionKey() && !it->first.HasChord()) || (data->lParam->vkCode == it->first.GetSecondKey() && it->first.HasChord())) && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN)) { // In case of mapping to disable do not send anything if (remapToKey && std::get(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED) @@ -688,69 +595,46 @@ namespace KeyboardEventHandlers return 1; } - size_t key_count = 1; - LPINPUT keyEventList = nullptr; + std::vector keyEventList; if (remapToShortcut) { - keyEventList = new INPUT[key_count]{}; - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else if (remapToKey) { - keyEventList = new INPUT[key_count]{}; - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else if (remapToText) { - auto remapping = std::get(it->second.targetShortcut); - const UINT inputEventCount = static_cast(remapping.length() * 2); - key_count = inputEventCount; - keyEventList = new INPUT[key_count]{}; - - for (size_t idx = 0; idx < inputEventCount; ++idx) - { - auto& input = keyEventList[idx]; - input.type = INPUT_KEYBOARD; - const bool upEvent = idx & 0x1; - input.ki.dwFlags = KEYEVENTF_UNICODE | (upEvent ? KEYEVENTF_KEYUP : 0); - input.ki.dwExtraInfo = KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG; - input.ki.wScan = remapping[idx >> 1]; - } + auto& remapping = std::get(it->second.targetShortcut); + Helpers::SetTextKeyEvents(keyEventList, remapping); } - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; + ii.SendVirtualInput(keyEventList); return 1; } // Case 3: If the action key is released from the original shortcut, keep modifiers of the new shortcut until some other key event which doesn't apply to the original shortcut - if (!remapToText && ((!it->first.HasChord() && data->lParam->vkCode == it->first.GetActionKey()) || (it->first.HasChord() && data->lParam->vkCode==it->first.GetSecondKey())) && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)) + if (!remapToText && ((!it->first.HasChord() && data->lParam->vkCode == it->first.GetActionKey()) || (it->first.HasChord() && data->lParam->vkCode == it->first.GetSecondKey())) && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)) { - size_t key_count = 1; - LPINPUT keyEventList = nullptr; + std::vector keyEventList; if (remapToShortcut && !it->first.HasChord()) { // Just lift the action key for no chords. - keyEventList = new INPUT[key_count]{}; - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else if (remapToShortcut && it->first.HasChord()) { // If it has a chord, we'll want a full clean contemplated in the else, since you can't really repeat chords by pressing the end key again. // Key up for all new shortcut keys, key down for original shortcut modifiers and current key press but common keys aren't repeated - key_count = (dest_size) + (src_size +1) - (2 * static_cast(commonKeys)); - int i = 0; - - keyEventList = new INPUT[key_count]{}; - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release new shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); // Set old shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // Reset the remap state it->second.isShortcutInvoked = false; @@ -762,7 +646,6 @@ namespace KeyboardEventHandlers { state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp); } - } else if (std::get(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED) { @@ -779,29 +662,21 @@ namespace KeyboardEventHandlers // If the keyboard state is clear, we release the target key but do not reset the remap state if (isKeyboardStateClear) { - keyEventList = new INPUT[key_count]{}; - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else { // If any other key is pressed, then the keyboard state must be reverted back to the physical keys. // This is to take cases like Ctrl+A->D remap and user presses B+Ctrl+A and releases A, or Ctrl+A+B and releases A - // 1 for releasing new key and original shortcut modifiers, and dummy key - key_count = dest_size + (src_size - 1) + KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE; - - keyEventList = new INPUT[key_count]{}; - // Release new key state - int i = 0; - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Set original shortcut key down state except the action key - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->V, press Shift+Win+A and release A, since Win will be pressed here we need to send a dummy event after it - Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Reset the remap state it->second.isShortcutInvoked = false; @@ -816,8 +691,7 @@ namespace KeyboardEventHandlers } } - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; + ii.SendVirtualInput(keyEventList); return 1; } @@ -854,8 +728,7 @@ namespace KeyboardEventHandlers ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, std::get(it->second.targetShortcut).GetActionKey()); } - size_t key_count; - LPINPUT keyEventList = nullptr; + std::vector keyEventList; // Check if a new remapping should be applied Shortcut currentlyPressed = it->first; @@ -868,40 +741,25 @@ namespace KeyboardEventHandlers if (newRemapping.RemapToKey()) { DWORD to = std::get<0>(newRemapping.targetShortcut); - bool isLastKeyStillPressed = ii.GetVirtualKeyState(static_cast(from.actionKey)); - key_count = static_cast(from.Size()) - 1 + 1 + (isLastKeyStillPressed ? 1 : 0); - keyEventList = new INPUT[key_count]{}; - int i = 0; - Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); if (ii.GetVirtualKeyState(static_cast(from.actionKey))) { // If the action key from the last shortcut is still being pressed, release it. - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(from.actionKey), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(from.actionKey), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(to), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(to), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else { Shortcut to = std::get(newRemapping.targetShortcut); - bool isLastKeyStillPressed = ii.GetVirtualKeyState(static_cast(from.actionKey)); - - size_t temp_key_count_calculation = static_cast(from.Size()) - 1; - temp_key_count_calculation += static_cast(to.Size()) - 1; - temp_key_count_calculation -= static_cast(2) * from.GetCommonModifiersCount(to); - key_count = temp_key_count_calculation + 1 + (isLastKeyStillPressed ? 1 : 0); - keyEventList = new INPUT[key_count]{}; - - int i = 0; - Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); + Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); if (ii.GetVirtualKeyState(static_cast(from.actionKey))) { // If the action key from the last shortcut is still being pressed, release it. - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(from.actionKey), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(from.actionKey), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } - Helpers::SetModifierKeyEvents(to, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(to.actionKey), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(to, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(to.actionKey), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); newRemapping.isShortcutInvoked = true; } @@ -917,41 +775,27 @@ namespace KeyboardEventHandlers } else { - // Key up for all new shortcut keys, key down for original shortcut modifiers and current key press but common keys aren't repeated - key_count = (dest_size) + (src_size - 1) - (2 * static_cast(commonKeys)); - // If the target shortcut's action key is pressed, then it should be released and original shortcut's action key should be set - bool isActionKeyPressed = false; - if (ii.GetVirtualKeyState((std::get(it->second.targetShortcut).GetActionKey()))) - { - isActionKeyPressed = true; - key_count += 2; - } - - keyEventList = new INPUT[key_count]{}; + bool isActionKeyPressed = ii.GetVirtualKeyState(std::get(it->second.targetShortcut).GetActionKey()); // Release new shortcut state (release in reverse order of shortcut to be accurate) - int i = 0; if (isActionKeyPressed) { - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); // Set old shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // key down for original shortcut action key with shortcut flag so that we don't invoke the same shortcut remap again if (isActionKeyPressed) { - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(it->first.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(it->first.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Send current key pressed without shortcut flag so that it can be reprocessed in case the physical keys pressed are a different remapped shortcut - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(data->lParam->vkCode), 0, 0); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(data->lParam->vkCode), 0, 0); // Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after shortcut to shortcut is released to open start menu } @@ -967,8 +811,7 @@ namespace KeyboardEventHandlers state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp); } - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; + ii.SendVirtualInput(keyEventList); return 1; } else @@ -1003,30 +846,20 @@ namespace KeyboardEventHandlers if (isRemapToDisable || !isOriginalActionKeyPressed) { - // Key down for original shortcut modifiers and action key, and current key press - size_t key_count = src_size + 1; - - LPINPUT keyEventList = new INPUT[key_count]{}; + std::vector keyEventList; // Set original shortcut key down state - int i = 0; - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Send the original action key only if it is physically pressed. For remappings to keys other than disabled we already check earlier that it is not pressed in this scenario. For remap to disable if (isRemapToDisable && isOriginalActionKeyPressed) { // Set original action key - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(it->first.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - i++; - } - else - { - key_count--; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(it->first.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Send current key pressed without shortcut flag so that it can be reprocessed in case the physical keys pressed are a different remapped shortcut - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(data->lParam->vkCode), 0, 0); - i++; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(data->lParam->vkCode), 0, 0); // Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after another shortcut to key remap is released to open start menu @@ -1041,8 +874,7 @@ namespace KeyboardEventHandlers state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp); } - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; + ii.SendVirtualInput(keyEventList); return 1; } else @@ -1344,7 +1176,7 @@ namespace KeyboardEventHandlers if (targetPid != 0 && shortcut.alreadyRunningAction != Shortcut::ProgramAlreadyRunningAction::StartAnother) { - if (shortcut.alreadyRunningAction == Shortcut::ProgramAlreadyRunningAction::EndTask) + if (shortcut.alreadyRunningAction == Shortcut::ProgramAlreadyRunningAction::EndTask) { TerminateProcessesByName(fileNamePart); return; @@ -1803,13 +1635,11 @@ namespace KeyboardEventHandlers // If the argument is either of the Ctrl/Shift/Alt modifier key codes if (Helpers::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)]{}; + std::vector keyEventList; // Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(key), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); - UINT res = ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(key), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); + ii.SendVirtualInput(keyEventList); } } } @@ -1834,21 +1664,9 @@ namespace KeyboardEventHandlers return 0; } - const size_t keyCount = remapping->length(); - const UINT eventCount = static_cast(keyCount * 2); - auto keyEventList = std::make_unique(keyCount * 2); - - for (size_t i = 0; i < eventCount; ++i) - { - auto& input = keyEventList[i]; - input.type = INPUT_KEYBOARD; - const bool upEvent = i & 0x1; - input.ki.dwFlags = KEYEVENTF_UNICODE | (upEvent ? KEYEVENTF_KEYUP : 0); - input.ki.dwExtraInfo = KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG; - input.ki.wScan = (*remapping)[i >> 1]; - } - - UINT res = ii.SendVirtualInput(eventCount, keyEventList.get(), sizeof(INPUT)); + std::vector keyEventList; + Helpers::SetTextKeyEvents(keyEventList, *remapping); + ii.SendVirtualInput(keyEventList); return 1; } diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/AppSpecificShortcutRemappingTests.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/AppSpecificShortcutRemappingTests.cpp index 3c531461c2..419f76a81a 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/AppSpecificShortcutRemappingTests.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/AppSpecificShortcutRemappingTests.cpp @@ -51,15 +51,13 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl and A key states should be unchanged, Alt and V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -83,15 +81,13 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp2); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl and A key states should be true, Alt and V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -115,28 +111,24 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Activated app should be testApp1 Assert::AreEqual(testApp1, testState.GetActivatedApp()); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } } + }; // Release A then Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Activated app should be empty string Assert::AreEqual(std::wstring(KeyboardManagerConstants::NoActivatedApp), testState.GetActivatedApp()); @@ -156,28 +148,24 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp2); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } } + }; // Release A then Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, A, Alt and Tab should all be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -198,15 +186,13 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl and A key states should be unchanged, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -226,15 +212,13 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp2); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl and A key states should be true, V key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -254,28 +238,24 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Activated app should be testApp1 Assert::AreEqual(testApp1, testState.GetActivatedApp()); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } } + }; // Release A then Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Activated app should be empty string Assert::AreEqual(std::wstring(KeyboardManagerConstants::NoActivatedApp), testState.GetActivatedApp()); @@ -292,28 +272,24 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp2); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } } + }; // Release A then Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, A, V should all be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -334,15 +310,13 @@ namespace RemappingLogicTests // Set the testApp as the foreground process mockedInputHandler.SetForegroundProcess(testApp1); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } } + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Check if Ctrl+A is released and disable key was not send Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.cpp index 947a6654b0..5a307817d0 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.cpp @@ -10,15 +10,15 @@ void MockedInput::SetHookProc(std::function ho } // Function to simulate keyboard input - arguments and return value based on SendInput function (https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-sendinput) -UINT MockedInput::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int /*cbSize*/) +void MockedInput::SendVirtualInput(const std::vector& inputs) { // Iterate over inputs - for (UINT i = 0; i < cInputs; i++) + for (const INPUT& input : inputs) { - LowlevelKeyboardEvent keyEvent; + LowlevelKeyboardEvent keyEvent{}; // Distinguish between key and sys key by checking if the key is either F10 (for syskeydown) or if the key message is sent while Alt is held down. SYSKEY messages are also sent if there is no window in focus, but that has not been mocked since it would require many changes. More details on key messages at https://learn.microsoft.com/windows/win32/inputdev/wm-syskeydown - if (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) + if (input.ki.dwFlags & KEYEVENTF_KEYUP) { if (keyboardState[VK_MENU] == true) { @@ -31,7 +31,7 @@ UINT MockedInput::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int /*cbSize*/ } else { - if (pInputs[i].ki.wVk == VK_F10 || keyboardState[VK_MENU] == true) + if (input.ki.wVk == VK_F10 || keyboardState[VK_MENU] == true) { keyEvent.wParam = WM_SYSKEYDOWN; } @@ -43,8 +43,8 @@ UINT MockedInput::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int /*cbSize*/ KBDLLHOOKSTRUCT lParam = {}; // Set only vkCode and dwExtraInfo since other values are unused - lParam.vkCode = pInputs[i].ki.wVk; - lParam.dwExtraInfo = pInputs[i].ki.dwExtraInfo; + lParam.vkCode = input.ki.wVk; + lParam.dwExtraInfo = input.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 @@ -60,55 +60,53 @@ UINT MockedInput::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int /*cbSize*/ if (result == 0) { // If key up flag is set, then set keyboard state to false - keyboardState[pInputs[i].ki.wVk] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[input.ki.wVk] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; // Handling modifier key codes - switch (pInputs[i].ki.wVk) + switch (input.ki.wVk) { case VK_CONTROL: - if (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) + if (input.ki.dwFlags & KEYEVENTF_KEYUP) { keyboardState[VK_LCONTROL] = false; keyboardState[VK_RCONTROL] = false; } break; case VK_LCONTROL: - keyboardState[VK_CONTROL] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[VK_CONTROL] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; break; case VK_RCONTROL: - keyboardState[VK_CONTROL] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[VK_CONTROL] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; break; case VK_MENU: - if (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) + if (input.ki.dwFlags & KEYEVENTF_KEYUP) { keyboardState[VK_LMENU] = false; keyboardState[VK_RMENU] = false; } break; case VK_LMENU: - keyboardState[VK_MENU] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[VK_MENU] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; break; case VK_RMENU: - keyboardState[VK_MENU] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[VK_MENU] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; break; case VK_SHIFT: - if (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) + if (input.ki.dwFlags & KEYEVENTF_KEYUP) { keyboardState[VK_LSHIFT] = false; keyboardState[VK_RSHIFT] = false; } break; case VK_LSHIFT: - keyboardState[VK_SHIFT] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[VK_SHIFT] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; break; case VK_RSHIFT: - keyboardState[VK_SHIFT] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; + keyboardState[VK_SHIFT] = (input.ki.dwFlags & KEYEVENTF_KEYUP) ? false : true; break; } } } - - return cInputs; } // Function to simulate keyboard hook behavior diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.h b/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.h index 33940bd471..c7fac51696 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.h +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInput.h @@ -34,7 +34,7 @@ namespace KeyboardManagerInput void SetHookProc(std::function hookProcedure); // Function to simulate keyboard input - UINT SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize); + void SendVirtualInput(const std::vector& inputs); // Function to simulate keyboard hook behavior intptr_t MockedKeyboardHook(LowlevelKeyboardEvent* data); diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInputSanityTests.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInputSanityTests.cpp index 29fadd0df6..0ebfeb2deb 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInputSanityTests.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/MockedInputSanityTests.cpp @@ -33,20 +33,22 @@ namespace RemappingLogicTests 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] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A key state should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), true); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send A keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/OSLevelShortcutRemappingTests.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/OSLevelShortcutRemappingTests.cpp index c99ce09851..4b470ec5a6 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/OSLevelShortcutRemappingTests.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/OSLevelShortcutRemappingTests.cpp @@ -57,15 +57,13 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl and A key states should be unchanged, Alt and V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -86,15 +84,13 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A key state should be unchanged, Ctrl and V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -114,21 +110,15 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = VK_CONTROL; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+A keydown, followed by A and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A, Alt, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -149,21 +139,15 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = VK_CONTROL; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+A keydown, followed by A and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -183,17 +167,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Since Ctrl+Shift+A is not remapped, no remapping should be invoked Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -217,17 +198,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A key states should be unchanged, Alt, LWin, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -252,17 +230,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Shift, A key states should be unchanged, Alt, Ctrl, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_SHIFT), false); @@ -286,17 +261,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A key state should be unchanged, Ctrl, Shift, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -319,26 +291,17 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 6; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x41; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; - input[4].type = INPUT_KEYBOARD; - input[4].ki.wVk = VK_SHIFT; - input[4].ki.dwFlags = KEYEVENTF_KEYUP; - input[5].type = INPUT_KEYBOARD; - input[5].ki.wVk = VK_CONTROL; - input[5].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+Shift+A keydown, followed by A, Shift and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A, Alt, LWin, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -363,26 +326,17 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 6; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x41; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; - input[4].type = INPUT_KEYBOARD; - input[4].ki.wVk = VK_SHIFT; - input[4].ki.dwFlags = KEYEVENTF_KEYUP; - input[5].type = INPUT_KEYBOARD; - input[5].ki.wVk = VK_CONTROL; - input[5].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+Shift+A keydown, followed by A, Shift and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A, Alt, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -406,26 +360,17 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 6; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x41; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; - input[4].type = INPUT_KEYBOARD; - input[4].ki.wVk = VK_SHIFT; - input[4].ki.dwFlags = KEYEVENTF_KEYUP; - input[5].type = INPUT_KEYBOARD; - input[5].ki.wVk = VK_CONTROL; - input[5].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+Shift+A keydown, followed by A, Shift and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -446,15 +391,14 @@ namespace RemappingLogicTests dest.SetKey(VK_MENU); dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Since Ctrl+A is not remapped, no remapping should be invoked Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -477,17 +421,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A key states should be unchanged, Alt, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -510,17 +451,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Shift, A key states should be unchanged, Ctrl, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_SHIFT), false); @@ -542,26 +480,17 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 6; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x41; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; - input[4].type = INPUT_KEYBOARD; - input[4].ki.wVk = VK_SHIFT; - input[4].ki.dwFlags = KEYEVENTF_KEYUP; - input[5].type = INPUT_KEYBOARD; - input[5].ki.wVk = VK_CONTROL; - input[5].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+Shift+A keydown, followed by A, Shift and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A, Alt, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -584,26 +513,17 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 6; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x41; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; - input[4].type = INPUT_KEYBOARD; - input[4].ki.wVk = VK_SHIFT; - input[4].ki.dwFlags = KEYEVENTF_KEYUP; - input[5].type = INPUT_KEYBOARD; - input[5].ki.wVk = VK_CONTROL; - input[5].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+Shift+A keydown, followed by A, Shift and Ctrl released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, Shift, A, V key states should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -625,15 +545,13 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A key states should be unchanged, Alt, Shift, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -656,15 +574,13 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A key state should be unchanged, Ctrl, Shift, V key states should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -686,21 +602,15 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = VK_CONTROL; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+A keydown and A, Ctrl are then released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A, Alt, Shift, V key states should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -723,21 +633,15 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = VK_CONTROL; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+A keydown and A, Ctrl are then released - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A, Shift, V key states should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -759,20 +663,15 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x43; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'C' } }, + }; // Send Ctrl+A keydown, A key up, then C key down - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, Alt, Shift, V key states should be unchanged, Ctrl, C should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -805,19 +704,13 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src1, dest1); // Test 2 cases for first remap - LWin, A, A(Up), LWin(Up). RWin, A, A(Up), RWin(Up) - const int nInputs = 2; - INPUT input[nInputs] = {}; - - // Case 1.1 - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send LWin+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // LWin, RWin, A key states should be unchanged, Alt, V should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false); @@ -826,15 +719,13 @@ namespace RemappingLogicTests Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), true); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_LWIN; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release LWin+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // LWin, RWin, A, Alt, V key states should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false); @@ -844,15 +735,13 @@ namespace RemappingLogicTests Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), false); // Case 1.2 - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_RWIN; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; + std::vector inputs3{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_RWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send RWin+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs3); // LWin, RWin, A key states should be unchanged, Alt, V should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false); @@ -861,15 +750,13 @@ namespace RemappingLogicTests Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), true); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_RWIN; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs4{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_RWIN, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release RWin+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs4); // LWin, RWin, A, Alt, V key states should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false); @@ -879,15 +766,13 @@ namespace RemappingLogicTests Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), false); // Case 2 - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_MENU; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x44; - input[1].ki.dwFlags = 0; + std::vector inputs5{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_MENU } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'D' } }, + }; // Send Alt+D keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs5); // Alt, D, RWin key states should be unchanged, LWin, B should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), true); @@ -896,15 +781,13 @@ namespace RemappingLogicTests Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x44), false); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x44; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_MENU; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs6{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'D', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_MENU, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Alt+D - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs6); // LWin, RWin, B, Alt, D key states should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false); @@ -927,23 +810,15 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, dest); // LWin, A, A(Up), C(Down) - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x43; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'C' } }, + }; // Send LWin+A, release A and press C - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // RWin, A, Alt, V key states should be unchanged, LWin, C should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), true); @@ -967,23 +842,15 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, dest); // RWin, A, A(Up), C(Down) - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_RWIN; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x43; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_RWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'C' } }, + }; // Send RWin+A, release A and press C - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // LWin, A, Alt, V key states should be unchanged, RWin, C should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), false); @@ -1006,20 +873,14 @@ namespace RemappingLogicTests dest.SetKey(VK_TAB); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A, Tab key states should be unchanged, Alt should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1049,23 +910,15 @@ namespace RemappingLogicTests dest1.SetKey(0x58); testState.AddOSLevelShortcut(src1, dest1); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_MENU; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x56; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_MENU } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'V' } }, + }; // Send Alt+A, release A, press V - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, A, C, V key states should be unchanged, Ctrl, X should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), false); @@ -1097,23 +950,15 @@ namespace RemappingLogicTests dest1.SetKey(0x58); testState.AddOSLevelShortcut(src1, dest1); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x56; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'V' } }, + }; // Send Ctrl+A, release A, press V - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, C, V key states should be unchanged, Ctrl, X should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -1134,30 +979,26 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Ctrl, A should be false, Alt should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), true); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, A, Alt should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1175,17 +1016,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Ctrl, Shift, A should be false, Alt should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1193,18 +1031,14 @@ namespace RemappingLogicTests Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), true); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl+Shift+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, Shift, A, Alt should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1222,29 +1056,25 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_CONTROL); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A should be false, Ctrl should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, A should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1261,35 +1091,28 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_CONTROL); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Ctrl+Shift+A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Shift, A should be false, Ctrl should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_SHIFT), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT, .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl+Shift+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, Shift, A should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1306,18 +1129,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A, Alt should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1336,18 +1155,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_CONTROL); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Both A and Ctrl should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1365,18 +1180,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)0x41); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Ctrl, A should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1394,18 +1205,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, Alt, Ctrl should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1424,18 +1231,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_CONTROL); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, Ctrl should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1453,18 +1256,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)0x41); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, Ctrl should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1480,17 +1279,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x42; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Press B+Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, Ctrl should be false, B, Alt should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1508,20 +1304,15 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x42; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x41; - input[3].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press B+Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, A should be false, Ctrl, B should be true Assert::AreEqual(true, mockedInputHandler.GetVirtualKeyState(VK_CONTROL)); @@ -1547,17 +1338,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_SHIFT; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Press Shift+Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, A, Shift should be false, Ctrl, V should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -1579,17 +1367,14 @@ namespace RemappingLogicTests src.SetKey(VK_SHIFT); testState.AddOSLevelShortcut(src, (DWORD)0x42); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_SHIFT; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Press Shift+Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, Ctrl, A, Shift should be false, B should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1608,17 +1393,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x42; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + }; // Press Ctrl+A+B - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A, Ctrl should be false, B, Alt should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1628,12 +1410,12 @@ namespace RemappingLogicTests // Shortcut invoked state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isShortcutInvoked); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release A - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A, Alt should be false, Ctrl, B should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -1652,18 +1434,14 @@ namespace RemappingLogicTests src.SetKey(VK_CONTROL); src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x42; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + }; // Press Ctrl+A+B - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A, Ctrl should be false, B, Alt should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1673,12 +1451,12 @@ namespace RemappingLogicTests // Shortcut invoked state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isShortcutInvoked); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, Alt, A should be false, B should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1698,18 +1476,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_MENU); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Press Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A, Ctrl, Alt should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1718,12 +1492,12 @@ namespace RemappingLogicTests // Shortcut invoked state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isShortcutInvoked); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x42; - input[0].ki.dwFlags = 0; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + }; // Press B - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A, Alt should be false, Ctrl, B should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -1743,30 +1517,26 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)CommonSharedConstants::VK_WIN_BOTH); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Press Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A, Ctrl should be false, LWin should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), true); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release A, Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Ctrl, A, LWin should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -1794,23 +1564,15 @@ namespace RemappingLogicTests dest1.SetKey(0x58); testState.AddOSLevelShortcut(src1, dest1); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_MENU; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x56; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_MENU } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'V' } }, + }; // Send Alt+A, release A, press V - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, A, D, V key states should be unchanged, Ctrl, X should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), false); @@ -1836,23 +1598,15 @@ namespace RemappingLogicTests src1.SetKey(0x56); testState.AddOSLevelShortcut(src1, (DWORD)0x58); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_MENU; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x56; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_MENU } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'V' } }, + }; // Send Alt+A, release A, press V - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, A, D, V key states should be unchanged, X should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), false); @@ -1880,23 +1634,15 @@ namespace RemappingLogicTests src1.SetKey(0x56); testState.AddOSLevelShortcut(src1, (DWORD)0x58); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_MENU; - input[0].ki.dwFlags = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[1].ki.dwFlags = 0; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x56; - input[3].ki.dwFlags = 0; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_MENU } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'V' } }, + }; // Send Alt+A, release A, press V - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Alt, A, C, V, Ctrl key states should be unchanged, X should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_MENU), false); @@ -1916,20 +1662,15 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)0x56); - const int nInputs = 4; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; - input[3].type = INPUT_KEYBOARD; - input[3].ki.wVk = 0x43; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'C' } }, + }; // Send Ctrl+A keydown, A key up, then C key down - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A, V key states should be unchanged, Ctrl, C should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -1960,16 +1701,13 @@ namespace RemappingLogicTests dest.SetKey(0x41); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CAPITAL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CAPITAL } }, + }; // Send LWin+CapsLock keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -1992,16 +1730,13 @@ namespace RemappingLogicTests src.SetKey(VK_CAPITAL); testState.AddOSLevelShortcut(src, (DWORD)VK_CONTROL); - const int nInputs = 2; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CAPITAL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CAPITAL } }, + }; // Send LWin+CapsLock keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2027,18 +1762,14 @@ namespace RemappingLogicTests dest.SetKey(VK_CAPITAL); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + }; // Send Ctrl+A keydown followed by Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2064,18 +1795,14 @@ namespace RemappingLogicTests dest.SetKey(VK_CAPITAL); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + }; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_SHIFT; - - // Send Ctrl+A keydown followed by Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + // Send Ctrl+A keydown followed by Shift + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2098,18 +1825,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_CAPITAL); - const int nInputs = 3; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_CONTROL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + }; // Send Ctrl+A keydown followed by Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2132,18 +1855,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)VK_CAPITAL); - const int nInputs = 3; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + }; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = VK_SHIFT; - - // Send Ctrl+A keydown followed by Ctrl - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + // Send Ctrl+A keydown followed by Shift + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2163,18 +1882,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x42; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send Ctrl+A keydown, then B key up - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // A key state should be unchanged, Ctrl, V should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -2198,15 +1913,13 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Check that Ctrl+A was released and Disable key was not sent Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -2224,17 +1937,14 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = actionKey; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+Shift+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // Check that Ctrl+Shift+A was not released and Disable key was not sent Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -2253,20 +1963,19 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x42; - // send B - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + }; + + mockedInputHandler.SendVirtualInput(inputs2); // Check that Ctrl+A+B was pressed Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -2287,18 +1996,14 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = actionKey; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey, .dwFlags = KEYEVENTF_KEYUP } }, + }; // send Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Check that no keys are pressed Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), false); @@ -2306,10 +2011,12 @@ namespace RemappingLogicTests // Shortcut invoked state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isShortcutInvoked); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x42; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + }; + // send B - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // Check that Ctrl+B was pressed Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); @@ -2330,15 +2037,13 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // IsOriginalActionKeyPressed state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); @@ -2355,25 +2060,23 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // IsOriginalActionKeyPressed state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = actionKey; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey, .dwFlags = KEYEVENTF_KEYUP } }, + }; // release A - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // IsOriginalActionKeyPressed state should be false Assert::AreEqual(false, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); @@ -2390,28 +2093,24 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 3; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = actionKey; - input[2].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey, .dwFlags = KEYEVENTF_KEYUP } } + }; // send Ctrl+A, release A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // IsOriginalActionKeyPressed state should be false Assert::AreEqual(false, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = actionKey; - input[0].ki.dwFlags = 0; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // press A - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // IsOriginalActionKeyPressed state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); @@ -2428,25 +2127,23 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // IsOriginalActionKeyPressed state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // release Ctrl - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // IsOriginalActionKeyPressed state should be false Assert::AreEqual(false, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); @@ -2463,25 +2160,23 @@ namespace RemappingLogicTests testState.AddOSLevelShortcut(src, disableKey); - const int nInputs = 2; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = actionKey; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = actionKey } }, + }; // send Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // IsOriginalActionKeyPressed state should be true Assert::AreEqual(true, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x42; - input[0].ki.dwFlags = 0; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'B' } }, + }; // press B - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // IsOriginalActionKeyPressed state should be false Assert::AreEqual(false, testState.osLevelShortcutReMap[src].isOriginalActionKeyPressed); @@ -2509,16 +2204,13 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 2; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send LWin+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly twice with the above condition (since two dummy key events are sent in one set) Assert::AreEqual(2, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2539,18 +2231,14 @@ namespace RemappingLogicTests dest.SetKey(0x56); testState.AddOSLevelShortcut(src, dest); - const int nInputs = 3; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send LWin+Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Set sendvirtualinput call count condition to return true if the key event was a dummy key and LWin is pressed mockedInputHandler.SetSendVirtualInputTestHandler([this](LowlevelKeyboardEvent* data) { @@ -2560,12 +2248,12 @@ namespace RemappingLogicTests return false; }); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // SendVirtualInput should be called exactly twice with the above condition (since two dummy key events are sent in one set) Assert::AreEqual(2, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2590,16 +2278,13 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)0x56); - const int nInputs = 2; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 0x41; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send LWin+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly twice with the above condition (since two dummy key events are sent in one set) Assert::AreEqual(2, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2617,18 +2302,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)0x56); - const int nInputs = 3; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LWIN; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_CONTROL; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send LWin+Ctrl+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Set sendvirtualinput call count condition to return true if the key event was a dummy key and LWin is pressed mockedInputHandler.SetSendVirtualInputTestHandler([this](LowlevelKeyboardEvent* data) { @@ -2638,12 +2319,12 @@ namespace RemappingLogicTests return false; }); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release Ctrl - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // SendVirtualInput should be called exactly twice with the above condition (since two dummy key events are sent in one set) Assert::AreEqual(2, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -2660,18 +2341,14 @@ namespace RemappingLogicTests src.SetKey(0x41); testState.AddOSLevelShortcut(src, (DWORD)0x56); - const int nInputs = 3; - - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_SHIFT; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_LWIN; - input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_SHIFT } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LWIN } }, + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send Shift+LWin+A - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // Set sendvirtualinput call count condition to return true if the key event was a dummy key and LWin is pressed mockedInputHandler.SetSendVirtualInputTestHandler([this](LowlevelKeyboardEvent* data) { @@ -2681,12 +2358,12 @@ namespace RemappingLogicTests return false; }); - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Release A - mockedInputHandler.SendVirtualInput(1, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // SendVirtualInput should be called exactly twice with the above condition (since two dummy key events are sent in one set) Assert::AreEqual(2, mockedInputHandler.GetSendVirtualInputCallCount()); diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/SetKeyEventTests.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/SetKeyEventTests.cpp index 00f0e276ab..75be7288de 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/SetKeyEventTests.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/SetKeyEventTests.cpp @@ -34,7 +34,7 @@ namespace RemappingLogicTests TEST_METHOD (SetKeyEvent_ShouldUseExtendedKeyFlag_WhenArgumentIsExtendedKey) { const int nInputs = 15; - INPUT input[nInputs] = {}; + std::vector inputs; // List of extended keys WORD keyCodes[nInputs] = { VK_RCONTROL, VK_RMENU, VK_NUMLOCK, VK_SNAPSHOT, VK_CANCEL, VK_INSERT, VK_HOME, VK_PRIOR, VK_DELETE, VK_END, VK_NEXT, VK_LEFT, VK_DOWN, VK_RIGHT, VK_UP }; @@ -42,24 +42,22 @@ namespace RemappingLogicTests for (int i = 0; i < nInputs; i++) { // Set key events for all the extended keys - Helpers::SetKeyEvent(input, i, INPUT_KEYBOARD, keyCodes[i], 0, 0); + Helpers::SetKeyEvent(inputs, INPUT_KEYBOARD, keyCodes[i], 0, 0); // Extended key flag should be set - Assert::AreEqual(true, bool(input[i].ki.dwFlags & KEYEVENTF_EXTENDEDKEY)); + Assert::AreEqual(true, bool(inputs[i].ki.dwFlags & KEYEVENTF_EXTENDEDKEY)); } } - + // Test if SetKeyEvent sets the scan code field to 0 for dummy key TEST_METHOD (SetKeyEvent_ShouldSetScanCodeFieldTo0_WhenArgumentIsDummyKey) { - const int nInputs = KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE; - INPUT input[nInputs] = {}; + std::vector inputs{}; - int index = 0; - Helpers::SetDummyKeyEvent(input, index, 0); + Helpers::SetDummyKeyEvent(inputs, 0); // Assert that wScan for both inputs is 0 - Assert::AreEqual(0, input[0].ki.wScan); - Assert::AreEqual(0, input[1].ki.wScan); + Assert::AreEqual(0, inputs[0].ki.wScan); + Assert::AreEqual(0, inputs[1].ki.wScan); } }; } diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp index ae7e7d668a..de6597ae5c 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineTest/SingleKeyRemappingTests.cpp @@ -39,22 +39,24 @@ namespace RemappingLogicTests { // Remap A to B testState.AddSingleKeyRemap(0x41, (DWORD)0x42); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A key state should be unchanged, and B key state should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x42), true); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send A keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A key state should be unchanged, and B key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -66,21 +68,23 @@ namespace RemappingLogicTests { // Remap A to VK_DISABLE (disabled) testState.AddSingleKeyRemap(0x41, CommonSharedConstants::VK_DISABLED); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A key state should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send A keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A key state should be unchanged Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -91,22 +95,24 @@ namespace RemappingLogicTests { // Remap A to Common Win key testState.AddSingleKeyRemap(0x41, CommonSharedConstants::VK_WIN_BOTH); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A key state should be unchanged, and common Win key state should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LWIN), true); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send A keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A key state should be unchanged, and common Win key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -126,14 +132,13 @@ namespace RemappingLogicTests // Remap Caps Lock to Ctrl testState.AddSingleKeyRemap(VK_CAPITAL, (DWORD)VK_CONTROL); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CAPITAL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CAPITAL } }, + }; // Send Caps Lock keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -152,14 +157,13 @@ namespace RemappingLogicTests // Remap Ctrl to Caps Lock testState.AddSingleKeyRemap(VK_CONTROL, (DWORD)VK_CAPITAL); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + }; // Send Ctrl keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -182,14 +186,13 @@ namespace RemappingLogicTests dest.SetKey(VK_SHIFT); dest.SetKey(0x56); testState.AddSingleKeyRemap(VK_CAPITAL, dest); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CAPITAL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CAPITAL } }, + }; // Send Caps Lock keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly twice with the above condition Assert::AreEqual(2, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -211,14 +214,13 @@ namespace RemappingLogicTests dest.SetKey(VK_CONTROL); dest.SetKey(VK_CAPITAL); testState.AddSingleKeyRemap(VK_CONTROL, dest); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_CONTROL; + std::vector inputs{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_CONTROL } }, + }; // Send Ctrl keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs); // SendVirtualInput should be called exactly once with the above condition Assert::AreEqual(1, mockedInputHandler.GetSendVirtualInputCallCount()); @@ -232,23 +234,25 @@ namespace RemappingLogicTests dest.SetKey(VK_CONTROL); dest.SetKey(0x56); testState.AddSingleKeyRemap(0x41, dest); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A key state should be unchanged, and Ctrl, V key state should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), true); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send A keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A key state should be unchanged, and Ctrl, V key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -265,24 +269,26 @@ namespace RemappingLogicTests dest.SetKey(VK_SHIFT); dest.SetKey(0x56); testState.AddSingleKeyRemap(0x41, dest); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = 0x41; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A' } }, + }; // Send A keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // A key state should be unchanged, and Ctrl, Shift, V key state should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_CONTROL), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_SHIFT), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), true); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = 'A', .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send A keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // A key state should be unchanged, and Ctrl, Shift, V key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x41), false); @@ -299,22 +305,24 @@ namespace RemappingLogicTests dest.SetKey(VK_LCONTROL); dest.SetKey(0x56); testState.AddSingleKeyRemap(VK_LCONTROL, dest); - const int nInputs = 1; - INPUT input[nInputs] = {}; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_LCONTROL; + std::vector inputs1{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LCONTROL } }, + }; // Send LCtrl keydown - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs1); // LCtrl, V key state should be true Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LCONTROL), true); Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(0x56), true); - input[0].ki.dwFlags = KEYEVENTF_KEYUP; + + std::vector inputs2{ + { .type = INPUT_KEYBOARD, .ki = { .wVk = VK_LCONTROL, .dwFlags = KEYEVENTF_KEYUP } }, + }; // Send LCtrl keyup - mockedInputHandler.SendVirtualInput(nInputs, input, sizeof(INPUT)); + mockedInputHandler.SendVirtualInput(inputs2); // LCtrl, V key state should be false Assert::AreEqual(mockedInputHandler.GetVirtualKeyState(VK_LCONTROL), false); diff --git a/src/modules/keyboardmanager/common/Helpers.cpp b/src/modules/keyboardmanager/common/Helpers.cpp index 00136c7ef5..e080dd4ec0 100644 --- a/src/modules/keyboardmanager/common/Helpers.cpp +++ b/src/modules/keyboardmanager/common/Helpers.cpp @@ -154,29 +154,29 @@ namespace Helpers } // Function to set the value of a key event based on the arguments - void SetKeyEvent(LPINPUT keyEventArray, int index, DWORD inputType, WORD keyCode, DWORD flags, ULONG_PTR extraInfo) + void SetKeyEvent(std::vector& keyEventArray, DWORD inputType, WORD keyCode, DWORD flags, ULONG_PTR extraInfo) { - keyEventArray[index].type = inputType; - keyEventArray[index].ki.wVk = keyCode; - keyEventArray[index].ki.dwFlags = flags; + INPUT keyEvent{}; + keyEvent.type = inputType; + keyEvent.ki.wVk = keyCode; + keyEvent.ki.dwFlags = flags; if (IsExtendedKey(keyCode)) { - keyEventArray[index].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + keyEvent.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; } - keyEventArray[index].ki.dwExtraInfo = extraInfo; + keyEvent.ki.dwExtraInfo = extraInfo; // Set wScan to the value from MapVirtualKey as some applications may use the scan code for handling input, for instance, Windows Terminal ignores non-character input which has scancode set to 0. // MapVirtualKey returns 0 if the key code does not correspond to a physical key (such as unassigned/reserved keys). More details at https://github.com/microsoft/PowerToys/pull/7143#issue-498877747 - keyEventArray[index].ki.wScan = static_cast(MapVirtualKey(keyCode, MAPVK_VK_TO_VSC)); + keyEvent.ki.wScan = static_cast(MapVirtualKey(keyCode, MAPVK_VK_TO_VSC)); + keyEventArray.push_back(keyEvent); } // Function to set the dummy key events used for remapping shortcuts, required to ensure releasing a modifier doesn't trigger another action (For example, Win->Start Menu or Alt->Menu bar) - void SetDummyKeyEvent(LPINPUT keyEventArray, int& index, ULONG_PTR extraInfo) + void SetDummyKeyEvent(std::vector& keyEventArray, ULONG_PTR extraInfo) { - SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(KeyboardManagerConstants::DUMMY_KEY), 0, extraInfo); - index++; - SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(KeyboardManagerConstants::DUMMY_KEY), KEYEVENTF_KEYUP, extraInfo); - index++; + SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(KeyboardManagerConstants::DUMMY_KEY), 0, extraInfo); + SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(KeyboardManagerConstants::DUMMY_KEY), KEYEVENTF_KEYUP, extraInfo); } // Function to return window handle for a full screen UWP app @@ -240,7 +240,7 @@ namespace Helpers } // Function to set key events for modifier keys: When shortcutToCompare is passed (non-empty shortcut), then the key event is sent only if both shortcut's don't have the same modifier key. When keyToBeReleased is passed (non-NULL), then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, LPINPUT keyEventArray, int& index, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare, const DWORD& keyToBeReleased) + void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare, const DWORD& keyToBeReleased) { // If key down is to be sent, send in the order Win, Ctrl, Alt, Shift if (isKeyDown) @@ -248,23 +248,19 @@ namespace Helpers // If shortcutToCompare is non-empty, then the key event is sent only if both shortcut's don't have the same modifier key. If keyToBeReleased is non-NULL, then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckWinKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), 0, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), 0, extraInfoFlag); } if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), 0, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), 0, extraInfoFlag); } if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckAltKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), 0, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), 0, extraInfoFlag); } if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckShiftKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), 0, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), 0, extraInfoFlag); } } @@ -274,23 +270,35 @@ namespace Helpers // If shortcutToCompare is non-empty, then the key event is sent only if both shortcut's don't have the same modifier key. If keyToBeReleased is non-NULL, then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey() || shortcutToBeSent.CheckShiftKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), KEYEVENTF_KEYUP, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), KEYEVENTF_KEYUP, extraInfoFlag); } if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey() || shortcutToBeSent.CheckAltKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), KEYEVENTF_KEYUP, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), KEYEVENTF_KEYUP, extraInfoFlag); } if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey() || shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), KEYEVENTF_KEYUP, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), KEYEVENTF_KEYUP, extraInfoFlag); } if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked) || shortcutToBeSent.CheckWinKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), KEYEVENTF_KEYUP, extraInfoFlag); - index++; + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), KEYEVENTF_KEYUP, extraInfoFlag); + } + } + } + + void SetTextKeyEvents(std::vector& keyEventArray, const std::wstring& remapping) + { + for (wchar_t c : remapping) + { + for (DWORD flag : { 0, KEYEVENTF_KEYUP }) + { + INPUT input{}; + input.type = INPUT_KEYBOARD; + input.ki.dwFlags = KEYEVENTF_UNICODE | flag; + input.ki.dwExtraInfo = KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG; + input.ki.wScan = c; + keyEventArray.push_back(input); } } } diff --git a/src/modules/keyboardmanager/common/Helpers.h b/src/modules/keyboardmanager/common/Helpers.h index 27005a0146..e9b02590a7 100644 --- a/src/modules/keyboardmanager/common/Helpers.h +++ b/src/modules/keyboardmanager/common/Helpers.h @@ -14,7 +14,7 @@ namespace Helpers Shift, Action }; - + // Functions to encode that a key is originated from numpad DWORD EncodeKeyNumpadOrigin(const DWORD key, const bool extended); DWORD ClearKeyNumpadOrigin(const DWORD key); @@ -31,10 +31,13 @@ namespace Helpers KeyType GetKeyType(DWORD key); // Function to set the value of a key event based on the arguments - void SetKeyEvent(LPINPUT keyEventArray, int index, DWORD inputType, WORD keyCode, DWORD flags, ULONG_PTR extraInfo); + void SetKeyEvent(std::vector& keyEventArray, DWORD inputType, WORD keyCode, DWORD flags, ULONG_PTR extraInfo); // Function to set the dummy key events used for remapping shortcuts, required to ensure releasing a modifier doesn't trigger another action (For example, Win->Start Menu or Alt->Menu bar) - void SetDummyKeyEvent(LPINPUT keyEventArray, int& index, ULONG_PTR extraInfo); + void SetDummyKeyEvent(std::vector& keyEventArray, ULONG_PTR extraInfo); + + // Function to set key events for remapping text. + void SetTextKeyEvents(std::vector& keyEventArray, const std::wstring& remapping); // Function to return window handle for a full screen UWP app HWND GetFullscreenUWPWindowHandle(); @@ -43,7 +46,7 @@ namespace Helpers std::wstring GetCurrentApplication(bool keepPath); // Function to set key events for modifier keys: When shortcutToCompare is passed (non-empty shortcut), then the key event is sent only if both shortcut's don't have the same modifier key. When keyToBeReleased is passed (non-NULL), then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, LPINPUT keyEventArray, int& index, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL); + void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL); // Function to filter the key codes for artificial key codes int32_t FilterArtificialKeys(const int32_t& key); diff --git a/src/modules/keyboardmanager/common/Input.h b/src/modules/keyboardmanager/common/Input.h index 4358403f70..552182079d 100644 --- a/src/modules/keyboardmanager/common/Input.h +++ b/src/modules/keyboardmanager/common/Input.h @@ -1,7 +1,9 @@ #pragma once -#include +#include +#include #include +#include namespace KeyboardManagerInput { @@ -10,9 +12,16 @@ namespace KeyboardManagerInput { public: // Function to simulate input - UINT SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize) + void SendVirtualInput(const std::vector& inputs) { - return SendInput(cInputs, pInputs, cbSize); + std::vector copy = inputs; + UINT eventCount = SendInput(static_cast(copy.size()), copy.data(), sizeof(INPUT)); + if (eventCount != copy.size()) + { + Logger::error( + L"Failed to send input events. {}", + get_last_error_or_default(GetLastError())); + } } // Function to get the state of a particular key diff --git a/src/modules/keyboardmanager/common/InputInterface.h b/src/modules/keyboardmanager/common/InputInterface.h index 2ae738a846..f6728d92d0 100644 --- a/src/modules/keyboardmanager/common/InputInterface.h +++ b/src/modules/keyboardmanager/common/InputInterface.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include + namespace KeyboardManagerInput { // Interface used to wrap keyboard input library methods @@ -7,7 +11,7 @@ namespace KeyboardManagerInput { public: // Function to simulate input - virtual UINT SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize) = 0; + virtual void SendVirtualInput(const std::vector& inputs) = 0; // Function to get the state of a particular key virtual bool GetVirtualKeyState(int key) = 0; diff --git a/src/modules/keyboardmanager/common/KeyboardEventHandlers.cpp b/src/modules/keyboardmanager/common/KeyboardEventHandlers.cpp index be965cab7a..d87151c573 100644 --- a/src/modules/keyboardmanager/common/KeyboardEventHandlers.cpp +++ b/src/modules/keyboardmanager/common/KeyboardEventHandlers.cpp @@ -10,14 +10,11 @@ namespace KeyboardEventHandlers void SetNumLockToPreviousState(KeyboardManagerInput::InputInterface& ii) { // Num Lock's key state is applied before it is intercepted by low level keyboard hooks, so we have to manually set back the state when we suppress the key. This is done by sending an additional key up, key down set of messages. - // We need 2 key events because after Num Lock is suppressed, key up to release num lock key and key down to revert the num lock state - int key_count = 2; - LPINPUT keyEventList = new INPUT[size_t(key_count)]{}; + std::vector keyEventList; // Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, VK_NUMLOCK, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); - Helpers::SetKeyEvent(keyEventList, 1, INPUT_KEYBOARD, VK_NUMLOCK, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); - ii.SendVirtualInput(static_cast(key_count), keyEventList, sizeof(INPUT)); - delete[] keyEventList; + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, VK_NUMLOCK, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); + Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, VK_NUMLOCK, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); + ii.SendVirtualInput(keyEventList); } }