From 65e9eca63b3f522065018777ac07c5a71c08ff37 Mon Sep 17 00:00:00 2001 From: Andrew Forrest Date: Mon, 3 Feb 2025 16:10:15 +0000 Subject: [PATCH] Android: Fix mouse button processing Fixes clicking UI elements with a mouse on Android. 8d8cbe87e21f05b7d611ed4be47299977288b267 introduced changes to support mouse buttons other than Qt::LeftButton, but the release always looked like no buttons changed, nor were they tracked (m_buttons is always Qt::NoButton). Qt was not notified of mouse up, so nothing was clickable. Now all mouse events go through sendMouseButtonEvents, and the last seen button state is tracked for every event. If a mouse up with no buttons occurs, the last seen set of buttons is used instead, so Qt correctly handles the event. Also adds the mouse button state information to mouse move events from Android, so the workaround for delivering Qt::LeftButton when a window is tracking a move while a button is pressed has been removed. Tested on a Samsung A1 with a Bluetooth mouse. Fixes: QTBUG-132700 Fixes: QTBUG-130297 Pick-to: 6.8 Change-Id: I241282c2915d7e6cf99db7f0bc1ad2d541349077 Reviewed-by: Assam Boudjelthia (cherry picked from commit d908e043984dcfed3aa80e30cd1cafacd13b644d) Reviewed-by: Qt Cherry-pick Bot --- .../qtproject/qt/android/QtInputDelegate.java | 6 ++-- .../platforms/android/androidjniinput.cpp | 32 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java index 358e838a9bd..41ad3f5ff16 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java @@ -515,7 +515,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt // pointer methods static native void mouseDown(int winId, int x, int y, int mouseButtonState); static native void mouseUp(int winId, int x, int y, int mouseButtonState); - static native void mouseMove(int winId, int x, int y); + static native void mouseMove(int winId, int x, int y, int mouseButtonState); static native void mouseWheel(int winId, int x, int y, float hDelta, float vDelta); static native void touchBegin(int winId); static native void touchAdd(int winId, int pointerId, int action, boolean primary, @@ -641,12 +641,12 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt case MotionEvent.ACTION_HOVER_MOVE: case MotionEvent.ACTION_MOVE: if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) { - mouseMove(id, (int) event.getX(), (int) event.getY()); + mouseMove(id, (int) event.getX(), (int) event.getY(), event.getButtonState()); } else { int dx = (int) (event.getX() - m_oldX); int dy = (int) (event.getY() - m_oldY); if (Math.abs(dx) > 5 || Math.abs(dy) > 5) { - mouseMove(id, (int) event.getX(), (int) event.getY()); + mouseMove(id, (int) event.getX(), (int) event.getY(), event.getButtonState()); m_oldX = (int) event.getX(); m_oldY = (int) event.getY(); } diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index a0faedcc5b2..461b2da51c9 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -28,7 +28,7 @@ Q_DECLARE_JNI_CLASS(QtInputInterface, "org/qtproject/qt/android/QtInputInterface namespace QtAndroidInput { static bool m_ignoreMouseEvents = false; - static Qt::MouseButtons m_buttons = Qt::NoButton; + static Qt::MouseButtons m_lastSeenButtons = Qt::NoButton; static QRect m_softwareKeyboardRect; @@ -143,19 +143,22 @@ namespace QtAndroidInput static void sendMouseButtonEvents(QWindow *topLevel, QPoint localPos, QPoint globalPos, jint mouseButtonState, QEvent::Type type) { - const Qt::MouseButtons mouseButtons = toMouseButtons(mouseButtonState); - const Qt::MouseButtons changedButtons = mouseButtons & ~m_buttons; + const Qt::MouseButtons qtButtons = toMouseButtons(mouseButtonState); + const bool mouseReleased = type == QEvent::MouseButtonRelease && qtButtons == Qt::NoButton; + const Qt::MouseButtons eventButtons = mouseReleased ? m_lastSeenButtons : qtButtons; + m_lastSeenButtons = qtButtons; - if (changedButtons == Qt::NoButton) + static_assert (sizeof(eventButtons) <= sizeof(uint), "Qt::MouseButtons size changed. Adapt code."); + + if (eventButtons == Qt::NoButton) { + QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos, qtButtons, Qt::NoButton, type); return; - - static_assert (sizeof(changedButtons) <= sizeof(uint), "Qt::MouseButtons size changed. Adapt code."); - - for (uint buttonInt = 0x1; static_cast(changedButtons) >= buttonInt; buttonInt <<= 1) { + } + for (uint buttonInt = 0x1; static_cast(eventButtons) >= buttonInt; buttonInt <<= 1) { const auto button = static_cast(buttonInt); - if (changedButtons.testFlag(button)) { + if (eventButtons.testFlag(button)) { QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos, - mouseButtons, button, type); + qtButtons, button, type); } } } @@ -188,9 +191,8 @@ namespace QtAndroidInput m_mouseGrabber.clear(); } - static void mouseMove(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) + static void mouseMove(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState) { - if (m_ignoreMouseEvents) return; @@ -200,9 +202,7 @@ namespace QtAndroidInput window = windowFromId(winId); const QPoint localPos = window && window->handle() ? window->handle()->mapFromGlobal(globalPos) : globalPos; - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, - Qt::MouseButtons(m_mouseGrabber ? Qt::LeftButton : Qt::NoButton), - Qt::NoButton, QEvent::MouseMove); + sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseMove); } static void mouseWheel(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jfloat hdelta, jfloat vdelta) @@ -909,7 +909,7 @@ namespace QtAndroidInput {"touchCancel", "(I)V", (void *)touchCancel}, {"mouseDown", "(IIII)V", (void *)mouseDown}, {"mouseUp", "(IIII)V", (void *)mouseUp}, - {"mouseMove", "(III)V", (void *)mouseMove}, + {"mouseMove", "(IIII)V", (void *)mouseMove}, {"mouseWheel", "(IIIFF)V", (void *)mouseWheel}, {"longPress", "(III)V", (void *)longPress}, {"isTabletEventSupported", "()Z", (void *)isTabletEventSupported},