aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer/DesktopWindow.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vncviewer/DesktopWindow.cxx')
-rw-r--r--vncviewer/DesktopWindow.cxx57
1 files changed, 48 insertions, 9 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index e86e90e6..e8750b4e 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -684,23 +684,18 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
if (dw) {
switch (event) {
+ // Focus might not stay with us just because we have grabbed the
+ // keyboard. E.g. we might have sub windows, or we're not using
+ // all monitors and the user clicked on another application.
+ // Make sure we update our grabs with the focus changes.
case FL_FOCUS:
if (fullscreenSystemKeys) {
- // FIXME: We reassert the keyboard grabbing on focus as FLTK there are
- // some issues we need to work around:
- // a) Fl::grab(0) on X11 will release the keyboard grab for us.
- // b) Gaining focus on the system level causes FLTK to switch
- // window level on OS X.
if (dw->fullscreen_active())
dw->grabKeyboard();
}
break;
-
case FL_UNFOCUS:
if (fullscreenSystemKeys) {
- // FIXME: We need to relinquish control when the entire window loses
- // focus as it is very tied to this specific window on some
- // platforms and we want to be able to open subwindows.
dw->ungrabKeyboard();
}
break;
@@ -766,6 +761,23 @@ void DesktopWindow::fullscreen_on()
fullscreen();
}
+#if !defined(WIN32) && !defined(__APPLE__)
+Bool eventIsFocusWithSerial(Display *display, XEvent *event, XPointer arg)
+{
+ unsigned long serial;
+
+ serial = *(unsigned long*)arg;
+
+ if (event->xany.serial != serial)
+ return False;
+
+ if ((event->type != FocusIn) && (event->type != FocusOut))
+ return False;
+
+ return True;
+}
+#endif
+
void DesktopWindow::grabKeyboard()
{
// Grabbing the keyboard is fairly safe as FLTK reroutes events to the
@@ -793,6 +805,11 @@ void DesktopWindow::grabKeyboard()
#else
int ret;
+ XEvent xev;
+ unsigned long serial;
+
+ serial = XNextRequest(fl_display);
+
ret = XGrabKeyboard(fl_display, fl_xid(this), True,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (ret) {
@@ -806,6 +823,16 @@ void DesktopWindow::grabKeyboard()
}
return;
}
+
+ // Xorg 1.20+ generates FocusIn/FocusOut even when there is no actual
+ // change of focus. This causes us to get stuck in an endless loop
+ // grabbing and ungrabbing the keyboard. Avoid this by filtering out
+ // any focus events generated by XGrabKeyboard().
+ XSync(fl_display, False);
+ while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
+ (XPointer)&serial) == True) {
+ vlog.debug("Ignored synthetic focus event cause by grab change");
+ }
#endif
keyboardGrabbed = true;
@@ -832,7 +859,19 @@ void DesktopWindow::ungrabKeyboard()
if (Fl::grab())
return;
+ XEvent xev;
+ unsigned long serial;
+
+ serial = XNextRequest(fl_display);
+
XUngrabKeyboard(fl_display, CurrentTime);
+
+ // See grabKeyboard()
+ XSync(fl_display, False);
+ while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
+ (XPointer)&serial) == True) {
+ vlog.debug("Ignored synthetic focus event cause by grab change");
+ }
#endif
}