aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2024-12-04 17:11:07 +0100
committerPierre Ossman <ossman@cendio.se>2024-12-04 17:11:07 +0100
commit994d2c64f8926fe780a2d572183232202145b6a6 (patch)
treead63081deeacb09bba7e24bb00e4d5889c3316ba /common
parent4680810cbd2d7aaa4d924db361c4c2ab39a3b500 (diff)
parent7e7e05075bccece85efa92f14f516c065a8fa531 (diff)
downloadtigervnc-994d2c64f8926fe780a2d572183232202145b6a6.tar.gz
tigervnc-994d2c64f8926fe780a2d572183232202145b6a6.zip
Merge branch 'keysplit' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'common')
-rw-r--r--common/rfb/CConnection.cxx87
-rw-r--r--common/rfb/CConnection.h20
2 files changed, 107 insertions, 0 deletions
diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx
index 2c347710..5e7530c8 100644
--- a/common/rfb/CConnection.cxx
+++ b/common/rfb/CConnection.cxx
@@ -40,6 +40,10 @@
#include <rfb/CConnection.h>
#include <rfb/util.h>
+#define XK_MISCELLANY
+#define XK_XKB_KEYS
+#include <rfb/keysymdef.h>
+
#include <rfb/LogWriter.h>
#include <rdr/InStream.h>
@@ -695,6 +699,89 @@ void CConnection::sendClipboardData(const char* data)
}
}
+void CConnection::sendKeyPress(int systemKeyCode,
+ uint32_t keyCode, uint32_t keySym)
+{
+ // For the first few years, there wasn't a good consensus on what the
+ // Windows keys should be mapped to for X11. So we need to help out a
+ // bit and map all variants to the same key...
+ switch (keySym) {
+ case XK_Hyper_L:
+ keySym = XK_Super_L;
+ break;
+ case XK_Hyper_R:
+ keySym = XK_Super_R;
+ break;
+ // There has been several variants for Shift-Tab over the years.
+ // RFB states that we should always send a normal tab.
+ case XK_ISO_Left_Tab:
+ keySym = XK_Tab;
+ break;
+ }
+
+#ifdef __APPLE__
+ // Alt on OS X behaves more like AltGr on other systems, and to get
+ // sane behaviour we should translate things in that manner for the
+ // remote VNC server. However that means we lose the ability to use
+ // Alt as a shortcut modifier. Do what RealVNC does and hijack the
+ // left command key as an Alt replacement.
+ switch (keySym) {
+ case XK_Super_L:
+ keySym = XK_Alt_L;
+ break;
+ case XK_Super_R:
+ keySym = XK_Super_L;
+ break;
+ case XK_Alt_L:
+ keySym = XK_Mode_switch;
+ break;
+ case XK_Alt_R:
+ keySym = XK_ISO_Level3_Shift;
+ break;
+ }
+#endif
+
+ // Because of the way keyboards work, we cannot expect to have the same
+ // symbol on release as when pressed. This breaks the VNC protocol however,
+ // so we need to keep track of what keysym a key _code_ generated on press
+ // and send the same on release.
+ downKeys[systemKeyCode].keyCode = keyCode;
+ downKeys[systemKeyCode].keySym = keySym;
+
+ vlog.debug("Key pressed: %d => 0x%02x / XK_%s (0x%04x)",
+ systemKeyCode, keyCode, KeySymName(keySym), keySym);
+
+ writer()->writeKeyEvent(keySym, keyCode, true);
+}
+
+void CConnection::sendKeyRelease(int systemKeyCode)
+{
+ DownMap::iterator iter;
+
+ iter = downKeys.find(systemKeyCode);
+ if (iter == downKeys.end()) {
+ // These occur somewhat frequently so let's not spam them unless
+ // logging is turned up.
+ vlog.debug("Unexpected release of key code %d", systemKeyCode);
+ return;
+ }
+
+ vlog.debug("Key released: %d => 0x%02x / XK_%s (0x%04x)",
+ systemKeyCode, iter->second.keyCode,
+ KeySymName(iter->second.keySym), iter->second.keySym);
+
+ writer()->writeKeyEvent(iter->second.keySym,
+ iter->second.keyCode, false);
+
+ downKeys.erase(iter);
+}
+
+void CConnection::releaseAllKeys()
+{
+ while (!downKeys.empty())
+ sendKeyRelease(downKeys.begin()->first);
+}
+
void CConnection::refreshFramebuffer()
{
forceNonincremental = true;
diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h
index 9101bf26..07e47e39 100644
--- a/common/rfb/CConnection.h
+++ b/common/rfb/CConnection.h
@@ -24,6 +24,7 @@
#ifndef __RFB_CCONNECTION_H__
#define __RFB_CCONNECTION_H__
+#include <map>
#include <string>
#include <rfb/CMsgHandler.h>
@@ -196,6 +197,18 @@ namespace rfb {
// clipboard via handleClipboardRequest().
virtual void sendClipboardData(const char* data);
+ // sendKeyPress()/sendKeyRelease() send keyboard events to the
+ // server
+ void sendKeyPress(int systemKeyCode, uint32_t keyCode, uint32_t keySym);
+ void sendKeyRelease(int systemKeyCode);
+
+ // releaseAllKeys() sends keyboard release events to the server for
+ // all keys that are currently pressed down by this client,
+ // avoiding keys getting stuck. This can be useful if the client
+ // loses keyboard focus or otherwise no longer gets keyboard events
+ // from the system.
+ void releaseAllKeys();
+
// refreshFramebuffer() forces a complete refresh of the entire
// framebuffer
void refreshFramebuffer();
@@ -313,6 +326,13 @@ namespace rfb {
bool hasRemoteClipboard;
bool hasLocalClipboard;
bool unsolicitedClipboardAttempt;
+
+ struct DownKey {
+ uint32_t keyCode;
+ uint32_t keySym;
+ };
+ typedef std::map<int, DownKey> DownMap;
+ DownMap downKeys;
};
}
#endif