]> source.dussan.org Git - tigervnc.git/commitdiff
rfb_win32: Use scan codes if available
authorRahul Kale <Rahul.Kale@barco.com>
Wed, 12 Jul 2017 22:35:58 +0000 (00:35 +0200)
committerPierre Ossman <ossman@cendio.se>
Mon, 11 Sep 2017 14:40:12 +0000 (16:40 +0200)
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 <Rahul.Kale@barco.com>
Signed-off-by: Peter Korsgaard <peter.korsgaard@barco.com>
win/rfb_win32/SInput.cxx
win/rfb_win32/SInput.h
win/vncconfig/Inputs.h
win/vncconfig/resource.h
win/vncconfig/vncconfig.rc

index 15ef4b063ad2cdf0825a83cf0ff3579333edbc49..f6075c1663e609bca3daae267992ef0e591913db 100644 (file)
@@ -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;
index f7949ec4e6e7be9c337aa96831e67199482ac49b..c927c65f18ccdc38f4341ab2d5ff22f88ddf35f0 100644 (file)
@@ -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<rdr::U32,rdr::U8> vkMap;
       std::map<rdr::U32,bool> extendedMap;
index 2ad3b42505475c55d4eb15264ff2164f894a1283..f290831ed67abf91312fa4dfca0aadcb9ffbfdae 100644 (file)
@@ -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));
index 243f8247fa82927fbe7851a9cbad1cb3cb8a8bda..16bbc15be8c3754fd68b4b029d6fd568f8f8b4fe 100644 (file)
@@ -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
index 4da1a3b8cb5f0f93623bf1731667c7f942feb425..f23bbdb402ffa1e80c0de6b59a5e1a03dab05690 100644 (file)
@@ -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