From abd5c9e478ac99f457a1df6292729b615f58bbda Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20L=C3=BCbking?= <thomas.luebking@gmail.com>
Date: Sat, 2 Jul 2016 14:55:08 +0200
Subject: smart handling of NotifyUngrab crossing events

closing a keyboard driven popup had the sideeffect to return the focus
where the pointer is, regardless of whether that window had the focus
before (due to a NotifyUngrab crossing event), bug #597
This was resolved by simply ignoring NotifyUngrab mode crossings, but
that had the unfortunate sideeffects to break focus passing when the
mouse was actually moved (in a DnD operation, 730) or the focus shall be
passed on for strict mouse focus and a mouse triggered lower action (1012)

So instead we record the window that was last entered by a *real*
crossing and only ignore the NotifyUngrab event if this window didn't
change.

BUG: 1012
BUG: 730
CCBUG: 597
---
 src/FbTk/EventManager.cc |  4 +---
 src/Window.cc            | 13 +++++++++++--
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/FbTk/EventManager.cc b/src/FbTk/EventManager.cc
index ae52908..b9d5e98 100644
--- a/src/FbTk/EventManager.cc
+++ b/src/FbTk/EventManager.cc
@@ -179,9 +179,7 @@ void EventManager::dispatch(Window win, XEvent &ev, bool parent) {
         evhand->exposeEvent(ev.xexpose);
     break;
     case EnterNotify:
-        if (ev.xcrossing.mode != NotifyGrab &&
-            ev.xcrossing.mode != NotifyUngrab)
-            evhand->enterNotifyEvent(ev.xcrossing);
+        evhand->enterNotifyEvent(ev.xcrossing);
     break;
     case LeaveNotify:
         if (ev.xcrossing.mode != NotifyGrab &&
diff --git a/src/Window.cc b/src/Window.cc
index 3c32d0e..4e2aed1 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -2716,12 +2716,21 @@ void FluxboxWindow::motionNotifyEvent(XMotionEvent &me) {
 
 void FluxboxWindow::enterNotifyEvent(XCrossingEvent &ev) {
 
+    static FluxboxWindow *s_last_really_entered = 0;
+
+    if (ev.mode == NotifyUngrab && s_last_really_entered == this) {
+        // if this results from an ungrab, only act if the window really changed.
+        // otherwise we might pollute the focus which could have been assigned
+        // by alt+tab (bug #597)
+        return;
+    }
+
     // ignore grab activates, or if we're not visible
-    if (ev.mode == NotifyGrab || ev.mode == NotifyUngrab ||
-        !isVisible()) {
+    if (ev.mode == NotifyGrab || !isVisible()) {
         return;
     }
 
+    s_last_really_entered = this;
     if (ev.window == frame().window())
         Fluxbox::instance()->keys()->doAction(ev.type, ev.state, 0,
                                               Keys::ON_WINDOW, m_client);
-- 
cgit v0.11.2