summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorAxel Spoerl <axel.spoerl@qt.io>2023-12-27 15:27:41 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-02-17 19:32:38 +0000
commit45efad7207ba47319e37be4ca5a61ef57eef7705 (patch)
treef93fafdc5893c352625980686ed0f5abac53566e /src/plugins
parent38c405d26a73064713da00419c28cf88616dbe4d (diff)
QXcbWindow::handleLeaveNotifyEvent(): Consume when leaving geometry
QXcbConnection::mousePressWindow() returns the XCB toplevel window, which has consumed the window system's last mouse press. When the function returns a valid pointer, QXcbWindow::handleLeaveNotifyEvent() didn't propagate the leave event to QWSI::handleLeaveEvent(). Instead, the leave event was ingored. That behavior is correct, e.g. when a button on the main window is pressed and the mouse hovers away from the button, with the mouse button continuously being pressed. It is not correct, if the mouse cursor leaves the main window. => Ignore the leave event only as long as the mouse cursor remains within mousePressWindow()->geometry(). => Deliver the leave event, when the mouse cursor leaves the window. Fixes: QTBUG-119864 Pick-to: 6.5 6.2 5.15 Change-Id: I30a6ebedcd148285b9f17dfd87885ff67726b54c Reviewed-by: Liang Qi <liang.qi@qt.io> (cherry picked from commit ec24b36d3db82c340d9386951ea48c26f77c2923) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 39e9b6b24cae07e7d11973ee680f9722ad10cf08)
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index b1b898908b..aad878fed1 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1981,10 +1981,15 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
return true;
}
-static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = nullptr)
+static bool windowContainsGlobalPoint(QXcbWindow *window, int x, int y)
+{
+ return window ? window->geometry().contains(window->mapFromGlobal(QPoint(x, y))) : false;
+}
+
+static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn)
{
return ((doCheckUnGrabAncestor(conn)
- && mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
+ && mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
|| (mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_INFERIOR)
|| detail == XCB_NOTIFY_DETAIL_VIRTUAL
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
@@ -2004,14 +2009,13 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in
{
connection()->setTime(timestamp);
- const QPoint global = QPoint(root_x, root_y);
-
if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow())
return;
// Updates scroll valuators, as user might have done some scrolling outside our X client.
connection()->xi2UpdateScrollingDevices();
+ const QPoint global = QPoint(root_x, root_y);
const QPoint local(event_x, event_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@@ -2021,8 +2025,11 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
{
connection()->setTime(timestamp);
- if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow())
+ QXcbWindow *mousePressWindow = connection()->mousePressWindow();
+ if (ignoreLeaveEvent(mode, detail, connection())
+ || (mousePressWindow && windowContainsGlobalPoint(mousePressWindow, root_x, root_y))) {
return;
+ }
// check if enter event is buffered
auto event = connection()->eventQueue()->peek([](xcb_generic_event_t *event, int type) {
@@ -2040,6 +2047,8 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
} else {
QWindowSystemInterface::handleLeaveEvent(window());
+ if (!windowContainsGlobalPoint(this, root_x, root_y))
+ connection()->setMousePressWindow(nullptr);
}
free(enter);