Basic infrastructure for continuous updates.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4801 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx
index 53f496b..eff4776 100644
--- a/common/rfb/CMsgHandler.cxx
+++ b/common/rfb/CMsgHandler.cxx
@@ -69,3 +69,8 @@
 {
   cp.supportsFence = true;
 }
+
+void CMsgHandler::endOfContinuousUpdates()
+{
+  cp.supportsContinuousUpdates = true;
+}
diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h
index 1e30eeb..d69d4f2 100644
--- a/common/rfb/CMsgHandler.h
+++ b/common/rfb/CMsgHandler.h
@@ -54,6 +54,7 @@
     virtual void setPixelFormat(const PixelFormat& pf);
     virtual void setName(const char* name);
     virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
+    virtual void endOfContinuousUpdates();
     virtual void serverInit() = 0;
 
     virtual void framebufferUpdateStart() = 0;
diff --git a/common/rfb/CMsgReaderV3.cxx b/common/rfb/CMsgReaderV3.cxx
index ebf08d3..085cc5a 100644
--- a/common/rfb/CMsgReaderV3.cxx
+++ b/common/rfb/CMsgReaderV3.cxx
@@ -61,6 +61,7 @@
     case msgTypeBell:                readBell(); break;
     case msgTypeServerCutText:       readServerCutText(); break;
     case msgTypeServerFence:         readFence(); break;
+    case msgTypeEndOfContinuousUpdates: readEndOfContinuousUpdates(); break;
 
     default:
       fprintf(stderr, "unknown message type %d\n", type);
@@ -166,3 +167,8 @@
   
   handler->fence(flags, len, data);
 }
+
+void CMsgReaderV3::readEndOfContinuousUpdates()
+{
+  handler->endOfContinuousUpdates();
+}
diff --git a/common/rfb/CMsgReaderV3.h b/common/rfb/CMsgReaderV3.h
index 9f55c65..bff70ef 100644
--- a/common/rfb/CMsgReaderV3.h
+++ b/common/rfb/CMsgReaderV3.h
@@ -33,6 +33,7 @@
     virtual void readSetDesktopName(int x, int y, int w, int h);
     virtual void readExtendedDesktopSize(int x, int y, int w, int h);
     virtual void readFence();
+    virtual void readEndOfContinuousUpdates();
     int nUpdateRectsLeft;
   };
 }
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index f221f22..ddc25ff 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -71,6 +71,7 @@
     encodings[nEncodings++] = pseudoEncodingDesktopName;
 
   encodings[nEncodings++] = pseudoEncodingLastRect;
+  encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
   encodings[nEncodings++] = pseudoEncodingFence;
 
   if (Decoder::supported(preferredEncoding)) {
diff --git a/common/rfb/CMsgWriter.h b/common/rfb/CMsgWriter.h
index e5cc590..6617459 100644
--- a/common/rfb/CMsgWriter.h
+++ b/common/rfb/CMsgWriter.h
@@ -46,6 +46,8 @@
     virtual void writeSetDesktopSize(int width, int height,
                                      const ScreenSet& layout)=0;
     virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0;
+    virtual void writeEnableContinuousUpdates(bool enable,
+                                              int x, int y, int w, int h)=0;
 
     // CMsgWriter implemented methods
     virtual void writeSetPixelFormat(const PixelFormat& pf);
diff --git a/common/rfb/CMsgWriterV3.cxx b/common/rfb/CMsgWriterV3.cxx
index ab3680a..b96e2b3 100644
--- a/common/rfb/CMsgWriterV3.cxx
+++ b/common/rfb/CMsgWriterV3.cxx
@@ -97,3 +97,21 @@
 
   endMsg();
 }
+
+void CMsgWriterV3::writeEnableContinuousUpdates(bool enable,
+                                                int x, int y, int w, int h)
+{
+  if (!cp->supportsContinuousUpdates)
+    throw Exception("Server does not support continuous updates");
+
+  startMsg(msgTypeEnableContinuousUpdates);
+
+  os->writeU8(!!enable);
+
+  os->writeU16(x);
+  os->writeU16(y);
+  os->writeU16(w);
+  os->writeU16(h);
+
+  endMsg();
+}
diff --git a/common/rfb/CMsgWriterV3.h b/common/rfb/CMsgWriterV3.h
index a0b9cab..fb1c42c 100644
--- a/common/rfb/CMsgWriterV3.h
+++ b/common/rfb/CMsgWriterV3.h
@@ -34,6 +34,8 @@
     virtual void writeSetDesktopSize(int width, int height,
                                      const ScreenSet& layout);
     virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]);
+    virtual void writeEnableContinuousUpdates(bool enable,
+                                              int x, int y, int w, int h);
   };
 }
 #endif
diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx
index 35b0054..2f0e275 100644
--- a/common/rfb/ConnParams.cxx
+++ b/common/rfb/ConnParams.cxx
@@ -34,6 +34,7 @@
     supportsDesktopResize(false), supportsExtendedDesktopSize(false),
     supportsDesktopRename(false), supportsLastRect(false),
     supportsSetDesktopSize(false), supportsFence(false),
+    supportsContinuousUpdates(false),
     customCompressLevel(false), compressLevel(6),
     noJpeg(false), qualityLevel(-1), fineQualityLevel(-1),
     subsampling(SUBSAMP_UNDEFINED),
@@ -127,6 +128,8 @@
       supportsLastRect = true;
     else if (encodings[i] == pseudoEncodingFence)
       supportsFence = true;
+    else if (encodings[i] == pseudoEncodingContinuousUpdates)
+      supportsContinuousUpdates = true;
     else if (encodings[i] >= pseudoEncodingCompressLevel0 &&
 	     encodings[i] <= pseudoEncodingCompressLevel9) {
       customCompressLevel = true;
diff --git a/common/rfb/ConnParams.h b/common/rfb/ConnParams.h
index 35e0605..fa0fe02 100644
--- a/common/rfb/ConnParams.h
+++ b/common/rfb/ConnParams.h
@@ -81,6 +81,7 @@
 
     bool supportsSetDesktopSize;
     bool supportsFence;
+    bool supportsContinuousUpdates;
 
     bool customCompressLevel;
     int compressLevel;
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
index ea56543..941d30a 100644
--- a/common/rfb/SConnection.cxx
+++ b/common/rfb/SConnection.cxx
@@ -342,3 +342,8 @@
 
   writer()->writeFence(flags, len, data);
 }
+
+void SConnection::enableContinuousUpdates(bool enable,
+                                          int x, int y, int w, int h)
+{
+}
diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h
index 51ceac0..a3a9fc8 100644
--- a/common/rfb/SConnection.h
+++ b/common/rfb/SConnection.h
@@ -113,6 +113,11 @@
     // support.
     virtual void fence(rdr::U32 flags, unsigned len, const char data[]);
 
+    // enableContinuousUpdates() is called when the client wants to enable
+    // or disable continuous updates, or change the active area.
+    virtual void enableContinuousUpdates(bool enable,
+                                         int x, int y, int w, int h);
+
     // setAccessRights() allows a security package to limit the access rights
     // of a VNCSConnectionST to the server.  How the access rights are treated
     // is up to the derived class.
diff --git a/common/rfb/SMsgHandler.cxx b/common/rfb/SMsgHandler.cxx
index ff15e19..d4046b1 100644
--- a/common/rfb/SMsgHandler.cxx
+++ b/common/rfb/SMsgHandler.cxx
@@ -41,9 +41,10 @@
 
 void SMsgHandler::setEncodings(int nEncodings, rdr::S32* encodings)
 {
-  bool firstFence;
+  bool firstFence, firstContinuousUpdates;
 
   firstFence = !cp.supportsFence;
+  firstContinuousUpdates = !cp.supportsContinuousUpdates;
 
   cp.setEncodings(nEncodings, encodings);
 
@@ -51,6 +52,8 @@
 
   if (cp.supportsFence && firstFence)
     supportsFence();
+  if (cp.supportsContinuousUpdates && firstContinuousUpdates)
+    supportsContinuousUpdates();
 }
 
 void SMsgHandler::supportsLocalCursor()
@@ -61,6 +64,10 @@
 {
 }
 
+void SMsgHandler::supportsContinuousUpdates()
+{
+}
+
 void SMsgHandler::setDesktopSize(int fb_width, int fb_height,
                                  const ScreenSet& layout)
 {
diff --git a/common/rfb/SMsgHandler.h b/common/rfb/SMsgHandler.h
index 0b1fd7e..c21cf52 100644
--- a/common/rfb/SMsgHandler.h
+++ b/common/rfb/SMsgHandler.h
@@ -51,6 +51,8 @@
     virtual void setDesktopSize(int fb_width, int fb_height,
                                 const ScreenSet& layout) = 0;
     virtual void fence(rdr::U32 flags, unsigned len, const char data[]) = 0;
+    virtual void enableContinuousUpdates(bool enable,
+                                         int x, int y, int w, int h) = 0;
 
     // InputHandler interface
     // The InputHandler methods will be called for the corresponding messages.
@@ -66,6 +68,12 @@
     // the client of server support.
     virtual void supportsFence();
 
+    // supportsContinuousUpdates() is called the first time we detect that
+    // the client wants the continuous updates extension. A
+    // EndOfContinuousUpdates message should be sent back to the client at
+    // this point if it is supported.
+    virtual void supportsContinuousUpdates();
+
     ConnParams cp;
   };
 }
