Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended Clipboard Support #834

Merged
merged 6 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 128 additions & 2 deletions common/rfb/CConnection.cxx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2017 Pierre Ossman for Cendio AB
* Copyright 2011-2019 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
Expand All @@ -21,6 +21,7 @@
#include <string.h>

#include <rfb/Exception.h>
#include <rfb/clipboardTypes.h>
#include <rfb/fenceTypes.h>
#include <rfb/CMsgReader.h>
#include <rfb/CMsgWriter.h>
Expand Down Expand Up @@ -52,7 +53,8 @@ CConnection::CConnection()
formatChange(false), encodingChange(false),
firstUpdate(true), pendingUpdate(false), continuousUpdates(false),
forceNonincremental(true),
framebuffer(NULL), decoder(this)
framebuffer(NULL), decoder(this),
serverClipboard(NULL), hasLocalClipboard(false)
{
}

Expand All @@ -65,6 +67,7 @@ CConnection::~CConnection()
reader_ = 0;
delete writer_;
writer_ = 0;
strFree(serverClipboard);
}

void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
Expand Down Expand Up @@ -463,6 +466,79 @@ void CConnection::dataRect(const Rect& r, int encoding)
decoder.decodeRect(r, encoding, framebuffer);
}

void CConnection::serverCutText(const char* str)
{
hasLocalClipboard = false;

strFree(serverClipboard);
serverClipboard = NULL;

serverClipboard = latin1ToUTF8(str);

handleClipboardAnnounce(true);
}

void CConnection::handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths)
{
rdr::U32 sizes[] = { 0 };

CMsgHandler::handleClipboardCaps(flags, lengths);

writer()->writeClipboardCaps(rfb::clipboardUTF8 |
rfb::clipboardRequest |
rfb::clipboardPeek |
rfb::clipboardNotify |
rfb::clipboardProvide,
sizes);
}

void CConnection::handleClipboardRequest(rdr::U32 flags)
{
if (!(flags & rfb::clipboardUTF8))
return;
if (!hasLocalClipboard)
return;
handleClipboardRequest();
}

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

void CConnection::handleClipboardNotify(rdr::U32 flags)
{
strFree(serverClipboard);
serverClipboard = NULL;

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

void CConnection::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
if (!(flags & rfb::clipboardUTF8))
return;

strFree(serverClipboard);
serverClipboard = NULL;

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

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

void CConnection::authSuccess()
{
}
Expand All @@ -476,6 +552,55 @@ void CConnection::resizeFramebuffer()
assert(false);
}

void CConnection::handleClipboardRequest()
{
}

void CConnection::handleClipboardAnnounce(bool available)
{
}

void CConnection::handleClipboardData(const char* data)
{
}

void CConnection::requestClipboard()
{
if (serverClipboard != NULL) {
handleClipboardData(serverClipboard);
return;
}

if (server.clipboardFlags() & rfb::clipboardRequest)
writer()->writeClipboardRequest(rfb::clipboardUTF8);
}

