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/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();
+  }
 }