aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2019-05-03 10:53:06 +0200
committerPierre Ossman <ossman@cendio.se>2019-07-01 11:18:27 +0200
commit615d16bd5ba11e89262cc5cfe94a35b6d6e7a628 (patch)
treec520bd561b0e44f005cc2fbc118b8e36f439bfcb /vncviewer
parent56fa7821560a60db39195e8c81d16b46e8f972c2 (diff)
downloadtigervnc-615d16bd5ba11e89262cc5cfe94a35b6d6e7a628.tar.gz
tigervnc-615d16bd5ba11e89262cc5cfe94a35b6d6e7a628.zip
Improved clipboard API
Change the internal clipboard API to use a request based model in order to be prepared for more advanced clipboard transfers.
Diffstat (limited to 'vncviewer')
-rw-r--r--vncviewer/CConn.cxx20
-rw-r--r--vncviewer/CConn.h6
-rw-r--r--vncviewer/DesktopWindow.cxx22
-rw-r--r--vncviewer/DesktopWindow.h8
-rw-r--r--vncviewer/Viewport.cxx143
-rw-r--r--vncviewer/Viewport.h15
6 files changed, 130 insertions, 84 deletions
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx
index 2cc1fe4c..6ba3276b 100644
--- a/vncviewer/CConn.cxx
+++ b/vncviewer/CConn.cxx
@@ -377,11 +377,6 @@ void CConn::bell()
fl_beep();
}
-void CConn::serverCutText(const char* str)
-{
- desktop->serverCutText(str);
-}
-
void CConn::dataRect(const Rect& r, int encoding)
{
sock->inStream().startTiming();
@@ -422,6 +417,21 @@ void CConn::setLEDState(unsigned int state)
desktop->setLEDState(state);
}
+void CConn::handleClipboardRequest()
+{
+ desktop->handleClipboardRequest();
+}
+
+void CConn::handleClipboardAnnounce(bool available)
+{
+ desktop->handleClipboardAnnounce(available);
+}
+
+void CConn::handleClipboardData(const char* data)
+{
+ desktop->handleClipboardData(data);
+}
+
////////////////////// Internal methods //////////////////////
diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h
index 38e09c25..4d935c96 100644
--- a/vncviewer/CConn.h
+++ b/vncviewer/CConn.h
@@ -61,8 +61,6 @@ public:
void bell();
- void serverCutText(const char* str);
-
void framebufferUpdateStart();
void framebufferUpdateEnd();
void dataRect(const rfb::Rect& r, int encoding);
@@ -74,6 +72,10 @@ public:
void setLEDState(unsigned int state);
+ virtual void handleClipboardRequest();
+ virtual void handleClipboardAnnounce(bool available);
+ virtual void handleClipboardData(const char* data);
+
private:
void resizeFramebuffer();
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 4429e775..4860b928 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -276,12 +276,6 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h)
}
-void DesktopWindow::serverCutText(const char* str)
-{
- viewport->serverCutText(str);
-}
-
-
void DesktopWindow::setCursor(int width, int height,
const rfb::Point& hotspot,
const rdr::U8* data)
@@ -420,6 +414,22 @@ void DesktopWindow::setLEDState(unsigned int state)
}
+void DesktopWindow::handleClipboardRequest()
+{
+ viewport->handleClipboardRequest();
+}
+
+void DesktopWindow::handleClipboardAnnounce(bool available)
+{
+ viewport->handleClipboardAnnounce(available);
+}
+
+void DesktopWindow::handleClipboardData(const char* data)
+{
+ viewport->handleClipboardData(data);
+}
+
+
void DesktopWindow::resize(int x, int y, int w, int h)
{
bool resizing;
diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h
index fe938d9b..6b03325c 100644
--- a/vncviewer/DesktopWindow.h
+++ b/vncviewer/DesktopWindow.h
@@ -62,9 +62,6 @@ public:
// Resize the current framebuffer, but retain the contents
void resizeFramebuffer(int new_w, int new_h);
- // Incoming clipboard from server
- void serverCutText(const char* str);
-
// New image for the locally rendered cursor
void setCursor(int width, int height, const rfb::Point& hotspot,
const rdr::U8* data);
@@ -72,6 +69,11 @@ public:
// Change client LED state
void setLEDState(unsigned int state);
+ // Clipboard events
+ void handleClipboardRequest();
+ void handleClipboardAnnounce(bool available);
+ void handleClipboardData(const char* data);
+
// Fl_Window callback methods
void draw();
void resize(int x, int y, int w, int h);
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 151ecb47..713d3648 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -119,7 +119,7 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_)
altGrArmed(false),
#endif
firstLEDState(true),
- pendingServerCutText(NULL), pendingClientCutText(NULL),
+ pendingServerClipboard(false), pendingClientClipboard(false),
menuCtrlKey(false), menuAltKey(false), cursor(NULL)
{
#if !defined(WIN32) && !defined(__APPLE__)
@@ -208,8 +208,6 @@ Viewport::~Viewport()
delete cursor;
}
- clearPendingClipboard();
-
// FLTK automatically deletes all child widgets, so we shouldn't touch
// them ourselves here
}
@@ -232,37 +230,6 @@ void Viewport::updateWindow()
damage(FL_DAMAGE_USER1, r.tl.x + x(), r.tl.y + y(), r.width(), r.height());
}
-void Viewport::serverCutText(const char* str)
-{
- char *buffer;
- size_t len;
-
- clearPendingClipboard();
-
- if (!acceptClipboard)
- return;
-
- buffer = latin1ToUTF8(str);
- len = strlen(buffer);
-
- vlog.debug("Got clipboard data (%d bytes)", (int)len);
-
- if (!hasFocus()) {
- pendingServerCutText = buffer;
- return;
- }
-
- // RFB doesn't have separate selection and clipboard concepts, so we
- // dump the data into both variants.
-#if !defined(WIN32) && !defined(__APPLE__)
- if (setPrimary)
- Fl::copy(buffer, len, 0);
-#endif
- Fl::copy(buffer, len, 1);
-
- strFree(buffer);
-}
-
static const char * dotcursor_xpm[] = {
"5 5 2 1",
". c #000000",
@@ -311,6 +278,59 @@ void Viewport::setCursor(int width, int height, const Point& hotspot,
window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y);
}
+void Viewport::handleClipboardRequest()
+{
+ Fl::paste(*this, clipboardSource);
+}
+
+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) {
+ pendingServerClipboard = false;
+ return;
+ }
+
+ pendingClientClipboard = false;
+
+ if (!hasFocus()) {
+ pendingServerClipboard = true;
+ return;
+ }
+
+ cc->requestClipboard();
+}
+
+void Viewport::handleClipboardData(const char* data)
+{
+ char* buffer;
+ size_t len;
+
+ if (!hasFocus())
+ return;
+
+ buffer = latin1ToUTF8(data);
+ len = strlen(buffer);
+
+ vlog.debug("Got clipboard data (%d bytes)", (int)len);
+
+ // RFB doesn't have separate selection and clipboard concepts, so we
+ // dump the data into both variants.
+#if !defined(WIN32) && !defined(__APPLE__)
+ if (setPrimary)
+ Fl::copy(buffer, len, 0);
+#endif
+ Fl::copy(buffer, len, 1);
+
+ strFree(buffer);
+}
void Viewport::setLEDState(unsigned int state)
{
@@ -547,21 +567,14 @@ int Viewport::handle(int event)
switch (event) {
case FL_PASTE:
- clearPendingClipboard();
-
buffer = utf8ToLatin1(Fl::event_text(), Fl::event_length());
filtered = convertLF(buffer);
strFree(buffer);
- if (!hasFocus()) {
- pendingClientCutText = filtered;
- return 1;
- }
-
vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(filtered));
try {
- cc->writer()->writeClientCutText(filtered);
+ cc->sendClipboardData(filtered);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
exit_vncviewer(e.str());
@@ -725,41 +738,47 @@ void Viewport::handleClipboardChange(int source, void *data)
return;
#endif
- Fl::paste(*self, source);
-}
+ self->clipboardSource = source;
+ self->pendingServerClipboard = false;
-void Viewport::clearPendingClipboard()
-{
- strFree(pendingServerCutText);
- pendingServerCutText = NULL;
- strFree(pendingClientCutText);
- pendingClientCutText = NULL;
+ if (!self->hasFocus()) {
+ self->pendingClientClipboard = true;
+ // Clear any older client clipboard from the server
+ self->cc->announceClipboard(false);
+ return;
+ }
+
+ try {
+ self->cc->announceClipboard(true);
+ } catch (rdr::Exception& e) {
+ vlog.error("%s", e.str());
+ exit_vncviewer(e.str());
+ }
}
void Viewport::flushPendingClipboard()
{
- if (pendingServerCutText) {
- size_t len = strlen(pendingServerCutText);
-#if !defined(WIN32) && !defined(__APPLE__)
- if (setPrimary)
- Fl::copy(pendingServerCutText, len, 0);
-#endif
- Fl::copy(pendingServerCutText, len, 1);
+ if (pendingServerClipboard) {
+ try {
+ cc->requestClipboard();
+ } catch (rdr::Exception& e) {
+ vlog.error("%s", e.str());
+ exit_vncviewer(e.str());
+ }
}
- if (pendingClientCutText) {
- size_t len = strlen(pendingClientCutText);
- vlog.debug("Sending pending clipboard data (%d bytes)", (int)len);
+ if (pendingClientClipboard) {
try {
- cc->writer()->writeClientCutText(pendingClientCutText);
+ cc->announceClipboard(true);
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
exit_vncviewer(e.str());
}
}
- clearPendingClipboard();
+ pendingServerClipboard = false;
+ pendingClientClipboard = false;
}
diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h
index 8b9b469b..1fb93c66 100644
--- a/vncviewer/Viewport.h
+++ b/vncviewer/Viewport.h
@@ -45,9 +45,6 @@ public:
// Flush updates to screen
void updateWindow();
- // Incoming clipboard from server
- void serverCutText(const char* str);
-
// New image for the locally rendered cursor
void setCursor(int width, int height, const rfb::Point& hotspot,
const rdr::U8* data);
@@ -57,6 +54,11 @@ public:
void draw(Surface* dst);
+ // Clipboard events
+ void handleClipboardRequest();
+ void handleClipboardAnnounce(bool available);
+ void handleClipboardData(const char* data);
+
// Fl_Widget callback methods
void draw();
@@ -72,7 +74,6 @@ private:
static void handleClipboardChange(int source, void *data);
- void clearPendingClipboard();
void flushPendingClipboard();
void handlePointerEvent(const rfb::Point& pos, int buttonMask);
@@ -114,8 +115,10 @@ private:
bool firstLEDState;
- char* pendingServerCutText;
- char* pendingClientCutText;
+ bool pendingServerClipboard;
+ bool pendingClientClipboard;
+
+ int clipboardSource;
rdr::U32 menuKeySym;
int menuKeyCode, menuKeyFLTK;