|
|
e08d0e |
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
|
|
|
e08d0e |
index f5ae425..cec8a68 100644
|
|
|
e08d0e |
--- a/vncviewer/DesktopWindow.cxx
|
|
|
e08d0e |
+++ b/vncviewer/DesktopWindow.cxx
|
|
|
e08d0e |
@@ -65,6 +65,7 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name,
|
|
|
e08d0e |
: Fl_Window(w, h), cc(cc_), offscreen(NULL), overlay(NULL),
|
|
|
e08d0e |
firstUpdate(true),
|
|
|
e08d0e |
delayedFullscreen(false), delayedDesktopSize(false),
|
|
|
e08d0e |
+ keyboardGrabbed(false), mouseGrabbed(false),
|
|
|
e08d0e |
statsLastFrame(0), statsLastPixels(0), statsLastPosition(0),
|
|
|
e08d0e |
statsGraph(NULL)
|
|
|
e08d0e |
{
|
|
|
e08d0e |
@@ -630,9 +631,18 @@ int DesktopWindow::handle(int event)
|
|
|
e08d0e |
break;
|
|
|
e08d0e |
|
|
|
e08d0e |
case FL_ENTER:
|
|
|
e08d0e |
+ if (keyboardGrabbed)
|
|
|
e08d0e |
+ grabPointer();
|
|
|
e08d0e |
case FL_LEAVE:
|
|
|
e08d0e |
case FL_DRAG:
|
|
|
e08d0e |
case FL_MOVE:
|
|
|
e08d0e |
+ // We don't get FL_LEAVE with a grabbed pointer, so check manually
|
|
|
e08d0e |
+ if (mouseGrabbed) {
|
|
|
e08d0e |
+ if ((Fl::event_x() < 0) || (Fl::event_x() >= w()) ||
|
|
|
e08d0e |
+ (Fl::event_y() < 0) || (Fl::event_y() >= h())) {
|
|
|
e08d0e |
+ ungrabPointer();
|
|
|
e08d0e |
+ }
|
|
|
e08d0e |
+ }
|
|
|
e08d0e |
if (fullscreen_active()) {
|
|
|
e08d0e |
if (((viewport->x() < 0) && (Fl::event_x() < EDGE_SCROLL_SIZE)) ||
|
|
|
e08d0e |
((viewport->x() + viewport->w() > w()) && (Fl::event_x() > w() - EDGE_SCROLL_SIZE)) ||
|
|
|
e08d0e |
@@ -677,6 +687,16 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
|
|
|
e08d0e |
case FL_UNFOCUS:
|
|
|
e08d0e |
dw->ungrabKeyboard();
|
|
|
e08d0e |
break;
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+ case FL_RELEASE:
|
|
|
e08d0e |
+ // We usually fail to grab the mouse if a mouse button was
|
|
|
e08d0e |
+ // pressed when we gained focus (e.g. clicking on our window),
|
|
|
e08d0e |
+ // so we may need to try again when the button is released.
|
|
|
e08d0e |
+ // (We do it here rather than handle() because a window does not
|
|
|
e08d0e |
+ // see FL_RELEASE events if a child widget grabs it first)
|
|
|
e08d0e |
+ if (dw->keyboardGrabbed && !dw->mouseGrabbed)
|
|
|
e08d0e |
+ dw->grabPointer();
|
|
|
e08d0e |
+ break;
|
|
|
e08d0e |
}
|
|
|
e08d0e |
}
|
|
|
e08d0e |
|
|
|
e08d0e |
@@ -757,14 +777,18 @@ void DesktopWindow::grabKeyboard()
|
|
|
e08d0e |
int ret;
|
|
|
e08d0e |
|
|
|
e08d0e |
ret = win32_enable_lowlevel_keyboard(fl_xid(this));
|
|
|
e08d0e |
- if (ret != 0)
|
|
|
e08d0e |
+ if (ret != 0) {
|
|
|
e08d0e |
vlog.error(_("Failure grabbing keyboard"));
|
|
|
e08d0e |
+ return;
|
|
|
e08d0e |
+ }
|
|
|
e08d0e |
#elif defined(__APPLE__)
|
|
|
e08d0e |
int ret;
|
|
|
e08d0e |
|
|
|
e08d0e |
ret = cocoa_capture_display(this, fullScreenAllMonitors);
|
|
|
e08d0e |
- if (ret != 0)
|
|
|
e08d0e |
+ if (ret != 0) {
|
|
|
e08d0e |
vlog.error(_("Failure grabbing keyboard"));
|
|
|
e08d0e |
+ return;
|
|
|
e08d0e |
+ }
|
|
|
e08d0e |
#else
|
|
|
e08d0e |
int ret;
|
|
|
e08d0e |
|
|
|
e08d0e |
@@ -784,18 +808,9 @@ void DesktopWindow::grabKeyboard()
|
|
|
e08d0e |
} else {
|
|
|
e08d0e |
vlog.error(_("Failure grabbing keyboard"));
|
|
|
e08d0e |
}
|
|
|
e08d0e |
+ return;
|
|
|
e08d0e |
}
|
|
|
e08d0e |
|
|
|
e08d0e |
- // We also need to grab the pointer as some WMs like to grab buttons
|
|
|
e08d0e |
- // combined with modifies (e.g. Alt+Button0 in metacity).
|
|
|
e08d0e |
- ret = XGrabPointer(fl_display, fl_xid(this), True,
|
|
|
e08d0e |
- ButtonPressMask|ButtonReleaseMask|
|
|
|
e08d0e |
- ButtonMotionMask|PointerMotionMask,
|
|
|
e08d0e |
- GrabModeAsync, GrabModeAsync,
|
|
|
e08d0e |
- None, None, CurrentTime);
|
|
|
e08d0e |
- if (ret)
|
|
|
e08d0e |
- vlog.error(_("Failure grabbing mouse"));
|
|
|
e08d0e |
-
|
|
|
e08d0e |
// Xorg 1.20+ generates FocusIn/FocusOut even when there is no actual
|
|
|
e08d0e |
// change of focus. This causes us to get stuck in an endless loop
|
|
|
e08d0e |
// grabbing and ungrabbing the keyboard. Avoid this by filtering out
|
|
|
e08d0e |
@@ -806,6 +821,11 @@ void DesktopWindow::grabKeyboard()
|
|
|
e08d0e |
vlog.debug("Ignored synthetic focus event cause by grab change");
|
|
|
e08d0e |
}
|
|
|
e08d0e |
#endif
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+ keyboardGrabbed = true;
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+ if (contains(Fl::belowmouse()))
|
|
|
e08d0e |
+ grabPointer();
|
|
|
e08d0e |
}
|
|
|
e08d0e |
|
|
|
e08d0e |
|
|
|
e08d0e |
@@ -813,6 +833,10 @@ void DesktopWindow::ungrabKeyboard()
|
|
|
e08d0e |
{
|
|
|
e08d0e |
Fl::remove_timeout(handleGrab, this);
|
|
|
e08d0e |
|
|
|
e08d0e |
+ keyboardGrabbed = false;
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+ ungrabPointer();
|
|
|
e08d0e |
+
|
|
|
e08d0e |
#if defined(WIN32)
|
|
|
e08d0e |
win32_disable_lowlevel_keyboard(fl_xid(this));
|
|
|
e08d0e |
#elif defined(__APPLE__)
|
|
|
e08d0e |
@@ -827,7 +851,6 @@ void DesktopWindow::ungrabKeyboard()
|
|
|
e08d0e |
|
|
|
e08d0e |
serial = XNextRequest(fl_display);
|
|
|
e08d0e |
|
|
|
e08d0e |
- XUngrabPointer(fl_display, CurrentTime);
|
|
|
e08d0e |
XUngrabKeyboard(fl_display, CurrentTime);
|
|
|
e08d0e |
|
|
|
e08d0e |
// See grabKeyboard()
|
|
|
e08d0e |
@@ -839,6 +862,38 @@ void DesktopWindow::ungrabKeyboard()
|
|
|
e08d0e |
#endif
|
|
|
e08d0e |
}
|
|
|
e08d0e |
|
|
|
e08d0e |
+void DesktopWindow::grabPointer()
|
|
|
e08d0e |
+{
|
|
|
e08d0e |
+#if !defined(WIN32) && !defined(__APPLE__)
|
|
|
e08d0e |
+ int ret;
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+ // We also need to grab the pointer as some WMs like to grab buttons
|
|
|
e08d0e |
+ // combined with modifies (e.g. Alt+Button0 in metacity).
|
|
|
e08d0e |
+ ret = XGrabPointer(fl_display, fl_xid(this), True,
|
|
|
e08d0e |
+ ButtonPressMask|ButtonReleaseMask|
|
|
|
e08d0e |
+ ButtonMotionMask|PointerMotionMask,
|
|
|
e08d0e |
+ GrabModeAsync, GrabModeAsync,
|
|
|
e08d0e |
+ None, None, CurrentTime);
|
|
|
e08d0e |
+ if (ret) {
|
|
|
e08d0e |
+ // Having a button pressed prevents us from grabbing, we make
|
|
|
e08d0e |
+ // a new attempt in fltkHandle()
|
|
|
e08d0e |
+ if (ret == AlreadyGrabbed)
|
|
|
e08d0e |
+ return;
|
|
|
e08d0e |
+ vlog.error(_("Failure grabbing mouse"));
|
|
|
e08d0e |
+ return;
|
|
|
e08d0e |
+ }
|
|
|
e08d0e |
+#endif
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+ mouseGrabbed = true;
|
|
|
e08d0e |
+}
|
|
|
e08d0e |
+
|
|
|
e08d0e |
+void DesktopWindow::ungrabPointer()
|
|
|
e08d0e |
+{
|
|
|
e08d0e |
+ mouseGrabbed = false;
|
|
|
e08d0e |
+#if !defined(WIN32) && !defined(__APPLE__)
|
|
|
e08d0e |
+ XUngrabPointer(fl_display, CurrentTime);
|
|
|
e08d0e |
+#endif
|
|
|
e08d0e |
+}
|
|
|
e08d0e |
|
|
|
e08d0e |
void DesktopWindow::handleGrab(void *data)
|
|
|
e08d0e |
{
|
|
|
e08d0e |
diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h
|
|
|
e08d0e |
index 4224699..2135be8 100644
|
|
|
e08d0e |
--- a/vncviewer/DesktopWindow.h
|
|
|
e08d0e |
+++ b/vncviewer/DesktopWindow.h
|
|
|
e08d0e |
@@ -84,6 +84,8 @@ private:
|
|
|
e08d0e |
|
|
|
e08d0e |
void grabKeyboard();
|
|
|
e08d0e |
void ungrabKeyboard();
|
|
|
e08d0e |
+ void grabPointer();
|
|
|
e08d0e |
+ void ungrabPointer();
|
|
|
e08d0e |
|
|
|
e08d0e |
static void handleGrab(void *data);
|
|
|
e08d0e |
|
|
|
e08d0e |
@@ -120,6 +122,9 @@ private:
|
|
|
e08d0e |
bool delayedFullscreen;
|
|
|
e08d0e |
bool delayedDesktopSize;
|
|
|
e08d0e |
|
|
|
e08d0e |
+ bool keyboardGrabbed;
|
|
|
e08d0e |
+ bool mouseGrabbed;
|
|
|
e08d0e |
+
|
|
|
e08d0e |
struct statsEntry {
|
|
|
e08d0e |
unsigned fps;
|
|
|
e08d0e |
unsigned pps;
|