Implemented support for DesktopName pseudo encoding, which allows
updating the desktop name on the fly.

Tested in ThinLinc since 2008-01-07. 



git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3549 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index cc28846..0e3d967 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -138,6 +138,19 @@
   handler->setCursor(width, height, hotspot, data.buf, mask.buf);
 }
 
+void CMsgReader::readSetDesktopName(int x, int y, int w, int h)
+{
+  char* name = is->readString();
+
+  if (x || y || w || h) {
+    fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n");
+  } else {
+    handler->setName(name);
+  }
+
+  delete [] name;
+}
+
 rdr::U8* CMsgReader::getImageBuf(int required, int requested, int* nPixels)
 {
   int requiredBytes = required * (handler->cp.pf().bpp / 8);
diff --git a/common/rfb/CMsgReader.h b/common/rfb/CMsgReader.h
index 7a611fc..ebf69da 100644
--- a/common/rfb/CMsgReader.h
+++ b/common/rfb/CMsgReader.h
@@ -60,6 +60,7 @@
     virtual void readCopyRect(const Rect& r);
 
     virtual void readSetCursor(int width, int height, const Point& hotspot);
+    virtual void readSetDesktopName(int x, int y, int w, int h);
 
     CMsgReader(CMsgHandler* handler, rdr::InStream* is);
 
diff --git a/common/rfb/CMsgReaderV3.cxx b/common/rfb/CMsgReaderV3.cxx
index ae5f455..b2ba113 100644
--- a/common/rfb/CMsgReaderV3.cxx
+++ b/common/rfb/CMsgReaderV3.cxx
@@ -84,6 +84,9 @@
     case pseudoEncodingDesktopSize:
       handler->setDesktopSize(w, h);
       break;
+    case pseudoEncodingDesktopName:
+      readSetDesktopName(x, y, w, h);
+      break;
     case pseudoEncodingCursor:
       readSetCursor(w, h, Point(x,y));
       break;
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index cdfb4e5..26e0d50 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -64,6 +64,8 @@
     encodings[nEncodings++] = pseudoEncodingCursor;
   if (cp->supportsDesktopResize)
     encodings[nEncodings++] = pseudoEncodingDesktopSize;
+  if (cp->supportsDesktopRename)
+    encodings[nEncodings++] = pseudoEncodingDesktopName;
   if (Decoder::supported(preferredEncoding)) {
     encodings[nEncodings++] = preferredEncoding;
   }
diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx
index 446c3ad..b328a1f 100644
--- a/common/rfb/ConnParams.cxx
+++ b/common/rfb/ConnParams.cxx
@@ -29,7 +29,7 @@
 ConnParams::ConnParams()
   : majorVersion(0), minorVersion(0), tightExtensionsEnabled(false),
     width(0), height(0), useCopyRect(false),
-    supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(true),
+    supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(true), supportsDesktopRename(false),
     supportsLastRect(false), customCompressLevel(false), compressLevel(6),
     noJpeg(false), qualityLevel(-1), 
     name_(0), nEncodings_(0), encodings_(0),
@@ -111,6 +111,8 @@
       supportsLocalXCursor = true;
     else if (encodings[i] == pseudoEncodingDesktopSize)
       supportsDesktopResize = true;
+    else if (encodings[i] == pseudoEncodingDesktopName)
+      supportsDesktopRename = true;
     else if (encodings[i] == pseudoEncodingLastRect)
       supportsLastRect = true;
     else if (encodings[i] >= pseudoEncodingCompressLevel0 &&
diff --git a/common/rfb/ConnParams.h b/common/rfb/ConnParams.h
index e29adf8..f00b1d6 100644
--- a/common/rfb/ConnParams.h
+++ b/common/rfb/ConnParams.h
@@ -73,6 +73,7 @@
     bool supportsLocalCursor;
     bool supportsLocalXCursor;
     bool supportsDesktopResize;
+    bool supportsDesktopRename;
     bool supportsLastRect;
 
     bool customCompressLevel;
diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h
index 6f7feeb..959f865 100644
--- a/common/rfb/SMsgWriter.h
+++ b/common/rfb/SMsgWriter.h
@@ -76,6 +76,8 @@
     // but will write the relevant pseudo-rectangle as part of the next update.
     virtual bool writeSetDesktopSize()=0;
 
+    virtual bool writeSetDesktopName()=0;
+
     // Like setDesktopSize, we can't just write out a setCursor message
     // immediately on a V3 writer.  Instead of calling writeSetCursor()
     // directly, you must call cursorChange(), and then invoke writeSetCursor()
diff --git a/common/rfb/SMsgWriterV3.cxx b/common/rfb/SMsgWriterV3.cxx
index a85f85e..1271619 100644
--- a/common/rfb/SMsgWriterV3.cxx
+++ b/common/rfb/SMsgWriterV3.cxx
@@ -27,7 +27,7 @@
 SMsgWriterV3::SMsgWriterV3(ConnParams* cp, rdr::OutStream* os)
   : SMsgWriter(cp, os), updateOS(0), realOS(os), nRectsInUpdate(0),
     nRectsInHeader(0), wsccb(0),
-    needSetDesktopSize(false)
+    needSetDesktopSize(false), needSetDesktopName(false)
 {
 }
 
@@ -64,6 +64,12 @@
   return true;
 }
 
+bool SMsgWriterV3::writeSetDesktopName() {
+  if (!cp->supportsDesktopRename) return false;
+  needSetDesktopName = true;
+  return true;
+}
+
 void SMsgWriterV3::cursorChange(WriteSetCursorCallback* cb)
 {
   wsccb = cb;
@@ -118,6 +124,7 @@
   os->pad(1);
   if (wsccb) nRects++;
   if (needSetDesktopSize) nRects++;
+  if (needSetDesktopName) nRects++;
   os->writeU16(nRects);
   nRectsInUpdate = 0;
   nRectsInHeader = nRects;
@@ -150,6 +157,18 @@
     needSetDesktopSize = false;
   }
 
+  if (needSetDesktopName) {
+    if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+      throw Exception("SMsgWriterV3 setDesktopName: nRects out of sync");
+    os->writeS16(0);
+    os->writeS16(0);
+    os->writeU16(0);
+    os->writeU16(0);
+    os->writeU32(pseudoEncodingDesktopName);
+    os->writeString(cp->name());
+    needSetDesktopName = false;
+  }
+
   if (nRectsInUpdate != nRectsInHeader && nRectsInHeader)
     throw Exception("SMsgWriterV3::writeFramebufferUpdateEnd: "
                     "nRects out of sync");
@@ -168,7 +187,7 @@
 
 bool SMsgWriterV3::needFakeUpdate()
 {
-  return wsccb || needSetDesktopSize;
+  return wsccb || needSetDesktopSize || needSetDesktopName;
 }
 
 void SMsgWriterV3::startRect(const Rect& r, unsigned int encoding)
diff --git a/common/rfb/SMsgWriterV3.h b/common/rfb/SMsgWriterV3.h
index 501fa48..d2c13df 100644
--- a/common/rfb/SMsgWriterV3.h
+++ b/common/rfb/SMsgWriterV3.h
@@ -32,6 +32,7 @@
     virtual void startMsg(int type);
     virtual void endMsg();
     virtual bool writeSetDesktopSize();
+    virtual bool writeSetDesktopName();
     virtual void cursorChange(WriteSetCursorCallback* cb);
     virtual void writeSetCursor(int width, int height, const Point& hotspot,
                                 void* data, void* mask);
@@ -51,6 +52,7 @@
     int nRectsInHeader;
     WriteSetCursorCallback* wsccb;
     bool needSetDesktopSize;
+    bool needSetDesktopName;
     bool needLastRect;
   };
 }
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 7153dd4..9fe644c 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -232,6 +232,22 @@
   }
 }
 
