summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbwindow.cpp
diff options
context:
space:
mode:
authorBłażej Szczygieł <spaz16@wp.pl>2016-01-19 22:32:52 +0100
committerBłażej Szczygieł <spaz16@wp.pl>2016-02-24 09:03:14 +0000
commit7091be1b7999d93fe2126042161dcd1d8fd20026 (patch)
treecdfed192630f706bbfc2b7f9073c690b7df86b9e /src/plugins/platforms/xcb/qxcbwindow.cpp
parent63b5f5cb98fe19af5bf20d4f581723cb91a46dcb (diff)
xcb: Deliver mouse enter event to window when closing modal window
When a modal window is closed and the mouse is not under the modal window - find a proper window and send a fake enter event. Added auto test for checking enter event on window when modal window is closed. Task-number: QTBUG-35109 Change-Id: I370b52d386503820ac9de21e6d05fd019ca456ec Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 46b7b70f80..7eae2d92ab 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -50,6 +50,7 @@
#include "qxcbsystemtraytracker.h"
#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformcursor.h>
#include <algorithm>
@@ -261,6 +262,26 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s)
}
#endif // XCB_USE_XLIB
+// TODO move this into a utility function in QWindow or QGuiApplication
+static QWindow *childWindowAt(QWindow *win, const QPoint &p)
+{
+ foreach (QObject *obj, win->children()) {
+ if (obj->isWindowType()) {
+ QWindow *childWin = static_cast<QWindow *>(obj);
+ if (childWin->isVisible()) {
+ if (QWindow *recurse = childWindowAt(childWin, p))
+ return recurse;
+ }
+ }
+ }
+ if (!win->isTopLevel()
+ && !(win->flags() & Qt::WindowTransparentForInput)
+ && win->geometry().contains(win->parent()->mapFromGlobal(p))) {
+ return win;
+ }
+ return Q_NULLPTR;
+}
+
static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window)
@@ -855,6 +876,33 @@ void QXcbWindow::hide()
connection()->setMouseGrabber(Q_NULLPTR);
m_mapped = false;
+
+ // Hiding a modal window doesn't send an enter event to its transient parent when the
+ // mouse is already over the parent window, so the enter event must be emulated.
+ if (window()->isModal()) {
+ // Get the cursor position at modal window screen
+ const QPoint nativePos = xcbScreen()->cursor()->pos();
+ const QPoint cursorPos = QHighDpi::fromNativePixels(nativePos, xcbScreen()->screenForPosition(nativePos)->screen());
+
+ // Find the top level window at cursor position.
+ // Don't use QGuiApplication::topLevelAt(): search only the virtual siblings of this window's screen
+ QWindow *enterWindow = Q_NULLPTR;
+ foreach (QPlatformScreen *screen, xcbScreen()->virtualSiblings()) {
+ if (screen->geometry().contains(cursorPos)) {
+ const QPoint devicePosition = QHighDpi::toNativePixels(cursorPos, screen->screen());
+ enterWindow = screen->topLevelAt(devicePosition);
+ break;
+ }
+ }
+
+ if (enterWindow && enterWindow != window()) {
+ // Find the child window at cursor position, otherwise use the top level window
+ if (QWindow *childWindow = childWindowAt(enterWindow, cursorPos))
+ enterWindow = childWindow;
+ const QPoint localPos = enterWindow->mapFromGlobal(cursorPos);
+ QWindowSystemInterface::handleEnterEvent(enterWindow, localPos, cursorPos);
+ }
+ }
}
static QWindow *tlWindow(QWindow *window)