diff options
-rw-r--r-- | vncviewer/Viewport.cxx | 136 | ||||
-rw-r--r-- | vncviewer/Viewport.h | 13 |
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; |