+
+void VNCSConnectionST::setDesktopName(const char *name)
+{
+  cp.setName(name);
+  try {
+    if (state() == RFBSTATE_NORMAL) {
+      if (!writer()->writeSetDesktopName()) {
+	fprintf(stderr, "Client does not support desktop rename\n");
+      }
+    }
+  } catch(rdr::Exception& e) {
+    close(e.str());
+  }
+}
+
+
 void VNCSConnectionST::setCursorOrClose()
 {
   try {
diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h
index d48c8c7..d1c0857 100644
--- a/common/rfb/VNCSConnectionST.h
+++ b/common/rfb/VNCSConnectionST.h
@@ -66,6 +66,7 @@
     void setColourMapEntriesOrClose(int firstColour, int nColours);
     void bell();
     void serverCutText(const char *str, int len);
+    void setDesktopName(const char *name);
     void setCursorOrClose();
 
     // checkIdleTimeout() returns the number of milliseconds left until the
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index fc2e931..d36354c 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -302,6 +302,16 @@
   }
 }
 
+void VNCServerST::setName(const char* name_)
+{
+  name.replaceBuf(strDup(name_));
+  std::list<VNCSConnectionST*>::iterator ci, ci_next;
+  for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
+    ci_next = ci; ci_next++;
+    (*ci)->setDesktopName(name_);
+  }
+}
+
 void VNCServerST::add_changed(const Region& region)
 {
   if (comparer != 0) {
diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h
index 90bbeb5..0b8a2e6 100644
--- a/common/rfb/VNCServerST.h
+++ b/common/rfb/VNCServerST.h
@@ -125,7 +125,7 @@
 
     // setName() specifies the desktop name that the server should provide to
     // clients
-    void setName(const char* name_) {name.replaceBuf(strDup(name_));}
+    virtual void setName(const char* name_);
 
     // A QueryConnectionHandler, if supplied, is passed details of incoming
     // connections to approve, reject, or query the user about.
diff --git a/common/rfb/encodings.h b/common/rfb/encodings.h
index 51f6f1e..1021be9 100644
--- a/common/rfb/encodings.h
+++ b/common/rfb/encodings.h
@@ -33,6 +33,7 @@
   const unsigned int pseudoEncodingXCursor = 0xffffff10;
   const unsigned int pseudoEncodingCursor = 0xffffff11;
   const unsigned int pseudoEncodingDesktopSize = 0xffffff21;
+  const unsigned int pseudoEncodingDesktopName = 0xfffffecdl;
 
   // TightVNC-specific
   const unsigned int pseudoEncodingLastRect = 0xFFFFFF20;