Skip to content

Commit 6350715

Browse files
author
Volodymyr Samokhatko
committed
libvncserver: Always show ptr. movement to collaborators
When multiple viewers are sharing a single TurboVNC session, ordinarily it would be necessary for a viewer to disable remote cursor shape updates in order to see the pointer movements initiated by other viewers. This commit automates that by using server-side cursor rendering (drawing the cursor into the framebuffer, not using remote cursor shape updates) to send cursor updates to all viewers that aren't moving the pointer ("collaborators.") The viewer that is moving the pointer (the "pointer owner") receives remote cursor shape updates while it is moving the pointer, if it has elected to receive them. This mimics the behavior of RealVNC.
1 parent 264d0ef commit 6350715

File tree

4 files changed

+56
-12
lines changed

4 files changed

+56
-12
lines changed

include/rfb/rfb.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ typedef struct _rfbScreenInfo
277277
rfbBool neverShared;
278278
rfbBool dontDisconnect;
279279
struct _rfbClientRec* clientHead;
280-
struct _rfbClientRec* pointerClient; /**< "Mutex" for pointer events */
280+
struct _rfbClientRec* pointerClient; /**< "Mutex" for pointer drag events */
281281

282282

283283
/* cursor */
@@ -378,6 +378,14 @@ typedef struct _rfbScreenInfo
378378
/** where the cursor is shown */
379379
int underCursorBufferX, underCursorBufferY;
380380
RWLOCK(showCursorRWLock);
381+
382+
/* The client that last moved the pointer
383+
Other clients will automatically receive cursor updates via the traditional
384+
mechanism of drawing the cursor into the framebuffer (AKA "server-side
385+
cursor rendering") so they can track the pointer's movement regardless of
386+
whether cursor shape updates (AKA "client-side cursor rendering") are
387+
enabled. */
388+
struct _rfbClientRec* pointerOwner;
381389
} rfbScreenInfo, *rfbScreenInfoPtr;
382390

383391

