Browse Source

Merge branch 'autoclip' of https://github.com/CendioOssman/tigervnc

tags/v1.11.90
Pierre Ossman 3 years ago
parent
commit
35b4eedc87

+ 37
- 10
common/rfb/CConnection.cxx View File

@@ -548,19 +548,21 @@ void CConnection::handleClipboardCaps(rdr::U32 flags,

void CConnection::handleClipboardRequest(rdr::U32 flags)
{
if (!(flags & rfb::clipboardUTF8))
if (!(flags & rfb::clipboardUTF8)) {
vlog.debug("Ignoring clipboard request for unsupported formats 0x%x", flags);
return;
if (!hasLocalClipboard)
}
if (!hasLocalClipboard) {
vlog.debug("Ignoring unexpected clipboard request");
return;
}
handleClipboardRequest();
}

void CConnection::handleClipboardPeek(rdr::U32 flags)
{
if (!hasLocalClipboard)
return;
if (server.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0);
}

void CConnection::handleClipboardNotify(rdr::U32 flags)
@@ -580,8 +582,10 @@ void CConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
if (!(flags & rfb::clipboardUTF8))
if (!(flags & rfb::clipboardUTF8)) {
vlog.debug("Ignoring clipboard provide with unsupported formats 0x%x", flags);
return;
}

strFree(serverClipboard);
serverClipboard = NULL;
@@ -631,13 +635,25 @@ void CConnection::requestClipboard()
void CConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;
unsolicitedClipboardAttempt = false;

// Attempt an unsolicited transfer?
if (available &&
(server.clipboardSize(rfb::clipboardUTF8) > 0) &&
(server.clipboardFlags() & rfb::clipboardProvide)) {
vlog.debug("Attempting unsolicited clipboard transfer...");
unsolicitedClipboardAttempt = true;
handleClipboardRequest();
return;
}

if (server.clipboardFlags() & rfb::clipboardNotify)
if (server.clipboardFlags() & rfb::clipboardNotify) {
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
else {
if (available)
handleClipboardRequest();
return;
}

if (available)
handleClipboardRequest();
}

void CConnection::sendClipboardData(const char* data)
@@ -646,6 +662,17 @@ void CConnection::sendClipboardData(const char* data)
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };

if (unsolicitedClipboardAttempt) {
unsolicitedClipboardAttempt = false;
if (sizes[0] > server.clipboardSize(rfb::clipboardUTF8)) {
vlog.debug("Clipboard was too large for unsolicited clipboard transfer");
if (server.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
return;
}
}

writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));

+ 1
- 0
common/rfb/CConnection.h View File

@@ -294,6 +294,7 @@ namespace rfb {

char* serverClipboard;
bool hasLocalClipboard;
bool unsolicitedClipboardAttempt;
};
}
#endif

+ 41
- 0
common/rfb/CMsgHandler.cxx View File

@@ -21,6 +21,7 @@
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/CMsgHandler.h>
#include <rfb/clipboardTypes.h>
#include <rfb/screenTypes.h>

static rfb::LogWriter vlog("CMsgHandler");
@@ -101,6 +102,46 @@ void CMsgHandler::setLEDState(unsigned int state)

void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i;

vlog.debug("Got server clipboard capabilities:");
for (i = 0;i < 16;i++) {
if (flags & (1 << i)) {
const char *type;

switch (1 << i) {
case clipboardUTF8:
type = "Plain text";
break;
case clipboardRTF:
type = "Rich text";
break;
case clipboardHTML:
type = "HTML";
break;
case clipboardDIB:
type = "Images";
break;
case clipboardFiles:
type = "Files";
break;
default:
vlog.debug(" Unknown format 0x%x", 1 << i);
continue;
}

if (lengths[i] == 0)
vlog.debug(" %s (only notify)", type);
else {
char bytes[1024];

iecPrefix(lengths[i], "B", bytes, sizeof(bytes));
vlog.debug(" %s (automatically send up to %s)",
type, bytes);
}
}
}

server.setClipboardCaps(flags, lengths);
}


+ 12
- 0
common/rfb/ClientParams.cxx View File

@@ -143,6 +143,18 @@ void ClientParams::setLEDState(unsigned int state)
ledState_ = state;
}

rdr::U32 ClientParams::clipboardSize(unsigned int format) const
{
int i;

for (i = 0;i < 16;i++) {
if (((unsigned)1 << i) == format)
return clipSizes[i];
}

throw Exception("Invalid clipboard format 0x%x", format);
}

void ClientParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i, num;

+ 1
- 0
common/rfb/ClientParams.h View File

@@ -85,6 +85,7 @@ namespace rfb {
void setLEDState(unsigned int state);

rdr::U32 clipboardFlags() const { return clipFlags; }
rdr::U32 clipboardSize(unsigned int format) const;
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);

