]> source.dussan.org Git - tigervnc.git/commitdiff
Minimal server side implementation of the extended desktop size protocol.
authorPierre Ossman <ossman@cendio.se>
Fri, 20 Mar 2009 12:59:05 +0000 (12:59 +0000)
committerPierre Ossman <ossman@cendio.se>
Fri, 20 Mar 2009 12:59:05 +0000 (12:59 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3698 3789f03b-4d11-0410-bbf8-ca57d06f2519

14 files changed:
common/rfb/ConnParams.cxx
common/rfb/ConnParams.h
common/rfb/SMsgHandler.cxx
common/rfb/SMsgHandler.h
common/rfb/SMsgReaderV3.cxx
common/rfb/SMsgReaderV3.h
common/rfb/SMsgWriter.h
common/rfb/SMsgWriterV3.cxx
common/rfb/SMsgWriterV3.h
common/rfb/VNCSConnectionST.cxx
common/rfb/VNCSConnectionST.h
common/rfb/encodings.h
common/rfb/msgTypes.h
common/rfb/screenTypes.h [new file with mode: 0644]

index b328a1f82af9bbd2492d2c6a0086673a44c51021..10b60fbd7eddd068ad3b524ca70ab02b3a08a769 100644 (file)
@@ -29,8 +29,10 @@ using namespace rfb;
 ConnParams::ConnParams()
   : majorVersion(0), minorVersion(0), tightExtensionsEnabled(false),
     width(0), height(0), useCopyRect(false),
-    supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(true), supportsDesktopRename(false),
-    supportsLastRect(false), customCompressLevel(false), compressLevel(6),
+    supportsLocalCursor(false), supportsLocalXCursor(false),
+    supportsDesktopResize(false), supportsExtendedDesktopSize(false),
+    supportsDesktopRename(false), supportsLastRect(false),
+    customCompressLevel(false), compressLevel(6),
     noJpeg(false), qualityLevel(-1), 
     name_(0), nEncodings_(0), encodings_(0),
     currentEncoding_(encodingRaw), verStrPos(0)
@@ -92,6 +94,7 @@ void ConnParams::setEncodings(int nEncodings, const rdr::U32* encodings)
   useCopyRect = false;
   supportsLocalCursor = false;
   supportsDesktopResize = false;
+  supportsExtendedDesktopSize = false;
   supportsLocalXCursor = false;
   supportsLastRect = false;
   customCompressLevel = false;
@@ -111,6 +114,8 @@ void ConnParams::setEncodings(int nEncodings, const rdr::U32* encodings)
       supportsLocalXCursor = true;
     else if (encodings[i] == pseudoEncodingDesktopSize)
       supportsDesktopResize = true;
+    else if (encodings[i] == pseudoEncodingExtendedDesktopSize)
+      supportsExtendedDesktopSize = true;
     else if (encodings[i] == pseudoEncodingDesktopName)
       supportsDesktopRename = true;
     else if (encodings[i] == pseudoEncodingLastRect)
index f00b1d6e75a0f774bd08083110ccb982e85ed603..bdd9cf231bc6f658cc80a03922328f090c897c30 100644 (file)
@@ -73,6 +73,7 @@ namespace rfb {
     bool supportsLocalCursor;
     bool supportsLocalXCursor;
     bool supportsDesktopResize;
+    bool supportsExtendedDesktopSize;
     bool supportsDesktopRename;
     bool supportsLastRect;
 
index c55a8b72c9025c1375437fda658a92aec52ad22e..0c74f0f5cbb386d0c1dd0d1cccb041680025d5ed 100644 (file)
@@ -43,11 +43,13 @@ void SMsgHandler::setEncodings(int nEncodings, rdr::U32* encodings)
   supportsLocalCursor();
 }
 
-void SMsgHandler::framebufferUpdateRequest(const Rect& r, bool incremental)
+void SMsgHandler::supportsLocalCursor()
 {
 }
 
-void SMsgHandler::supportsLocalCursor()
+void SMsgHandler::setDesktopSize(int fb_width, int fb_height)
 {
+  cp.width = fb_width;
+  cp.height = fb_height;
 }
 
index 50a2dc4d491cebbb798acbdff5eb06824af73482..78cff2f76d3c321462080c631f7ed558674e48f7 100644 (file)
@@ -38,14 +38,15 @@ namespace rfb {
 
     // The following methods are called as corresponding messages are read.  A
     // derived class should override these methods as desired.  Note that for
-    // the setPixelFormat() and setEncodings() methods, a derived class must
-    // call on to SMsgHandler's methods.
+    // the setPixelFormat(), setEncodings() and setDesktopSize() methods, a
+    // derived class must call on to SMsgHandler's methods.
 
     virtual void clientInit(bool shared);
 
     virtual void setPixelFormat(const PixelFormat& pf);
     virtual void setEncodings(int nEncodings, rdr::U32* encodings);
-    virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
+    virtual void framebufferUpdateRequest(const Rect& r, bool incremental) = 0;
+    virtual void setDesktopSize(int fb_width, int fb_height) = 0;
 
     // InputHandler interface
     // The InputHandler methods will be called for the corresponding messages.
index 8e870cd4a2579d8914c2560407b7a4f72cc617e8..1408fe66b2bec6231bace262e7f23ba1151e5792 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2009 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -51,9 +52,30 @@ void SMsgReaderV3::readMsg()
   case msgTypeKeyEvent:                 readKeyEvent(); break;
   case msgTypePointerEvent:             readPointerEvent(); break;
   case msgTypeClientCutText:            readClientCutText(); break;
+  case msgTypeSetDesktopSize:           readSetDesktopSize(); break;
 
   default:
     fprintf(stderr, "unknown message type %d\n", msgType);
     throw Exception("unknown message type");
   }
 }
