aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2018-06-12 15:58:34 +0200
committerPierre Ossman <ossman@cendio.se>2018-06-12 15:58:34 +0200
commit1d94124f6854e73eef58c595b2b1a4d2a7333962 (patch)
tree2db3ec0b7e9fc5f1f3bfab090b5da2531eabab3d
parent46665b6c791597d5f4f7a0351c491e4dd38b0d71 (diff)
downloadtigervnc-1d94124f6854e73eef58c595b2b1a4d2a7333962.tar.gz
tigervnc-1d94124f6854e73eef58c595b2b1a4d2a7333962.zip
Ignore fake focus events from XGrabKeyboard()
Grabbing (and ungrabbing) the keyboard generates fake focus events with modern versions of Xorg. This causes an infinite loop since we update the grab status on focus events. Work around this by ignoring these fake events.
-rw-r--r--vncviewer/DesktopWindow.cxx44
1 files changed, 44 insertions, 0 deletions
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
index 17be6e03..e8750b4e 100644
--- a/vncviewer/DesktopWindow.cxx
+++ b/vncviewer/DesktopWindow.cxx
@@ -761,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
@@ -788,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) {
@@ -801,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;
@@ -827,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
}