// Wrappers to check for functionality rather than specific

+ 48
- 14
common/rfb/SConnection.cxx View File

@@ -54,7 +54,8 @@ SConnection::SConnection()
is(0), os(0), reader_(0), writer_(0), ssecurity(0),
authFailureTimer(this, &SConnection::handleAuthFailureTimeout),
state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw),
clientClipboard(NULL), hasLocalClipboard(false)
clientClipboard(NULL), hasLocalClipboard(false),
unsolicitedClipboardAttempt(false)
{
defaultMajorVersion = 3;
defaultMinorVersion = 8;
@@ -370,6 +371,8 @@ void SConnection::setEncodings(int nEncodings, const rdr::S32* encodings)

void SConnection::clientCutText(const char* str)
{
hasLocalClipboard = false;

strFree(clientClipboard);
clientClipboard = NULL;

@@ -380,19 +383,21 @@ void SConnection::clientCutText(const char* str)

void SConnection::handleClipboardRequest(rdr::U32 flags)
{
if (!(flags & rfb::clipboardUTF8))
if (!(flags & rfb::clipboardUTF8)) {
vlog.debug("Ignoring clipboard request for unsupported formats 0x%x", flags);
return;
if (!hasLocalClipboard)
}
if (!hasLocalClipboard) {
vlog.debug("Ignoring unexpected clipboard request");
return;
}
handleClipboardRequest();
}

void SConnection::handleClipboardPeek(rdr::U32 flags)
{
if (!hasLocalClipboard)
return;
if (client.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
writer()->writeClipboardNotify(hasLocalClipboard ? rfb::clipboardUTF8 : 0);
}

void SConnection::handleClipboardNotify(rdr::U32 flags)
@@ -400,24 +405,29 @@ void SConnection::handleClipboardNotify(rdr::U32 flags)
strFree(clientClipboard);
clientClipboard = NULL;

if (flags & rfb::clipboardUTF8)
if (flags & rfb::clipboardUTF8) {
hasLocalClipboard = false;
handleClipboardAnnounce(true);
else
} else {
handleClipboardAnnounce(false);
}
}

void SConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
if (!(flags & rfb::clipboardUTF8))
if (!(flags & rfb::clipboardUTF8)) {
vlog.debug("Ignoring clipboard provide with unsupported formats 0x%x", flags);
return;
}

strFree(clientClipboard);
clientClipboard = NULL;

clientClipboard = convertLF((const char*)data[0], lengths[0]);

// FIXME: Should probably verify that this data was actually requested
handleClipboardData(clientClipboard);
}

@@ -547,14 +557,27 @@ void SConnection::requestClipboard()
void SConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;
unsolicitedClipboardAttempt = false;

if (client.supportsEncoding(pseudoEncodingExtendedClipboard) &&
(client.clipboardFlags() & rfb::clipboardNotify))
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
else {
if (available)
if (client.supportsEncoding(pseudoEncodingExtendedClipboard)) {
// Attempt an unsolicited transfer?
if (available &&
(client.clipboardSize(rfb::clipboardUTF8) > 0) &&
(client.clipboardFlags() & rfb::clipboardProvide)) {
vlog.debug("Attempting unsolicited clipboard transfer...");
unsolicitedClipboardAttempt = true;
handleClipboardRequest();
return;
}

if (client.clipboardFlags() & rfb::clipboardNotify) {
writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
return;
}
}

if (available)
handleClipboardRequest();
}

void SConnection::sendClipboardData(const char* data)
@@ -564,6 +587,17 @@ void SConnection::sendClipboardData(const char* data)
CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf };

if (unsolicitedClipboardAttempt) {
unsolicitedClipboardAttempt = false;
if (sizes[0] > client.clipboardSize(rfb::clipboardUTF8)) {
vlog.debug("Clipboard was too large for unsolicited clipboard transfer");
if (client.clipboardFlags() & rfb::clipboardNotify)
writer()->writeClipboardNotify(rfb::clipboardUTF8);
return;
}
}

writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else {
CharArray latin1(utf8ToLatin1(data));

+ 1
- 0
common/rfb/SConnection.h View File

@@ -264,6 +264,7 @@ namespace rfb {

char* clientClipboard;
bool hasLocalClipboard;
bool unsolicitedClipboardAttempt;
};
}
#endif

+ 44
- 0
common/rfb/SMsgHandler.cxx View File

@@ -17,12 +17,16 @@
* USA.
*/
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/SMsgHandler.h>
#include <rfb/ScreenSet.h>
#include <rfb/clipboardTypes.h>
#include <rfb/encodings.h>

using namespace rfb;