void CConnection::announceClipboard(bool available)
{
hasLocalClipboard = available;

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

void CConnection::sendClipboardData(const char* data)
{
if (server.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()->writeClientCutText(latin1.buf);
}
}

void CConnection::refreshFramebuffer()
{
forceNonincremental = true;
Expand Down Expand Up @@ -611,6 +736,7 @@ void CConnection::updateEncodings()

encodings.push_back(pseudoEncodingDesktopName);
encodings.push_back(pseudoEncodingLastRect);
encodings.push_back(pseudoEncodingExtendedClipboard);
encodings.push_back(pseudoEncodingContinuousUpdates);
encodings.push_back(pseudoEncodingFence);
encodings.push_back(pseudoEncodingQEMUKeyEvent);
Expand Down
49 changes: 48 additions & 1 deletion common/rfb/CConnection.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011-2017 Pierre Ossman for Cendio AB
* Copyright 2011-2019 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
Expand Down Expand Up @@ -109,6 +109,17 @@ namespace rfb {
virtual void framebufferUpdateEnd();
virtual void dataRect(const Rect& r, int encoding);

virtual void serverCutText(const char* str);

virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);


// Methods to be overridden in a derived class

Expand All @@ -128,9 +139,42 @@ namespace rfb {
// sure the pixel buffer has been updated once this call returns.
virtual void resizeFramebuffer();

// handleClipboardRequest() is called whenever the server requests
// the client to send over its clipboard data. It will only be
// called after the client has first announced a clipboard change
// via announceClipboard().
virtual void handleClipboardRequest();

// handleClipboardAnnounce() is called to indicate a change in the
// clipboard on the server. Call requestClipboard() to access the
// actual data.
virtual void handleClipboardAnnounce(bool available);

// handleClipboardData() is called when the server has sent over
// the clipboard data as a result of a previous call to
// requestClipboard(). Note that this function might never be
// called if the clipboard data was no longer available when the
// server received the request.
virtual void handleClipboardData(const char* data);


// Other methods

// requestClipboard() will result in a request to the server to
// transfer its clipboard data. A call to handleClipboardData()
// will be made once the data is available.
virtual void requestClipboard();

// announceClipboard() informs the server of changes to the
// clipboard on the client. The server may later request the
// clipboard data via handleClipboardRequest().
virtual void announceClipboard(bool available);

// sendClipboardData() transfers the clipboard data to the server
// and should be called whenever the server has requested the
// clipboard via handleClipboardRequest().
virtual void sendClipboardData(const char* data);

// refreshFramebuffer() forces a complete refresh of the entire
// framebuffer
void refreshFramebuffer();
Expand Down Expand Up @@ -240,6 +284,9 @@ namespace rfb {

ModifiablePixelBuffer* framebuffer;
DecodeManager decoder;

char* serverClipboard;
bool hasLocalClipboard;
};
}
#endif
25 changes: 24 additions & 1 deletion common/rfb/CMsgHandler.cxx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009-2011 Pierre Ossman for Cendio AB
* Copyright 2009-2019 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
Expand Down Expand Up @@ -98,3 +98,26 @@ void CMsgHandler::setLEDState(unsigned int state)
{
server.setLEDState(state);
}

void CMsgHandler::handleClipboardCaps(rdr::U32 flags, const rdr::U32* lengths)
{
server.setClipboardCaps(flags, lengths);
}

void CMsgHandler::handleClipboardRequest(rdr::U32 flags)
{
}

void CMsgHandler::handleClipboardPeek(rdr::U32 flags)
{
}

void CMsgHandler::handleClipboardNotify(rdr::U32 flags)
{
}

void CMsgHandler::handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data)
{
}
18 changes: 14 additions & 4 deletions common/rfb/CMsgHandler.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009-2011 Pierre Ossman for Cendio AB
* Copyright 2009-2019 Pierre Ossman for Cendio AB
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -42,8 +42,9 @@ namespace rfb {
// The following methods are called as corresponding messages are read. A
// derived class should override these methods as desired. Note that for
// the setDesktopSize(), setExtendedDesktopSize(), setPixelFormat(),
// setName() and serverInit() methods, a derived class should call on to
// CMsgHandler's methods to set the members of "server" appropriately.
// setName(), serverInit() and clipboardCaps methods, a derived class
// should call on to CMsgHandler's methods to set the members of "server"
// appropriately.

virtual void setDesktopSize(int w, int h);
virtual void setExtendedDesktopSize(unsigned reason, unsigned result,
Expand All @@ -70,10 +71,19 @@ namespace rfb {
virtual void setColourMapEntries(int firstColour, int nColours,
rdr::U16* rgbs) = 0;
virtual void bell() = 0;
virtual void serverCutText(const char* str, rdr::U32 len) = 0;
virtual void serverCutText(const char* str) = 0;

virtual void setLEDState(unsigned int state);

virtual void handleClipboardCaps(rdr::U32 flags,
const rdr::U32* lengths);
virtual void handleClipboardRequest(rdr::U32 flags);
virtual void handleClipboardPeek(rdr::U32 flags);
virtual void handleClipboardNotify(rdr::U32 flags);
virtual void handleClipboardProvide(rdr::U32 flags,
const size_t* lengths,
const rdr::U8* const* data);

ServerParams server;
};
}
Expand Down
Loading