From f73214c9ea5ee965c8bd5d7102d761408601118a Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 13 Nov 2017 09:06:03 +0100 Subject: [PATCH] Handle Windows scan code exceptions Windows mostly follows the AT set 1 scan codes that we want, but there are a few exceptions. --- vncviewer/Viewport.cxx | 32 +++++++++++++++++++++++--------- win/rfb_win32/SInput.cxx | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx index 31d09a1e..960a085c 100644 --- a/vncviewer/Viewport.cxx +++ b/vncviewer/Viewport.cxx @@ -894,10 +894,24 @@ int Viewport::handleSystemEvent(void *event, void *data) if (isExtended) keyCode |= 0x80; - // VK_SNAPSHOT sends different scan codes depending on the state of - // Alt. This means that we can get different scan codes on press and - // release. Force it to be something standard. - if (vKey == VK_SNAPSHOT) + + // Fortunately RFB and Windows use the same scan code set (mostly), + // so there is no conversion needed + // (as long as we encode the extended keys with the high bit) + + // However Pause sends a code that conflicts with NumLock, so use + // the code most RFB implementations use (part of the sequence for + // Ctrl+Pause, i.e. Break) + if (keyCode == 0x45) + keyCode = 0xc6; + + // And NumLock incorrectly has the extended bit set + if (keyCode == 0xc5) + keyCode = 0x45; + + // And Alt+PrintScreen (i.e. SysRq) sends a different code than + // PrintScreen + if (keyCode == 0xb7) keyCode = 0x54; keySym = win32_vkey_to_keysym(vKey, isExtended); @@ -908,10 +922,6 @@ int Viewport::handleSystemEvent(void *event, void *data) vlog.error(_("No symbol for virtual key 0x%02x"), (int)vKey); } - // Fortunately RFB and Windows use the same scan code set, - // so there is no conversion needed - // (as long as we encode the extended keys with the high bit) - self->handleKeyPress(keyCode, keySym); return 1; @@ -934,7 +944,11 @@ int Viewport::handleSystemEvent(void *event, void *data) keyCode = MapVirtualKey(vKey, MAPVK_VK_TO_VSC); if (isExtended) keyCode |= 0x80; - if (vKey == VK_SNAPSHOT) + if (keyCode == 0x45) + keyCode = 0xc6; + if (keyCode == 0xc5) + keyCode = 0x45; + if (keyCode == 0xb7) keyCode = 0x54; self->handleKeyRelease(keyCode); diff --git a/win/rfb_win32/SInput.cxx b/win/rfb_win32/SInput.cxx index f6075c16..e6da9b84 100644 --- a/win/rfb_win32/SInput.cxx +++ b/win/rfb_win32/SInput.cxx @@ -253,6 +253,16 @@ inline void doScanCodeEvent(BYTE scancode, bool down) { vlog.debug("SendInput ScanCode: 0x%x Flags: 0x%lx %s", scancode, evt.ki.dwFlags, down ? "Down" : "Up"); + // Windows has some bug where it doesn't look up scan code 0x45 + // properly, so we need to help it out + if (evt.ki.wScan == 0x45) { + evt.ki.dwFlags &= ~KEYEVENTF_SCANCODE; + if (evt.ki.dwFlags & KEYEVENTF_EXTENDEDKEY) + evt.ki.wVk = VK_NUMLOCK; + else + evt.ki.wVk = VK_PAUSE; + } + if (SendInput(1, &evt, sizeof(evt)) != 1) vlog.error("SendInput %lu", GetLastError()); } @@ -354,6 +364,19 @@ void win32::SKeyboard::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) // If scan code is available use that directly as windows uses // compatible scancodes if (keycode && rawKeyboard) { + // However NumLock incorrectly has the extended bit set + if (keycode == 0x45) + keycode = 0xc5; + + // And Pause uses NumLock's proper code, except when Control is + // also pressed (i.e. when it is generating Break) + if ((keycode == 0xc6) && !(GetAsyncKeyState(VK_CONTROL) & 0x8000)) + keycode = 0x45; + + // And PrintScreen uses a different code than Alt+PrintScreen (SysRq) + if ((keycode == 0x54) && !(GetAsyncKeyState(VK_MENU) & 0x8000)) + keycode = 0xb7; + doScanCodeEvent(keycode, down); return; } -- 2.39.5