static LogWriter vlog("SMsgHandler");

SMsgHandler::SMsgHandler()
{
}
@@ -66,6 +70,46 @@ void SMsgHandler::setEncodings(int nEncodings, const rdr::S32* encodings)

void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i;

vlog.debug("Got client clipboard capabilities:");
for (i = 0;i < 16;i++) {
if (flags & (1 << i)) {
const char *type;

switch (1 << i) {
case clipboardUTF8:
type = "Plain text";
break;
case clipboardRTF:
type = "Rich text";
break;
case clipboardHTML:
type = "HTML";
break;
case clipboardDIB:
type = "Images";
break;
case clipboardFiles:
type = "Files";
break;
default:
vlog.debug(" Unknown format 0x%x", 1 << i);
continue;
}

if (lengths[i] == 0)
vlog.debug(" %s (only notify)", type);
else {
char bytes[1024];

iecPrefix(lengths[i], "B", bytes, sizeof(bytes));
vlog.debug(" %s (automatically send up to %s)",
type, bytes);
}
}
}

client.setClipboardCaps(flags, lengths);
}


+ 12
- 0
common/rfb/ServerParams.cxx View File

@@ -87,6 +87,18 @@ void ServerParams::setLEDState(unsigned int state)
ledState_ = state;
}

rdr::U32 ServerParams::clipboardSize(unsigned int format) const
{
int i;

for (i = 0;i < 16;i++) {
if (((unsigned)1 << i) == format)
return clipSizes[i];
}

throw Exception("Invalid clipboard format 0x%x", format);
}

void ServerParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
int i, num;

+ 1
- 0
common/rfb/ServerParams.h View File

@@ -70,6 +70,7 @@ namespace rfb {
void setLEDState(unsigned int state);

rdr::U32 clipboardFlags() const { return clipFlags; }
rdr::U32 clipboardSize(unsigned int format) const;
void setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths);

bool supportsQEMUKeyEvent;

+ 4
- 2
common/rfb/VNCServerST.cxx View File

@@ -171,7 +171,7 @@ void VNCServerST::removeSocket(network::Socket* sock) {
if (pointerClient == *ci)
pointerClient = NULL;
if (clipboardClient == *ci)
clipboardClient = NULL;
handleClipboardAnnounce(*ci, false);
clipboardRequestors.remove(*ci);

CharArray name(strDup((*ci)->getPeerEndpoint()));
@@ -517,8 +517,10 @@ void VNCServerST::handleClipboardAnnounce(VNCSConnectionST* client,
void VNCServerST::handleClipboardData(VNCSConnectionST* client,
const char* data)
{
if (client != clipboardClient)
if (client != clipboardClient) {
slog.debug("Ignoring unexpected clipboard data");
return;
}
desktop->handleClipboardData(data);
}


+ 7
- 5
vncviewer/Viewport.cxx View File

@@ -291,12 +291,8 @@ void Viewport::handleClipboardAnnounce(bool available)
if (!acceptClipboard)
return;

if (available)
vlog.debug("Got notification of new clipboard on server");
else
vlog.debug("Clipboard is no longer available on server");

if (!available) {
vlog.debug("Clipboard is no longer available on server");
pendingServerClipboard = false;
return;
}
@@ -304,10 +300,12 @@ void Viewport::handleClipboardAnnounce(bool available)
pendingClientClipboard = false;

if (!hasFocus()) {
vlog.debug("Got notification of new clipboard on server whilst not focused, will request data later");
pendingServerClipboard = true;
return;
}

vlog.debug("Got notification of new clipboard on server, requesting data");
cc->requestClipboard();
}

@@ -761,12 +759,14 @@ void Viewport::handleClipboardChange(int source, void *data)
self->pendingServerClipboard = false;

if (!self->hasFocus()) {
vlog.debug("Local clipboard changed whilst not focused, will notify server later");
self->pendingClientClipboard = true;
// Clear any older client clipboard from the server
self->cc->announceClipboard(false);
return;
}

vlog.debug("Local clipboard changed, notifying server");
try {
self->cc->announceClipboard(true);
} catch (rdr::Exception& e) {
@@ -780,6 +780,7 @@ void Viewport::handleClipboardChange(int source, void *data)
void Viewport::flushPendingClipboard()
{
if (pendingServerClipboard) {
vlog.debug("Focus regained after remote clipboard change, requesting data");
try {
cc->requestClipboard();
} catch (rdr::Exception& e) {
@@ -789,6 +790,7 @@ void Viewport::flushPendingClipboard()
}
}
if (pendingClientClipboard) {
vlog.debug("Focus regained after local clipboard change, notifying server");
try {
cc->announceClipboard(true);
} catch (rdr::Exception& e) {

Loading…
Cancel
Save