From: Rahul Kale Date: Wed, 12 Jul 2017 22:35:58 +0000 (+0200) Subject: rfb_win32: Use scan codes if available X-Git-Tag: v1.8.90~116^2~3 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7423417f7a4da1da90b4d31b9cbeadce83668126;p=tigervnc.git rfb_win32: Use scan codes if available If scan codes are available using QEMU Extended Keyboard Messages from clients, use that to inject scancodes directly into the system using the SendInput API. No conversion is needed as Windows uses the same scancode encoding. Signed-off-by: Rahul Kale Signed-off-by: Peter Korsgaard --- diff --git a/win/rfb_win32/SInput.cxx b/win/rfb_win32/SInput.cxx index 15ef4b06..f6075c16 100644 --- a/win/rfb_win32/SInput.cxx +++ b/win/rfb_win32/SInput.cxx @@ -134,6 +134,9 @@ win32::SPointer::pointerEvent(const Point& pos, int buttonmask) BoolParameter rfb::win32::SKeyboard::deadKeyAware("DeadKeyAware", "Whether to assume the viewer has already interpreted dead key sequences " "into latin-1 characters", true); +BoolParameter rfb::win32::SKeyboard::rawKeyboard("RawKeyboard", + "Send keyboard events straight through and avoid mapping them to the " + "current keyboard layout", false); // The keysymToAscii table transforms a couple of awkward keysyms into their // ASCII equivalents. @@ -229,6 +232,31 @@ inline void doKeyboardEvent(BYTE vkCode, DWORD flags) { keybd_event(vkCode, MapVirtualKey(vkCode, 0), flags, 0); } +inline void doScanCodeEvent(BYTE scancode, bool down) { + INPUT evt; + + evt.type = INPUT_KEYBOARD; + evt.ki.wVk = 0; + evt.ki.dwFlags = KEYEVENTF_SCANCODE; + + if (!down) + evt.ki.dwFlags |= KEYEVENTF_KEYUP; + + if (scancode & 0x80) { + evt.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + scancode &= ~0x80; + } + + evt.ki.wScan = scancode; + evt.ki.dwExtraInfo = 0; + evt.ki.time = 0; + vlog.debug("SendInput ScanCode: 0x%x Flags: 0x%lx %s", scancode, + evt.ki.dwFlags, down ? "Down" : "Up"); + + if (SendInput(1, &evt, sizeof(evt)) != 1) + vlog.error("SendInput %lu", GetLastError()); +} + // KeyStateModifier is a class which helps simplify generating a "fake" press // or release of shift, ctrl, alt, etc. An instance of the class is created // for every key which may need to be pressed or released. Then either press() @@ -323,6 +351,13 @@ win32::SKeyboard::SKeyboard() 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) { + doScanCodeEvent(keycode, down); + return; + } + for (unsigned int i = 0; i < sizeof(keysymToAscii) / sizeof(keysymToAscii_t); i++) { if (keysymToAscii[i].keysym == keysym) { keysym = keysymToAscii[i].ascii; diff --git a/win/rfb_win32/SInput.h b/win/rfb_win32/SInput.h index f7949ec4..c927c65f 100644 --- a/win/rfb_win32/SInput.h +++ b/win/rfb_win32/SInput.h @@ -55,6 +55,7 @@ namespace rfb { SKeyboard(); void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); static BoolParameter deadKeyAware; + static BoolParameter rawKeyboard; private: std::map vkMap; std::map extendedMap; diff --git a/win/vncconfig/Inputs.h b/win/vncconfig/Inputs.h index 2ad3b425..f290831e 100644 --- a/win/vncconfig/Inputs.h +++ b/win/vncconfig/Inputs.h @@ -37,6 +37,7 @@ namespace rfb { regKey(rk), enableAffectSSaver(true) {} void initDialog() { setItemChecked(IDC_ACCEPT_KEYS, rfb::Server::acceptKeyEvents); + setItemChecked(IDC_RAW_KEYBOARD, SKeyboard::rawKeyboard); setItemChecked(IDC_ACCEPT_PTR, rfb::Server::acceptPointerEvents); setItemChecked(IDC_ACCEPT_CUTTEXT, rfb::Server::acceptCutText); setItemChecked(IDC_SEND_CUTTEXT, rfb::Server::sendCutText); @@ -52,6 +53,7 @@ namespace rfb { BOOL inputResetsBlocked; SystemParametersInfo(SPI_GETBLOCKSENDINPUTRESETS, 0, &inputResetsBlocked, 0); setChanged((rfb::Server::acceptKeyEvents != isItemChecked(IDC_ACCEPT_KEYS)) || + (SKeyboard::rawKeyboard != isItemChecked(IDC_RAW_KEYBOARD)) || (rfb::Server::acceptPointerEvents != isItemChecked(IDC_ACCEPT_PTR)) || (rfb::Server::acceptCutText != isItemChecked(IDC_ACCEPT_CUTTEXT)) || (rfb::Server::sendCutText != isItemChecked(IDC_SEND_CUTTEXT)) || @@ -61,6 +63,7 @@ namespace rfb { } bool onOk() { regKey.setBool(_T("AcceptKeyEvents"), isItemChecked(IDC_ACCEPT_KEYS)); + regKey.setBool(_T("RawKeyboard"), isItemChecked(IDC_RAW_KEYBOARD)); regKey.setBool(_T("AcceptPointerEvents"), isItemChecked(IDC_ACCEPT_PTR)); regKey.setBool(_T("AcceptCutText"), isItemChecked(IDC_ACCEPT_CUTTEXT)); regKey.setBool(_T("SendCutText"), isItemChecked(IDC_SEND_CUTTEXT)); diff --git a/win/vncconfig/resource.h b/win/vncconfig/resource.h index 243f8247..16bbc15b 100644 --- a/win/vncconfig/resource.h +++ b/win/vncconfig/resource.h @@ -77,6 +77,7 @@ #define IDC_RFB_ENABLE 1082 #define IDC_LOAD_CERT 1087 #define IDC_LOAD_CERTKEY 1088 +#define IDC_RAW_KEYBOARD 1089 #define ID_OPTIONS 40001 #define ID_CLOSE 40002 #define ID_ABOUT 40003 diff --git a/win/vncconfig/vncconfig.rc b/win/vncconfig/vncconfig.rc index 4da1a3b8..f23bbdb4 100644 --- a/win/vncconfig/vncconfig.rc +++ b/win/vncconfig/vncconfig.rc @@ -206,17 +206,19 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,10,172,15 CONTROL "Accept keyboard events from clients",IDC_ACCEPT_KEYS, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,25,172,15 + CONTROL "Send raw keyboard events to applications",IDC_RAW_KEYBOARD, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,172,15 CONTROL "Accept clipboard updates from clients", IDC_ACCEPT_CUTTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, - 7,40,172,15 + 7,55,172,15 CONTROL "Send clipboard updates to clients",IDC_SEND_CUTTEXT, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,172,15 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,70,172,15 CONTROL "Allow input events to affect the screen-saver", IDC_AFFECT_SCREENSAVER,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,70,172,15 + WS_TABSTOP,7,85,172,15 CONTROL "Disable local inputs while server is in use", IDC_DISABLE_LOCAL_INPUTS,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,95,172,15 + WS_TABSTOP,7,110,172,15 END IDD_ABOUT DIALOG DISCARDABLE 0, 0, 300, 92