Initial implementation of continuous updates in the server code. This code does not handle framebuffer size changes properly yet. Also, the server does not send the client EndOfContinuousUpdates message yet (documented in doc/rfbproto.tex).

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2251 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index 9e47900..bede90e 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <rfb/Exception.h>
 #include <rfb/secTypes.h>
+#include <rfb/msgTypes.h>
 #include <rfb/CapsList.h>
 #include <rfb/SMsgReaderV3.h>
 #include <rfb/SMsgWriterV3.h>
@@ -422,14 +423,50 @@
 // FIXME: Move sendInteractionCaps() to a class derived from SMsgWriterV3?
 void SConnection::sendInteractionCaps()
 {
+  //
   // Advertise support for non-standard server-to-client messages
-  // (this version has nothing to advertise).
+  //
+
   CapsList scaps;
 
+  // File transfer:
+  /* FIXME: File transfers are not finished yet: 
+  scaps.addTightExt(msgTypeFileListData,            "FTS_LSDT");
+  scaps.addTightExt(msgTypeFileDownloadData,        "FTS_DNDT");
+  scaps.addTightExt(msgTypeFileUploadCancel,        "FTS_UPCN");
+  scaps.addTightExt(msgTypeFileDownloadFailed,      "FTS_DNFL");
+  scaps.addTightExt(msgTypeFileDirSizeData,         "FTS_DSDT");
+  scaps.addTightExt(msgTypeFileLastRequestFailed,   "FTS_RQFL");
+  */
+
+  // Continuous updates:
+  /* FIXME: EndOfContinuousUpdates message is not supported yet:
+  scaps.addTightExt(msgTypeEndOfContinuousUpdates,  "CUS_EOCU");
+  */
+
+  //
   // Advertise support for non-standard client-to-server messages
-  // (this version has nothing to advertise).
+  //
+
   CapsList ccaps;
 
+  // File transfer:
+  /* FIXME: File transfers are not finished yet: 
+  ccaps.addTightExt(msgTypeFileListRequest,         "FTC_LSRQ");
+  ccaps.addTightExt(msgTypeFileDownloadRequest,     "FTC_DNRQ");
+  ccaps.addTightExt(msgTypeFileUploadRequest,       "FTC_UPRQ");
+  ccaps.addTightExt(msgTypeFileUploadRequest,       "FTC_UPDT");
+  ccaps.addTightExt(msgTypeFileDownloadCancel,      "FTC_DNCN");
+  ccaps.addTightExt(msgTypeFileUploadFailed,        "FTC_UPFL");
+  ccaps.addTightExt(msgTypeFileCreateDirRequest,    "FTC_FCDR");
+  ccaps.addTightExt(msgTypeFileDirSizeRequest,      "FTC_DSRQ");
+  ccaps.addTightExt(msgTypeFileRenameRequest,       "FTC_RNRQ");
+  ccaps.addTightExt(msgTypeFileDeleteRequest,       "FTC_RMRQ");
+  */
+
+  // Continuous updates:
+  ccaps.addTightExt(msgTypeEnableContinuousUpdates, "CUC_ENCU");
+
   // Advertise all supported encoding types (except raw encoding).
   CapsList ecaps;
 
diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx
index ccc97ad..f18a048 100644
--- a/common/rfb/SMsgHandler.cxx
+++ b/common/rfb/SMsgHandler.cxx
@@ -50,3 +50,11 @@
 void SMsgHandler::supportsLocalCursor()
 {
 }
+
+void SMsgHandler::enableContinuousUpdates(const Rect& r)
+{
+}
+
+void SMsgHandler::disableContinuousUpdates()
+{
+}
diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h
index cf3377d..ff74246 100644
--- a/common/rfb/SMsgHandler.h
+++ b/common/rfb/SMsgHandler.h
@@ -47,6 +47,9 @@
     virtual void setEncodings(int nEncodings, rdr::U32* encodings);
     virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
 
+    virtual void enableContinuousUpdates(const Rect& r);
+    virtual void disableContinuousUpdates();
+
     // InputHandler interface
     // The InputHandler methods will be called for the corresponding messages.
 
diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx
index f89e0f4..0e57ea7 100644
--- a/common/rfb/SMsgReader.cxx
+++ b/common/rfb/SMsgReader.cxx
@@ -95,3 +95,18 @@
   is->readBytes(ca.buf, len);
   handler->clientCutText(ca.buf, len);
 }
+
+void SMsgReader::readEnableContinuousUpdates()
+{
+  bool enable = is->readU8();
+  int x = is->readU16();
+  int y = is->readU16();
+  int w = is->readU16();
+  int h = is->readU16();
+  if (enable) {
+    handler->enableContinuousUpdates(Rect(x, y, x+w, y+h));
+  } else {
+    handler->disableContinuousUpdates();
+  }
+}
+
diff --git a/common/rfb/SMsgReader.h b/common/rfb/SMsgReader.h
index e6e4044..958c03a 100644
--- a/common/rfb/SMsgReader.h
+++ b/common/rfb/SMsgReader.h
@@ -47,6 +47,9 @@
     virtual void readPointerEvent();
     virtual void readClientCutText();
 