@@ -722,7 +730,9 @@ typedef struct _rfbClientRec {
722730

723731
#define FB_UPDATE_PENDING(cl) \
724732
(((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
725-
(((cl)->enableCursorShapeUpdates == FALSE && \
733+
(( \
734+
((cl)->enableCursorShapeUpdates == FALSE || \
735+
(cl)->screen->pointerOwner != (cl)) && \
726736
((cl)->cursorX != (cl)->screen->cursorX || \
727737
(cl)->cursorY != (cl)->screen->cursorY))) || \
728738
((cl)->useNewFBSize && (cl)->newFBSizePending) || \

src/libvncserver/cursor.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
781781
if(rfbScreen->cursor) {
782782
iterator=rfbGetClientIterator(rfbScreen);
783783
while((cl=rfbClientIteratorNext(iterator)))
784-
if(!cl->enableCursorShapeUpdates)
784+
if(!cl->enableCursorShapeUpdates || (cl->screen->pointerOwner && cl->screen->pointerOwner != cl))
785785
rfbRedrawAfterHideCursor(cl,NULL);
786786
rfbReleaseClientIterator(iterator);
787787

@@ -794,8 +794,11 @@ void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
794794
iterator=rfbGetClientIterator(rfbScreen);
795795
while((cl=rfbClientIteratorNext(iterator))) {
796796
cl->cursorWasChanged = TRUE;
797-
if(!cl->enableCursorShapeUpdates)
797+
if(!cl->enableCursorShapeUpdates || (cl->screen->pointerOwner && cl->screen->pointerOwner != cl))
798798
rfbRedrawAfterHideCursor(cl,NULL);
799+
LOCK(cl->updateMutex);
800+
TSIGNAL(cl->updateCond);
801+
UNLOCK(cl->updateMutex);
799802
}
800803
rfbReleaseClientIterator(iterator);
801804

src/libvncserver/main.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,11 +732,26 @@ rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
732732
if (cl->enableCursorPosUpdates)
733733
cl->cursorWasMoved = FALSE;
734734

735+
/* Will become the pointer owner, need to hide the server-side cursor. */
736+
if (!cl->screen->pointerOwner) {
737+
rfbRedrawAfterHideCursor(cl, NULL);
738+
LOCK(cl->updateMutex);
739+
TSIGNAL(cl->updateCond);
740+
UNLOCK(cl->updateMutex);
741+
}
742+
735743
/* But inform all remaining clients about this cursor movement. */
736744
iterator = rfbGetClientIterator(s);
737745
while ((other_client = rfbClientIteratorNext(iterator)) != NULL) {
738-
if (other_client != cl && other_client->enableCursorPosUpdates) {
739-
other_client->cursorWasMoved = TRUE;
746+
if (other_client != cl) {
747+
if (other_client->enableCursorPosUpdates) {
748+
other_client->cursorWasMoved = TRUE;
749+
}
750+
if (other_client != cl->screen->pointerOwner) {
751+
LOCK(other_client->updateMutex);
752+
TSIGNAL(other_client->updateCond);
753+
UNLOCK(other_client->updateMutex);
754+
}
740755
}
741756
}
742757
rfbReleaseClientIterator(iterator);
@@ -1001,6 +1016,8 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
10011016
screen->underCursorBufferY = 0;
10021017
INIT_RWLOCK(screen->showCursorRWLock);
10031018

1019+
screen->pointerOwner = NULL;
1020+
10041021
if(!rfbProcessArguments(screen,argc,argv)) {
10051022
free(screen);
10061023
return NULL;

src/libvncserver/rfbserver.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,9 @@ rfbClientConnectionGone(rfbClientPtr cl)
627627
if (cl->screen->pointerClient == cl)
628628
cl->screen->pointerClient = NULL;
629629

630+
if (cl->screen->pointerOwner == cl)
631+
cl->screen->pointerOwner = NULL;
632+
630633
sraRgnDestroy(cl->modifiedRegion);
631634
sraRgnDestroy(cl->requestedRegion);
632635
sraRgnDestroy(cl->copyRegion);
@@ -2688,6 +2691,14 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
26882691
cl->screen->pointerClient = cl;
26892692

26902693
if(!cl->viewOnly) {
2694+
/* If the pointer was most recently moved by another client, we set
2695+
pointerOwner to NULL here so that the client that is currently
2696+
moving the pointer (cl), assuming it understands cursor shape
2697+
updates, will receive a cursor shape update with the last known
2698+
pointer position. */
2699+
if (cl->screen->pointerOwner != cl)
2700+
cl->screen->pointerOwner = NULL;
2701+
26912702
if (msg.pe.buttonMask != cl->lastPtrButtons ||
26922703
cl->screen->deferPtrUpdateTime == 0) {
26932704
cl->screen->ptrAddEvent(msg.pe.buttonMask,
@@ -2700,6 +2711,8 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
27002711
cl->lastPtrY = ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y));
27012712
cl->lastPtrButtons = msg.pe.buttonMask;
27022713
}
2714+
2715+
cl->screen->pointerOwner = cl;
27032716
}
27042717
return;
27052718

@@ -3158,8 +3171,9 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
31583171
}
31593172

31603173
/*
3161-
* If this client understands cursor shape updates, cursor should be
3162-
* removed from the framebuffer. Otherwise, make sure it's put up.
3174+
* If this client understands cursor shape updates and owns the pointer or is
3175+
* about to own the pointer, then the cursor should be removed from the
3176+
* framebuffer. Otherwise, make sure it's drawn.
31633177
*/
31643178

31653179
if (cl->enableCursorShapeUpdates) {
@@ -3264,7 +3278,7 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
32643278
sraRgnOr(updateRegion,cl->copyRegion);
32653279
if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
32663280
sraRgnEmpty(updateRegion) &&
3267-
(cl->enableCursorShapeUpdates ||
3281+
((cl->enableCursorShapeUpdates && (!cl->screen->pointerOwner || cl->screen->pointerOwner == cl)) ||
32683282
(cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) &&
32693283
!sendCursorShape && !sendCursorPos && !sendKeyboardLedState &&
32703284
!sendSupportedMessages && !sendSupportedEncodings && !sendServerIdentity) {
@@ -3319,7 +3333,7 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
33193333

33203334
UNLOCK(cl->updateMutex);
33213335

3322-
if (!cl->enableCursorShapeUpdates) {
3336+
if (!cl->enableCursorShapeUpdates || (cl->screen->pointerOwner && cl->screen->pointerOwner != cl)) {
33233337
if(cl->cursorX != cl->screen->cursorX || cl->cursorY != cl->screen->cursorY) {
33243338
rfbRedrawAfterHideCursor(cl,updateRegion);
33253339
LOCK(cl->screen->cursorMutex);
@@ -3576,8 +3590,8 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
35763590
result = FALSE;
35773591
}
35783592

3579-
if (!cl->enableCursorShapeUpdates) {
3580-
rfbHideCursor(cl);
3593+
if (!cl->enableCursorShapeUpdates || (cl->screen->pointerOwner && cl->screen->pointerOwner != cl)) {
3594+
rfbHideCursor(cl->screen);
35813595
}
35823596
RWUNLOCK(cl->screen->showCursorRWLock);
35833597

0 commit comments

Comments
 (0)