diff --git a/common/rfb/SMsgReaderV3.cxx b/common/rfb/SMsgReaderV3.cxx
index eddeccf..cd957b9 100644
--- a/common/rfb/SMsgReaderV3.cxx
+++ b/common/rfb/SMsgReaderV3.cxx
@@ -55,6 +55,7 @@
   case msgTypeClientCutText:            readClientCutText(); break;
   case msgTypeSetDesktopSize:           readSetDesktopSize(); break;
   case msgTypeClientFence:              readFence(); break;
+  case msgTypeEnableContinuousUpdates:  readEnableContinuousUpdates(); break;
 
   default:
     fprintf(stderr, "unknown message type %d\n", msgType);
@@ -113,3 +114,18 @@
   
   handler->fence(flags, len, data);
 }
+
+void SMsgReaderV3::readEnableContinuousUpdates()
+{
+  bool enable;
+  int x, y, w, h;
+
+  enable = is->readU8();
+
+  x = is->readU16();
+  y = is->readU16();
+  w = is->readU16();
+  h = is->readU16();
+
+  handler->enableContinuousUpdates(enable, x, y, w, h);
+}
diff --git a/common/rfb/SMsgReaderV3.h b/common/rfb/SMsgReaderV3.h
index f4cc7d7..805fd87 100644
--- a/common/rfb/SMsgReaderV3.h
+++ b/common/rfb/SMsgReaderV3.h
@@ -31,6 +31,7 @@
   protected:
     virtual void readSetDesktopSize();
     virtual void readFence();
+    virtual void readEnableContinuousUpdates();
   };
 }
 #endif
diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h
index aaa98e4..3933b38 100644
--- a/common/rfb/SMsgWriter.h
+++ b/common/rfb/SMsgWriter.h
@@ -69,6 +69,10 @@
     // writeFence() sends a new fence request or response to the client.
     virtual void writeFence(rdr::U32 flags, unsigned len, const char data[])=0;
 
+    // writeEndOfContinuousUpdates() indicates that we have left continuous
+    // updates mode.
+    virtual void writeEndOfContinuousUpdates()=0;
+
     // setupCurrentEncoder() should be called before each framebuffer update,
     // prior to calling getNumRects() or writeFramebufferUpdateStart().
     void setupCurrentEncoder();
diff --git a/common/rfb/SMsgWriterV3.cxx b/common/rfb/SMsgWriterV3.cxx
index 0867b10..86f3507 100644
--- a/common/rfb/SMsgWriterV3.cxx
+++ b/common/rfb/SMsgWriterV3.cxx
@@ -82,6 +82,15 @@
   endMsg();
 }
 
+void SMsgWriterV3::writeEndOfContinuousUpdates()
+{
+  if (!cp->supportsContinuousUpdates)
+    throw Exception("Client does not support continuous updates");
+
+  startMsg(msgTypeEndOfContinuousUpdates);
+  endMsg();
+}
+
 bool SMsgWriterV3::writeSetDesktopSize() {
   if (!cp->supportsDesktopResize) return false;
   needSetDesktopSize = true;
diff --git a/common/rfb/SMsgWriterV3.h b/common/rfb/SMsgWriterV3.h
index 35f1f94..6710fa6 100644
--- a/common/rfb/SMsgWriterV3.h
+++ b/common/rfb/SMsgWriterV3.h
@@ -36,6 +36,7 @@
     virtual void startMsg(int type);
     virtual void endMsg();
     virtual void writeFence(rdr::U32 flags, unsigned len, const char data[]);
+    virtual void writeEndOfContinuousUpdates();
     virtual bool writeSetDesktopSize();
     virtual bool writeExtendedDesktopSize();
     virtual bool writeExtendedDesktopSize(rdr::U16 reason, rdr::U16 result,
diff --git a/common/rfb/encodings.h b/common/rfb/encodings.h
index 84844c5..5c6c5ea 100644
--- a/common/rfb/encodings.h
+++ b/common/rfb/encodings.h
@@ -37,6 +37,7 @@
   const int pseudoEncodingExtendedDesktopSize = -308;
   const int pseudoEncodingDesktopName = -307;
   const int pseudoEncodingFence = -312;
+  const int pseudoEncodingContinuousUpdates = -313;
 
   // TightVNC-specific
   const int pseudoEncodingLastRect = -224;
diff --git a/common/rfb/msgTypes.h b/common/rfb/msgTypes.h
index e42d95a..a55e1c5 100644
--- a/common/rfb/msgTypes.h
+++ b/common/rfb/msgTypes.h
@@ -26,6 +26,8 @@
   const int msgTypeBell = 2;
   const int msgTypeServerCutText = 3;
 
+  const int msgTypeEndOfContinuousUpdates = 150;
+
   const int msgTypeServerFence = 248;
 
   // client to server
@@ -38,6 +40,8 @@
   const int msgTypePointerEvent = 5;
   const int msgTypeClientCutText = 6;
 
+  const int msgTypeEnableContinuousUpdates = 150;
+
   const int msgTypeClientFence = 248;
 
   const int msgTypeSetDesktopSize = 251;