Skip to content

Commit

Permalink
Server: Time-limit pointer drag mutex by default
Browse files Browse the repository at this point in the history
Closes #417
  • Loading branch information
dcommander committed Jul 5, 2024
1 parent e9cdac1 commit 9695851
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 7 deletions.
8 changes: 8 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ number of simultaneously connected viewers.
server. (These events can be generated with horizontal scroll gestures on a
trackpad or, with certain mice, by side-clicking the scroll wheel.)

3. By default, the TurboVNC Server now limits the amount of time that it will
wait for a new pointer event from a connected viewer that is dragging the mouse
(and thus has exclusive control over the pointer.) This prevents other viewers
connected to the same session from being locked out of pointer control
indefinitely if a viewer's network connection drops while it is dragging the
mouse. A new Xvnc command-line option (`-pointerlocktimeout`) can be used to
specify the time limit.


3.1.1
=====
Expand Down
15 changes: 13 additions & 2 deletions unix/Xvnc/programs/Xserver/Xvnc.man.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.\" ** The above line should force tbl to be a preprocessor **
.\" Man page for Xvnc
.\"
.\" Copyright (C) 2010, 2012, 2014-2022 D. R. Commander
.\" Copyright (C) 2010, 2012, 2014-2022, 2024 D. R. Commander
.\" Copyright (C) 2021 Steffen Kieß
.\" Copyright (C) 2010 University Corporation for Atmospheric Research
.\" Copyright (C) 2005-2008 Sun Microsystems, Inc.
Expand All @@ -14,7 +14,7 @@
.\" License as specified in the file LICENCE.TXT that comes with the
.\" TurboVNC distribution.
.\"
.TH Xvnc 1 "March 2021" "" "TurboVNC"
.TH Xvnc 1 "July 2024" "" "TurboVNC"
.SH NAME
Xvnc \- the TurboVNC X server
.SH SYNOPSIS
Expand Down Expand Up @@ -213,6 +213,17 @@ version of Xvnc by AT&T labs.
\fB\-nocursor\fR
Don't display a mouse pointer on the remote desktop.

.TP
\fB\-pointerlocktimeout \fItime\fR
Maximum amount of time, in milliseconds, to wait for a new pointer event from a
connected viewer that is dragging the mouse (moving the mouse with one or more
mouse buttons held down) and thus has exclusive control over the pointer
[default: 3000]. 0 = indefinitely.

This prevents other viewers connected to the same session from being locked out
of pointer control indefinitely if a viewer's network connection drops while it
is dragging the mouse.

.TP
\fB\-viewonly\fR
Don't accept keyboard and pointer events from viewers. All viewers will
Expand Down
17 changes: 17 additions & 0 deletions unix/Xvnc/programs/Xserver/hw/vnc/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,16 @@ int ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}

if (strcasecmp(argv[i], "-pointerlocktimeout") == 0) {
REQUIRE_ARG();
rfbPointerLockTimeout = atoi(argv[i + 1]);
if (rfbPointerLockTimeout < 0) {
UseMsg();
exit(1);
}
return 2;
}

