aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;