diff options
author | Pierre Ossman <ossman@cendio.se> | 2017-09-18 16:05:48 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2017-09-18 16:05:48 +0200 |
commit | 7e546febadb6e6cc66138c2316c8c19ca8aab2b1 (patch) | |
tree | 5257117a47cb9acf04f800f18a0e14dff0311abc /vncviewer/DesktopWindow.cxx | |
parent | ca0c5f571410d03fdbdf6e1b6cb18fcf79f26ea4 (diff) | |
download | tigervnc-7e546febadb6e6cc66138c2316c8c19ca8aab2b1.tar.gz tigervnc-7e546febadb6e6cc66138c2316c8c19ca8aab2b1.zip |
Release pointer grab when cursor leaves window
We don't need the grab any more if the pointer cannot click on our
window. This makes it possible to shift focus to another application
when we aren't covering all monitors.
Diffstat (limited to 'vncviewer/DesktopWindow.cxx')
-rw-r--r-- | vncviewer/DesktopWindow.cxx | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index 897f9557..d026b902 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -65,6 +65,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, : Fl_Window(w, h), cc(cc_), offscreen(NULL), overlay(NULL), firstUpdate(true), delayedFullscreen(false), delayedDesktopSize(false), + keyboardGrabbed(false), mouseGrabbed(false), statsLastFrame(0), statsLastPixels(0), statsLastPosition(0), statsGraph(NULL) { @@ -633,9 +634,18 @@ int DesktopWindow::handle(int event) break; case FL_ENTER: + if (keyboardGrabbed) + grabPointer(); case FL_LEAVE: case FL_DRAG: case FL_MOVE: + // We don't get FL_LEAVE with a grabbed pointer, so check manually + if (mouseGrabbed) { + if ((Fl::event_x() < 0) || (Fl::event_x() >= w()) || + (Fl::event_y() < 0) || (Fl::event_y() >= h())) { + ungrabPointer(); + } + } if (fullscreen_active()) { if (((viewport->x() < 0) && (Fl::event_x() < EDGE_SCROLL_SIZE)) || ((viewport->x() + viewport->w() > w()) && (Fl::event_x() > w() - EDGE_SCROLL_SIZE)) || @@ -692,6 +702,16 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win) dw->ungrabKeyboard(); } break; + + case FL_RELEASE: + // We usually fail to grab the mouse if a mouse button was + // pressed when we gained focus (e.g. clicking on our window), + // so we may need to try again when the button is released. + // (We do it here rather than handle() because a window does not + // see FL_RELEASE events if a child widget grabs it first) + if (dw->keyboardGrabbed && !dw->mouseGrabbed) + dw->grabPointer(); + break; } } @@ -755,14 +775,18 @@ void DesktopWindow::grabKeyboard() int ret; ret = win32_enable_lowlevel_keyboard(fl_xid(this)); - if (ret != 0) + if (ret != 0) { vlog.error(_("Failure grabbing keyboard")); + return; + } #elif defined(__APPLE__) int ret; ret = cocoa_capture_display(this, fullScreenAllMonitors); - if (ret != 0) + if (ret != 0) { vlog.error(_("Failure grabbing keyboard")); + return; + } #else int ret; @@ -777,18 +801,14 @@ void DesktopWindow::grabKeyboard() } else { vlog.error(_("Failure grabbing keyboard")); } + return; } - - // We also need to grab the pointer as some WMs like to grab buttons - // combined with modifies (e.g. Alt+Button0 in metacity). - ret = XGrabPointer(fl_display, fl_xid(this), True, - ButtonPressMask|ButtonReleaseMask| - ButtonMotionMask|PointerMotionMask, - GrabModeAsync, GrabModeAsync, - None, None, CurrentTime); - if (ret) - vlog.error(_("Failure grabbing mouse")); #endif + + keyboardGrabbed = true; + + if (contains(Fl::belowmouse())) + grabPointer(); } @@ -796,6 +816,10 @@ void DesktopWindow::ungrabKeyboard() { Fl::remove_timeout(handleGrab, this); + keyboardGrabbed = false; + + ungrabPointer(); + #if defined(WIN32) win32_disable_lowlevel_keyboard(fl_xid(this)); #elif defined(__APPLE__) @@ -805,12 +829,47 @@ void DesktopWindow::ungrabKeyboard() if (Fl::grab()) return; - XUngrabPointer(fl_display, fl_event_time); XUngrabKeyboard(fl_display, fl_event_time); #endif } +void DesktopWindow::grabPointer() +{ +#if !defined(WIN32) && !defined(__APPLE__) + int ret; + + // We also need to grab the pointer as some WMs like to grab buttons + // combined with modifies (e.g. Alt+Button0 in metacity). + ret = XGrabPointer(fl_display, fl_xid(this), True, + ButtonPressMask|ButtonReleaseMask| + ButtonMotionMask|PointerMotionMask, + GrabModeAsync, GrabModeAsync, + None, None, CurrentTime); + if (ret) { + // Having a button pressed prevents us from grabbing, we make + // a new attempt in fltkHandle() + if (ret == AlreadyGrabbed) + return; + vlog.error(_("Failure grabbing mouse")); + return; + } +#endif + + mouseGrabbed = true; +} + + +void DesktopWindow::ungrabPointer() +{ + vlog.info("ungrabPointer"); + mouseGrabbed = false; +#if !defined(WIN32) && !defined(__APPLE__) + XUngrabPointer(fl_display, fl_event_time); +#endif +} + + void DesktopWindow::handleGrab(void *data) { DesktopWindow *self = (DesktopWindow*)data; |