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



void CConnection::handleClipboardRequest(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; return;
if (!hasLocalClipboard)
}
if (!hasLocalClipboard) {
vlog.debug("Ignoring unexpected clipboard request");
return; return;
}
handleClipboardRequest(); handleClipboardRequest();
} }


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


void CConnection::handleClipboardNotify(rdr::U32 flags) void CConnection::handleClipboardNotify(rdr::U32 flags)
const size_t* lengths, const size_t* lengths,
const rdr::U8* const* data) 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; return;
}


strFree(serverClipboard); strFree(serverClipboard);
serverClipboard = NULL; serverClipboard = NULL;
void CConnection::announceClipboard(bool available) void CConnection::announceClipboard(bool available)
{ {
hasLocalClipboard = 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); writer()->writeClipboardNotify(available ? rfb::clipboardUTF8 : 0);
else {
if (available)
handleClipboardRequest();
return;
} }

if (available)
handleClipboardRequest();
} }


void CConnection::sendClipboardData(const char* data) void CConnection::sendClipboardData(const char* data)
CharArray filtered(convertCRLF(data)); CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 }; size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf }; 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); writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else { } else {
CharArray latin1(utf8ToLatin1(data)); CharArray latin1(utf8ToLatin1(data));

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



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

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

#include <rfb/Exception.h> #include <rfb/Exception.h>
#include <rfb/LogWriter.h> #include <rfb/LogWriter.h>
#include <rfb/CMsgHandler.h> #include <rfb/CMsgHandler.h>
#include <rfb/clipboardTypes.h>
#include <rfb/screenTypes.h> #include <rfb/screenTypes.h>


static rfb::LogWriter vlog("CMsgHandler"); static rfb::LogWriter vlog("CMsgHandler");


void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) 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); server.setClipboardCaps(flags, lengths);
} }



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

ledState_ = 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) void ClientParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{ {
int i, num; int i, num;

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

void setLEDState(unsigned int state); void setLEDState(unsigned int state);


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


// Wrappers to check for functionality rather than specific // Wrappers to check for functionality rather than specific

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

is(0), os(0), reader_(0), writer_(0), ssecurity(0), is(0), os(0), reader_(0), writer_(0), ssecurity(0),
authFailureTimer(this, &SConnection::handleAuthFailureTimeout), authFailureTimer(this, &SConnection::handleAuthFailureTimeout),
state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw), state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw),
clientClipboard(NULL), hasLocalClipboard(false)
clientClipboard(NULL), hasLocalClipboard(false),
unsolicitedClipboardAttempt(false)
{ {
defaultMajorVersion = 3; defaultMajorVersion = 3;
defaultMinorVersion = 8; defaultMinorVersion = 8;


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

strFree(clientClipboard); strFree(clientClipboard);
clientClipboard = NULL; clientClipboard = NULL;




void SConnection::handleClipboardRequest(rdr::U32 flags) 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; return;
if (!hasLocalClipboard)
}
if (!hasLocalClipboard) {
vlog.debug("Ignoring unexpected clipboard request");
return; return;
}
handleClipboardRequest(); handleClipboardRequest();
} }


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


void SConnection::handleClipboardNotify(rdr::U32 flags) void SConnection::handleClipboardNotify(rdr::U32 flags)
strFree(clientClipboard); strFree(clientClipboard);
clientClipboard = NULL; clientClipboard = NULL;


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


void SConnection::handleClipboardProvide(rdr::U32 flags, void SConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths, const size_t* lengths,
const rdr::U8* const* data) 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; return;
}


strFree(clientClipboard); strFree(clientClipboard);
clientClipboard = NULL; clientClipboard = NULL;


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


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


void SConnection::announceClipboard(bool available) void SConnection::announceClipboard(bool available)
{ {
hasLocalClipboard = 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(); handleClipboardRequest();
return;
}

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

if (available)
handleClipboardRequest();
} }


void SConnection::sendClipboardData(const char* data) void SConnection::sendClipboardData(const char* data)
CharArray filtered(convertCRLF(data)); CharArray filtered(convertCRLF(data));
size_t sizes[1] = { strlen(filtered.buf) + 1 }; size_t sizes[1] = { strlen(filtered.buf) + 1 };
const rdr::U8* data[1] = { (const rdr::U8*)filtered.buf }; 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); writer()->writeClipboardProvide(rfb::clipboardUTF8, sizes, data);
} else { } else {
CharArray latin1(utf8ToLatin1(data)); CharArray latin1(utf8ToLatin1(data));

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



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

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

* USA. * USA.
*/ */
#include <rfb/Exception.h> #include <rfb/Exception.h>
#include <rfb/LogWriter.h>
#include <rfb/SMsgHandler.h> #include <rfb/SMsgHandler.h>
#include <rfb/ScreenSet.h> #include <rfb/ScreenSet.h>
#include <rfb/clipboardTypes.h>
#include <rfb/encodings.h> #include <rfb/encodings.h>


using namespace rfb; using namespace rfb;


static LogWriter vlog("SMsgHandler");

SMsgHandler::SMsgHandler() SMsgHandler::SMsgHandler()
{ {
} }


void SMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths) 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); client.setClipboardCaps(flags, lengths);
} }



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

ledState_ = 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) void ServerParams::setClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{ {
int i, num; int i, num;

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

void setLEDState(unsigned int state); void setLEDState(unsigned int state);


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


bool supportsQEMUKeyEvent; bool supportsQEMUKeyEvent;

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

if (pointerClient == *ci) if (pointerClient == *ci)
pointerClient = NULL; pointerClient = NULL;
if (clipboardClient == *ci) if (clipboardClient == *ci)
clipboardClient = NULL;
handleClipboardAnnounce(*ci, false);
clipboardRequestors.remove(*ci); clipboardRequestors.remove(*ci);


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



+ 7
- 5
vncviewer/Viewport.cxx View File

if (!acceptClipboard) if (!acceptClipboard)
return; return;


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

if (!available) { if (!available) {
vlog.debug("Clipboard is no longer available on server");
pendingServerClipboard = false; pendingServerClipboard = false;
return; return;
} }
pendingClientClipboard = false; pendingClientClipboard = false;


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


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


self->pendingServerClipboard = false; self->pendingServerClipboard = false;


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


vlog.debug("Local clipboard changed, notifying server");
try { try {
self->cc->announceClipboard(true); self->cc->announceClipboard(true);
} catch (rdr::Exception& e) { } catch (rdr::Exception& e) {
void Viewport::flushPendingClipboard() void Viewport::flushPendingClipboard()
{ {
if (pendingServerClipboard) { if (pendingServerClipboard) {
vlog.debug("Focus regained after remote clipboard change, requesting data");
try { try {
cc->requestClipboard(); cc->requestClipboard();
} catch (rdr::Exception& e) { } catch (rdr::Exception& e) {
} }
} }
if (pendingClientClipboard) { if (pendingClientClipboard) {
vlog.debug("Focus regained after local clipboard change, notifying server");
try { try {
cc->announceClipboard(true); cc->announceClipboard(true);
} catch (rdr::Exception& e) { } catch (rdr::Exception& e) {

Loading…
Cancel
Save