summaryrefslogtreecommitdiffstats
path: root/vncviewer
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2018-04-20 13:45:07 +0200
committerPierre Ossman <ossman@cendio.se>2018-04-20 13:47:32 +0200
commitfa646bc6e2fdabae4b8f85829691f33327baea16 (patch)
treee423ac94f3383270702902ad387fc80ffdbe23fc /vncviewer
parentd5391142f7c44cd27384c3af9ebf5bc51f916caa (diff)
parentbe6909b3c03f61dab35c491b2a9dea0ffd2e5658 (diff)
downloadtigervnc-fa646bc6e2fdabae4b8f85829691f33327baea16.tar.gz
tigervnc-fa646bc6e2fdabae4b8f85829691f33327baea16.zip
Merge branch 'clipfocus' of https://github.com/CendioOssman/tigervnc
Diffstat (limited to 'vncviewer')
-rw-r--r--vncviewer/CConn.cxx27
-rw-r--r--vncviewer/DesktopWindow.cxx10
-rw-r--r--vncviewer/DesktopWindow.h3
-rw-r--r--vncviewer/Viewport.cxx121
-rw-r--r--vncviewer/Viewport.h14
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;