]> source.dussan.org Git - tigervnc.git/commitdiff
Basic support for QEMU Extended Key Events
authorPierre Ossman <ossman@cendio.se>
Tue, 16 May 2017 12:30:38 +0000 (14:30 +0200)
committerPierre Ossman <ossman@cendio.se>
Mon, 28 Aug 2017 11:54:30 +0000 (13:54 +0200)
This adds the basic infrastructure and handshake for the QEMU
Extended Key Events extension. No viewer or server makes use of
the extra functionality yet though.

29 files changed:
common/rfb/CMsgHandler.cxx
common/rfb/CMsgHandler.h
common/rfb/CMsgReader.cxx
common/rfb/CMsgWriter.cxx
common/rfb/CMsgWriter.h
common/rfb/ConnParams.cxx
common/rfb/ConnParams.h
common/rfb/InputHandler.h
common/rfb/SConnection.cxx
common/rfb/SConnection.h
common/rfb/SMsgHandler.cxx
common/rfb/SMsgHandler.h
common/rfb/SMsgReader.cxx
common/rfb/SMsgReader.h
common/rfb/SMsgWriter.cxx
common/rfb/SMsgWriter.h
common/rfb/VNCSConnectionST.cxx
common/rfb/VNCSConnectionST.h
common/rfb/encodings.h
common/rfb/msgTypes.h
common/rfb/qemuTypes.h [new file with mode: 0644]
unix/x0vncserver/x0vncserver.cxx
unix/xserver/hw/vnc/XserverDesktop.cc
unix/xserver/hw/vnc/XserverDesktop.h
vncviewer/Viewport.cxx
win/rfb_win32/SDisplay.cxx
win/rfb_win32/SDisplay.h
win/rfb_win32/SInput.cxx
win/rfb_win32/SInput.h

index 74c7bf92377c84b83192c3eeb995ac3d5b20fabc..b89bc1842b93c92eda0f4e15e4211b7c3c462bab 100644 (file)
@@ -75,6 +75,11 @@ void CMsgHandler::endOfContinuousUpdates()
   cp.supportsContinuousUpdates = true;
 }
 
+void CMsgHandler::supportsQEMUKeyEvent()
+{
+  cp.supportsQEMUKeyEvent = true;
+}
+
 void CMsgHandler::framebufferUpdateStart()
 {
 }
