From 245c5421323966a87e8d6d70e391bef0d85b2e65 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 14 May 2021 12:18:46 +0200 Subject: Move keyboard tracking to CConnection This is a general thing so move it in to the core library instead, letting vncviewer focus on just translation of system events to VNC ones. --- common/rfb/CConnection.cxx | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'common/rfb/CConnection.cxx') diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx index b4017dba..eb9972f1 100644 --- a/common/rfb/CConnection.cxx +++ b/common/rfb/CConnection.cxx @@ -40,6 +40,10 @@ #include #include +#define XK_MISCELLANY +#define XK_XKB_KEYS +#include + #include #include @@ -693,6 +697,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; -- cgit v1.2.3