Basic support for QEMU Extended Key Events
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.
diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx
index 74c7bf9..b89bc18 100644
--- a/common/rfb/CMsgHandler.cxx
+++ b/common/rfb/CMsgHandler.cxx
@@ -75,6 +75,11 @@
cp.supportsContinuousUpdates = true;
}
+void CMsgHandler::supportsQEMUKeyEvent()
+{
+ cp.supportsQEMUKeyEvent = true;
+}
+
void CMsgHandler::framebufferUpdateStart()
{
}
diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h
index ef2cda2..903ee15 100644
--- a/common/rfb/CMsgHandler.h
+++ b/common/rfb/CMsgHandler.h
@@ -55,6 +55,7 @@
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,
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index 0aaf71f..eee6d27 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -111,6 +111,8 @@
break;
case pseudoEncodingLEDState:
readLEDState();
+ case pseudoEncodingQEMUKeyEvent:
+ handler->supportsQEMUKeyEvent();
break;
default:
readRect(Rect(x, y, x+w, y+h), encoding);
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index 7a89a93..57d1283 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -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 @@
encodings[nEncodings++] = pseudoEncodingLastRect;
encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
encodings[nEncodings++] = pseudoEncodingFence;
+ encodings[nEncodings++] = pseudoEncodingQEMUKeyEvent;
if (Decoder::supported(preferredEncoding)) {
encodings[nEncodings++] = preferredEncoding;
@@ -215,13 +217,26 @@
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();
+ }
}
diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h
index 06ecbe7..56e0b7b 100644
--- a/common/rfb/CMsgWriter.h
+++ b/common/rfb/CMsgWriter.h
@@ -55,7 +55,7 @@
// 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);
diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx
index f0b6932..23f02ed 100644
--- a/common/rfb/ConnParams.cxx
+++ b/common/rfb/ConnParams.cxx
@@ -35,8 +35,9 @@
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 @@
supportsExtendedDesktopSize = false;
supportsLocalXCursor = false;
supportsLastRect = false;
+ supportsQEMUKeyEvent = false;
compressLevel = -1;
qualityLevel = -1;
fineQualityLevel = -1;
@@ -145,6 +147,8 @@
break;
case pseudoEncodingLEDState:
supportsLEDState = true;
+ case pseudoEncodingQEMUKeyEvent:
+ supportsQEMUKeyEvent = true;
break;
case pseudoEncodingFence:
supportsFence = true;
diff --git a/common/rfb/ConnParams.h b/common/rfb/ConnParams.h
index d99d142..b322293 100644
--- a/common/rfb/ConnParams.h
+++ b/common/rfb/ConnParams.h
@@ -97,6 +97,7 @@
bool supportsDesktopRename;
bool supportsLastRect;
bool supportsLEDState;
+ bool supportsQEMUKeyEvent;
bool supportsSetDesktopSize;
bool supportsFence;
diff --git a/common/rfb/InputHandler.h b/common/rfb/InputHandler.h
index b5e5e87..0344bc3 100644
--- a/common/rfb/InputHandler.h
+++ b/common/rfb/InputHandler.h
@@ -31,7 +31,7 @@
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) {}
};
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index 85cc6e8..c5c9038 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -278,6 +278,11 @@
SMsgHandler::setEncodings(nEncodings, encodings);
}
+void SConnection::supportsQEMUKeyEvent()
+{
+ writer()->writeQEMUKeyEvent();
+}
+
void SConnection::versionReceived()
{
}
diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h
index 63dc314..bc43583 100644
--- a/common/rfb/SConnection.h
+++ b/common/rfb/SConnection.h
@@ -73,6 +73,7 @@
virtual void setEncodings(int nEncodings, const rdr::S32* encodings);
+ virtual void supportsQEMUKeyEvent();
// Methods to be overridden in a derived class
diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx
index 8e48c67..c38458c 100644
--- a/common/rfb/SMsgHandler.cxx
+++ b/common/rfb/SMsgHandler.cxx
@@ -41,11 +41,13 @@
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 @@
supportsContinuousUpdates();
if (cp.supportsLEDState && firstLEDState)
supportsLEDState();
+ if (cp.supportsQEMUKeyEvent && firstQEMUKeyEvent)
+ supportsQEMUKeyEvent();
}
void SMsgHandler::supportsLocalCursor()
@@ -75,6 +79,10 @@
{
}
+void SMsgHandler::supportsQEMUKeyEvent()
+{
+}
+
void SMsgHandler::setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout)
{
diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h
index cf6b6b3..749f056 100644
--- a/common/rfb/SMsgHandler.h
+++ b/common/rfb/SMsgHandler.h
@@ -80,6 +80,11 @@
// 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;
};
}
diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx
index 3c08fd6..cb71ac8 100644
--- a/common/rfb/SMsgReader.cxx
+++ b/common/rfb/SMsgReader.cxx
@@ -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 @@
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 @@
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 @@
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);
+}
diff --git a/common/rfb/SMsgReader.h b/common/rfb/SMsgReader.h
index 00cb303..146b29f 100644
--- a/common/rfb/SMsgReader.h
+++ b/common/rfb/SMsgReader.h
@@ -55,6 +55,9 @@
void readPointerEvent();
void readClientCutText();
+ void readQEMUMessage();
+ void readQEMUKeyEvent();
+
SMsgHandler* handler;
rdr::InStream* is;
};
diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx
index d8adfbc..2d4998b 100644
--- a/common/rfb/SMsgWriter.cxx
+++ b/common/rfb/SMsgWriter.cxx
@@ -39,7 +39,7 @@
needSetDesktopSize(false), needExtendedDesktopSize(false),
needSetDesktopName(false), needSetCursor(false),
needSetXCursor(false), needSetCursorWithAlpha(false),
- needLEDState(false)
+ needLEDState(false), needQEMUKeyEvent(false)
{
}
@@ -207,6 +207,16 @@
return true;
}
+bool SMsgWriter::writeQEMUKeyEvent()
+{
+ if (!cp->supportsQEMUKeyEvent)
+ return false;
+
+ needQEMUKeyEvent = true;
+
+ return true;
+}
+
bool SMsgWriter::needFakeUpdate()
{
if (needSetDesktopName)
@@ -215,6 +225,8 @@
return true;
if (needLEDState)
return true;
+ if (needQEMUKeyEvent)
+ return true;
if (needNoDataUpdate())
return true;
@@ -265,6 +277,8 @@
nRects++;
if (needLEDState)
nRects++;
+ if (needQEMUKeyEvent)
+ nRects++;
}
os->writeU16(nRects);
@@ -385,6 +399,11 @@
writeLEDStateRect(cp->ledState());
needLEDState = false;
}
+
+ if (needQEMUKeyEvent) {
+ writeQEMUKeyEventRect();
+ needQEMUKeyEvent = false;
+ }
}
void SMsgWriter::writeNoDataRects()
@@ -565,3 +584,17 @@
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);
+}
diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h
index 890b2b5..f2adadc 100644
--- a/common/rfb/SMsgWriter.h
+++ b/common/rfb/SMsgWriter.h
@@ -85,6 +85,9 @@
// 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 @@
int hotspotX, int hotspotY,
const rdr::U8* data);
void writeLEDStateRect(rdr::U8 state);
+ void writeQEMUKeyEventRect();
ConnParams* cp;
rdr::OutStream* os;
@@ -150,6 +154,7 @@
bool needSetXCursor;
bool needSetCursorWithAlpha;
bool needLEDState;
+ bool needQEMUKeyEvent;
typedef struct {
rdr::U16 reason, result;
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 232776f..be496e7 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -103,7 +103,7 @@
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 @@
~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 @@
// 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 @@
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 @@
// 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 @@
//
} 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 @@
// 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)
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index 8f33962..9c58331 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -136,7 +136,7 @@
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,
diff --git a/common/rfb/encodings.h b/common/rfb/encodings.h
index adeecaa..122afe7 100644
--- a/common/rfb/encodings.h
+++ b/common/rfb/encodings.h
@@ -40,6 +40,7 @@
const int pseudoEncodingFence = -312;
const int pseudoEncodingContinuousUpdates = -313;
const int pseudoEncodingCursorWithAlpha = -314;
+ const int pseudoEncodingQEMUKeyEvent = -258;
// TightVNC-specific
const int pseudoEncodingLastRect = -224;
diff --git a/common/rfb/msgTypes.h b/common/rfb/msgTypes.h
index a55e1c5..a17493c 100644
--- a/common/rfb/msgTypes.h
+++ b/common/rfb/msgTypes.h
@@ -45,5 +45,7 @@
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
index 0000000..6a67f78
--- /dev/null
+++ b/common/rfb/qemuTypes.h
@@ -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
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index 9e5da4f..7fb197a 100644
--- a/unix/x0vncserver/x0vncserver.cxx
+++ b/unix/x0vncserver/x0vncserver.cxx
@@ -295,10 +295,10 @@
#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
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index 1c74bc6..031fb53 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -771,7 +771,7 @@
}
}
-void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
+void XserverDesktop::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
{
vncKeyboardEvent(keysym, down);
}
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index cd85e4b..7f7823a 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -89,7 +89,7 @@
// 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,
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index bfadd4c..1923f53 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -709,8 +709,8 @@
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 @@
#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 @@
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 @@
#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());
diff --git a/win/rfb_win32/SDisplay.cxx b/win/rfb_win32/SDisplay.cxx
index 2696f5d..ad55d49 100644
--- a/win/rfb_win32/SDisplay.cxx
+++ b/win/rfb_win32/SDisplay.cxx
@@ -280,12 +280,12 @@
}
}
-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() {
diff --git a/win/rfb_win32/SDisplay.h b/win/rfb_win32/SDisplay.h
index e43e302..9892ed9 100644
--- a/win/rfb_win32/SDisplay.h
+++ b/win/rfb_win32/SDisplay.h
@@ -66,7 +66,7 @@
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();
diff --git a/win/rfb_win32/SInput.cxx b/win/rfb_win32/SInput.cxx
index 0923118..15ef4b0 100644
--- a/win/rfb_win32/SInput.cxx
+++ b/win/rfb_win32/SInput.cxx
@@ -321,7 +321,7 @@
}
-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) {
diff --git a/win/rfb_win32/SInput.h b/win/rfb_win32/SInput.h
index 2a0b3e6..f7949ec 100644
--- a/win/rfb_win32/SInput.h
+++ b/win/rfb_win32/SInput.h
@@ -53,7 +53,7 @@
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;