index ef2cda20d32e4d75280689005ec720375755e011..903ee156a6ac4a87cd6764564764af408ed59e8b 100644 (file)
@@ -55,6 +55,7 @@ namespace rfb {
     virtual void setName(const char* name);
     virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
     virtual void endOfContinuousUpdates();
+    virtual void supportsQEMUKeyEvent();
     virtual void serverInit() = 0;
 
     virtual void readAndDecodeRect(const Rect& r, int encoding,
index 0aaf71fabb3dff46aac90561973fe10bc38d0492..eee6d277362d4926dc2e5866b47a61258aef354e 100644 (file)
@@ -111,6 +111,8 @@ void CMsgReader::readMsg()
       break;
     case pseudoEncodingLEDState:
       readLEDState();
+    case pseudoEncodingQEMUKeyEvent:
+      handler->supportsQEMUKeyEvent();
       break;
     default:
       readRect(Rect(x, y, x+w, y+h), encoding);
index 7a89a934051d4e33c467f4dcd04594551522efba..57d1283aeea17fb3dfe7b97f6dd733cbe7a00a6b 100644 (file)
@@ -21,6 +21,7 @@
 #include <rfb/msgTypes.h>
 #include <rfb/fenceTypes.h>
 #include <rfb/encodings.h>
+#include <rfb/qemuTypes.h>
 #include <rfb/Exception.h>
 #include <rfb/PixelFormat.h>
 #include <rfb/Rect.h>
@@ -88,6 +89,7 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
   encodings[nEncodings++] = pseudoEncodingLastRect;
   encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
   encodings[nEncodings++] = pseudoEncodingFence;
+  encodings[nEncodings++] = pseudoEncodingQEMUKeyEvent;
 
   if (Decoder::supported(preferredEncoding)) {
     encodings[nEncodings++] = preferredEncoding;
@@ -215,13 +217,26 @@ void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
   endMsg();
 }
 
-void CMsgWriter::keyEvent(rdr::U32 key, bool down)
+void CMsgWriter::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
 {
-  startMsg(msgTypeKeyEvent);
-  os->writeU8(down);
-  os->pad(2);
-  os->writeU32(key);
-  endMsg();
+  if (!cp->supportsQEMUKeyEvent || !keycode) {
+    /* This event isn't meaningful without a valid keysym */
+    if (!keysym)
+      return;
+
+    startMsg(msgTypeKeyEvent);
+    os->writeU8(down);
+    os->pad(2);
+    os->writeU32(keysym);
+    endMsg();
+  } else {
+    startMsg(msgTypeQEMUClientMessage);
+    os->writeU8(qemuExtendedKeyEvent);
+    os->writeU16(down);
+    os->writeU32(keysym);
+    os->writeU32(keycode);
+    endMsg();
+  }
 }
 
 
index 06ecbe7de749682ea45f11657679ebac6023abda..56e0b7b9f9673e73ce1eacae87bd670010572442 100644 (file)
@@ -55,7 +55,7 @@ namespace rfb {
 
     // InputHandler implementation
 
-    virtual void keyEvent(rdr::U32 key, bool down);
+    virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
     virtual void pointerEvent(const Point& pos, int buttonMask);
     virtual void clientCutText(const char* str, rdr::U32 len);
 
index f0b69327f2a61da46913163e2f858b219bdfe3fc..23f02ed0e43caf55740682f0ab20d3e939a209b5 100644 (file)
@@ -35,8 +35,9 @@ ConnParams::ConnParams()
     supportsLocalCursorWithAlpha(false),
     supportsDesktopResize(false), supportsExtendedDesktopSize(false),
     supportsDesktopRename(false), supportsLastRect(false),
-    supportsLEDState(false), supportsSetDesktopSize(false),
-    supportsFence(false), supportsContinuousUpdates(false),
+    supportsLEDState(false), supportsQEMUKeyEvent(false),
+    supportsSetDesktopSize(false), supportsFence(false),
+    supportsContinuousUpdates(false),
     compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
     subsampling(subsampleUndefined), name_(0), verStrPos(0),
     ledState_(ledUnknown)
@@ -109,6 +110,7 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
   supportsExtendedDesktopSize = false;
   supportsLocalXCursor = false;
   supportsLastRect = false;
+  supportsQEMUKeyEvent = false;
   compressLevel = -1;
   qualityLevel = -1;
   fineQualityLevel = -1;
@@ -145,6 +147,8 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
       break;
     case pseudoEncodingLEDState:
       supportsLEDState = true;
+    case pseudoEncodingQEMUKeyEvent:
+      supportsQEMUKeyEvent = true;
       break;
     case pseudoEncodingFence:
       supportsFence = true;
index d99d142c4c8f586805bfba7fd57da71956a0f673..b3222936e0cc76aa87a81acc658ab9667d9c1d27 100644 (file)
@@ -97,6 +97,7 @@ namespace rfb {
     bool supportsDesktopRename;
     bool supportsLastRect;
     bool supportsLEDState;
+    bool supportsQEMUKeyEvent;
 
     bool supportsSetDesktopSize;
     bool supportsFence;
index b5e5e87974065effc1f9351b2ed631f7d314dc6b..0344bc3f97f9ec62788ff60918106a5b3edfcb3c 100644 (file)
@@ -31,7 +31,7 @@ namespace rfb {
   class InputHandler {
   public:
     virtual ~InputHandler() {}
-    virtual void keyEvent(rdr::U32 key, bool down) {}
+    virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {}
     virtual void pointerEvent(const Point& pos, int buttonMask) {}
     virtual void clientCutText(const char* str, int len) {}
   };
index 85cc6e82476d880cf7cb5dcb6b4276897324b671..c5c9038ce8013be1f68c7f09c80f30e98869e6a2 100644 (file)
@@ -278,6 +278,11 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings)
   SMsgHandler::setEncodings(nEncodings, encodings);
 }
 
+void SConnection::supportsQEMUKeyEvent()
+{
+  writer()->writeQEMUKeyEvent();
+}
+
 void SConnection::versionReceived()
 {
 }
index 63dc31469ba463389c6927e28dd8dc5626e4bc11..bc435834ebdad7259082eba75b77d600fbf88794 100644 (file)
@@ -73,6 +73,7 @@ namespace rfb {
 
     virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
 
+    virtual void supportsQEMUKeyEvent();
 
     // Methods to be overridden in a derived class
 
index 8e48c6738120f423d9ce087241b81f3835f4a4bf..c38458c3df96f0adbb1cfc72903e1af2fe1c3f63 100644 (file)
@@ -41,11 +41,13 @@ void SMsgHandler::setPixelFormat(const PixelFormat& pf)
 
 void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
 {
-  bool firstFence, firstContinuousUpdates, firstLEDState;
+  bool firstFence, firstContinuousUpdates, firstLEDState,
+       firstQEMUKeyEvent;
 
   firstFence = !cp.supportsFence;
   firstContinuousUpdates = !cp.supportsContinuousUpdates;
   firstLEDState = !cp.supportsLEDState;
+  firstQEMUKeyEvent = !cp.supportsQEMUKeyEvent;
 
   cp.setEncodings(nEncodings, encodings);
 
@@ -57,6 +59,8 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)
     supportsContinuousUpdates();
   if (cp.supportsLEDState && firstLEDState)
     supportsLEDState();
+  if (cp.supportsQEMUKeyEvent && firstQEMUKeyEvent)
+    supportsQEMUKeyEvent();
 }
 
 void SMsgHandler::supportsLocalCursor()
@@ -75,6 +79,10 @@ void SMsgHandler::supportsLEDState()
 {
 }
 
+void SMsgHandler::supportsQEMUKeyEvent()
+{
+}
+
 void SMsgHandler::setDesktopSize(int fb_width, int fb_height,
                                  const ScreenSet& layout)
 {
index cf6b6b3b78bf95edf88b667aa9d682fad5ddfb79..749f05603df8802e78b895e36de884fd47f12a6d 100644 (file)
@@ -80,6 +80,11 @@ namespace rfb {
     // server state.
     virtual void supportsLEDState();
 
+    // supportsQEMUKeyEvent() is called the first time we detect that the
+    // client wants the QEMU Extended Key Event extension. The default
+    // handler will send a pseudo-rect back, signalling server support.
+    virtual void supportsQEMUKeyEvent();
+
     ConnParams cp;
   };
 }
index 3c08fd6fd58a5207fd28c2cd7ee21880e6708c88..cb71ac849cb9321e5cf7ca55d9220cf5c7f1d9e3 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <rdr/InStream.h>
 #include <rfb/msgTypes.h>
+#include <rfb/qemuTypes.h>
 #include <rfb/Exception.h>
 #include <rfb/util.h>
 #include <rfb/SMsgHandler.h>
@@ -78,6 +79,9 @@ void SMsgReader::readMsg()
   case msgTypeClientCutText:
     readClientCutText();
     break;
+  case msgTypeQEMUClientMessage:
+    readQEMUMessage();
+    break;
   default:
     fprintf(stderr, "unknown message type %d\n", msgType);
     throw Exception("unknown message type");
@@ -184,7 +188,7 @@ void SMsgReader::readKeyEvent()
   bool down = is->readU8();
   is->skip(2);
   rdr::U32 key = is->readU32();
-  handler->keyEvent(key, down);
+  handler->keyEvent(key, 0, down);
 }
 
 void SMsgReader::readPointerEvent()
@@ -214,3 +218,26 @@ void SMsgReader::readClientCutText()
   handler->clientCutText(ca.buf, len);
 }
 
+void SMsgReader::readQEMUMessage()
+{
+  int subType = is->readU8();
+  switch (subType) {
+  case qemuExtendedKeyEvent:
+    readQEMUKeyEvent();
+    break;
+  default:
+    throw Exception("unknown QEMU submessage type %d", subType);
+  }
+}
+
+void SMsgReader::readQEMUKeyEvent()
+{
+  bool down = is->readU16();
+  rdr::U32 keysym = is->readU32();
+  rdr::U32 keycode = is->readU32();
+  if (!keycode) {
+    vlog.error("Key event without keycode - ignoring");
+    return;
+  }
+  handler->keyEvent(keysym, keycode, down);
+}
index 00cb303177f44566651bff3df0eef4bfb83f45fa..146b29f8bea64aa1e2c97fae4873898afe79aec3 100644 (file)
@@ -55,6 +55,9 @@ namespace rfb {
     void readPointerEvent();
     void readClientCutText();
 
+    void readQEMUMessage();
+    void readQEMUKeyEvent();
+
     SMsgHandler* handler;
     rdr::InStream* is;
   };
index d8adfbc1c693b08a5701139b1fd6e8721644fe1b..2d4998b35b835f3f5fdcf03ddb805667ef47089e 100644 (file)
@@ -39,7 +39,7 @@ SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
     needSetDesktopSize(false), needExtendedDesktopSize(false),
     needSetDesktopName(false), needSetCursor(false),
     needSetXCursor(false), needSetCursorWithAlpha(false),
-    needLEDState(false)
+    needLEDState(false), needQEMUKeyEvent(false)
 {
 }
 
@@ -207,6 +207,16 @@ bool SMsgWriter::writeLEDState()
   return true;
 }
 
