diff options
author | Pierre Ossman <ossman@cendio.se> | 2018-04-20 13:45:07 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2018-04-20 13:47:32 +0200 |
commit | fa646bc6e2fdabae4b8f85829691f33327baea16 (patch) | |
tree | e423ac94f3383270702902ad387fc80ffdbe23fc /vncviewer | |
parent | d5391142f7c44cd27384c3af9ebf5bc51f916caa (diff) | |
parent | be6909b3c03f61dab35c491b2a9dea0ffd2e5658 (diff) | |
download | tigervnc-fa646bc6e2fdabae4b8f85829691f33327baea16.tar.gz tigervnc-fa646bc6e2fdabae4b8f85829691f33327baea16.zip |
Merge branch 'clipfocus' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'vncviewer')
-rw-r--r-- | vncviewer/CConn.cxx | 27 | ||||
-rw-r--r-- | vncviewer/DesktopWindow.cxx | 10 | ||||
-rw-r--r-- | vncviewer/DesktopWindow.h | 3 | ||||
-rw-r--r-- | vncviewer/Viewport.cxx | 121 | ||||
-rw-r--r-- | vncviewer/Viewport.h | 14 |
5 files changed, 126 insertions, 49 deletions
diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index d95c6ab7..35d6e231 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -423,32 +423,7 @@ void CConn::bell() void CConn::serverCutText(const char* str, rdr::U32 len) { - char *buffer; - int size, ret; - - if (!acceptClipboard) - return; - - size = fl_utf8froma(NULL, 0, str, len); - if (size <= 0) - return; - - size++; - - buffer = new char[size]; - - ret = fl_utf8froma(buffer, size, str, len); - assert(ret < size); - - vlog.debug("Got clipboard data (%d bytes)", (int)strlen(buffer)); - - // RFB doesn't have separate selection and clipboard concepts, so we - // dump the data into both variants. - if (setPrimary) - Fl::copy(buffer, ret, 0); - Fl::copy(buffer, ret, 1); - - delete [] buffer; + desktop->serverCutText(str, len); } void CConn::dataRect(const Rect& r, int encoding) diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index 306803f9..b36f92bf 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -276,6 +276,12 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) } +void DesktopWindow::serverCutText(const char* str, rdr::U32 len) +{ + viewport->serverCutText(str, len); +} + + void DesktopWindow::setCursor(int width, int height, const rfb::Point& hotspot, const rdr::U8* data) @@ -688,10 +694,6 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win) if (dw->fullscreen_active()) dw->grabKeyboard(); } - - // We may have gotten our lock keys out of sync with the server - // whilst we didn't have focus. Try to sort this out. - dw->viewport->pushLEDState(); break; case FL_UNFOCUS: diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h index ce589385..6ec8e1bd 100644 --- a/vncviewer/DesktopWindow.h +++ b/vncviewer/DesktopWindow.h @@ -62,6 +62,9 @@ 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, rdr::U32 len); + // New image for the locally rendered cursor void setCursor(int width, int height, const rfb::Point& hotspot, const rdr::U8* data); diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx index 14163aa4..4a44f401 100644 --- a/vncviewer/Viewport.cxx +++ b/vncviewer/Viewport.cxx @@ -118,6 +118,7 @@ Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_) #ifdef WIN32 altGrArmed(false), #endif + pendingServerCutText(NULL), pendingClientCutText(NULL), menuCtrlKey(false), menuAltKey(false), cursor(NULL) { #if !defined(WIN32) && !defined(__APPLE__) @@ -206,6 +207,8 @@ Viewport::~Viewport() delete cursor; } + clearPendingClipboard(); + // FLTK automatically deletes all child widgets, so we shouldn't touch // them ourselves here } @@ -228,6 +231,43 @@ 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, rdr::U32 len) +{ + char *buffer; + int size, ret; + + clearPendingClipboard(); + + if (!acceptClipboard) + return; + + size = fl_utf8froma(NULL, 0, str, len); + if (size <= 0) + return; + + size++; + + buffer = new char[size]; + + ret = fl_utf8froma(buffer, size, str, len); + assert(ret < size); + + vlog.debug("Got clipboard data (%d bytes)", (int)strlen(buffer)); + + if (!hasFocus()) { + pendingServerCutText = buffer; + return; + } + + // RFB doesn't have separate selection and clipboard concepts, so we + // dump the data into both variants. + if (setPrimary) + Fl::copy(buffer, ret, 0); + Fl::copy(buffer, ret, 1); + + delete [] buffer; +} + static const char * dotcursor_xpm[] = { "5 5 2 1", ". c #000000", @@ -279,17 +319,9 @@ void Viewport::setCursor(int width, int height, const Point& hotspot, void Viewport::setLEDState(unsigned int state) { - Fl_Widget *focus; - vlog.debug("Got server LED state: 0x%08x", state); - focus = Fl::grab(); - if (!focus) - focus = Fl::focus(); - if (!focus) - return; - - if (focus != this) + if (!hasFocus()) return; #if defined(WIN32) @@ -512,11 +544,18 @@ int Viewport::handle(int event) case FL_PASTE: buffer = new char[Fl::event_length() + 1]; + clearPendingClipboard(); + // This is documented as to ASCII, but actually does to 8859-1 ret = fl_utf8toa(Fl::event_text(), Fl::event_length(), buffer, Fl::event_length() + 1); assert(ret < (Fl::event_length() + 1)); + if (!hasFocus()) { + pendingClientCutText = buffer; + return 1; + } + vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(buffer)); try { @@ -574,6 +613,18 @@ int Viewport::handle(int event) case FL_FOCUS: Fl::disable_im(); + + try { + flushPendingClipboard(); + + // We may have gotten our lock keys out of sync with the server + // whilst we didn't have focus. Try to sort this out. + pushLEDState(); + } catch (rdr::Exception& e) { + vlog.error("%s", e.str()); + exit_vncviewer(e.str()); + } + // Yes, we would like some focus please! return 1; @@ -595,6 +646,17 @@ int Viewport::handle(int event) } +bool Viewport::hasFocus() +{ + Fl_Widget* focus; + + focus = Fl::grab(); + if (!focus) + focus = Fl::focus(); + + return focus == this; +} + #if ! (defined(WIN32) || defined(__APPLE__)) unsigned int Viewport::getModifierMask(unsigned int keysym) { @@ -661,6 +723,33 @@ void Viewport::handleClipboardChange(int source, void *data) } +void Viewport::clearPendingClipboard() +{ + delete [] pendingServerCutText; + pendingServerCutText = NULL; + delete [] pendingClientCutText; + pendingClientCutText = NULL; +} + + +void Viewport::flushPendingClipboard() +{ + if (pendingServerCutText) { + size_t len = strlen(pendingServerCutText); + if (setPrimary) + Fl::copy(pendingServerCutText, len, 0); + Fl::copy(pendingServerCutText, len, 1); + } + if (pendingClientCutText) { + size_t len = strlen(pendingClientCutText); + vlog.debug("Sending pending clipboard data (%d bytes)", (int)len); + cc->writer()->writeClientCutText(pendingClientCutText, len); + } + + clearPendingClipboard(); +} + + void Viewport::handlePointerEvent(const rfb::Point& pos, int buttonMask) { if (!viewOnly) { @@ -806,17 +895,10 @@ void Viewport::handleKeyRelease(int keyCode) int Viewport::handleSystemEvent(void *event, void *data) { Viewport *self = (Viewport *)data; - Fl_Widget *focus; assert(self); - focus = Fl::grab(); - if (!focus) - focus = Fl::focus(); - if (!focus) - return 0; - - if (focus != self) + if (!self->hasFocus()) return 0; assert(event); @@ -1138,8 +1220,13 @@ void Viewport::popupContextMenu() if (Fl::belowmouse() == this) window()->cursor(FL_CURSOR_DEFAULT); + // FLTK also doesn't switch focus properly for menus + handle(FL_UNFOCUS); + m = contextMenu->popup(); + handle(FL_FOCUS); + // Back to our proper mouse pointer. if ((Fl::belowmouse() == this) && cursor) window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y); diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h index 536fbb21..d9d73a8e 100644 --- a/vncviewer/Viewport.h +++ b/vncviewer/Viewport.h @@ -45,14 +45,15 @@ public: // Flush updates to screen void updateWindow(); + // Incoming clipboard from server + void serverCutText(const char* str, rdr::U32 len); + // New image for the locally rendered cursor void setCursor(int width, int height, const rfb::Point& hotspot, const rdr::U8* data); // Change client LED state void setLEDState(unsigned int state); - // Change server LED state - void pushLEDState(); void draw(Surface* dst); @@ -65,11 +66,15 @@ public: int handle(int event); private: + bool hasFocus(); unsigned int getModifierMask(unsigned int keysym); static void handleClipboardChange(int source, void *data); + void clearPendingClipboard(); + void flushPendingClipboard(); + void handlePointerEvent(const rfb::Point& pos, int buttonMask); static void handlePointerTimeout(void *data); @@ -82,6 +87,8 @@ private: static void handleAltGrTimeout(void *data); #endif + void pushLEDState(); + void initContextMenu(); void popupContextMenu(); @@ -105,6 +112,9 @@ private: unsigned int altGrCtrlTime; #endif + const char* pendingServerCutText; + const char* pendingClientCutText; + rdr::U32 menuKeySym; int menuKeyCode, menuKeyFLTK; Fl_Menu_Button *contextMenu; |