aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2024-10-16 10:51:23 +0200
committerPierre Ossman <ossman@cendio.se>2024-10-16 11:14:03 +0200
commit16f98788710fbac557069f39dc760219cdbd21c7 (patch)
tree80b35c9bfa4acfc2ae0f2cba8a044795987cb5e7
parenta4c86a7f07d81450c5e0147c27ed737b7af4547c (diff)
downloadtigervnc-16f98788710fbac557069f39dc760219cdbd21c7.tar.gz
tigervnc-16f98788710fbac557069f39dc760219cdbd21c7.zip
Track keys using system key code
We might not always be able to map to an RFB key code, so let's use the platform specific code to track which keys are pressed.
-rw-r--r--vncviewer/Viewport.cxx136
-rw-r--r--vncviewer/Viewport.h13
2 files changed, 74 insertions, 75 deletions
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index e29c877c..e7b4ac9f 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -115,6 +115,14 @@ enum { ID_DISCONNECT, ID_FULLSCREEN, ID_MINIMIZE, ID_RESIZE,
static const WORD SCAN_FAKE = 0xaa;
#endif
+// Used for fake key presses from the menu
+static const int FAKE_CTRL_KEY_CODE = 0x10001;
+static const int FAKE_ALT_KEY_CODE = 0x10002;
+static const int FAKE_DEL_KEY_CODE = 0x10003;
+
+// Used for fake key presses for lock key sync
+static const int FAKE_KEY_CODE = 0xffff;
+
Viewport::Viewport(int w, int h, const rfb::PixelFormat& /*serverPF*/, CConn* cc_)
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(nullptr),
lastPointerPos(0, 0), lastButtonMask(0),
@@ -499,18 +507,18 @@ void Viewport::pushLEDState()
if ((ledState & ledCapsLock) != (cc->server.ledState() & ledCapsLock)) {
vlog.debug("Inserting fake CapsLock to get in sync with server");
- handleKeyPress(0x3a, XK_Caps_Lock);
- handleKeyRelease(0x3a);
+ handleKeyPress(FAKE_KEY_CODE, 0x3a, XK_Caps_Lock);
+ handleKeyRelease(FAKE_KEY_CODE);
}
if ((ledState & ledNumLock) != (cc->server.ledState() & ledNumLock)) {
vlog.debug("Inserting fake NumLock to get in sync with server");
- handleKeyPress(0x45, XK_Num_Lock);
- handleKeyRelease(0x45);
+ handleKeyPress(FAKE_KEY_CODE, 0x45, XK_Num_Lock);
+ handleKeyRelease(FAKE_KEY_CODE);
}
if ((ledState & ledScrollLock) != (cc->server.ledState() & ledScrollLock)) {
vlog.debug("Inserting fake ScrollLock to get in sync with server");
- handleKeyPress(0x46, XK_Scroll_Lock);
- handleKeyRelease(0x46);
+ handleKeyPress(FAKE_KEY_CODE, 0x46, XK_Scroll_Lock);
+ handleKeyRelease(FAKE_KEY_CODE);
}
}
@@ -637,9 +645,9 @@ int Viewport::handle(int event)
// Resend Ctrl/Alt if needed
if (menuCtrlKey)
- handleKeyPress(0x1d, XK_Control_L);
+ handleKeyPress(FAKE_CTRL_KEY_CODE, 0x1d, XK_Control_L);
if (menuAltKey)
- handleKeyPress(0x38, XK_Alt_L);
+ handleKeyPress(FAKE_ALT_KEY_CODE, 0x38, XK_Alt_L);
// Yes, we would like some focus please!
return 1;
@@ -822,12 +830,13 @@ void Viewport::handlePointerTimeout(void *data)
void Viewport::resetKeyboard()
{
- while (!downKeySym.empty())
- handleKeyRelease(downKeySym.begin()->first);
+ while (!downKeys.empty())
+ handleKeyRelease(downKeys.begin()->first);
}
-void Viewport::handleKeyPress(int keyCode, uint32_t keySym)
+void Viewport::handleKeyPress(int systemKeyCode,
+ uint32_t keyCode, uint32_t keySym)
{
static bool menuRecursion = false;
@@ -843,11 +852,6 @@ void Viewport::handleKeyPress(int keyCode, uint32_t keySym)
if (viewOnly)
return;
- if (keyCode == 0) {
- vlog.error(_("No key code specified on key press"));
- return;
- }
-
#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
@@ -874,17 +878,14 @@ void Viewport::handleKeyPress(int keyCode, uint32_t keySym)
// 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.
- downKeySym[keyCode] = keySym;
+ downKeys[systemKeyCode].keyCode = keyCode;
+ downKeys[systemKeyCode].keySym = keySym;
- vlog.debug("Key pressed: 0x%04x => XK_%s (0x%04x)",
- keyCode, KeySymName(keySym), keySym);
+ vlog.debug("Key pressed: %d => 0x%02x / XK_%s (0x%04x)",
+ systemKeyCode, keyCode, KeySymName(keySym), keySym);
try {
- // Fake keycode?
- if (keyCode > 0xff)
- cc->writer()->writeKeyEvent(keySym, 0, true);
- else
- cc->writer()->writeKeyEvent(keySym, keyCode, true);
+ cc->writer()->writeKeyEvent(keySym, keyCode, true);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
abort_connection_with_unexpected_error(e);
@@ -892,35 +893,34 @@ void Viewport::handleKeyPress(int keyCode, uint32_t keySym)
}
-void Viewport::handleKeyRelease(int keyCode)
+void Viewport::handleKeyRelease(int systemKeyCode)
{
DownMap::iterator iter;
if (viewOnly)
return;
- iter = downKeySym.find(keyCode);
- if (iter == downKeySym.end()) {
+ 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", keyCode);
+ vlog.debug("Unexpected release of key code %d", systemKeyCode);
return;
}
- vlog.debug("Key released: 0x%04x => XK_%s (0x%04x)",
- keyCode, KeySymName(iter->second), iter->second);
+ vlog.debug("Key released: %d => 0x%02x / XK_%s (0x%04x)",
+ systemKeyCode, iter->second.keyCode,
+ KeySymName(iter->second.keySym), iter->second.keySym);
try {
- if (keyCode > 0xff)
- cc->writer()->writeKeyEvent(iter->second, 0, false);
- else
- cc->writer()->writeKeyEvent(iter->second, keyCode, false);
+ cc->writer()->writeKeyEvent(iter->second.keySym,
+ iter->second.keyCode, false);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
abort_connection_with_unexpected_error(e);
}
- downKeySym.erase(iter);
+ downKeys.erase(iter);
}
@@ -1057,7 +1057,7 @@ int Viewport::handleSystemEvent(void *event, void *data)
}
}
- self->handleKeyPress(keyCode, keySym);
+ self->handleKeyPress(keyCode, keyCode, keySym);
// We don't get reliable WM_KEYUP for these
switch (keySym) {
@@ -1112,9 +1112,9 @@ int Viewport::handleSystemEvent(void *event, void *data)
// Windows has a rather nasty bug where it won't send key release
// events for a Shift button if the other Shift is still pressed
if ((keyCode == 0x2a) || (keyCode == 0x36)) {
- if (self->downKeySym.count(0x2a))
+ if (self->downKeys.count(0x2a))
self->handleKeyRelease(0x2a);
- if (self->downKeySym.count(0x36))
+ if (self->downKeys.count(0x36))
self->handleKeyRelease(0x36);
}
@@ -1128,31 +1128,33 @@ int Viewport::handleSystemEvent(void *event, void *data)
}
if (cocoa_is_keyboard_event(event)) {
- int keyCode;
+ int systemKeyCode;
- keyCode = cocoa_event_keycode(event);
- if ((unsigned)keyCode >= code_map_osx_to_qnum_len)
- keyCode = 0;
- else
- keyCode = code_map_osx_to_qnum[keyCode];
+ systemKeyCode = cocoa_event_keycode(event);
if (cocoa_is_key_press(event)) {
+ uint32_t keyCode;
uint32_t keySym;
+ if ((unsigned)systemKeyCode >= code_map_osx_to_qnum_len)
+ keyCode = 0;
+ else
+ keyCode = code_map_osx_to_qnum[systemKeyCode];
+
keySym = cocoa_event_keysym(event);
if (keySym == NoSymbol) {
vlog.error(_("No symbol for key code 0x%02x (in the current state)"),
(int)keyCode);
}
- self->handleKeyPress(keyCode, keySym);
+ self->handleKeyPress(systemKeyCode, keyCode, keySym);
// We don't get any release events for CapsLock, so we have to
// send the release right away.
if (keySym == XK_Caps_Lock)
- self->handleKeyRelease(keyCode);
+ self->handleKeyRelease(systemKeyCode);
} else {
- self->handleKeyRelease(keyCode);
+ self->handleKeyRelease(systemKeyCode);
}
return 1;
@@ -1167,11 +1169,6 @@ int Viewport::handleSystemEvent(void *event, void *data)
keycode = code_map_keycode_to_qnum[xevent->xkey.keycode];
- // Generate a fake keycode just for tracking if we can't figure
- // out the proper one
- if (keycode == 0)
- keycode = 0x100 | xevent->xkey.keycode;
-
XLookupString(&xevent->xkey, &str, 1, &keysym, nullptr);
if (keysym == NoSymbol) {
vlog.error(_("No symbol for key code %d (in the current state)"),
@@ -1195,13 +1192,10 @@ int Viewport::handleSystemEvent(void *event, void *data)
break;
}
- self->handleKeyPress(keycode, keysym);
+ self->handleKeyPress(xevent->xkey.keycode, keycode, keysym);
return 1;
} else if (xevent->type == KeyRelease) {
- int keycode = code_map_keycode_to_qnum[xevent->xkey.keycode];
- if (keycode == 0)
- keycode = 0x100 | xevent->xkey.keycode;
- self->handleKeyRelease(keycode);
+ self->handleKeyRelease(xevent->xkey.keycode);
return 1;
}
#endif
@@ -1217,7 +1211,7 @@ void Viewport::handleAltGrTimeout(void *data)
assert(self);
self->altGrArmed = false;
- self->handleKeyPress(0x1d, XK_Control_L);
+ self->handleKeyPress(0x1d, 0x1d, XK_Control_L);
}
void Viewport::resolveAltGrDetection(bool isAltGrSequence)
@@ -1226,7 +1220,7 @@ void Viewport::resolveAltGrDetection(bool isAltGrSequence)
Fl::remove_timeout(handleAltGrTimeout);
// when it's not an AltGr sequence we can't supress the Ctrl anymore
if (!isAltGrSequence)
- handleKeyPress(0x1d, XK_Control_L);
+ handleKeyPress(0x1d, 0x1d, XK_Control_L);
}
#endif
@@ -1338,30 +1332,30 @@ void Viewport::popupContextMenu()
break;
case ID_CTRL:
if (m->value())
- handleKeyPress(0x1d, XK_Control_L);
+ handleKeyPress(FAKE_CTRL_KEY_CODE, 0x1d, XK_Control_L);
else
- handleKeyRelease(0x1d);
+ handleKeyRelease(FAKE_CTRL_KEY_CODE);
menuCtrlKey = !menuCtrlKey;
break;
case ID_ALT:
if (m->value())
- handleKeyPress(0x38, XK_Alt_L);
+ handleKeyPress(FAKE_ALT_KEY_CODE, 0x38, XK_Alt_L);
else
- handleKeyRelease(0x38);
+ handleKeyRelease(FAKE_ALT_KEY_CODE);
menuAltKey = !menuAltKey;
break;
case ID_MENUKEY:
- handleKeyPress(menuKeyCode, menuKeySym);
- handleKeyRelease(menuKeyCode);
+ handleKeyPress(FAKE_KEY_CODE, menuKeyCode, menuKeySym);
+ handleKeyRelease(FAKE_KEY_CODE);
break;
case ID_CTRLALTDEL:
- handleKeyPress(0x1d, XK_Control_L);
- handleKeyPress(0x38, XK_Alt_L);
- handleKeyPress(0xd3, XK_Delete);
+ handleKeyPress(FAKE_CTRL_KEY_CODE, 0x1d, XK_Control_L);
+ handleKeyPress(FAKE_ALT_KEY_CODE, 0x38, XK_Alt_L);
+ handleKeyPress(FAKE_DEL_KEY_CODE, 0xd3, XK_Delete);
- handleKeyRelease(0xd3);
- handleKeyRelease(0x38);
- handleKeyRelease(0x1d);
+ handleKeyRelease(FAKE_DEL_KEY_CODE);
+ handleKeyRelease(FAKE_ALT_KEY_CODE);
+ handleKeyRelease(FAKE_CTRL_KEY_CODE);
break;
case ID_REFRESH:
cc->refreshFramebuffer();
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index 5f4c1ca7..16fa1da8 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -86,8 +86,9 @@ private:
void resetKeyboard();
- void handleKeyPress(int keyCode, uint32_t keySym);
- void handleKeyRelease(int keyCode);
+ void handleKeyPress(int systemKeyCode,
+ uint32_t keyCode, uint32_t keySym);
+ void handleKeyRelease(int systemKeyCode);
static int handleSystemEvent(void *event, void *data);
@@ -113,8 +114,12 @@ private:
rfb::Point lastPointerPos;
uint8_t lastButtonMask;
- typedef std::map<int, uint32_t> DownMap;
- DownMap downKeySym;
+ struct DownKey {
+ uint32_t keyCode;
+ uint32_t keySym;
+ };
+ typedef std::map<int, DownKey> DownMap;
+ DownMap downKeys;
#ifdef WIN32
bool altGrArmed;