From 8024aa9ab113adcd94d4010925b82dff5f81002d Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 4 Nov 2014 12:06:30 -0500 Subject: [PATCH] Working fix for #4055 (client shift key problem) in place --- src/lib/synwinhk/synwinhk.cpp | 48 +++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/lib/synwinhk/synwinhk.cpp b/src/lib/synwinhk/synwinhk.cpp index 5eeeb6f5..750075ac 100644 --- a/src/lib/synwinhk/synwinhk.cpp +++ b/src/lib/synwinhk/synwinhk.cpp @@ -118,6 +118,7 @@ static WPARAM g_deadVirtKey = 0; static WPARAM g_deadRelease = 0; static LPARAM g_deadLParam = 0; static BYTE g_deadKeyState[256] = { 0 }; +static BYTE g_keyState[256] = { 0 }; static DWORD g_hookThread = 0; static DWORD g_attachedThread = 0; static bool g_fakeInput = false; @@ -166,6 +167,7 @@ attachThreadToForeground() return false; DWORD threadID = GetWindowThreadProcessId(window, NULL); + // skip if no change if (g_attachedThread != threadID) { // detach from previous thread @@ -192,17 +194,37 @@ makeKeyMsg(UINT virtKey, char c, bool noAltGr) static void -keyboardGetState(BYTE keys[256]) +keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up) { - // we have to use GetAsyncKeyState() rather than GetKeyState() because - // we don't pass through most keys so the event synchronous state - // doesn't get updated. we do that because certain modifier keys have - // side effects, like alt and the windows key. - SHORT key; - for (int i = 0; i < 256; ++i) { - key = GetAsyncKeyState(i); - keys[i] = (BYTE)((key < 0) ? 0x80u : 0); + if (vkCode < 0 || vkCode >= 256) { + return; } + + // 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]; + + SHORT key; + // Test whether GetAsyncKeyState() is being honest with us + key = GetAsyncKeyState(vkCode); + + if (key & 0x80) { + // The only time we know for sure that GetAsyncKeyState() is working + // is when it tells us that the current key is down. + // In this case, update g_keyState to reflect what GetAsyncKeyState() + // is telling us, just in case we have gotten out of sync + + for (int i = 0; i < 256; ++i) { + key = GetAsyncKeyState(i); + g_keyState[i] = (BYTE)((key < 0) ? 0x80u : 0); + } + } + + // copy g_keyState to keys + for (int i = 0; i < 256; ++i) { + keys[i] = g_keyState[i]; + } + key = GetKeyState(VK_CAPITAL); keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1)); } @@ -211,6 +233,9 @@ static bool doKeyboardHookHandler(WPARAM wParam, LPARAM lParam) { + DWORD vkCode = wParam; + bool kf_up = (lParam & (KF_UP << 16)) != 0; + // check for special events indicating if we should start or stop // passing events through and not report them to the server. this // is used to allow the server to synthesize events locally but @@ -254,7 +279,7 @@ doKeyboardHookHandler(WPARAM wParam, LPARAM lParam) // we need the keyboard state for ToAscii() BYTE keys[256]; - keyboardGetState(keys); + 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 @@ -437,6 +462,7 @@ doKeyboardHookHandler(WPARAM wParam, LPARAM lParam) PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, charAndVirtKey, lParam); } + if (g_mode == kHOOK_RELAY_EVENTS) { // let certain keys pass through switch (wParam) { @@ -469,7 +495,7 @@ static bool keyboardHookHandler(WPARAM wParam, LPARAM lParam) { - attachThreadToForeground(); + bool attached = attachThreadToForeground(); return doKeyboardHookHandler(wParam, lParam); } #endif