diff options
Diffstat (limited to 'common/rfb/VNCSConnectionST.cxx')
-rw-r--r-- | common/rfb/VNCSConnectionST.cxx | 140 |
1 files changed, 88 insertions, 52 deletions
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index de41e8fc..232776fc 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -313,6 +313,16 @@ void VNCSConnectionST::setCursorOrClose() } +void VNCSConnectionST::setLEDStateOrClose(unsigned int state) +{ + try { + setLEDState(state); + } catch(rdr::Exception& e) { + close(e.str()); + } +} + + int VNCSConnectionST::checkIdleTimeout() { int idleTimeout = rfb::Server::idleTimeout; @@ -418,6 +428,7 @@ void VNCSConnectionST::authSuccess() cp.height = server->pb->height(); cp.screenLayout = server->screenLayout; cp.setName(server->getName()); + cp.setLEDState(server->ledState); // - Set the default pixel format cp.setPF(server->pb->getPF()); @@ -570,61 +581,66 @@ void VNCSConnectionST::keyEvent(rdr::U32 key, bool down) { vlog.debug("Ignoring lock key (e.g. caps lock)"); return; } - // Always ignore ScrollLock though as we don't have a heuristic - // for that - if (key == XK_Scroll_Lock) { - vlog.debug("Ignoring lock key (e.g. caps lock)"); - return; - } - if (down && (server->ledState != ledUnknown)) { - // CapsLock synchronisation heuristic - // (this assumes standard interaction between CapsLock the Shift - // keys and normal characters) - if (((key >= XK_A) && (key <= XK_Z)) || - ((key >= XK_a) && (key <= XK_z))) { - bool uppercase, shift, lock; - - uppercase = (key >= XK_A) && (key <= XK_Z); - shift = pressedKeys.find(XK_Shift_L) != pressedKeys.end() || - pressedKeys.find(XK_Shift_R) != pressedKeys.end(); - lock = server->ledState & ledCapsLock; - - if (lock == (uppercase == shift)) { - vlog.debug("Inserting fake CapsLock to get in sync with client"); - server->desktop->keyEvent(XK_Caps_Lock, true); - server->desktop->keyEvent(XK_Caps_Lock, false); - } + // Lock key heuristics + // (only for clients that do not support the LED state extension) + if (!cp.supportsLEDState) { + // Always ignore ScrollLock as we don't have a heuristic + // for that + if (key == XK_Scroll_Lock) { + vlog.debug("Ignoring lock key (e.g. caps lock)"); + return; } - // NumLock synchronisation heuristic - // (this is more cautious because of the differences between Unix, - // Windows and macOS) - if (((key >= XK_KP_Home) && (key <= XK_KP_Delete)) || - ((key >= XK_KP_0) && (key <= XK_KP_9)) || - (key == XK_KP_Separator) || (key == XK_KP_Decimal)) { - bool number, shift, lock; - - number = ((key >= XK_KP_0) && (key <= XK_KP_9)) || - (key == XK_KP_Separator) || (key == XK_KP_Decimal); - shift = pressedKeys.find(XK_Shift_L) != pressedKeys.end() || - pressedKeys.find(XK_Shift_R) != pressedKeys.end(); - lock = server->ledState & ledNumLock; - - if (shift) { - // We don't know the appropriate NumLock state for when Shift - // is pressed as it could be one of: - // - // a) A Unix client where Shift negates NumLock - // - // b) A Windows client where Shift only cancels NumLock - // - // c) A macOS client where Shift doesn't have any effect - // - } else if (lock == (number == shift)) { - vlog.debug("Inserting fake NumLock to get in sync with client"); - server->desktop->keyEvent(XK_Num_Lock, true); - server->desktop->keyEvent(XK_Num_Lock, false); + if (down && (server->ledState != ledUnknown)) { + // CapsLock synchronisation heuristic + // (this assumes standard interaction between CapsLock the Shift + // keys and normal characters) + if (((key >= XK_A) && (key <= XK_Z)) || + ((key >= XK_a) && (key <= XK_z))) { + bool uppercase, shift, lock; + + uppercase = (key >= XK_A) && (key <= XK_Z); + shift = pressedKeys.find(XK_Shift_L) != pressedKeys.end() || + pressedKeys.find(XK_Shift_R) != pressedKeys.end(); + lock = server->ledState & ledCapsLock; + + if (lock == (uppercase == shift)) { + vlog.debug("Inserting fake CapsLock to get in sync with client"); + server->desktop->keyEvent(XK_Caps_Lock, true); + server->desktop->keyEvent(XK_Caps_Lock, false); + } + } + + // NumLock synchronisation heuristic + // (this is more cautious because of the differences between Unix, + // Windows and macOS) + if (((key >= XK_KP_Home) && (key <= XK_KP_Delete)) || + ((key >= XK_KP_0) && (key <= XK_KP_9)) || + (key == XK_KP_Separator) || (key == XK_KP_Decimal)) { + bool number, shift, lock; + + number = ((key >= XK_KP_0) && (key <= XK_KP_9)) || + (key == XK_KP_Separator) || (key == XK_KP_Decimal); + shift = pressedKeys.find(XK_Shift_L) != pressedKeys.end() || + pressedKeys.find(XK_Shift_R) != pressedKeys.end(); + lock = server->ledState & ledNumLock; + + if (shift) { + // We don't know the appropriate NumLock state for when Shift + // is pressed as it could be one of: + // + // a) A Unix client where Shift negates NumLock + // + // b) A Windows client where Shift only cancels NumLock + // + // c) A macOS client where Shift doesn't have any effect + // + } else if (lock == (number == shift)) { + vlog.debug("Inserting fake NumLock to get in sync with client"); + server->desktop->keyEvent(XK_Num_Lock, true); + server->desktop->keyEvent(XK_Num_Lock, false); + } } } } @@ -818,6 +834,11 @@ void VNCSConnectionST::supportsContinuousUpdates() writer()->writeEndOfContinuousUpdates(); } +void VNCSConnectionST::supportsLEDState() +{ + writer()->writeLEDState(); +} + bool VNCSConnectionST::handleTimeout(Timer* t) { @@ -1230,6 +1251,21 @@ void VNCSConnectionST::setDesktopName(const char *name) writeFramebufferUpdate(); } +void VNCSConnectionST::setLEDState(unsigned int ledstate) +{ + if (state() != RFBSTATE_NORMAL) + return; + + cp.setLEDState(ledstate); + + if (!writer()->writeLEDState()) { + // No client support + return; + } + + writeFramebufferUpdate(); +} + void VNCSConnectionST::setSocketTimeouts() { int timeoutms = rfb::Server::clientWaitTimeMillis; |