From 5c4a79a53dd9d0179903e947a03c35e32b755bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tinja=20Paavosepp=C3=A4?= Date: Thu, 12 Oct 2023 09:41:51 +0300 Subject: [PATCH] Android: Fix touch events for child windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the touch dispatcher methods, all events were routed for the top level window at the position, which lead to all the events being delivered for the parent window. Since the JNI methods already have a parameter for window ID, take that into use and determine the window to deliver the events to by ID. Change-Id: I07ad7851c32a3e633ee748036d6818b6d0fa5588 Reviewed-by: Assam Boudjelthia Reviewed-by: Tor Arne Vestbø (cherry picked from commit b2e44a2d1d1fa109bb2971177a4fda1210637410) Reviewed-by: Qt Cherry-pick Bot --- .../platforms/android/androidjniinput.cpp | 83 ++++++++++--------- .../platforms/android/androidjnimain.cpp | 15 ++++ .../platforms/android/androidjnimain.h | 1 + 3 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 0262f69c5c4..9ae39269fbd 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -160,71 +160,75 @@ namespace QtAndroidInput anchor.x(), anchor.y(), rtl); } - static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y) + static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) { if (m_ignoreMouseEvents) return; const QPoint globalPos(x,y); - QWindow *tlw = topLevelWindowAt(globalPos); - m_mouseGrabber = tlw; - const QPoint localPos = tlw && tlw->handle() ? tlw->handle()->mapFromGlobal(globalPos) : globalPos; - QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, + 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); } - 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) { const QPoint globalPos(x,y); - QWindow *tlw = m_mouseGrabber.data(); - if (!tlw) - tlw = topLevelWindowAt(globalPos); + QWindow *window = m_mouseGrabber.data(); + if (!window) + window = windowFromId(winId); - const QPoint localPos = tlw && tlw->handle() ? tlw->handle()->mapFromGlobal(globalPos) : globalPos; - QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, + const QPoint localPos = window && window->handle() ? + window->handle()->mapFromGlobal(globalPos) : globalPos; + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, Qt::MouseButtons(Qt::NoButton), Qt::LeftButton, QEvent::MouseButtonRelease); m_ignoreMouseEvents = false; 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) { if (m_ignoreMouseEvents) return; const QPoint globalPos(x,y); - QWindow *tlw = m_mouseGrabber.data(); - if (!tlw) - tlw = topLevelWindowAt(globalPos); - const QPoint localPos = tlw && tlw->handle() ? tlw->handle()->mapFromGlobal(globalPos) : globalPos; - QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, + QWindow *window = m_mouseGrabber.data(); + if (!window) + 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); } - static void mouseWheel(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y, jfloat hdelta, jfloat vdelta) + static void mouseWheel(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y, jfloat hdelta, jfloat vdelta) { if (m_ignoreMouseEvents) return; const QPoint globalPos(x,y); - QWindow *tlw = m_mouseGrabber.data(); - if (!tlw) - tlw = topLevelWindowAt(globalPos); - const QPoint localPos = tlw && tlw->handle() ? tlw->handle()->mapFromGlobal(globalPos) : globalPos; + QWindow *window = m_mouseGrabber.data(); + if (!window) + window = windowFromId(winId); + const QPoint localPos = window && window->handle() ? + window->handle()->mapFromGlobal(globalPos) : globalPos; const QPoint angleDelta(hdelta * 120, vdelta * 120); - QWindowSystemInterface::handleWheelEvent(tlw, + QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta); } - static void longPress(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y) + static void longPress(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint x, jint y) { QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext(); if (inputContext && qGuiApp) @@ -236,15 +240,16 @@ namespace QtAndroidInput return; m_ignoreMouseEvents = true; const QPoint globalPos(x,y); - QWindow *tlw = topLevelWindowAt(globalPos); - const QPoint localPos = tlw && tlw->handle() ? tlw->handle()->mapFromGlobal(globalPos) : globalPos; + QWindow *window = windowFromId(winId); + const QPoint localPos = window && window->handle() ? + window->handle()->mapFromGlobal(globalPos) : globalPos; // Click right button if no other button is already pressed. if (!m_mouseGrabber) { - QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, Qt::MouseButtons(Qt::RightButton), Qt::RightButton, QEvent::MouseButtonPress); - QWindowSystemInterface::handleMouseEvent(tlw, localPos, globalPos, + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, Qt::MouseButtons(Qt::NoButton), Qt::RightButton, QEvent::MouseButtonRelease); } @@ -287,7 +292,6 @@ namespace QtAndroidInput double(minor * 2), double(major * 2)); m_touchPoints.push_back(touchPoint); - if (state == QEventPoint::State::Pressed) { QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext(); if (inputContext && qGuiApp) @@ -318,7 +322,7 @@ namespace QtAndroidInput return touchDevice; } - static void touchEnd(JNIEnv * /*env*/, jobject /*thiz*/, jint /*winId*/, jint /*action*/) + static void touchEnd(JNIEnv * /*env*/, jobject /*thiz*/, jint winId, jint /*action*/) { if (m_touchPoints.isEmpty()) return; @@ -328,11 +332,13 @@ namespace QtAndroidInput if (!touchDevice) return; - QWindow *window = QtAndroid::topLevelWindowAt(m_touchPoints.at(0).area.center().toPoint()); + QWindow *window = QtAndroid::windowFromId(winId); + if (!window) + return; QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints); } - static void touchCancel(JNIEnv * /*env*/, jobject /*thiz*/, jint /*winId*/) + static void touchCancel(JNIEnv * /*env*/, jobject /*thiz*/, jint winId) { if (m_touchPoints.isEmpty()) return; @@ -342,7 +348,9 @@ namespace QtAndroidInput if (!touchDevice) return; - QWindow *window = QtAndroid::topLevelWindowAt(m_touchPoints.at(0).area.center().toPoint()); + QWindow *window = QtAndroid::windowFromId(winId); + if (!window) + return; QWindowSystemInterface::handleTouchCancelEvent(window, touchDevice); } @@ -355,13 +363,14 @@ namespace QtAndroidInput #endif // QT_CONFIG(tabletevent) } - static void tabletEvent(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint deviceId, jlong time, jint action, + static void tabletEvent(JNIEnv */*env*/, jobject /*thiz*/, jint winId, jint deviceId, jlong time, jint action, jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure) { #if QT_CONFIG(tabletevent) const QPointF globalPosF(x, y); - QWindow *tlw = topLevelWindowAt(globalPosF.toPoint()); - const QPointF localPos = tlw && tlw->handle() ? tlw->handle()->mapFromGlobalF(globalPosF) : globalPosF; + QWindow *window = windowFromId(winId); + const QPointF localPos = window && window->handle() ? + window->handle()->mapFromGlobalF(globalPosF) : globalPosF; // Galaxy Note with plain Android: // 0 1 0 stylus press @@ -395,7 +404,7 @@ namespace QtAndroidInput qCDebug(lcQpaInputMethods) << action << pointerType << buttonState << '@' << x << y << "pressure" << pressure << ": buttons" << buttons; - QWindowSystemInterface::handleTabletEvent(tlw, ulong(time), + QWindowSystemInterface::handleTabletEvent(window, ulong(time), localPos, globalPosF, int(QInputDevice::DeviceType::Stylus), pointerType, buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier); #endif // QT_CONFIG(tabletevent) diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index d59c170095d..9a9a0ac777f 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -125,6 +125,21 @@ namespace QtAndroid : 0; } + QWindow *windowFromId(int windowId) + { + if (!qGuiApp) + return nullptr; + + for (QWindow *w : qGuiApp->allWindows()) { + if (!w->handle()) + continue; + QAndroidPlatformWindow *window = static_cast(w->handle()); + if (window->nativeViewId() == windowId) + return w; + } + return nullptr; + } + int availableWidthPixels() { return m_availableWidthPixels; diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index f65f82d6c3d..2affde49613 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -38,6 +38,7 @@ namespace QtAndroid void setViewVisibility(jobject view, bool visible); QWindow *topLevelWindowAt(const QPoint &globalPos); + QWindow *windowFromId(int windowId); int availableWidthPixels(); int availableHeightPixels(); double scaledDensity();