From 34fc97a52add15a0b3060fac23bad6bc5324403a Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Wed, 21 Jan 2004 15:25:41 +0000
Subject: add "-progressive height" option to make SendFramebufferUpdate
 "preemptive"

---
 ChangeLog   |  1 +
 cargs.c     |  7 +++++++
 main.c      | 11 +++++++----
 rfb/rfb.h   |  9 +++++++++
 rfbserver.c | 22 ++++++++++++++++++++++
 5 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2d8b5ae..8a02c14 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@
 	* do not send unneccessary updates when drawing a cursor
 	* ignore SIGPIPE; it is handled by EPIPE
 	* add an example how to use rfbDoCopyRect
+	* add experimental progressive updating (off by default)
 	
 2004-01-19  Karl Runge <runge@karlrunge.com>
 	* handle mouse button number mismatch
diff --git a/cargs.c b/cargs.c
index f393698..22ce9ad 100644
--- a/cargs.c
+++ b/cargs.c
@@ -35,6 +35,7 @@ rfbUsage(void)
     fprintf(stderr, "-httpdir dir-path      enable http server using dir-path home\n");
     fprintf(stderr, "-httpport portnum      use portnum for http connection\n");
     fprintf(stderr, "-enablehttpproxy       enable http proxy support\n");
+    fprintf(stderr, "-progressive height    enable progressive updating for slow links\n");
 }
 
 /* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
@@ -119,6 +120,12 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
             rfbScreen->httpPort = atoi(argv[++i]);
         } else if (strcmp(argv[i], "-enablehttpproxy") == 0) {
             rfbScreen->httpEnableProxyConnect = TRUE;
+        } else if (strcmp(argv[i], "-progressive") == 0) {  /* -httpport portnum */
+            if (i + 1 >= *argc) {
+		rfbUsage();
+		return FALSE;
+	    }
+            rfbScreen->progressiveSliceHeight = atoi(argv[++i]);
         } else {
 	    /* we just remove the processed arguments from the list */
 	    if(i != i1)
diff --git a/main.c b/main.c
index 6eded98..e6d7969 100644
--- a/main.c
+++ b/main.c
@@ -589,6 +589,11 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
 
    rfbScreen->passwordCheck = defaultPasswordCheck;
 
+   rfbScreen->ignoreSIGPIPE = TRUE;
+
+   /* disable progressive updating per default */
+   rfbScreen->progressiveSliceHeight = 0;
+
    if(!rfbProcessArguments(rfbScreen,argc,argv)) {
      free(rfbScreen);
      return 0;
@@ -638,8 +643,6 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
    /* initialize client list and iterator mutex */
    rfbClientListInit(rfbScreen);
 
-   rfbScreen->ignoreSIGPIPE = TRUE;
-
    return(rfbScreen);
 }
 
@@ -801,7 +804,7 @@ rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
   while(cl) {
     if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) &&
         !sraRgnEmpty(cl->requestedRegion)) {
-      if(cl->screen->rfbDeferUpdateTime == 0) {
+      if(rfbScreen->rfbDeferUpdateTime == 0) {
 	  rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
       } else if(cl->startDeferring.tv_usec == 0) {
 	gettimeofday(&cl->startDeferring,NULL);
@@ -812,7 +815,7 @@ rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
 	if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
 	   || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
 	       +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
-	     > cl->screen->rfbDeferUpdateTime) {
+	     > rfbScreen->rfbDeferUpdateTime) {
 	  cl->startDeferring.tv_usec = 0;
 	  rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
 	}
diff --git a/rfb/rfb.h b/rfb/rfb.h
index a571235..d472684 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -274,7 +274,13 @@ typedef struct _rfbScreenInfo
     rfbBool backgroundLoop;
 #endif
 
+    /* if TRUE, an ignoring signal handler is installed for SIGPIPE */
     rfbBool ignoreSIGPIPE;
+
+    /* if not zero, only a slice of this height is processed every time
+     * an update should be sent. This should make working on a slow
+     * link more interactive. */
+    int progressiveSliceHeight;
 } rfbScreenInfo, *rfbScreenInfoPtr;
 
 
@@ -469,6 +475,9 @@ typedef struct _rfbClientRec {
     void* zrleData;
 #endif
 
+    /* if progressive updating is on, this variable holds the current
+     * y coordinate of the progressive slice. */
+    int progressiveSliceY;
 } rfbClientRec, *rfbClientPtr;
 
 /*
diff --git a/rfbserver.c b/rfbserver.c
index 914aa0b..1b11e6b 100644
--- a/rfbserver.c
+++ b/rfbserver.c
@@ -340,6 +340,8 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
       cl->zlibCompressLevel = 5;
 #endif
 
+      cl->progressiveSliceY = 0;
+
       sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
 	      rfbProtocolMinorVersion);
 
@@ -1109,6 +1111,26 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
      */
 
     updateRegion = sraRgnCreateRgn(givenUpdateRegion);
+    if(cl->screen->progressiveSliceHeight>0) {
+	    int height=cl->screen->progressiveSliceHeight,
+	    	y=cl->progressiveSliceY;
+	    sraRegionPtr bbox=sraRgnBBox(updateRegion);
+	    sraRect rect;
+	    if(sraRgnPopRect(bbox,&rect,0)) {
+		sraRegionPtr slice;
+		if(y<rect.y1 || y>=rect.y2)
+		    y=rect.y1;
+	    	slice=sraRgnCreateRect(0,y,cl->screen->width,y+height);
+		sraRgnAnd(updateRegion,slice);
+		sraRgnDestroy(slice);
+	    }
+	    sraRgnDestroy(bbox);
+	    y+=height;
+	    if(y>=cl->screen->height)
+		    y=0;
+	    cl->progressiveSliceY=y;
+    }
+
     sraRgnOr(updateRegion,cl->copyRegion);
     if(!sraRgnAnd(updateRegion,cl->requestedRegion) &&
        !sendCursorShape && !sendCursorPos) {
-- 
cgit v1.2.3

