[rkward] /: Fix several window activation quirks in "Focus follows mouse" mode

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Fri Jan 1 12:35:30 UTC 2016


Git commit 0ac80a868158f3e7150adef751917fbf05cfb187 by Thomas Friedrichsmeier.
Committed on 01/01/2016 at 12:35.
Pushed by tfry into branch 'master'.

Fix several window activation quirks in "Focus follows mouse" mode

M  +1    -0    ChangeLog
M  +35   -3    rkward/windows/rkmdiwindow.cpp
M  +1    -1    rkward/windows/rkmdiwindow.h

http://commits.kde.org/rkward/0ac80a868158f3e7150adef751917fbf05cfb187

diff --git a/ChangeLog b/ChangeLog
index 11930a0..6ca254a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+- Fix several window activation quirks in "Focus follows mouse" mode
 - File selectors in "Import XYZ" plugins now filter for standard file extensions, by default
 - Show a warning screen when invoking plugins from the command line (or from clicking an rkward://-link in an external application)
 
diff --git a/rkward/windows/rkmdiwindow.cpp b/rkward/windows/rkmdiwindow.cpp
index 0535cf7..5c51270 100644
--- a/rkward/windows/rkmdiwindow.cpp
+++ b/rkward/windows/rkmdiwindow.cpp
@@ -261,10 +261,37 @@ void RKMDIWindow::windowActivationChange (bool) {
 	if (active || (!isAttached ())) update ();
 }
 
-void RKMDIWindow::slotActivate () {
+void RKMDIWindow::slotActivateForFocusFollowsMouse () {
 	RK_TRACE (APP);
 
+	if (!underMouse ()) return;
+
+	// we can't do without activateWindow(), below. Unfortunately, this has the side effect of raising the window (in some cases). This is not always what we want, e.g. if a 
+	// plot window is stacked above this window. (And since this is activation by mouse hover, this window is already visible, by definition!)
+	// So we try a heuristic (imperfect) to find, if there are any other windows stacked above this one, in order to re-raise them above this.
+	QWidgetList toplevels = qApp->topLevelWidgets ();
+	QWidgetList overlappers;
+	QWidget *window = topLevelWidget ();
+	QRect rect = window->frameGeometry ();
+	for (int i = toplevels.size () - 1; i >= 0; --i) {
+		QWidget *tl = toplevels[i];
+		if (!tl->isWindow ()) continue;
+		if (tl == window) continue;
+		if (tl->isHidden ()) continue;
+
+		QRect tlrect = tl->geometry ();
+		QRect intersected = tlrect.intersected (rect);
+		if (!intersected.isEmpty ()) {
+			QWidget *above = qApp->topLevelAt ((intersected.left () +intersected.right ()) / 2, (intersected.top () +intersected.bottom ()) / 2);
+			if (above && (above != window) && (above->isWindow ()) && (!above->isHidden ()) && (overlappers.indexOf (above) < 0)) overlappers.append (above);
+		}
+	}
+
 	activate (true);
+
+	for (int i = 0; i < overlappers.size (); ++i) {
+		overlappers[i]->raise ();
+	}
 }
 
 void RKMDIWindow::enterEvent (QEvent *event) {
@@ -275,9 +302,14 @@ void RKMDIWindow::enterEvent (QEvent *event) {
 			if (!QApplication::activePopupWidget ()) {
 				// see http://sourceforge.net/p/rkward/bugs/90/
 				// enter events may be delivered while a popup-menu (in a different window) is executing. If we activate in this case, the popup-menu might get deleted
-				// while still handling events. Similar problems seem to occur, when the popup menu has just finished (by the user selecting an action) and this results
+				// while still handling events.
+				//
+				// Similar problems seem to occur, when the popup menu has just finished (by the user selecting an action) and this results
 				// in the mouse entering this widget. To prevent crashes in this second case, we delay the activation until the next iteration of the event loop.
-				QTimer::singleShot (0, this, SLOT (slotActivate()));
+				//
+				// Finally, in some cases (such as when a new script window was created), we need a short delay, as we may be catching an enter event on a window that is in the same place,
+				// where the newly created window goes. This would cause activation to switch back, immediately.
+				QTimer::singleShot (50, this, SLOT (slotActivateForFocusFollowsMouse()));
 			}
 		}
 	}
diff --git a/rkward/windows/rkmdiwindow.h b/rkward/windows/rkmdiwindow.h
index 54c7154..913f485 100644
--- a/rkward/windows/rkmdiwindow.h
+++ b/rkward/windows/rkmdiwindow.h
@@ -134,7 +134,7 @@ friend class RKWorkplace;
 /** type of this window */
 	int type;
 private slots:
-	void slotActivate ();
+	void slotActivateForFocusFollowsMouse ();
 private:
 friend class RKToolWindowBar;
 /** state of this window (attached / detached). This is usually set from the RKWorkplace */



More information about the rkward-tracker mailing list