+
+void SMsgReaderV3::readSetDesktopSize()
+{
+  int width, height;
+  int screens, i;
+
+  is->skip(1);
+
+  width = is->readU16();
+  height = is->readU16();
+
+  screens = is->readU8();
+  is->skip(1);
+
+  // XXX: We don't support this command properly yet
+  is->skip(screens * 16);
+
+  handler->setDesktopSize(width, height);
+}
+
index c6b7bf420fb018a936df7210fe979826e94b6f91..8b52632bb6fbc2ad5653f40b8315c90dec5aefdf 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2009 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,6 +28,8 @@ namespace rfb {
     virtual ~SMsgReaderV3();
     virtual void readClientInit();
     virtual void readMsg();
+  protected:
+    virtual void readSetDesktopSize();
   };
 }
 #endif
index bab9a1a2495f28c4b9d39ac689d20a3a17dfcb79..3c6da95a2264463445aa9b4b4fcf2a6cbd02d841 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <rdr/types.h>
 #include <rfb/encodings.h>
+#include <rfb/screenTypes.h>
 #include <rfb/Encoder.h>
 #include <rfb/PixelBuffer.h>
 
@@ -74,6 +75,8 @@ namespace rfb {
     // writeSetDesktopSize() on a V3 writer won't actually write immediately,
     // but will write the relevant pseudo-rectangle as part of the next update.
     virtual bool writeSetDesktopSize()=0;
+    // Same thing for the extended version
+    virtual bool writeExtendedDesktopSize(rdr::U16 error = resultUnsolicited)=0;
 
     virtual bool writeSetDesktopName()=0;
 
index 1271619505e1058b9652ba5731d25a6e99d3f452..ca6f3f03aa8208fed68a06b36c60187c4f648ef0 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2009 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +19,7 @@
 #include <rdr/OutStream.h>
 #include <rdr/MemOutStream.h>
 #include <rfb/msgTypes.h>
+#include <rfb/screenTypes.h>
 #include <rfb/Exception.h>
 #include <rfb/ConnParams.h>
 #include <rfb/SMsgWriterV3.h>
@@ -64,6 +66,15 @@ bool SMsgWriterV3::writeSetDesktopSize() {
   return true;
 }
 
+bool SMsgWriterV3::writeExtendedDesktopSize(rdr::U16 error) {
+  if (!cp->supportsExtendedDesktopSize) return false;
+  if (error == resultUnsolicited)
+    needExtendedDesktopSize = true;
+  else
+    edsErrors.push_back(error);
+  return true;
+}
+
 bool SMsgWriterV3::writeSetDesktopName() {
   if (!cp->supportsDesktopRename) return false;
   needSetDesktopName = true;
@@ -124,6 +135,8 @@ void SMsgWriterV3::writeFramebufferUpdateStart(int nRects)
   os->pad(1);
   if (wsccb) nRects++;
   if (needSetDesktopSize) nRects++;
+  if (needExtendedDesktopSize) nRects++;
+  if (!edsErrors.empty()) nRects += edsErrors.size();
   if (needSetDesktopName) nRects++;
   os->writeU16(nRects);
   nRectsInUpdate = 0;
@@ -144,6 +157,50 @@ void SMsgWriterV3::writeFramebufferUpdateStart()
 
 void SMsgWriterV3::writeFramebufferUpdateEnd()
 {
+  /* Start with responses to SetDesktopSize messages */
+  if (!edsErrors.empty()) {
+    std::list<rdr::U16>::const_iterator iter;
+
+    if (!cp->supportsExtendedDesktopSize)
+      throw Exception("Client does not support extended desktop resize");
+    if ((nRectsInUpdate += edsErrors.size()) > nRectsInHeader && nRectsInHeader)
+      throw Exception("SMsgWriterV3 setExtendedDesktopSize: nRects out of sync");
+
+    for (iter = edsErrors.begin();iter != edsErrors.end();iter++) {
+      os->writeU16(1);
+      os->writeU16(*iter);
+      os->writeU16(0);
+      os->writeU16(0);
+      os->writeU32(pseudoEncodingExtendedDesktopSize);
+      os->writeU8(0);             // # screens
+      os->pad(3);
+    }
+
+    edsErrors.clear();
+  }
+
+  /* Send this before SetDesktopSize to make life easier on the clients */
+  if (needExtendedDesktopSize) {
+    if (!cp->supportsExtendedDesktopSize)
+      throw Exception("Client does not support extended desktop resize");
+    if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+      throw Exception("SMsgWriterV3 setExtendedDesktopSize: nRects out of sync");
+    os->writeU16(0);
+    os->writeU16(0);
+    os->writeU16(cp->width);
+    os->writeU16(cp->height);
+    os->writeU32(pseudoEncodingExtendedDesktopSize);
+    os->writeU8(1);             // # screens
+    os->pad(3);
+    os->writeU32(1);            // id
+    os->writeU16(0);            // x-pos
+    os->writeU16(0);            // y-pos
+    os->writeU16(cp->width);    // width
+    os->writeU16(cp->height);   // height
+    os->writeU32(0);            // flags
+    needExtendedDesktopSize = false;
+  }
+
   if (needSetDesktopSize) {
     if (!cp->supportsDesktopResize)
       throw Exception("Client does not support desktop resize");
index d2c13df9aa58c62d1c4819d79b193828da2d0506..509bfdcb6ad8c271a27253c4c21c0f27a0893bac 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2009 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +19,8 @@
 #ifndef __RFB_SMSGWRITERV3_H__
 #define __RFB_SMSGWRITERV3_H__
 
+#include <list>
+
 #include <rfb/SMsgWriter.h>
 
 namespace rdr { class MemOutStream; }
@@ -32,6 +35,7 @@ namespace rfb {
     virtual void startMsg(int type);
     virtual void endMsg();
     virtual bool writeSetDesktopSize();
+    virtual bool writeExtendedDesktopSize(rdr::U16 error);
     virtual bool writeSetDesktopName();
     virtual void cursorChange(WriteSetCursorCallback* cb);
     virtual void writeSetCursor(int width, int height, const Point& hotspot,
@@ -52,6 +56,8 @@ namespace rfb {
     int nRectsInHeader;
     WriteSetCursorCallback* wsccb;
     bool needSetDesktopSize;
+    bool needExtendedDesktopSize;
+    std::list<rdr::U16> edsErrors;
     bool needSetDesktopName;
     bool needLastRect;
   };
index e021aa6ff1c3a86f5d5b55a378d75a78ef3e659d..3b4448b41ebd96059384e6bc21d095315f1fefef 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2009 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +20,7 @@
 #include <rfb/VNCSConnectionST.h>
 #include <rfb/LogWriter.h>
 #include <rfb/secTypes.h>
+#include <rfb/screenTypes.h>
 #include <rfb/ServerCore.h>
 #include <rfb/ComparingUpdateTracker.h>
 #include <rfb/KeyRemapper.h>
@@ -168,7 +170,8 @@ void VNCSConnectionST::pixelBufferChange()
       cp.width = server->pb->width();
       cp.height = server->pb->height();
       if (state() == RFBSTATE_NORMAL) {
-        if (!writer()->writeSetDesktopSize()) {
+        if (!writer()->writeSetDesktopSize() &&
+            !writer()->writeExtendedDesktopSize()) {
           close("Client does not support desktop resize");
           return;
         }
@@ -490,9 +493,18 @@ void VNCSConnectionST::framebufferUpdateRequest(const Rect& r,bool incremental)
     // Non-incremental update - treat as if area requested has changed
     updates.add_changed(reqRgn);
     server->comparer->add_changed(reqRgn);
+    // And update the clients view of screen layout
+    writer()->writeSetDesktopSize();
+    writer()->writeExtendedDesktopSize();
   }
 }
 
+void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height)
+{
+  vlog.info("Rejecting client request to change desktop size");
+  writer()->writeExtendedDesktopSize(resultProhibited);
+}
+
 void VNCSConnectionST::setInitialColourMap()
 {
   setColourMapEntries(0, 0);
index 2121150df06453373949b4032f42095dc88e365b..d5c7a36ba722142ed839f4029259cc5751ffbb26 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2009 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -124,6 +125,7 @@ namespace rfb {
     virtual void keyEvent(rdr::U32 key, bool down);
     virtual void clientCutText(const char* str, int len);
     virtual void framebufferUpdateRequest(const Rect& r, bool incremental);
+    virtual void setDesktopSize(int fb_width, int fb_height);
     virtual void setInitialColourMap();
     virtual void supportsLocalCursor();
 
index 1021be9652795c139f6fac77293f1d8b10416176..2f3b430f3459196f9958b964dd1337cf1781672a 100644 (file)
@@ -33,6 +33,7 @@ namespace rfb {
   const unsigned int pseudoEncodingXCursor = 0xffffff10;
   const unsigned int pseudoEncodingCursor = 0xffffff11;
   const unsigned int pseudoEncodingDesktopSize = 0xffffff21;
+  const unsigned int pseudoEncodingExtendedDesktopSize = 0xfffffecb; // FIXME: Unofficial
   const unsigned int pseudoEncodingDesktopName = 0xfffffecdl;
 
   // TightVNC-specific
index 2b24f3cdf476cafcbccbd357cf1eaae732cbb57d..6bda3453c3dfa0537a25ee69e2ae4b5cc9a6e3d9 100644 (file)
@@ -39,5 +39,7 @@ namespace rfb {
   const int msgTypeClientCutText = 6;
 
   const int msgTypeEnableContinuousUpdates = 150;
+
+  const int msgTypeSetDesktopSize = 251; // FIXME: Unofficial
 }
 #endif
diff --git a/common/rfb/screenTypes.h b/common/rfb/screenTypes.h
new file mode 100644 (file)
index 0000000..70971e4
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright 2009 Pierre Ossman for Cendio AB
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+#ifndef __RFB_SCREENTYPES_H__
+#define __RFB_SCREENTYPES_H__
+
+namespace rfb {
+
+  // Reasons
+  const unsigned int reasonServer = 0;
+  const unsigned int reasonClient = 1;
+  const unsigned int reasonOtherClient = 2;
+
+  // Result codes
+  const unsigned int resultSuccess = 0;
+  const unsigned int resultProhibited = 1;
+  const unsigned int resultNoResources = 2;
+  const unsigned int resultInvalid = 3;
+
+  const int resultUnsolicited = 0xffff; // internal code used for server changes
+
+}
+#endif