From cbd1b2c85f0bb39aea4ea226cced78889efe8f22 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 20 Mar 2009 16:05:04 +0000 Subject: [PATCH] Properly parse the ExtendedDesktopSize rects in the client. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3702 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- common/rfb/CMsgHandler.cxx | 12 +++++- common/rfb/CMsgHandler.h | 5 ++- common/rfb/CMsgReaderV3.cxx | 20 ++++++++-- common/rfb/ConnParams.cxx | 1 + common/rfb/ConnParams.h | 4 ++ common/rfb/Makefile.am | 4 +- common/rfb/ScreenSet.h | 80 +++++++++++++++++++++++++++++++++++++ common/rfb/rfb.dsp | 4 ++ unix/vncviewer/CConn.cxx | 5 ++- unix/vncviewer/CConn.h | 3 +- 10 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 common/rfb/ScreenSet.h diff --git a/common/rfb/CMsgHandler.cxx b/common/rfb/CMsgHandler.cxx index fa675dcc..f459d18f 100644 --- a/common/rfb/CMsgHandler.cxx +++ b/common/rfb/CMsgHandler.cxx @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ +#include + #include #include #include @@ -36,13 +38,21 @@ void CMsgHandler::setDesktopSize(int width, int height) cp.height = height; } -void CMsgHandler::setExtendedDesktopSize(int reason, int result, int width, int height) +void CMsgHandler::setExtendedDesktopSize(int reason, int result, + int width, int height, + const ScreenSet& layout) { + cp.supportsSetDesktopSize = true; + if ((reason == reasonClient) && (result != resultSuccess)) return; + if (!layout.validate(width, height)) + fprintf(stderr, "Server sent us an invalid screen layout\n"); + cp.width = width; cp.height = height; + cp.screenLayout = layout; } void CMsgHandler::setCursor(int w, int h, const Point& hotspot, void* data, void* mask) diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h index 49d407ad..36fc48ef 100644 --- a/common/rfb/CMsgHandler.h +++ b/common/rfb/CMsgHandler.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace rdr { class InStream; } @@ -44,7 +45,9 @@ namespace rfb { // methods to set the members of cp appropriately. virtual void setDesktopSize(int w, int h); - virtual void setExtendedDesktopSize(int reason, int result, int w, int h); + virtual void setExtendedDesktopSize(int reason, int result, + int w, int h, + const ScreenSet& layout); virtual void setCursor(int width, int height, const Point& hotspot, void* data, void* mask); virtual void setPixelFormat(const PixelFormat& pf); diff --git a/common/rfb/CMsgReaderV3.cxx b/common/rfb/CMsgReaderV3.cxx index 05fd9488..5471593c 100644 --- a/common/rfb/CMsgReaderV3.cxx +++ b/common/rfb/CMsgReaderV3.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include using namespace rfb; @@ -121,14 +122,25 @@ void CMsgReaderV3::readSetDesktopName(int x, int y, int w, int h) void CMsgReaderV3::readExtendedDesktopSize(int x, int y, int w, int h) { - unsigned int screens; + unsigned int screens, i; + rdr::U32 id, flags; + int sx, sy, sw, sh; + ScreenSet layout; screens = is->readU8(); is->skip(3); - // XXX: We just ignore screen info right now - is->skip(16 * screens); + for (i = 0;i < screens;i++) { + id = is->readU32(); + sx = is->readU16(); + sy = is->readU16(); + sw = is->readU16(); + sh = is->readU16(); + flags = is->readU32(); - handler->setExtendedDesktopSize(x, y, w, h); + layout.add_screen(Screen(id, sx, sy, sw, sh, flags)); + } + + handler->setExtendedDesktopSize(x, y, w, h, layout); } diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx index 10b60fbd..7b27a734 100644 --- a/common/rfb/ConnParams.cxx +++ b/common/rfb/ConnParams.cxx @@ -32,6 +32,7 @@ ConnParams::ConnParams() supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(false), supportsExtendedDesktopSize(false), supportsDesktopRename(false), supportsLastRect(false), + supportsSetDesktopSize(false), customCompressLevel(false), compressLevel(6), noJpeg(false), qualityLevel(-1), name_(0), nEncodings_(0), encodings_(0), diff --git a/common/rfb/ConnParams.h b/common/rfb/ConnParams.h index bdd9cf23..7779640a 100644 --- a/common/rfb/ConnParams.h +++ b/common/rfb/ConnParams.h @@ -24,6 +24,7 @@ #include #include +#include namespace rdr { class InStream; } @@ -57,6 +58,7 @@ namespace rfb { int width; int height; + ScreenSet screenLayout; const PixelFormat& pf() { return pf_; } void setPF(const PixelFormat& pf); @@ -77,6 +79,8 @@ namespace rfb { bool supportsDesktopRename; bool supportsLastRect; + bool supportsSetDesktopSize; + bool customCompressLevel; int compressLevel; bool noJpeg; diff --git a/common/rfb/Makefile.am b/common/rfb/Makefile.am index 61f37bd1..d3b7e767 100644 --- a/common/rfb/Makefile.am +++ b/common/rfb/Makefile.am @@ -12,8 +12,8 @@ HDRS = Blacklist.h CapsContainer.h CapsList.h CConnection.h \ Logger_stdio.h LogWriter.h msgTypes.h Password.h PixelBuffer.h \ PixelFormat.h PixelFormat.inl Pixel.h RawDecoder.h RawEncoder.h \ Rect.h Region.h rreDecode.h RREDecoder.h rreEncode.h RREEncoder.h \ - ScaledPixelBuffer.h ScaleFilters.h SConnection.h screenTypes.h \ - SDesktop.h secTypes.h ServerCore.h SMsgHandler.h \ + ScaledPixelBuffer.h ScaleFilters.h SConnection.h ScreenSet.h \ + screenTypes.h SDesktop.h secTypes.h ServerCore.h SMsgHandler.h \ SMsgReader.h SMsgReaderV3.h SMsgWriter.h SMsgWriterV3.h \ SSecurityFactoryStandard.h SSecurity.h SSecurityNone.h \ SSecurityVncAuth.h Threading.h tightDecode.h TightDecoder.h \ diff --git a/common/rfb/ScreenSet.h b/common/rfb/ScreenSet.h new file mode 100644 index 00000000..07838710 --- /dev/null +++ b/common/rfb/ScreenSet.h @@ -0,0 +1,80 @@ +/* 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. + */ + +// Management class for the RFB virtual screens + +#ifndef __RFB_SCREENSET_INCLUDED__ +#define __RFB_SCREENSET_INCLUDED__ + +#include +#include +#include + +namespace rfb { + + // rfb::Screen + // + // Represents a single RFB virtual screen, which includes + // coordinates, an id and flags. + + struct Screen { + Screen(void) : id(0), flags(0) {}; + Screen(rdr::U32 id_, int x_, int y_, int w_, int h_, rdr::U32 flags_) : + id(id_), dimensions(x_, y_, x_+w_, y_+h_), flags(flags_) {}; + rdr::U32 id; + Rect dimensions; + rdr::U32 flags; + }; + + // rfb::ScreenSet + // + // Represents a complete screen configuration, excluding framebuffer + // dimensions. + + struct ScreenSet { + ScreenSet(void) {}; + inline void add_screen(const Screen screen) { screens.push_back(screen); }; + inline bool validate(int fb_width, int fb_height) const { + std::list::const_iterator iter; + std::set seen_ids; + Rect fb_rect; + + if (screens.empty()) + return false; + + fb_rect.setXYWH(0, 0, fb_width, fb_height); + + for (iter = screens.begin();iter != screens.end();++iter) { + if (iter->dimensions.is_empty()) + return false; + if (!iter->dimensions.enclosed_by(fb_rect)) + return false; + if (seen_ids.find(iter->id) != seen_ids.end()) + return false; + seen_ids.insert(iter->id); + } + + return true; + }; + std::list screens; + }; + +}; + +#endif + diff --git a/common/rfb/rfb.dsp b/common/rfb/rfb.dsp index fc1742e4..321c4e61 100644 --- a/common/rfb/rfb.dsp +++ b/common/rfb/rfb.dsp @@ -576,6 +576,10 @@ SOURCE=.\SConnection.h SOURCE=.\screenTypes.h # End Source File # Begin Source File + +SOURCE=.\ScreenSet.h +# End Source File +# Begin Source File SOURCE=.\SDesktop.h # End Source File diff --git a/unix/vncviewer/CConn.cxx b/unix/vncviewer/CConn.cxx index 79195a8b..47ccbb27 100644 --- a/unix/vncviewer/CConn.cxx +++ b/unix/vncviewer/CConn.cxx @@ -273,8 +273,9 @@ void CConn::setDesktopSize(int w, int h) { } // setExtendedDesktopSize() is a more advanced version of setDesktopSize() -void CConn::setExtendedDesktopSize(int reason, int result, int w, int h) { - CConnection::setExtendedDesktopSize(reason, result, w,h); +void CConn::setExtendedDesktopSize(int reason, int result, int w, int h, + const rfb::ScreenSet& layout) { + CConnection::setExtendedDesktopSize(reason, result, w, h, layout); if ((reason == reasonClient) && (result != resultSuccess)) return; diff --git a/unix/vncviewer/CConn.h b/unix/vncviewer/CConn.h index 27ab8e31..10a12e49 100644 --- a/unix/vncviewer/CConn.h +++ b/unix/vncviewer/CConn.h @@ -75,7 +75,8 @@ public: rfb::CSecurity* getCSecurity(int secType); void serverInit(); void setDesktopSize(int w, int h); - void setExtendedDesktopSize(int reason, int result, int w, int h); + void setExtendedDesktopSize(int reason, int result, int w, int h, + const rfb::ScreenSet& layout); void setName(const char* name); void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); void bell(); -- 2.39.5