/* Run server in view-only mode - Ehud Karni SW */
if (strcasecmp(argv[i], "-viewonly") == 0) {
rfbViewOnly = TRUE;
Expand Down Expand Up @@ -1627,6 +1637,7 @@ void ddxGiveUp(enum ExitCode error)
rfbPAMEnd(cl);
#endif
ShutdownTightThreads();
TimerFree(pointerLockTimer);
free(rfbFB.pfbMemory);
if (initOutputCalled) {
char unixSocketName[32];
Expand Down Expand Up @@ -1738,6 +1749,12 @@ void ddxUseMsg(void)
ErrorF("======================\n");
ErrorF("-compatiblekbd set META key = ALT key as in the original VNC\n");
ErrorF("-nocursor don't display a cursor\n");
ErrorF("-pointerlocktimeout time\n");
ErrorF(" max time in ms (0 = indefinitely) to wait for a new\n");
ErrorF(" pointer event from a connected viewer that is dragging\n");
ErrorF(" the mouse (and thus has exclusive control over the\n");
ErrorF(" pointer) [default: %d]\n",
DEFAULT_POINTER_LOCK_TIMEOUT);
ErrorF("-viewonly only let viewers view, not control, the remote desktop\n");
ErrorF("-virtualtablet set up virtual stylus and eraser devices for this\n");
ErrorF(" session, to emulate a Wacom tablet, and map all\n");
Expand Down
5 changes: 5 additions & 0 deletions unix/Xvnc/programs/Xserver/hw/vnc/rfb.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@

#define DEFAULT_MAX_CLIENT_WAIT 20000

#define DEFAULT_POINTER_LOCK_TIMEOUT 3000

/* Constants for handling the UltraVNC Viewer's multitouch GII valuator event
format */
#define UVNCGII_MAX_TOUCHES 10
Expand Down Expand Up @@ -986,6 +988,9 @@ extern int rfbNumThreads;

extern char *rfbCaptureFile;

extern int rfbPointerLockTimeout;
extern OsTimerPtr pointerLockTimer;

#define debugregion(r, m) \
rfbLog(m" %d, %d %d x %d\n", (r).extents.x1, (r).extents.y1, \
(r).extents.x2 - (r).extents.x1, (r).extents.y2 - (r).extents.y1)
Expand Down
45 changes: 40 additions & 5 deletions unix/Xvnc/programs/Xserver/hw/vnc/rfbserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
*/

/* Copyright (C) 2009-2022, 2024 D. R. Commander. All Rights Reserved.
* Copyright (C) 2021, 2024 AnatoScope SA. All Rights Reserved.
* Copyright (C) 2015-2017, 2020-2021 Pierre Ossman for Cendio AB.
* All Rights Reserved.
* Copyright (C) 2021 AnatoScope SA. All Rights Reserved.
* Copyright (C) 2011 Joel Martin
* Copyright (C) 2010 University Corporation for Atmospheric Research.
* All Rights Reserved.
Expand Down Expand Up @@ -54,6 +54,13 @@ rfbClientPtr rfbClientHead = NULL;
/* The client that is currently dragging the pointer
This serves as a mutex for RFB pointer events. */
rfbClientPtr pointerDragClient = NULL;
/* Pointer lock timeout (in milliseconds)
Maximum amount of time, in milliseconds, to wait for a new pointer event
from a connected viewer that is dragging the mouse (and thus has exclusive
control over the pointer.) This prevents other viewers connected to the
same session from being locked out of pointer control indefinitely if a
viewer's network connection drops while it is dragging the mouse. */
int rfbPointerLockTimeout = DEFAULT_POINTER_LOCK_TIMEOUT;
/* The client that last moved the pointer
Other clients will automatically receive cursor updates via the traditional
mechanism of drawing the cursor into the framebuffer (AKA "server-side
Expand Down Expand Up @@ -124,6 +131,23 @@ void rfbWriteCapture(int captureFD, char *buf, int len)
}


/*
* Pointer lock timeout
*/

OsTimerPtr pointerLockTimer;

static CARD32 PointerLockTimerCallback(OsTimerPtr timer, CARD32 time,
void *arg)
{
if (pointerDragClient != NULL)
rfbLog("[%u] Timeout expired. Releasing pointer lock\n",
pointerDragClient->id);
pointerDragClient = NULL;
return 0;
}


/*
* Idle timeout
*/
Expand Down Expand Up @@ -570,8 +594,11 @@ void rfbClientConnectionGone(rfbClientPtr cl)
deflateEnd(&cl->zsStruct[i]);
}

if (pointerDragClient == cl)
if (pointerDragClient == cl) {
RFBLOGID("Releasing pointer lock\n");
pointerDragClient = NULL;
TimerCancel(pointerLockTimer);
}

if (pointerOwner == cl)
pointerOwner = NULL;
Expand Down Expand Up @@ -1282,10 +1309,18 @@ static void rfbProcessClientNormalMessage(rfbClientPtr cl)
if (pointerDragClient && (pointerDragClient != cl))
return;

if (msg.pe.buttonMask == 0)
pointerDragClient = NULL;
else
if (msg.pe.buttonMask == 0) {
if (pointerDragClient != NULL) {
pointerDragClient = NULL;
TimerCancel(pointerLockTimer);
}
} else {
pointerDragClient = cl;
if (rfbPointerLockTimeout)
pointerLockTimer = TimerSet(pointerLockTimer, 0,
rfbPointerLockTimeout,
PointerLockTimerCallback, NULL);
}

if (!rfbViewOnly && !cl->viewOnly) {
cl->cursorX = (int)Swap16IfLE(msg.pe.x);
Expand Down

0 comments on commit 9695851

Please sign in to comment.