]> source.dussan.org Git - tigervnc.git/commitdiff
Ignore fake focus events from XGrabKeyboard() 661/head
authorPierre Ossman <ossman@cendio.se>
Tue, 12 Jun 2018 13:58:34 +0000 (15:58 +0200)
committerPierre Ossman <ossman@cendio.se>
Tue, 12 Jun 2018 13:58:34 +0000 (15:58 +0200)
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.

vncviewer/DesktopWindow.cxx

index 17be6e03e2eaba6258bfa69fdfe9a77bd2d5e2d3..e8750b4ef58193bdb69413e9c9f3e54fca632754 100644 (file)
@@ -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
 }