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.
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 7b79139..c83254f 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -84,12 +84,9 @@
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::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 @@
rdr::U32 lookup;
lastEventTime = time(0);
- server->lastUserInputTime = lastEventTime;
if (!(accessRights & AccessKeyEvents)) return;
if (!rfb::Server::acceptKeyEvents) return;
@@ -545,16 +534,6 @@
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 @@
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 @@
//
} 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 @@
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 7e36876..6affe92 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -147,6 +147,10 @@
std::list<VNCSConnectionST*>::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 @@
}
}
+// 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 ef83619..eff52d0 100644
--- a/common/rfb/VNCServerST.h
+++ b/common/rfb/VNCServerST.h
@@ -120,6 +120,11 @@
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);