From b68434129bc7be45718940b999e0c93f773d1883 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 5 Oct 2018 17:30:52 +0200 Subject: [PATCH] Encapsulate event handling in VNCServerST There is some client coordination needed which is better encapsulated inside VNCServerST. This also helps hiding the desktop from the individual clients. --- common/rfb/VNCSConnectionST.cxx | 51 ++++++++++----------------------- common/rfb/VNCServerST.cxx | 46 +++++++++++++++++++++++++++++ common/rfb/VNCServerST.h | 5 ++++ 3 files changed, 66 insertions(+), 36 deletions(-) diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index 7b791391..c83254fb 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -84,12 +84,9 @@ VNCSConnectionST::~VNCSConnectionST() vlog.debug("Releasing key 0x%x / 0x%x on client disconnect", keysym, keycode); - server->desktop->keyEvent(keysym, keycode, false); + server->keyEvent(keysym, keycode, false); } - if (server->pointerClient == this) - server->pointerClient = 0; - // Remove this client from the server server->clients.remove(this); @@ -497,36 +494,29 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf) void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask) { pointerEventTime = lastEventTime = time(0); - server->lastUserInputTime = lastEventTime; if (!(accessRights & AccessPtrEvents)) return; if (!rfb::Server::acceptPointerEvents) return; - if (!server->pointerClient || server->pointerClient == this) { - pointerEventPos = pos; - if (buttonMask) - server->pointerClient = this; - else - server->pointerClient = 0; - server->desktop->pointerEvent(pointerEventPos, buttonMask); - } + pointerEventPos = pos; + server->pointerEvent(this, pointerEventPos, buttonMask); } class VNCSConnectionSTShiftPresser { public: - VNCSConnectionSTShiftPresser(SDesktop* desktop_) - : desktop(desktop_), pressed(false) {} + VNCSConnectionSTShiftPresser(VNCServerST* server_) + : server(server_), pressed(false) {} ~VNCSConnectionSTShiftPresser() { if (pressed) { vlog.debug("Releasing fake Shift_L"); - desktop->keyEvent(XK_Shift_L, 0, false); + server->keyEvent(XK_Shift_L, 0, false); } } void press() { vlog.debug("Pressing fake Shift_L"); - desktop->keyEvent(XK_Shift_L, 0, true); + server->keyEvent(XK_Shift_L, 0, true); pressed = true; } - SDesktop* desktop; + VNCServerST* server; bool pressed; }; @@ -536,7 +526,6 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { rdr::U32 lookup; lastEventTime = time(0); - server->lastUserInputTime = lastEventTime; if (!(accessRights & AccessKeyEvents)) return; if (!rfb::Server::acceptKeyEvents) return; @@ -545,16 +534,6 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { else vlog.debug("Key released: 0x%x / 0x%x", keysym, keycode); - // Remap the key if required - if (server->keyRemapper) { - rdr::U32 newkey; - newkey = server->keyRemapper->remapKey(keysym); - if (newkey != keysym) { - vlog.debug("Key remapped to 0x%x", newkey); - keysym = newkey; - } - } - // Avoid lock keys if we don't know the server state if ((server->getLEDState() == ledUnknown) && ((keysym == XK_Caps_Lock) || @@ -588,8 +567,8 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { if (lock == (uppercase == shift)) { vlog.debug("Inserting fake CapsLock to get in sync with client"); - server->desktop->keyEvent(XK_Caps_Lock, 0, true); - server->desktop->keyEvent(XK_Caps_Lock, 0, false); + server->keyEvent(XK_Caps_Lock, 0, true); + server->keyEvent(XK_Caps_Lock, 0, false); } } @@ -618,15 +597,15 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { // } else if (lock == (number == shift)) { vlog.debug("Inserting fake NumLock to get in sync with client"); - server->desktop->keyEvent(XK_Num_Lock, 0, true); - server->desktop->keyEvent(XK_Num_Lock, 0, false); + server->keyEvent(XK_Num_Lock, 0, true); + server->keyEvent(XK_Num_Lock, 0, false); } } } } // Turn ISO_Left_Tab into shifted Tab. - VNCSConnectionSTShiftPresser shiftPresser(server->desktop); + VNCSConnectionSTShiftPresser shiftPresser(server); if (keysym == XK_ISO_Left_Tab) { if (!isShiftPressed()) shiftPresser.press(); @@ -652,14 +631,14 @@ void VNCSConnectionST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) { return; } - server->desktop->keyEvent(keysym, keycode, down); + server->keyEvent(keysym, keycode, down); } void VNCSConnectionST::clientCutText(const char* str, int len) { if (!(accessRights & AccessCutText)) return; if (!rfb::Server::acceptCutText) return; - server->desktop->clientCutText(str, len); + server->clientCutText(str, len); } void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental) diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index 7e36876c..6affe928 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -147,6 +147,10 @@ void VNCServerST::removeSocket(network::Socket* sock) { std::list::iterator ci; for (ci = clients.begin(); ci != clients.end(); ci++) { if ((*ci)->getSock() == sock) { + // - Release the cursor if this client owns it + if (pointerClient == *ci) + pointerClient = NULL; + // - Delete the per-Socket resources delete *ci; @@ -467,6 +471,48 @@ void VNCServerST::setLEDState(unsigned int state) } } +// Event handlers + +void VNCServerST::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down) +{ + lastUserInputTime = time(0); + + // Remap the key if required + if (keyRemapper) { + rdr::U32 newkey; + newkey = keyRemapper->remapKey(keysym); + if (newkey != keysym) { + slog.debug("Key remapped to 0x%x", newkey); + keysym = newkey; + } + } + + desktop->keyEvent(keysym, keycode, down); +} + +void VNCServerST::pointerEvent(VNCSConnectionST* client, + const Point& pos, int buttonMask) +{ + lastUserInputTime = time(0); + + // Let one client own the cursor whilst buttons are pressed in order + // to provide a bit more sane user experience + if ((pointerClient != NULL) && (pointerClient != client)) + return; + + if (buttonMask) + pointerClient = client; + else + pointerClient = NULL; + + desktop->pointerEvent(pos, buttonMask); +} + +void VNCServerST::clientCutText(const char* str, int len) +{ + desktop->clientCutText(str, len); +} + // Other public methods void VNCServerST::approveConnection(network::Socket* sock, bool accept, diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index ef83619c..eff52d07 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -120,6 +120,11 @@ namespace rfb { const char* getName() const { return name.buf; } unsigned getLEDState() const { return ledState; } + // Event handlers + void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); + void pointerEvent(VNCSConnectionST* client, const Point& pos, int buttonMask); + void clientCutText(const char* str, int len); + // closeClients() closes all RFB sessions, except the specified one (if // any), and logs the specified reason for closure. void closeClients(const char* reason, network::Socket* sock); -- 2.39.5