diff options
author | Axel Spoerl <axel.spoerl@qt.io> | 2024-04-15 10:42:00 +0200 |
---|---|---|
committer | Axel Spoerl <axel.spoerl@qt.io> | 2024-04-22 23:28:36 +0200 |
commit | 8d8cbe87e21f05b7d611ed4be47299977288b267 (patch) | |
tree | b52ebc18fd635e461263d55b3c900aa338946e86 /src/plugins/platforms | |
parent | 038c199d59ff5e9e16fe2a010f3f1f55764cf5ba (diff) |
Android: Detect mouse buttons
The mouseDown() and mouseUp() methods in androidjniinput.cpp hardcoded
Qt::LeftButton to all mouse-press / release events.
If a mouse is connected to an android device, all three buttons are
mapped to the left button.
Extend both mehtods' signature by a mouse button state.
Add a converter method to map from Android button states to
Qt::MouseButtons. Add a sendMouseButtonEvents method, that iterates
through all buttons pressed/released and sends the respective events
to QWSI.
Adapt the mouse handler in java, to obtain and pass the button state
to C++.
The patch can't be verified in an autotest. Testlib's mouse emulation
injects into QWSI.
Fixes: QTBUG-99106
Pick-to: 6.7 6.6 6.5 6.2
Change-Id: I933f490901928db9761d2ef254ae1e5b4f473f28
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/android/androidjniinput.cpp | 86 |
1 files changed, 75 insertions, 11 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 00e6b7ca51..d074e73b9e 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -28,6 +28,8 @@ Q_DECLARE_JNI_CLASS(QtLayout, "org/qtproject/qt/android/QtLayout") namespace QtAndroidInput { static bool m_ignoreMouseEvents = false; + static Qt::MouseButtons m_buttons = Qt::NoButton; + static QRect m_softwareKeyboardRect; static QList<QWindowSystemInterface::TouchPoint> m_touchPoints; @@ -160,7 +162,72 @@ namespace QtAndroidInput anchor.x(), anchor.y(), rtl); } - static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) + // from https://developer.android.com/reference/android/view/MotionEvent#getButtonState() + enum AndroidMouseButton { + BUTTON_PRIMARY = 0x00000001, + BUTTON_SECONDARY = 0x00000002, + BUTTON_TERTIARY = 0x00000004, + BUTTON_BACK = 0x00000008, + BUTTON_FORWARD = 0x00000010, + BUTTON_STYLUS_PRIMARY = 0x00000020, + BUTTON_STYLUS_SECONDARY = 0x00000040, + }; + Q_DECLARE_FLAGS(AndroidMouseButtons, AndroidMouseButton) + + static Qt::MouseButtons toMouseButtons(jint j_buttons) + { + const auto buttons = static_cast<AndroidMouseButtons>(j_buttons); + Qt::MouseButtons mouseButtons; + if (buttons.testFlag(BUTTON_PRIMARY)) + mouseButtons.setFlag(Qt::LeftButton); + + if (buttons.testFlag(BUTTON_SECONDARY)) + mouseButtons.setFlag(Qt::RightButton); + + if (buttons.testFlag(BUTTON_TERTIARY)) + mouseButtons.setFlag(Qt::MiddleButton); + + if (buttons.testFlag(BUTTON_BACK)) + mouseButtons.setFlag(Qt::BackButton); + + if (buttons.testFlag(BUTTON_FORWARD)) + mouseButtons.setFlag(Qt::ForwardButton); + + if (buttons.testFlag(BUTTON_STYLUS_PRIMARY)) + mouseButtons.setFlag(Qt::LeftButton); + + if (buttons.testFlag(BUTTON_STYLUS_SECONDARY)) + mouseButtons.setFlag(Qt::RightButton); + + // Fall back to left button + if (Q_UNLIKELY(buttons != 0 && mouseButtons == Qt::NoButton)) { + qWarning() << "Unhandled button value:" << buttons << "Falling back to Qt::LeftButton"; + mouseButtons = Qt::LeftButton; + } + return mouseButtons; + } + + 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; + + if (changedButtons == Qt::NoButton) + return; + + static_assert (sizeof(changedButtons) <= sizeof(uint), "Qt::MouseButtons size changed. Adapt code."); + + for (uint buttonInt = 0x1; static_cast<uint>(changedButtons) >= buttonInt; buttonInt <<= 1) { + const auto button = static_cast<Qt::MouseButton>(buttonInt); + if (changedButtons.testFlag(button)) { + QWindowSystemInterface::handleMouseEvent(topLevel, localPos, globalPos, + mouseButtons, button, type); + } + } + } + + static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState) { if (m_ignoreMouseEvents) return; @@ -169,13 +236,11 @@ namespace QtAndroidInput QWindow *window = windowFromId(winId); m_mouseGrabber = window; const QPoint localPos = window && window->handle() ? - window->handle()->mapFromGlobal(globalPos) : globalPos; - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, - Qt::MouseButtons(Qt::LeftButton), - Qt::LeftButton, QEvent::MouseButtonPress); + window->handle()->mapFromGlobal(globalPos) : globalPos; + sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonPress); } - static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) + static void mouseUp(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jint mouseButtonState) { const QPoint globalPos(x,y); QWindow *window = m_mouseGrabber.data(); @@ -184,9 +249,8 @@ namespace QtAndroidInput const QPoint localPos = window && window->handle() ? window->handle()->mapFromGlobal(globalPos) : globalPos; - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, - Qt::MouseButtons(Qt::NoButton), - Qt::LeftButton, QEvent::MouseButtonRelease); + + sendMouseButtonEvents(window, localPos, globalPos, mouseButtonState, QEvent::MouseButtonRelease); m_ignoreMouseEvents = false; m_mouseGrabber.clear(); } @@ -900,8 +964,8 @@ namespace QtAndroidInput {"touchAdd","(IIIZIIFFFF)V",(void*)touchAdd}, {"touchEnd","(II)V",(void*)touchEnd}, {"touchCancel", "(I)V", (void *)touchCancel}, - {"mouseDown", "(III)V", (void *)mouseDown}, - {"mouseUp", "(III)V", (void *)mouseUp}, + {"mouseDown", "(IIII)V", (void *)mouseDown}, + {"mouseUp", "(IIII)V", (void *)mouseUp}, {"mouseMove", "(III)V", (void *)mouseMove}, {"mouseWheel", "(IIIFF)V", (void *)mouseWheel}, {"longPress", "(III)V", (void *)longPress}, |