+    // Read TightVNC-specific protocol messages.
+    virtual void readEnableContinuousUpdates();
+
     SMsgReader(SMsgHandler* handler, rdr::InStream* is);
 
     SMsgHandler* handler;
diff --git a/common/rfb/SMsgReaderV3.cxx b/common/rfb/SMsgReaderV3.cxx
index be01b5d..e9b020b 100644
--- a/common/rfb/SMsgReaderV3.cxx
+++ b/common/rfb/SMsgReaderV3.cxx
@@ -61,6 +61,8 @@
   case msgTypeFileRenameRequest:
   case msgTypeFileDeleteRequest:        handler->processFTMsg(msgType); break;
 
+  case msgTypeEnableContinuousUpdates:  readEnableContinuousUpdates(); break;
+
   default:
     fprintf(stderr, "unknown message type %d\n", msgType);
     throw Exception("unknown message type");
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index fe60e43..bd067be 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -35,6 +35,7 @@
   : SConnection(server_->securityFactory, reverse), sock(s), server(server_),
     updates(false), image_getter(server->useEconomicTranslate),
     drawRenderedCursor(false), removeRenderedCursor(false),
+    autoUpdatesActive(false),
     pointerEventTime(0), accessRights(AccessDefault),
     startTime(time(0)), m_pFileTransfer(0)
 {
@@ -480,6 +481,35 @@
   writeFramebufferUpdate();
 }
 
+void VNCSConnectionST::enableContinuousUpdates(const Rect& r)
+{
+  // TightVNC-specific EnableContinuousUpdates message is very much like
+  // incremental FramebufferUpdateRequest. So here we copy some code from
+  // VNCSConnectionST::framebufferUpdateRequest().
+
+  if (!(accessRights & AccessView)) return;
+
+  SConnection::framebufferUpdateRequest(r, true);
+
+  autoUpdatesActive = true;
+  autoUpdatedRect = r;
+
+  Region reqRgn(autoUpdatedRect);
+  requested.assign_union(reqRgn);
+
+  writeFramebufferUpdate();
+}
+
+void VNCSConnectionST::disableContinuousUpdates()
+{
+  autoUpdatesActive = false;
+  autoUpdatedRect.clear();
+
+  writeFramebufferUpdate();
+
+  // FIXME: Send EndOfContinuousUpdates message.
+}
+
 void VNCSConnectionST::setInitialColourMap()
 {
   setColourMapEntries(0, 0);
@@ -615,6 +645,15 @@
     if (drawRenderedCursor)
       writeRenderedCursorRect();
     writer()->writeFramebufferUpdateEnd();
+    resetRequestedRegion();
+  }
+}
+
+void VNCSConnectionST::resetRequestedRegion()
+{
+  if (autoUpdatesActive) {
+    requested.reset(autoUpdatedRect);
+  } else {
     requested.clear();
   }
 }
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index a04296d..7fe2e32 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -129,6 +129,9 @@
     virtual void setInitialColourMap();
     virtual void supportsLocalCursor();
 
+    virtual void enableContinuousUpdates(const Rect& r);
+    virtual void disableContinuousUpdates();
+
     // setAccessRights() allows a security package to limit the access rights
     // of a VNCSConnectioST to the server.  These access rights are applied
     // such that the actual rights granted are the minimum of the server's
@@ -150,6 +153,8 @@
     void setCursor();
     void setSocketTimeouts();
 
+    void resetRequestedRegion();
+
     network::Socket* sock;
     CharArray peerEndpoint;
     VNCServerST* server;
@@ -159,6 +164,9 @@
     bool drawRenderedCursor, removeRenderedCursor;
     Rect renderedCursorRect;
 
+    bool autoUpdatesActive;       // continuous updates enabled
+    Rect autoUpdatedRect;         // continuously updated area
+
     std::set<rdr::U32> pressedKeys;
 
     time_t lastEventTime;
diff --git a/common/rfb/msgTypes.h b/common/rfb/msgTypes.h
index f6f8d5c..ec26adc 100644
--- a/common/rfb/msgTypes.h
+++ b/common/rfb/msgTypes.h
@@ -33,6 +33,8 @@
   const int msgTypeFileDirSizeData = 134;
   const int msgTypeFileLastRequestFailed = 135;
 
+  const int msgTypeEndOfContinuousUpdates = 150;
+
   // client to server
 
   const int msgTypeSetPixelFormat = 0;
@@ -53,5 +55,7 @@
   const int msgTypeFileDirSizeRequest = 137;
   const int	msgTypeFileRenameRequest = 138;
   const int msgTypeFileDeleteRequest = 139;
+
+  const int msgTypeEnableContinuousUpdates = 150;
 }
 #endif