Blame SOURCES/tigervnc-ignore-fake-focus-events-from-xgrabkeyboard.patch

b0f0da
diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx
b0f0da
index 47fe8f8..8f387dc 100644
b0f0da
--- a/vncviewer/DesktopWindow.cxx
b0f0da
+++ b/vncviewer/DesktopWindow.cxx
b0f0da
@@ -1,16 +1,16 @@
b0f0da
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
b0f0da
  * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
b0f0da
- * 
b0f0da
+ *
b0f0da
  * This is free software; you can redistribute it and/or modify
b0f0da
  * it under the terms of the GNU General Public License as published by
b0f0da
  * the Free Software Foundation; either version 2 of the License, or
b0f0da
  * (at your option) any later version.
b0f0da
- * 
b0f0da
+ *
b0f0da
  * This software is distributed in the hope that it will be useful,
b0f0da
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
b0f0da
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b0f0da
  * GNU General Public License for more details.
b0f0da
- * 
b0f0da
+ *
b0f0da
  * You should have received a copy of the GNU General Public License
b0f0da
  * along with this software; if not, write to the Free Software
b0f0da
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
b0f0da
@@ -662,20 +662,16 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
b0f0da
 
b0f0da
   if (dw && fullscreenSystemKeys) {
b0f0da
     switch (event) {
b0f0da
+    // Focus might not stay with us just because we have grabbed the
b0f0da
+    // keyboard. E.g. we might have sub windows, or we're not using
b0f0da
+    // all monitors and the user clicked on another application.
b0f0da
+    // Make sure we update our grabs with the focus changes.
b0f0da
     case FL_FOCUS:
b0f0da
-      // FIXME: We reassert the keyboard grabbing on focus as FLTK there are
b0f0da
-      //        some issues we need to work around:
b0f0da
-      //        a) Fl::grab(0) on X11 will release the keyboard grab for us.
b0f0da
-      //        b) Gaining focus on the system level causes FLTK to switch
b0f0da
-      //           window level on OS X.
b0f0da
       if (dw->fullscreen_active())
b0f0da
         dw->grabKeyboard();
b0f0da
       break;
b0f0da
 
b0f0da
     case FL_UNFOCUS:
b0f0da
-      // FIXME: We need to relinquish control when the entire window loses
b0f0da
-      //        focus as it is very tied to this specific window on some
b0f0da
-      //        platforms and we want to be able to open subwindows.
b0f0da
       dw->ungrabKeyboard();
b0f0da
       break;
b0f0da
     }
b0f0da
@@ -729,6 +725,23 @@ void DesktopWindow::fullscreen_on()
b0f0da
   fullscreen();
b0f0da
 }
b0f0da
 
b0f0da
+#if !defined(WIN32) && !defined(__APPLE__)
b0f0da
+Bool eventIsFocusWithSerial(Display *display, XEvent *event, XPointer arg)
b0f0da
+{
b0f0da
+  unsigned long serial;
b0f0da
+
b0f0da
+  serial = *(unsigned long*)arg;
b0f0da
+
b0f0da
+  if (event->xany.serial != serial)
b0f0da
+    return False;
b0f0da
+
b0f0da
+  if ((event->type != FocusIn) && (event->type != FocusOut))
b0f0da
+   return False;
b0f0da
+
b0f0da
+  return True;
b0f0da
+}
b0f0da
+#endif
b0f0da
+
b0f0da
 void DesktopWindow::grabKeyboard()
b0f0da
 {
b0f0da
   // Grabbing the keyboard is fairly safe as FLTK reroutes events to the
b0f0da
@@ -739,19 +752,24 @@ void DesktopWindow::grabKeyboard()
b0f0da
 
b0f0da
 #if defined(WIN32)
b0f0da
   int ret;
b0f0da
-  
b0f0da
+
b0f0da
   ret = win32_enable_lowlevel_keyboard(fl_xid(this));
b0f0da
   if (ret != 0)
b0f0da
     vlog.error(_("Failure grabbing keyboard"));
b0f0da
 #elif defined(__APPLE__)
b0f0da
   int ret;
b0f0da
-  
b0f0da
+
b0f0da
   ret = cocoa_capture_display(this, fullScreenAllMonitors);
b0f0da
   if (ret != 0)
b0f0da
     vlog.error(_("Failure grabbing keyboard"));
b0f0da
 #else
b0f0da
   int ret;
b0f0da
 
b0f0da
+  XEvent xev;
b0f0da
+  unsigned long serial;
b0f0da
+
b0f0da
+  serial = XNextRequest(fl_display);
b0f0da
+
b0f0da
   ret = XGrabKeyboard(fl_display, fl_xid(this), True,
b0f0da
                       GrabModeAsync, GrabModeAsync, CurrentTime);
b0f0da
   if (ret) {
b0f0da
@@ -774,6 +792,16 @@ void DesktopWindow::grabKeyboard()
b0f0da
                      None, None, CurrentTime);
b0f0da
   if (ret)
b0f0da
     vlog.error(_("Failure grabbing mouse"));
b0f0da
+
b0f0da
+  // Xorg 1.20+ generates FocusIn/FocusOut even when there is no actual
b0f0da
+  // change of focus. This causes us to get stuck in an endless loop
b0f0da
+  // grabbing and ungrabbing the keyboard. Avoid this by filtering out
b0f0da
+  // any focus events generated by XGrabKeyboard().
b0f0da
+  XSync(fl_display, False);
b0f0da
+  while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
b0f0da
+                       (XPointer)&serial) == True) {
b0f0da
+    vlog.debug("Ignored synthetic focus event cause by grab change");
b0f0da
+  }
b0f0da
 #endif
b0f0da
 }
b0f0da
 
b0f0da
@@ -791,8 +819,20 @@ void DesktopWindow::ungrabKeyboard()
b0f0da
   if (Fl::grab())
b0f0da
     return;
b0f0da
 
b0f0da
+  XEvent xev;
b0f0da
+  unsigned long serial;
b0f0da
+
b0f0da
+  serial = XNextRequest(fl_display);
b0f0da
+
b0f0da
   XUngrabPointer(fl_display, fl_event_time);
b0f0da
   XUngrabKeyboard(fl_display, fl_event_time);
b0f0da
+
b0f0da
+  // See grabKeyboard()
b0f0da
+  XSync(fl_display, False);
b0f0da
+  while (XCheckIfEvent(fl_display, &xev, &eventIsFocusWithSerial,
b0f0da
+                       (XPointer)&serial) == True) {
b0f0da
+    vlog.debug("Ignored synthetic focus event cause by grab change");
b0f0da
+  }
b0f0da
 #endif
b0f0da
 }
b0f0da