+bool SMsgWriter::writeQEMUKeyEvent()
+{
+  if (!cp->supportsQEMUKeyEvent)
+    return false;
+
+  needQEMUKeyEvent = true;
+
+  return true;
+}
+
 bool SMsgWriter::needFakeUpdate()
 {
   if (needSetDesktopName)
@@ -215,6 +225,8 @@ bool SMsgWriter::needFakeUpdate()
     return true;
   if (needLEDState)
     return true;
+  if (needQEMUKeyEvent)
+    return true;
   if (needNoDataUpdate())
     return true;
 
@@ -265,6 +277,8 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
       nRects++;
     if (needLEDState)
       nRects++;
+    if (needQEMUKeyEvent)
+      nRects++;
   }
 
   os->writeU16(nRects);
@@ -385,6 +399,11 @@ void SMsgWriter::writePseudoRects()
     writeLEDStateRect(cp->ledState());
     needLEDState = false;
   }
+
+  if (needQEMUKeyEvent) {
+    writeQEMUKeyEventRect();
+    needQEMUKeyEvent = false;
+  }
 }
 
 void SMsgWriter::writeNoDataRects()
@@ -565,3 +584,17 @@ void SMsgWriter::writeLEDStateRect(rdr::U8 state)
   os->writeU32(pseudoEncodingLEDState);
   os->writeU8(state);
 }
