summaryrefslogtreecommitdiffstats
path: root/libvncserver/cursor.c
diff options
context:
space:
mode:
authordscho <dscho>2005-01-18 23:18:04 +0000
committerdscho <dscho>2005-01-18 23:18:04 +0000
commita84b3d072a89e05c5aa5f702d223cfe304379293 (patch)
tree6e8b11537f0fe91e5a62b2dc559521ce8c9a9a13 /libvncserver/cursor.c
parentdd923e866021418379ee88b8a927597f616fbc84 (diff)
downloadlibtdevnc-a84b3d072a89e05c5aa5f702d223cfe304379293.tar.gz
libtdevnc-a84b3d072a89e05c5aa5f702d223cfe304379293.zip
pointerClient was still static.
do not make requestedRegion empty without reason. the cursor handling for clients which don't handle CursorShape updates was completely broken. It originally was very complicated for performance reasons, however, in most cases it made performance even worse, because at idle times there was way too much checking going on, and furthermore, sometimes unnecessary updates were inevitable. The code now is much more elegant: the ClientRec structure knows exactly where it last painted the cursor, and the ScreenInfo structure knows where the cursor shall be. As a consequence there is no more rfbDrawCursor()/rfbUndrawCursor(), no more dontSendFramebufferUpdate, and no more isCursorDrawn. It is now possible to have clients which understand CursorShape updates and clients which don't at the same time. rfbSetCursor no longer has the option freeOld; this is obsolete, as the cursor structure knows what to free and what not.
Diffstat (limited to 'libvncserver/cursor.c')
-rw-r--r--libvncserver/cursor.c100
1 files changed, 64 insertions, 36 deletions
diff --git a/libvncserver/cursor.c b/libvncserver/cursor.c
index 1600cb5..60730d4 100644
--- a/libvncserver/cursor.c
+++ b/libvncserver/cursor.c
@@ -23,6 +23,7 @@
*/
#include <rfb/rfb.h>
+#include <rfb/rfbregion.h>
/*
* Send cursor shape either in X-style format or in client pixel format.
@@ -387,19 +388,20 @@ void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor
/* functions to draw/hide cursor directly in the frame buffer */
-void rfbUndrawCursor(rfbScreenInfoPtr s)
+void rfbHideCursor(rfbClientPtr cl)
{
+ rfbScreenInfoPtr s=cl->screen;
rfbCursorPtr c=s->cursor;
int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8,
rowstride=s->paddedWidthInBytes;
LOCK(s->cursorMutex);
- if(!s->cursorIsDrawn || !c) {
+ if(!c) {
UNLOCK(s->cursorMutex);
return;
}
/* restore what is under the cursor */
- x1=s->cursorX-c->xhot;
+ x1=cl->cursorX-c->xhot;
x2=x1+c->width;
if(x1<0) x1=0;
if(x2>=s->width) x2=s->width-1;
@@ -407,7 +409,7 @@ void rfbUndrawCursor(rfbScreenInfoPtr s)
UNLOCK(s->cursorMutex);
return;
}
- y1=s->cursorY-c->yhot;
+ y1=cl->cursorY-c->yhot;
y2=y1+c->height;
if(y1<0) y1=0;
if(y2>=s->height) y2=s->height-1;
@@ -422,15 +424,12 @@ void rfbUndrawCursor(rfbScreenInfoPtr s)
s->underCursorBuffer+j*x2*bpp,
x2*bpp);
- /* rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); */
- s->cursorIsDrawn = FALSE;
- s->oldCursorX=s->cursorX;
- s->oldCursorY=s->cursorY;
UNLOCK(s->cursorMutex);
}
-void rfbDrawCursor(rfbScreenInfoPtr s)
+void rfbShowCursor(rfbClientPtr cl)
{
+ rfbScreenInfoPtr s=cl->screen;
rfbCursorPtr c=s->cursor;
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8,
rowstride=s->paddedWidthInBytes,
@@ -439,18 +438,7 @@ void rfbDrawCursor(rfbScreenInfoPtr s)
if(!c) return;
LOCK(s->cursorMutex);
- if(s->cursorIsDrawn) {
- /* is already drawn */
- UNLOCK(s->cursorMutex);
- return;
- }
- if(s->cursor && s->underCursorBuffer &&
- (s->cursorX!=s->oldCursorX || s->cursorY!=s->oldCursorY)) {
- int x1=s->oldCursorX-s->cursor->xhot,x2=x1+s->cursor->width;
- int y1=s->oldCursorY-s->cursor->yhot,y2=y1+s->cursor->height;
- rfbMarkRectAsModified(s,x1,y1,x2,y2);
- }
bufSize=c->width*c->height*bpp;
w=(c->width+7)/8;
if(s->underCursorBufferLen<bufSize) {
@@ -459,9 +447,10 @@ void rfbDrawCursor(rfbScreenInfoPtr s)
s->underCursorBuffer=malloc(bufSize);
s->underCursorBufferLen=bufSize;
}
+
/* save what is under the cursor */
i1=j1=0; /* offset in cursor */
- x1=s->cursorX-c->xhot;
+ x1=cl->cursorX-c->xhot;
x2=x1+c->width;
if(x1<0) { i1=-x1; x1=0; }
if(x2>=s->width) x2=s->width-1;
@@ -469,7 +458,8 @@ void rfbDrawCursor(rfbScreenInfoPtr s)
UNLOCK(s->cursorMutex);
return; /* nothing to do */
}
- y1=s->cursorY-c->yhot;
+
+ y1=cl->cursorY-c->yhot;
y2=y1+c->height;
if(y1<0) { j1=-y1; y1=0; }
if(y2>=s->height) y2=s->height-1;
@@ -491,7 +481,9 @@ void rfbDrawCursor(rfbScreenInfoPtr s)
if(!c->richSource)
rfbMakeRichCursorFromXCursor(s,c);
-
+
+ fprintf(stderr,"show cursor at %d %d\n",x1,y1);
+
if (c->alphaSource) {
int rmax, rshift;
int gmax, gshift;
@@ -571,12 +563,38 @@ void rfbDrawCursor(rfbScreenInfoPtr s)
c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
}
- if(wasChanged)
- rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
- s->cursorIsDrawn = TRUE;
UNLOCK(s->cursorMutex);
}
+/*
+ * If enableCursorShapeUpdates is FALSE, and the cursor is hidden, make sure
+ * that if the frameBuffer was transmitted with a cursor drawn, then that
+ * region gets redrawn.
+ */
+
+void rfbRedrawAfterHideCursor(rfbClientPtr cl)
+{
+ rfbScreenInfoPtr s = cl->screen;
+ rfbCursorPtr c = s->cursor;
+
+ if(c) {
+ int x,y,x2,y2;
+
+ x = cl->cursorX-c->xhot;
+ y = cl->cursorY-c->yhot;
+ x2 = x+c->width;
+ y2 = y+c->height;
+
+ if(sraClipRect2(&x,&y,&x2,&y2,0,0,s->width,s->height)) {
+ sraRegionPtr rect;
+ fprintf(stderr,"%d %d %d %d\n",x,y,x2,y2);
+ rect = sraRgnCreateRect(x,y,x2,y2);
+ sraRgnOr(cl->modifiedRegion,rect);
+ sraRgnDestroy(rect);
+ }
+ }
+}
+
/* for debugging */
void rfbPrintXCursor(rfbCursorPtr cursor)
@@ -593,23 +611,33 @@ void rfbPrintXCursor(rfbCursorPtr cursor)
}
}
-void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,rfbBool freeOld)
+void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c)
{
+ rfbClientIteratorPtr iterator;
+ rfbClientPtr cl;
+
LOCK(rfbScreen->cursorMutex);
- while(rfbScreen->cursorIsDrawn) {
- UNLOCK(rfbScreen->cursorMutex);
- rfbUndrawCursor(rfbScreen);
- LOCK(rfbScreen->cursorMutex);
- }
- free(rfbScreen->underCursorBuffer);
- rfbScreen->underCursorBuffer=0;
- rfbScreen->underCursorBufferLen=0;
+ if(rfbScreen->cursor && rfbScreen->cursor->cleanup) {
+ iterator=rfbGetClientIterator(rfbScreen);
+ while((cl=rfbClientIteratorNext(iterator)))
+ if(!cl->enableCursorShapeUpdates)
+ rfbRedrawAfterHideCursor(cl);
+ rfbReleaseClientIterator(iterator);
- if(rfbScreen->cursor && (freeOld || rfbScreen->cursor->cleanup))
rfbFreeCursor(rfbScreen->cursor);
+ }
rfbScreen->cursor = c;
+ iterator=rfbGetClientIterator(rfbScreen);
+ while((cl=rfbClientIteratorNext(iterator))) {
+ cl->cursorWasChanged = TRUE;
+ if(!cl->enableCursorShapeUpdates)
+ rfbRedrawAfterHideCursor(cl);
+ }
+ rfbReleaseClientIterator(iterator);
+
UNLOCK(rfbScreen->cursorMutex);
}
+