diff options
Diffstat (limited to 'common/rfb/SConnection.cxx')
-rw-r--r-- | common/rfb/SConnection.cxx | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx index 46f0a850..4869199a 100644 --- a/common/rfb/SConnection.cxx +++ b/common/rfb/SConnection.cxx @@ -20,6 +20,7 @@ #include <string.h> #include <rfb/Exception.h> #include <rfb/Security.h> +#include <rfb/clipboardTypes.h> #include <rfb/msgTypes.h> #include <rfb/fenceTypes.h> #include <rfb/SMsgReader.h> @@ -53,7 +54,7 @@ SConnection::SConnection() is(0), os(0), reader_(0), writer_(0), ssecurity(0), state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw), - clientClipboard(NULL) + clientClipboard(NULL), hasLocalClipboard(false) { defaultMajorVersion = 3; defaultMinorVersion = 8; @@ -299,6 +300,16 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings) } SMsgHandler::setEncodings(nEncodings, encodings); + + if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) { + rdr::U32 sizes[] = { 0 }; + writer()->writeClipboardCaps(rfb::clipboardUTF8 | + rfb::clipboardRequest | + rfb::clipboardPeek | + rfb::clipboardNotify | + rfb::clipboardProvide, + sizes); + } } void SConnection::clientCutText(const char* str) @@ -311,6 +322,49 @@ void SConnection::clientCutText(const char* str) handleClipboardAnnounce(true); } +void SConnection::handleClipboardRequest(rdr::U32 flags) +{ + if (!(flags & rfb::clipboardUTF8)) + return; + if (!hasLocalClipboard) + return; + handleClipboardRequest(); +} + +void SConnection::handleClipboardPeek(rdr::U32 flags) +{ + if (!hasLocalClipboard) + return; + if (client.clipboardFlags() & rfb::clipboardNotify) + writer()->writeClipboardNotify(rfb::clipboardUTF8); +} + +void SConnection::handleClipboardNotify(rdr::U32 flags) +{ + strFree(clientClipboard); + clientClipboard = NULL; + + if (flags & rfb::clipboardUTF8) + handleClipboardAnnounce(true); + else + handleClipboardAnnounce(false); +} + +void SConnection::handleClipboardProvide(rdr::U32 flags, + const size_t* lengths, + const rdr::U8* const* data) +{ + if (!(flags & rfb::clipboardUTF8)) + return; + + strFree(clientClipboard); + clientClipboard = NULL; + + clientClipboard = convertLF((const char*)data[0], lengths[0]); + + handleClipboardData(clientClipboard); +} + void SConnection::supportsQEMUKeyEvent() { writer()->writeQEMUKeyEvent(); @@ -440,19 +494,38 @@ void SConnection::requestClipboard() handleClipboardData(clientClipboard); return; } + + if (client.supportsEncoding(pseudoEncodingExtendedClipboard) && + (client.clipboardFlags() & rfb::clipboardRequest)) + writer()->writeClipboardRequest(rfb::clipboardUTF8); } void SConnection::announceClipboard(bool available) { - if (available) - handleClipboardRequest(); + hasLocalClipboard = available; + + if (client.supportsEncoding(pseudoEncodingExtendedClipboard) && + (client.clipboardFlags() & rfb::clipboardNotify)) + writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0); + else { + if (available) + handleClipboardRequest(); + } } void SConnection::sendClipboardData(const char* data) { - CharArray latin1(utf8ToLatin1(data)); + if (client.supportsEncoding(pseudoEncodingExtendedClipboard) && + (client.clipboardFlags() & rfb::clipboardProvide)) { + CharArray filtered(convertCRLF(data)); + size_t sizes[1] = { strlen(filtered.buf) + 1 }; + const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf }; + writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data); + } else { + CharArray latin1(utf8ToLatin1(data)); - writer()->writeServerCutText(latin1.buf); + writer()->writeServerCutText(latin1.buf); + } } void SConnection::writeFakeColourMap(void) |