+
+void SMsgWriter::writeQEMUKeyEventRect()
+{
+  if (!cp->supportsQEMUKeyEvent)
+    throw Exception("Client does not support QEMU extended key events");
+  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+    throw Exception("SMsgWriter::writeQEMUKeyEventRect: nRects out of sync");
+
+  os->writeS16(0);
+  os->writeS16(0);
+  os->writeU16(0);
+  os->writeU16(0);
+  os->writeU32(pseudoEncodingQEMUKeyEvent);
+}
index 890b2b5bb82d537705a04f0723684b5ea71bf7af..f2adadca531adfe405d4f9b2ea0ded70ec2277ee 100644 (file)
@@ -85,6 +85,9 @@ namespace rfb {
     // Same for LED state message
     bool writeLEDState();
 
+    // And QEMU keyboard event handshake
+    bool writeQEMUKeyEvent();
+
     // needFakeUpdate() returns true when an immediate update is needed in
     // order to flush out pseudo-rectangles to the client.
     bool needFakeUpdate();
@@ -135,6 +138,7 @@ namespace rfb {
                                      int hotspotX, int hotspotY,
                                      const rdr::U8* data);
     void writeLEDStateRect(rdr::U8 state);
+    void writeQEMUKeyEventRect();
 
     ConnParams* cp;
     rdr::OutStream* os;
@@ -150,6 +154,7 @@ namespace rfb {
     bool needSetXCursor;
     bool needSetCursorWithAlpha;
     bool needLEDState;
+    bool needQEMUKeyEvent;
 
     typedef struct {
       rdr::U16 reason, result;
index 232776fc3bc946e2f45d87926265b7418ac9ad73..be496e73cf9e0d51a090612a08d66c6f79646b30 100644 (file)
@@ -103,7 +103,7 @@ VNCSConnectionST::~VNCSConnectionST()
   std::set<rdr::U32>::iterator i;
   for (i=pressedKeys.begin(); i!=pressedKeys.end(); i++) {
     vlog.debug("Releasing key 0x%x on client disconnect", *i);
-    server->desktop->keyEvent(*i, false);
+    server->desktop->keyEvent(*i, 0, false);
   }
   if (server->pointerClient == this)
     server->pointerClient = 0;
@@ -538,12 +538,12 @@ public:
   ~VNCSConnectionSTShiftPresser() {
     if (pressed) {
       vlog.debug("Releasing fake Shift_L");
-      desktop->keyEvent(XK_Shift_L, false);
+      desktop->keyEvent(XK_Shift_L, 0, false);
     }
   }
   void press() {
     vlog.debug("Pressing fake Shift_L");
-    desktop->keyEvent(XK_Shift_L, true);
+    desktop->keyEvent(XK_Shift_L, 0, true);
     pressed = true;
   }
   SDesktop* desktop;
@@ -552,32 +552,32 @@ public:
 
 // keyEvent() - record in the pressedKeys which keys were pressed.  Allow
 // multiple down events (for autorepeat), but only allow a single up event.
-void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) {
+void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
   lastEventTime = time(0);
   server->lastUserInputTime = lastEventTime;
   if (!(accessRights & AccessKeyEvents)) return;
   if (!rfb::Server::acceptKeyEvents) return;
 
   if (down)
-    vlog.debug("Key pressed: 0x%x", key);
+    vlog.debug("Key pressed: 0x%x / 0x%x", keysym, keycode);
   else
-    vlog.debug("Key released: 0x%x", key);
+    vlog.debug("Key released: 0x%x / 0x%x", keysym, keycode);
 
   // Remap the key if required
   if (server->keyRemapper) {
     rdr::U32 newkey;
-    newkey = server->keyRemapper->remapKey(key);
-    if (newkey != key) {
+    newkey = server->keyRemapper->remapKey(keysym);
+    if (newkey != keysym) {
       vlog.debug("Key remapped to 0x%x", newkey);
-      key = newkey;
+      keysym = newkey;
     }
   }
 
   // Avoid lock keys if we don't know the server state
   if ((server->ledState == ledUnknown) &&
-      ((key == XK_Caps_Lock) ||
-       (key == XK_Num_Lock) ||
-       (key == XK_Scroll_Lock))) {
+      ((keysym == XK_Caps_Lock) ||
+       (keysym == XK_Num_Lock) ||
+       (keysym == XK_Scroll_Lock))) {
     vlog.debug("Ignoring lock key (e.g. caps lock)");
     return;
   }
@@ -587,7 +587,7 @@ void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) {
   if (!cp.supportsLEDState) {
     // Always ignore ScrollLock as we don't have a heuristic
     // for that
-    if (key == XK_Scroll_Lock) {
+    if (keysym == XK_Scroll_Lock) {
       vlog.debug("Ignoring lock key (e.g. caps lock)");
       return;
     }
@@ -596,32 +596,32 @@ void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) {
       // CapsLock synchronisation heuristic
       // (this assumes standard interaction between CapsLock the Shift
       // keys and normal characters)
-      if (((key >= XK_A) && (key <= XK_Z)) ||
-          ((key >= XK_a) && (key <= XK_z))) {
+      if (((keysym >= XK_A) && (keysym <= XK_Z)) ||
+          ((keysym >= XK_a) && (keysym <= XK_z))) {
         bool uppercase, shift, lock;
 
-        uppercase = (key >= XK_A) && (key <= XK_Z);
+        uppercase = (keysym >= XK_A) && (keysym <= XK_Z);
         shift = pressedKeys.find(XK_Shift_L) != pressedKeys.end() ||
                 pressedKeys.find(XK_Shift_R) != pressedKeys.end();
         lock = server->ledState & ledCapsLock;
 
         if (lock == (uppercase == shift)) {
           vlog.debug("Inserting fake CapsLock to get in sync with client");
-          server->desktop->keyEvent(XK_Caps_Lock, true);
-          server->desktop->keyEvent(XK_Caps_Lock, false);
+          server->desktop->keyEvent(XK_Caps_Lock, 0, true);
+          server->desktop->keyEvent(XK_Caps_Lock, 0, false);
         }
       }
 
       // NumLock synchronisation heuristic
       // (this is more cautious because of the differences between Unix,
       // Windows and macOS)
-      if (((key >= XK_KP_Home) && (key <= XK_KP_Delete)) ||
-          ((key >= XK_KP_0) && (key <= XK_KP_9)) ||
-          (key == XK_KP_Separator) || (key == XK_KP_Decimal)) {
+      if (((keysym >= XK_KP_Home) && (keysym <= XK_KP_Delete)) ||
+          ((keysym >= XK_KP_0) && (keysym <= XK_KP_9)) ||
+          (keysym == XK_KP_Separator) || (keysym == XK_KP_Decimal)) {
         bool number, shift, lock;
 
-        number = ((key >= XK_KP_0) && (key <= XK_KP_9)) ||
-                  (key == XK_KP_Separator) || (key == XK_KP_Decimal);
+        number = ((keysym >= XK_KP_0) && (keysym <= XK_KP_9)) ||
+                  (keysym == XK_KP_Separator) || (keysym == XK_KP_Decimal);
         shift = pressedKeys.find(XK_Shift_L) != pressedKeys.end() ||
                 pressedKeys.find(XK_Shift_R) != pressedKeys.end();
         lock = server->ledState & ledNumLock;
@@ -638,8 +638,8 @@ void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) {
           //
         } else if (lock == (number == shift)) {
           vlog.debug("Inserting fake NumLock to get in sync with client");
-          server->desktop->keyEvent(XK_Num_Lock, true);
-          server->desktop->keyEvent(XK_Num_Lock, false);
+          server->desktop->keyEvent(XK_Num_Lock, 0, true);
+          server->desktop->keyEvent(XK_Num_Lock, 0, false);
         }
       }
     }
@@ -647,19 +647,20 @@ void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) {
 
   // Turn ISO_Left_Tab into shifted Tab.
   VNCSConnectionSTShiftPresser shiftPresser(server->desktop);
-  if (key == XK_ISO_Left_Tab) {
+  if (keysym == XK_ISO_Left_Tab) {
     if (pressedKeys.find(XK_Shift_L) == pressedKeys.end() &&
         pressedKeys.find(XK_Shift_R) == pressedKeys.end())
       shiftPresser.press();
-    key = XK_Tab;
+    keysym = XK_Tab;
   }
 
   if (down) {
-    pressedKeys.insert(key);
+    pressedKeys.insert(keysym);
   } else {
-    if (!pressedKeys.erase(key)) return;
+    if (!pressedKeys.erase(keysym))
+      return;
   }
-  server->desktop->keyEvent(key, down);
+  server->desktop->keyEvent(keysym, keycode, down);
 }
 
 void VNCSConnectionST::clientCutText(const char* str, int len)
index 8f33962da16799704e002a8daee70bbf0993eb92..9c58331efd6b240da8cf9b8e9784e2058f804b01 100644 (file)
@@ -136,7 +136,7 @@ namespace rfb {
     virtual void clientInit(bool shared);
     virtual void setPixelFormat(const PixelFormat& pf);
     virtual void pointerEvent(const Point& pos, int buttonMask);
-    virtual void keyEvent(rdr::U32 key, bool down);
+    virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
     virtual void clientCutText(const char* str, int len);
     virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
     virtual void setDesktopSize(int fb_width, int fb_height,
index adeecaa94ab4973f371d7696267639989a331402..122afe7f65b27fb571526b9d538e3c5aea136ba4 100644 (file)
@@ -40,6 +40,7 @@ namespace rfb {
   const int pseudoEncodingFence = -312;
   const int pseudoEncodingContinuousUpdates = -313;
   const int pseudoEncodingCursorWithAlpha = -314;
+  const int pseudoEncodingQEMUKeyEvent = -258;
 
   // TightVNC-specific
   const int pseudoEncodingLastRect = -224;
index a55e1c508e989bb6dee528452637b7f96dfcef29..a17493cd804c0c1aef2ae454e555249f2c6d60ab 100644 (file)
@@ -45,5 +45,7 @@ namespace rfb {
   const int msgTypeClientFence = 248;
 
   const int msgTypeSetDesktopSize = 251;
+
+  const int msgTypeQEMUClientMessage = 255;
 }
 #endif
diff --git a/common/rfb/qemuTypes.h b/common/rfb/qemuTypes.h
new file mode 100644 (file)
index 0000000..6a67f78
--- /dev/null
@@ -0,0 +1,25 @@
+/* Copyright 2017 Pierre Ossman for Cendio AB
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+#ifndef __RFB_QEMUTYPES_H__
+#define __RFB_QEMUTYPES_H__
+
+namespace rfb {
+  const int qemuExtendedKeyEvent = 0;
+  const int qemuAudio = 1;
+}
+#endif
index 9e5da4f9d1bfe963c83f300ab93ae39278558922..7fb197aad834cc9649c7b8dc382e99ff8d47f192 100644 (file)
@@ -295,10 +295,10 @@ public:
 #endif
   }
 
-  virtual void keyEvent(rdr::U32 key, bool down) {
+  virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
 #ifdef HAVE_XTEST
     if (!haveXtest) return;
-    int keycode = XKeysymToKeycode(dpy, key);
+    int keycode = XKeysymToKeycode(dpy, keysym);
     if (keycode)
       XTestFakeKeyEvent(dpy, keycode, down, CurrentTime);
 #endif
index 1c74bc66c5c22736dcba010dcc48ef55fb0b8f94..031fb535b1b3f8c644469224fd023214315a868a 100644 (file)
@@ -771,7 +771,7 @@ void XserverDesktop::grabRegion(const rfb::Region& region)
   }
 }
 
-void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
+void XserverDesktop::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
 {
   vncKeyboardEvent(keysym, down);
 }
index cd85e4b0742d122bb7f7b64e6233b8a83be3975d..7f7823a766c1915a94f6731daaa178e225917bff 100644 (file)
@@ -89,7 +89,7 @@ public:
 
   // rfb::SDesktop callbacks
   virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
-  virtual void keyEvent(rdr::U32 key, bool down);
+  virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
   virtual void clientCutText(const char* str, int len);
   virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); }
   virtual unsigned int setScreenLayout(int fb_width, int fb_height,
index bfadd4c0ec7c25681f711f2de53b2c08258f1e50..1923f53adb4dd93f561057bca5ba64f1c3462454 100644 (file)
@@ -709,8 +709,8 @@ void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
   if (ctrlPressed && altPressed) {
     vlog.debug("Faking release of AltGr (Ctrl_L+Alt_R)");
     try {
-      cc->writer()->keyEvent(XK_Control_L, false);
-      cc->writer()->keyEvent(XK_Alt_R, false);
+      cc->writer()->keyEvent(XK_Control_L, 0, false);
+      cc->writer()->keyEvent(XK_Alt_R, 0, false);
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
       exit_vncviewer(e.str());
@@ -732,7 +732,7 @@ void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
 #endif
 
   try {
-    cc->writer()->keyEvent(keySym, true);
+    cc->writer()->keyEvent(keySym, 0, true);
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
     exit_vncviewer(e.str());
@@ -743,8 +743,8 @@ void Viewport::handleKeyPress(int keyCode, rdr::U32 keySym)
   if (ctrlPressed && altPressed) {
     vlog.debug("Restoring AltGr state");
     try {
-      cc->writer()->keyEvent(XK_Control_L, true);
-      cc->writer()->keyEvent(XK_Alt_R, true);
+      cc->writer()->keyEvent(XK_Control_L, 0, true);
+      cc->writer()->keyEvent(XK_Alt_R, 0, true);
     } catch (rdr::Exception& e) {
       vlog.error("%s", e.str());
       exit_vncviewer(e.str());
@@ -777,7 +777,7 @@ void Viewport::handleKeyRelease(int keyCode)
 #endif
 
   try {
-    cc->writer()->keyEvent(iter->second, false);
+    cc->writer()->keyEvent(iter->second, 0, false);
   } catch (rdr::Exception& e) {
     vlog.error("%s", e.str());
     exit_vncviewer(e.str());
index 2696f5dc7cf07b21ed953e81b443b20db59aae9b..ad55d49073f3eb5f8a94afe9a4869e6faec9c7bb 100644 (file)
@@ -280,12 +280,12 @@ void SDisplay::pointerEvent(const Point& pos, int buttonmask) {
   }
 }
 
-void SDisplay::keyEvent(rdr::U32 key, bool down) {
+void SDisplay::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) {
   // - Check that the SDesktop doesn't need restarting
   if (isRestartRequired())
     restartCore();
   if (kbd)
-    kbd->keyEvent(key, down);
+    kbd->keyEvent(keysym, keycode, down);
 }
 
 bool SDisplay::checkLedState() {
index e43e3021c6542a7c74a910955c4c63d31375c882..9892ed99ff044babea933a1bf18308f9a993383d 100644 (file)
@@ -66,7 +66,7 @@ namespace rfb {
       virtual void start(VNCServer* vs);
       virtual void stop();
       virtual void pointerEvent(const Point& pos, int buttonmask);
-      virtual void keyEvent(rdr::U32 key, bool down);
+      virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
       virtual void clientCutText(const char* str, int len);
       virtual Point getFbSize();
 
index 0923118adca55477b62c11fae07275c6b17e715b..15ef4b063ad2cdf0825a83cf0ff3579333edbc49 100644 (file)
@@ -321,7 +321,7 @@ win32::SKeyboard::SKeyboard()
 }
 
 
-void win32::SKeyboard::keyEvent(rdr::U32 keysym, bool down)
+void win32::SKeyboard::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
 {
   for (unsigned int i = 0; i < sizeof(keysymToAscii) / sizeof(keysymToAscii_t); i++) {
     if (keysymToAscii[i].keysym == keysym) {
index 2a0b3e675eac0405a709d88e2704e2617bd4e7ef..f7949ec4e6e7be9c337aa96831e67199482ac49b 100644 (file)
@@ -53,7 +53,7 @@ namespace rfb {
     class SKeyboard {
     public:
       SKeyboard();
-      void keyEvent(rdr::U32 key, bool down);
+      void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
       static BoolParameter deadKeyAware;
     private:
       std::map<rdr::U32,rdr::U8> vkMap;