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-ca57d06f2519tags/v0.0.90
@@ -138,6 +138,19 @@ void CMsgReader::readSetCursor(int width, int height, const Point& hotspot) | |||
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); |
@@ -60,6 +60,7 @@ namespace rfb { | |||
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); | |||
@@ -84,6 +84,9 @@ void CMsgReaderV3::readMsg() | |||
case pseudoEncodingDesktopSize: | |||
handler->setDesktopSize(w, h); | |||
break; | |||
case pseudoEncodingDesktopName: | |||
readSetDesktopName(x, y, w, h); | |||
break; | |||
case pseudoEncodingCursor: | |||
readSetCursor(w, h, Point(x,y)); | |||
break; |
@@ -64,6 +64,8 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) | |||
encodings[nEncodings++] = pseudoEncodingCursor; | |||
if (cp->supportsDesktopResize) | |||
encodings[nEncodings++] = pseudoEncodingDesktopSize; | |||
if (cp->supportsDesktopRename) | |||
encodings[nEncodings++] = pseudoEncodingDesktopName; | |||
if (Decoder::supported(preferredEncoding)) { | |||
encodings[nEncodings++] = preferredEncoding; | |||
} |
@@ -29,7 +29,7 @@ using namespace rfb; | |||
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 @@ void ConnParams::setEncodings(int nEncodings, const rdr::U32* encodings) | |||
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 && |
@@ -73,6 +73,7 @@ namespace rfb { | |||
bool supportsLocalCursor; | |||
bool supportsLocalXCursor; | |||
bool supportsDesktopResize; | |||
bool supportsDesktopRename; | |||
bool supportsLastRect; | |||
bool customCompressLevel; |
@@ -76,6 +76,8 @@ namespace rfb { | |||
// 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() |
@@ -27,7 +27,7 @@ using namespace rfb; | |||
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 @@ bool SMsgWriterV3::writeSetDesktopSize() { | |||
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 @@ void SMsgWriterV3::writeFramebufferUpdateStart(int nRects) | |||
os->pad(1); | |||
if (wsccb) nRects++; | |||
if (needSetDesktopSize) nRects++; | |||
if (needSetDesktopName) nRects++; | |||
os->writeU16(nRects); | |||
nRectsInUpdate = 0; | |||
nRectsInHeader = nRects; | |||
@@ -150,6 +157,18 @@ void SMsgWriterV3::writeFramebufferUpdateEnd() | |||
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 @@ void SMsgWriterV3::writeFramebufferUpdateEnd() | |||
bool SMsgWriterV3::needFakeUpdate() | |||
{ | |||
return wsccb || needSetDesktopSize; | |||
return wsccb || needSetDesktopSize || needSetDesktopName; | |||
} | |||
void SMsgWriterV3::startRect(const Rect& r, unsigned int encoding) |
@@ -32,6 +32,7 @@ namespace rfb { | |||
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 @@ namespace rfb { | |||
int nRectsInHeader; | |||
WriteSetCursorCallback* wsccb; | |||
bool needSetDesktopSize; | |||
bool needSetDesktopName; | |||
bool needLastRect; | |||
}; | |||
} |
@@ -232,6 +232,22 @@ void VNCSConnectionST::serverCutText(const char *str, int len) | |||
} | |||
} | |||
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 { |
@@ -66,6 +66,7 @@ namespace rfb { | |||
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 |
@@ -302,6 +302,16 @@ void VNCServerST::serverCutText(const char* str, int len) | |||
} | |||
} | |||
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) { |
@@ -125,7 +125,7 @@ namespace rfb { | |||
// 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. |
@@ -33,6 +33,7 @@ namespace rfb { | |||
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; |
@@ -286,6 +286,11 @@ void TXWindow::toplevel(const char* name, TXDeleteWindowCallback* dwc_, | |||
addEventMask(StructureNotifyMask); | |||
} | |||
void TXWindow::setName(const char* name) | |||
{ | |||
XStoreName(dpy, win(), name); | |||
} | |||
void TXWindow::setMaxSize(int w, int h) | |||
{ | |||
sizeHints.flags |= PMaxSize; |
@@ -82,6 +82,8 @@ public: | |||
void setGeometry(const char* geom, int x, int y, int w, int h); | |||
void setName(const char* name); | |||
// setTransientFor() tells the window manager that this window is "owned" by | |||
// the given window. The window manager can use this information as it sees | |||
// fit. |
@@ -74,6 +74,7 @@ CConn::CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, | |||
currentEncoding = encNum; | |||
} | |||
cp.supportsDesktopResize = true; | |||
cp.supportsDesktopRename = true; | |||
cp.supportsLocalCursor = useLocalCursor; | |||
cp.customCompressLevel = customCompressLevel; | |||
cp.compressLevel = compressLevel; | |||
@@ -271,6 +272,14 @@ void CConn::setDesktopSize(int w, int h) { | |||
} | |||
} | |||
// setName() is called when the desktop name changes | |||
void CConn::setName(const char* name) { | |||
CConnection::setName(name); | |||
if (viewport) { | |||
viewport->setName(name); | |||
} | |||
} | |||
// framebufferUpdateEnd() is called at the end of an update. | |||
// For each rectangle, the FdInStream will have timed the speed | |||
// of the connection, allowing us to select format and encoding |
@@ -74,6 +74,7 @@ public: | |||
rfb::CSecurity* getCSecurity(int secType); | |||
void serverInit(); | |||
void setDesktopSize(int w, int h); | |||
void setName(const char* name); | |||
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); | |||
void bell(); | |||
void serverCutText(const char* str, int len); |
@@ -390,6 +390,15 @@ void XserverDesktop::serverCutText(const char* str, int len) | |||
} | |||
} | |||
void XserverDesktop::setDesktopName(const char* name) | |||
{ | |||
try { | |||
server->setName(name); | |||
} catch (rdr::Exception& e) { | |||
vlog.error("XserverDesktop::setDesktopName: %s",e.str()); | |||
} | |||
} | |||
void XserverDesktop::setCursor(CursorPtr cursor) | |||
{ | |||
try { |
@@ -71,6 +71,7 @@ public: | |||
void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef); | |||
void bell(); | |||
void serverCutText(const char* str, int len); | |||
void setDesktopName(const char* name); | |||
void setCursor(CursorPtr cursor); | |||
void add_changed(RegionPtr reg); | |||
void add_copied(RegionPtr dst, int dx, int dy); |
@@ -410,7 +410,32 @@ static int ProcVncExtSetParam(ClientPtr client) | |||
rep.type = X_Reply; | |||
rep.length = 0; | |||
rep.sequenceNumber = client->sequence; | |||
// Retrieve desktop name before setting | |||
char* value1 = 0; | |||
rfb::VoidParameter* desktop1 = rfb::Configuration::getParam("desktop"); | |||
if (desktop1) | |||
value1 = desktop1->getValueStr(); | |||
rep.success = rfb::Configuration::setParam(param.buf); | |||
// Send DesktopName update if desktop name has been changed | |||
char* value2 = 0; | |||
rfb::VoidParameter* desktop2 = rfb::Configuration::getParam("desktop"); | |||
if (desktop2) | |||
value2 = desktop2->getValueStr(); | |||
if (value1 && value2 && strcmp(value1, value2)) { | |||
for (int scr = 0; scr < screenInfo.numScreens; scr++) { | |||
if (desktop[scr]) { | |||
desktop[scr]->setDesktopName(value2); | |||
} | |||
} | |||
} | |||
if (value1) | |||
delete [] value1; | |||
if (value2) | |||
delete [] value2; | |||
if (client->swapped) { | |||
swaps(&rep.sequenceNumber, n); | |||
swapl(&rep.length, n); |
@@ -137,6 +137,7 @@ CConn::applyOptions(CConnOptions& opt) { | |||
// - Set optional features in ConnParams | |||
cp.supportsLocalCursor = options.useLocalCursor; | |||
cp.supportsDesktopResize = options.useDesktopResize; | |||
cp.supportsDesktopRename = true; | |||
cp.customCompressLevel = options.customCompressLevel; | |||
cp.compressLevel = options.compressLevel; | |||
cp.noJpeg = options.noJpeg; |