aboutsummaryrefslogtreecommitdiffstats
path: root/common/rfb/VNCSConnectionST.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'common/rfb/VNCSConnectionST.cxx')
-rw-r--r--common/rfb/VNCSConnectionST.cxx140
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;