Skip to content

Commit 264d0ef

Browse files
author
Volodymyr Samokhatko
committed
libvncserver: fix show server-side cursor by multiple clients
1 parent 0550c0d commit 264d0ef

File tree

5 files changed

+43
-11
lines changed

5 files changed

+43
-11
lines changed

include/rfb/rfb.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,12 @@ typedef struct _rfbScreenInfo
372372
#ifdef LIBVNCSERVER_HAVE_LIBZ
373373
rfbSetXCutTextUTF8ProcPtr setXCutTextUTF8;
374374
#endif
375+
376+
/** how many clients have requested to show the cursor in the framebuffer */
377+
int showCursorRefCount;
378+
/** where the cursor is shown */
379+
int underCursorBufferX, underCursorBufferY;
380+
RWLOCK(showCursorRWLock);
375381
} rfbScreenInfo, *rfbScreenInfoPtr;
376382

377383

src/libvncserver/cursor.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -500,29 +500,32 @@ void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor
500500

501501
/* functions to draw/hide cursor directly in the frame buffer */
502502

503-
void rfbHideCursor(rfbClientPtr cl)
503+
void rfbHideCursor(rfbScreenInfoPtr s)
504504
{
505-
rfbScreenInfoPtr s=cl->screen;
506505
rfbCursorPtr c;
507506
int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8,
508507
rowstride=s->paddedWidthInBytes;
509508
LOCK(s->cursorMutex);
509+
if(--s->showCursorRefCount != 0) {
510+
UNLOCK(s->cursorMutex);
511+
return;
512+
}
510513
c=s->cursor;
511514
if(!c) {
512515
UNLOCK(s->cursorMutex);
513516
return;
514517
}
515518

516519
/* restore what is under the cursor */
517-
x1=cl->cursorX-c->xhot;
520+
x1=s->underCursorBufferX-c->xhot;
518521
x2=x1+c->width;
519522
if(x1<0) x1=0;
520523
if(x2>=s->width) x2=s->width-1;
521524
x2-=x1; if(x2<=0) {
522525
UNLOCK(s->cursorMutex);
523526
return;
524527
}
525-
y1=cl->cursorY-c->yhot;
528+
y1=s->underCursorBufferY-c->yhot;
526529
y2=y1+c->height;
527530
if(y1<0) y1=0;
528531
if(y2>=s->height) y2=s->height-1;
@@ -543,16 +546,19 @@ void rfbHideCursor(rfbClientPtr cl)
543546
UNLOCK(s->cursorMutex);
544547
}
545548

546-
void rfbShowCursor(rfbClientPtr cl)
549+
void rfbShowCursor(rfbScreenInfoPtr s)
547550
{
548-
rfbScreenInfoPtr s=cl->screen;
549551
rfbCursorPtr c;
550552
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8,
551553
rowstride=s->paddedWidthInBytes,
552554
bufSize,w;
553555
rfbBool wasChanged=FALSE;
554556

555557
LOCK(s->cursorMutex);
558+
if(++s->showCursorRefCount != 1) {
559+
UNLOCK(s->cursorMutex);
560+
return;
561+
}
556562
c=s->cursor;
557563
if(!c) {
558564
UNLOCK(s->cursorMutex);
@@ -570,7 +576,7 @@ void rfbShowCursor(rfbClientPtr cl)
570576

571577
/* save what is under the cursor */
572578
i1=j1=0; /* offset in cursor */
573-
x1=cl->cursorX-c->xhot;
579+
x1=s->cursorX-c->xhot;
574580
x2=x1+c->width;
575581
if(x1<0) { i1=-x1; x1=0; }
576582
if(x2>=s->width) x2=s->width-1;
@@ -579,7 +585,7 @@ void rfbShowCursor(rfbClientPtr cl)
579585
return; /* nothing to do */
580586
}
581587

582-
y1=cl->cursorY-c->yhot;
588+
y1=s->cursorY-c->yhot;
583589
y2=y1+c->height;
584590
if(y1<0) { j1=-y1; y1=0; }
585591
if(y2>=s->height) y2=s->height-1;
@@ -704,6 +710,10 @@ void rfbShowCursor(rfbClientPtr cl)
704710
/* Copy to all scaled versions */
705711
rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2);
706712

713+
/* Memorize the coords where the cursor was drawn */
714+
s->underCursorBufferX = s->cursorX;
715+
s->underCursorBufferY = s->cursorY;
716+
707717
UNLOCK(s->cursorMutex);
708718
}
709719

@@ -764,6 +774,8 @@ void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
764774
rfbClientIteratorPtr iterator;
765775
rfbClientPtr cl;
766776

777+
/* wait until the cursor is not shown in the framebuffer */
778+
WRLOCK(rfbScreen->showCursorRWLock);
767779
LOCK(rfbScreen->cursorMutex);
768780

769781
if(rfbScreen->cursor) {
@@ -788,5 +800,6 @@ void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
788800
rfbReleaseClientIterator(iterator);
789801

790802
UNLOCK(rfbScreen->cursorMutex);
803+
RWUNLOCK(rfbScreen->showCursorRWLock);
791804
}
792805

src/libvncserver/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,11 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
996996

997997
screen->permitFileTransfer = FALSE;
998998

999+
screen->showCursorRefCount = 0;
1000+
screen->underCursorBufferX = 0;
1001+
screen->underCursorBufferY = 0;
1002+
INIT_RWLOCK(screen->showCursorRWLock);
1003+
9991004
if(!rfbProcessArguments(screen,argc,argv)) {
10001005
free(screen);
10011006
return NULL;
@@ -1156,6 +1161,8 @@ void rfbScreenCleanup(rfbScreenInfoPtr screen)
11561161
cl1=cl;
11571162
}
11581163
rfbReleaseClientIterator(i);
1164+
1165+
TINI_RWLOCK(screen->showCursorRWLock);
11591166

11601167
#define FREE_IF(x) if(screen->x) free(screen->x)
11611168
FREE_IF(colourMap.data.bytes);

src/libvncserver/private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
/* from cursor.c */
55

6-
void rfbShowCursor(rfbClientPtr cl);
7-
void rfbHideCursor(rfbClientPtr cl);
6+
void rfbShowCursor(rfbScreenInfoPtr s);
7+
void rfbHideCursor(rfbScreenInfoPtr s);
88
void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion);
99

1010
/* from main.c */

src/libvncserver/rfbserver.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3328,7 +3328,12 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
33283328
UNLOCK(cl->screen->cursorMutex);
33293329
rfbRedrawAfterHideCursor(cl,updateRegion);
33303330
}
3331-
rfbShowCursor(cl);
3331+
/* show the cursor if the cursor is not shown in the framebuffer, increment the refcount */
3332+
RDLOCK(cl->screen->showCursorRWLock);
3333+
rfbShowCursor(cl->screen);
3334+
} else {
3335+
/* wait until the cursor is not shown in the framebuffer */
3336+
WRLOCK(cl->screen->showCursorRWLock);
33323337
}
33333338

33343339
/*
@@ -3574,6 +3579,7 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
35743579
if (!cl->enableCursorShapeUpdates) {
35753580
rfbHideCursor(cl);
35763581
}
3582+
RWUNLOCK(cl->screen->showCursorRWLock);
35773583

35783584
if(i)
35793585
sraRgnReleaseIterator(i);

0 commit comments

Comments
 (0)