mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
* Move KBM engine into separate process (#10672) * [KBM] Migrate KBM UI out of the runner (#10709) * Clean up keyboard hook handles (#10817) * [C++ common] Unhandled exception handler (#10821) * [KBM] Use icon in the KeyboardManagerEditor (#10845) * [KBM] Move resources from the Common project to the Editor. (#10844) * KBM Editor tests (#10858) * Rename engine executable (#10868) * clean up (#10870) * [KBM] Changed Editor and libraries output folders (#10871) * [KBM] New logs structure (#10872) * Add unhandled exception handling to the editor (#10874) * [KBM] Trace for edit keyboard window * Logging for XamlBridge message loop * [KBM] Added Editor and Engine to the installer (#10876) * Fix spelling * Interprocess communication logs, remove unnecessary windows message logs * [KBM] Separated telemetry for the engine and editor. (#10889) * [KBM] Editor test project (#10891) * Versions for the engine and the editor (#10897) * Add the editor's and the engine's executables to signing process (#10900) * [KBM editor] Run only one instance, exit when parent process exits (#10890) * [KBM] Force kill editor process to avoid XAML crash (#10907) * [KBM] Force kill editor process to avoid XAML crash * Fix event releasing Co-authored-by: mykhailopylyp <17161067+mykhailopylyp@users.noreply.github.com> * Make the editor dpi aware (#10908) * [KBM] KeyboardManagerCommon refactoring (#10909) * Do not start the process if it is already started (#10910) * logs * Update src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp * Update src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp * [KBM] Rename InitUnhandledExceptionHandler to make it explicit that is for x64 only. We will fix it properly when adding support for ARM64 and add a header with the proper conditional building. * [KBM] rename file/class/variables using camel case * [KBM] Rename "event_locker" -> "EventLocker" * [KBM] rename process_waiter Add a TODO comment * [KBM] rename methods Add TODO comment * [KBM] use uppercase for function names * [KBM] use uppercase for methos, lowercase for properties * [KBM] rename method, make methods private, formatting * [KBM] rename private variables * [KBM] use uppercase for function names * [KBM] Added support to run the editor stand-alone when built in debug mode * Update src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp * Check success of event creation, comment (#10947) * [KBM] code formatting (#10951) * [KBM] code formatting * Update src/modules/keyboardmanager/KeyboardManagerEditorLibrary/BufferValidationHelpers.cpp * [KBM] tracing * [KBM] Remappings not showing fix. (#10954) * removed mutex * retry loop for reading * retry on reading config once * log error Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com> Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com> Co-authored-by: Seraphima Zykova <zykovas91@gmail.com> Co-authored-by: Enrico Giordani <enricogior@users.noreply.github.com> Co-authored-by: Enrico Giordani <enrico.giordani@gmail.com>
164 lines
5.5 KiB
C++
164 lines
5.5 KiB
C++
#include "pch.h"
|
|
#include "MockedInput.h"
|
|
|
|
using namespace KeyboardManagerInput;
|
|
|
|
// Set the keyboard hook procedure to be tested
|
|
void MockedInput::SetHookProc(std::function<intptr_t(LowlevelKeyboardEvent*)> hookProcedure)
|
|
{
|
|
hookProc = hookProcedure;
|
|
}
|
|
|
|
// Function to simulate keyboard input - arguments and return value based on SendInput function (https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput)
|
|
UINT MockedInput::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize)
|
|
{
|
|
// Iterate over inputs
|
|
for (UINT i = 0; i < cInputs; i++)
|
|
{
|
|
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://docs.microsoft.com/en-us/windows/win32/inputdev/wm-syskeydown
|
|
if (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP)
|
|
{
|
|
if (keyboardState[VK_MENU] == true)
|
|
{
|
|
keyEvent.wParam = WM_SYSKEYUP;
|
|
}
|
|
else
|
|
{
|
|
keyEvent.wParam = WM_KEYUP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pInputs[i].ki.wVk == VK_F10 || keyboardState[VK_MENU] == true)
|
|
{
|
|
keyEvent.wParam = WM_SYSKEYDOWN;
|
|
}
|
|
else
|
|
{
|
|
keyEvent.wParam = WM_KEYDOWN;
|
|
}
|
|
}
|
|
KBDLLHOOKSTRUCT lParam = {};
|
|
|
|
// Set only vkCode and dwExtraInfo since other values are unused
|
|
lParam.vkCode = pInputs[i].ki.wVk;
|
|
lParam.dwExtraInfo = pInputs[i].ki.dwExtraInfo;
|
|
keyEvent.lParam = &lParam;
|
|
|
|
// If the SendVirtualInput call condition is true, increment the count. If no condition is set then always increment the count
|
|
if (sendVirtualInputCallCondition == nullptr || sendVirtualInputCallCondition(&keyEvent))
|
|
{
|
|
sendVirtualInputCallCount++;
|
|
}
|
|
|
|
// Call low level hook handler
|
|
intptr_t result = MockedKeyboardHook(&keyEvent);
|
|
|
|
// Set keyboard state if the hook does not suppress the input
|
|
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;
|
|
|
|
// Handling modifier key codes
|
|
switch (pInputs[i].ki.wVk)
|
|
{
|
|
case VK_CONTROL:
|
|
if (pInputs[i].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;
|
|
break;
|
|
case VK_RCONTROL:
|
|
keyboardState[VK_CONTROL] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true;
|
|
break;
|
|
case VK_MENU:
|
|
if (pInputs[i].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;
|
|
break;
|
|
case VK_RMENU:
|
|
keyboardState[VK_MENU] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true;
|
|
break;
|
|
case VK_SHIFT:
|
|
if (pInputs[i].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;
|
|
break;
|
|
case VK_RSHIFT:
|
|
keyboardState[VK_SHIFT] = (pInputs[i].ki.dwFlags & KEYEVENTF_KEYUP) ? false : true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return cInputs;
|
|
}
|
|
|
|
// Function to simulate keyboard hook behavior
|
|
intptr_t MockedInput::MockedKeyboardHook(LowlevelKeyboardEvent* data)
|
|
{
|
|
// If the hookProc is set to null, then skip the hook
|
|
if (hookProc != nullptr)
|
|
{
|
|
return hookProc(data);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Function to get the state of a particular key
|
|
bool MockedInput::GetVirtualKeyState(int key)
|
|
{
|
|
return keyboardState[key];
|
|
}
|
|
|
|
// Function to reset the mocked keyboard state
|
|
void MockedInput::ResetKeyboardState()
|
|
{
|
|
std::fill(keyboardState.begin(), keyboardState.end(), false);
|
|
}
|
|
|
|
// Function to set SendVirtualInput call count condition
|
|
void MockedInput::SetSendVirtualInputTestHandler(std::function<bool(LowlevelKeyboardEvent*)> condition)
|
|
{
|
|
sendVirtualInputCallCount = 0;
|
|
sendVirtualInputCallCondition = condition;
|
|
}
|
|
|
|
// Function to get SendVirtualInput call count
|
|
int MockedInput::GetSendVirtualInputCallCount()
|
|
{
|
|
return sendVirtualInputCallCount;
|
|
}
|
|
|
|
// Function to get the foreground process name
|
|
void MockedInput::SetForegroundProcess(std::wstring process)
|
|
{
|
|
currentProcess = process;
|
|
}
|
|
|
|
// Function to get the foreground process name
|
|
void MockedInput::GetForegroundProcess(_Out_ std::wstring& foregroundProcess)
|
|
{
|
|
foregroundProcess = currentProcess;
|
|
}
|