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 "base/Log.h"
|
||||||
#include "deskflow/ScreenException.h"
|
#include "deskflow/ScreenException.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#ifndef WM_MOUSEHWHEEL
|
#ifndef WM_MOUSEHWHEEL
|
||||||
#define WM_MOUSEHWHEEL 0x020E
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -34,6 +37,8 @@ static WPARAM g_deadRelease = 0;
|
||||||
static LPARAM g_deadLParam = 0;
|
static LPARAM g_deadLParam = 0;
|
||||||
static BYTE g_deadKeyState[256] = {0};
|
static BYTE g_deadKeyState[256] = {0};
|
||||||
static BYTE g_keyState[256] = {0};
|
static BYTE g_keyState[256] = {0};
|
||||||
|
static bool g_keyStateValid = false;
|
||||||
|
static std::mutex g_keyStateMutex;
|
||||||
static DWORD g_hookThread = 0;
|
static DWORD g_hookThread = 0;
|
||||||
static bool g_fakeServerInput = false;
|
static bool g_fakeServerInput = false;
|
||||||
static BOOL g_isPrimary = TRUE;
|
static BOOL g_isPrimary = TRUE;
|
||||||
|
|
@ -142,6 +147,15 @@ void MSWindowsHook::setMode(EHookMode mode)
|
||||||
g_mode = 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)
|
static void keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up)
|
||||||
{
|
{
|
||||||
// we have to use GetAsyncKeyState() rather than GetKeyState() because
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(g_keyStateMutex);
|
||||||
|
|
||||||
// Keep track of key state on our own in case GetAsyncKeyState() fails
|
// Keep track of key state on our own in case GetAsyncKeyState() fails
|
||||||
g_keyState[vkCode] = kf_up ? 0 : 0x80;
|
g_keyState[vkCode] = kf_up ? 0 : 0x80;
|
||||||
g_keyState[VK_SHIFT] = g_keyState[VK_LSHIFT] | g_keyState[VK_RSHIFT];
|
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);
|
key = GetKeyState(VK_CAPITAL);
|
||||||
keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1));
|
keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1));
|
||||||
|
g_keyStateValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WPARAM makeKeyMsg(UINT virtKey, WCHAR wc, bool noAltGr)
|
static WPARAM makeKeyMsg(UINT virtKey, WCHAR wc, bool noAltGr)
|
||||||
|
|
@ -240,17 +257,17 @@ static bool keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
// tell server about event
|
// tell server about event
|
||||||
PostThreadMessage(g_threadID, DESKFLOW_MSG_DEBUG, wParam, lParam);
|
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) {
|
if ((g_deadVirtKey == wParam || g_deadRelease == wParam) && (lParam & 0x80000000u) != 0) {
|
||||||
g_deadRelease = 0;
|
g_deadRelease = 0;
|
||||||
PostThreadMessage(g_threadID, DESKFLOW_MSG_DEBUG, wParam | 0x04000000, lParam);
|
PostThreadMessage(g_threadID, DESKFLOW_MSG_DEBUG, wParam | 0x04000000, lParam);
|
||||||
return false;
|
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
|
// ToAscii() maps ctrl+letter to the corresponding control code
|
||||||
// and ctrl+backspace to delete. we don't want those translations
|
// and ctrl+backspace to delete. we don't want those translations
|
||||||
// so clear the control modifier state. however, if we want to
|
// so clear the control modifier state. however, if we want to
|
||||||
|
|
@ -671,6 +688,10 @@ int MSWindowsHook::uninstall()
|
||||||
g_getMessage = nullptr;
|
g_getMessage = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(g_keyStateMutex);
|
||||||
|
std::memset(g_keyState, 0, sizeof(g_keyState));
|
||||||
|
g_keyStateValid = false;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,9 @@ public:
|
||||||
|
|
||||||
void setMode(EHookMode mode);
|
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 EHookResult install();
|
||||||
|
|
||||||
static int uninstall();
|
static int uninstall();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "platform/MSWindowsDesks.h"
|
#include "platform/MSWindowsDesks.h"
|
||||||
#include "platform/MSWindowsHandle.h"
|
#include "platform/MSWindowsHandle.h"
|
||||||
|
#include "platform/MSWindowsHook.h"
|
||||||
|
|
||||||
// extended mouse buttons
|
// extended mouse buttons
|
||||||
#if !defined(VK_XBUTTON1)
|
#if !defined(VK_XBUTTON1)
|
||||||
|
|
@ -844,7 +845,8 @@ int32_t MSWindowsKeyState::pollActiveGroup() const
|
||||||
void MSWindowsKeyState::pollPressedKeys(KeyButtonSet &pressedKeys) const
|
void MSWindowsKeyState::pollPressedKeys(KeyButtonSet &pressedKeys) const
|
||||||
{
|
{
|
||||||
BYTE keyState[256];
|
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_WARN("keyboard state is unexpected");
|
||||||
LOG_DEBUG("function 'GetKeyboardState' returned false on 'pollPressedKeys'");
|
LOG_DEBUG("function 'GetKeyboardState' returned false on 'pollPressedKeys'");
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue