diff options
author | Pierre Ossman <ossman@cendio.se> | 2019-05-03 10:53:06 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2019-07-01 11:18:27 +0200 |
commit | 615d16bd5ba11e89262cc5cfe94a35b6d6e7a628 (patch) | |
tree | c520bd561b0e44f005cc2fbc118b8e36f439bfcb /vncviewer | |
parent | 56fa7821560a60db39195e8c81d16b46e8f972c2 (diff) | |
download | tigervnc-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.cxx | 20 | ||||
-rw-r--r-- | vncviewer/CConn.h | 6 | ||||
-rw-r--r-- | vncviewer/DesktopWindow.cxx | 22 | ||||
-rw-r--r-- | vncviewer/DesktopWindow.h | 8 | ||||
-rw-r--r-- | vncviewer/Viewport.cxx | 143 | ||||
-rw-r--r-- | vncviewer/Viewport.h | 15 |
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; |