fix: resync Windows keys from low-level hook state
This commit is contained in:
parent
079dee7682
commit
141779be1d
3 changed files with 32 additions and 6 deletions
|
|
@ -10,6 +10,9 @@
|
|||
#include "base/Log.h"
|
||||
#include "deskflow/ScreenException.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
|
@ -34,6 +37,8 @@ static WPARAM g_deadRelease = 0;
|
|||
static LPARAM g_deadLParam = 0;
|
||||
static BYTE g_deadKeyState[256] = {0};
|
||||
static BYTE g_keyState[256] = {0};
|
||||
static bool g_keyStateValid = false;
|
||||
static std::mutex g_keyStateMutex;
|
||||
static DWORD g_hookThread = 0;
|
||||
static bool g_fakeServerInput = false;
|
||||
static BOOL g_isPrimary = TRUE;
|
||||
|
|
@ -142,6 +147,15 @@ void MSWindowsHook::setMode(EHookMode mode)
|
|||
g_mode = mode;
|
||||
}
|
||||
|
||||
bool MSWindowsHook::getPhysicalKeyState(BYTE keys[256])
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_keyStateMutex);
|
||||
if (g_keyStateValid) {
|
||||
std::memcpy(keys, g_keyState, sizeof(g_keyState));
|
||||
}
|
||||
return g_keyStateValid;
|
||||
}
|
||||
|
||||
static void keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up)
|
||||
{
|
||||
// we have to use GetAsyncKeyState() rather than GetKeyState() because
|
||||
|
|
@ -152,6 +166,8 @@ static void keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up)
|
|||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_keyStateMutex);
|
||||
|
||||
// Keep track of key state on our own in case GetAsyncKeyState() fails
|
||||
g_keyState[vkCode] = kf_up ? 0 : 0x80;
|
||||
g_keyState[VK_SHIFT] = g_keyState[VK_LSHIFT] | g_keyState[VK_RSHIFT];
|
||||
|
|
@ -179,6 +195,7 @@ static void keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up)
|
|||
|
||||
key = GetKeyState(VK_CAPITAL);
|
||||
keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1));
|
||||
g_keyStateValid = true;
|
||||
}
|
||||
|
||||
static WPARAM makeKeyMsg(UINT virtKey, WCHAR wc, bool noAltGr)
|
||||
|
|
@ -240,17 +257,17 @@ static bool keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
|||
// tell server about event
|
||||
PostThreadMessage(g_threadID, DESKFLOW_MSG_DEBUG, wParam, lParam);
|
||||
|
||||
// ignore dead key release
|
||||
// we need the keyboard state for ToAscii()
|
||||
BYTE keys[256];
|
||||
keyboardGetState(keys, vkCode, kf_up);
|
||||
|
||||
// Update the physical state before ignoring a dead key release so it cannot remain down in the resync snapshot.
|
||||
if ((g_deadVirtKey == wParam || g_deadRelease == wParam) && (lParam & 0x80000000u) != 0) {
|
||||
g_deadRelease = 0;
|
||||
PostThreadMessage(g_threadID, DESKFLOW_MSG_DEBUG, wParam | 0x04000000, lParam);
|
||||
return false;
|
||||
}
|
||||
|
||||
// we need the keyboard state for ToAscii()
|
||||
BYTE keys[256];
|
||||
keyboardGetState(keys, vkCode, kf_up);
|
||||
|
||||
// ToAscii() maps ctrl+letter to the corresponding control code
|
||||
// and ctrl+backspace to delete. we don't want those translations
|
||||
// so clear the control modifier state. however, if we want to
|
||||
|
|
@ -671,6 +688,10 @@ int MSWindowsHook::uninstall()
|
|||
g_getMessage = nullptr;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_keyStateMutex);
|
||||
std::memset(g_keyState, 0, sizeof(g_keyState));
|
||||
g_keyStateValid = false;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ public:
|
|||
|
||||
void setMode(EHookMode mode);
|
||||
|
||||
//! Copy the hook's physical key state; false until it has observed an event.
|
||||
static bool getPhysicalKeyState(BYTE keys[256]);
|
||||
|
||||
static EHookResult install();
|
||||
|
||||
static int uninstall();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "common/Constants.h"
|
||||
#include "platform/MSWindowsDesks.h"
|
||||
#include "platform/MSWindowsHandle.h"
|
||||
#include "platform/MSWindowsHook.h"
|
||||
|
||||
// extended mouse buttons
|
||||
#if !defined(VK_XBUTTON1)
|
||||
|
|
@ -844,7 +845,8 @@ int32_t MSWindowsKeyState::pollActiveGroup() const
|
|||
void MSWindowsKeyState::pollPressedKeys(KeyButtonSet &pressedKeys) const
|
||||
{
|
||||
BYTE keyState[256];
|
||||
if (!GetKeyboardState(keyState)) {
|
||||
// The caller's GetKeyboardState queue can lag the low-level hook during a screen switch.
|
||||
if (!MSWindowsHook::getPhysicalKeyState(keyState) && !GetKeyboardState(keyState)) {
|
||||
LOG_WARN("keyboard state is unexpected");
|
||||
LOG_DEBUG("function 'GetKeyboardState' returned false on 'pollPressedKeys'");
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in a new issue