Android: Fix touch events for child windows

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 <assam.boudjelthia@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit b2e44a2d1d1fa109bb2971177a4fda1210637410)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tinja Paavoseppä 2023-10-12 09:41:51 +03:00 committed by Qt Cherry-pick Bot
parent 030a60d681
commit 5c4a79a53d
3 changed files with 62 additions and 37 deletions

View File

@ -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)

View File

@ -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<QAndroidPlatformWindow *>(w->handle());
if (window->nativeViewId() == windowId)
return w;
}
return nullptr;
}
int availableWidthPixels()
{
return m_availableWidthPixels;

View File

@ -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();