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

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