From d6da61f3b9e7e57e85d1e16f2756a8e39e571f77 Mon Sep 17 00:00:00 2001 From: Mike Achtelik Date: Wed, 4 Aug 2021 14:30:34 +0200 Subject: [PATCH] Android: Treat ACTION_CANCEL as TouchCancelEvent Change 64d62c53c1e92a1cc07449a0ea3c71501592c1e7 started treating an ACTION_CANCEL as a TouchPointReleased. This leads to unintentional presses, if e.g. an edge swipe for the android back gesture starts on a MouseArea. When Android takes possession of the motion, an ACTION_CANCEL is delivered, which needs to be handled as such. It should not be treated as a normal up event that triggers a press. Otherwise, we get the above-mentioned issue, where an unintentional action is performed. So let's use QWindowSystemInterface::handleTouchCancelEvent to treat it as a canceled touch in Qt. Task-number: QTBUG-72110 Pick-to: 6.2 5.15 Change-Id: I68650a180130501568e5a1e9a7f20ea469461e97 Reviewed-by: Assam Boudjelthia Reviewed-by: Shawn Rutledge --- .../org/qtproject/qt/android/QtNative.java | 11 ++++-- .../platforms/android/androidjniinput.cpp | 36 +++++++++++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtNative.java b/src/android/jar/src/org/qtproject/qt/android/QtNative.java index 11bb0b37ef5..e208f7361e3 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java @@ -726,9 +726,11 @@ public class QtNative } return 1; } - if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN && index == event.getActionIndex()) { + if (action == MotionEvent.ACTION_DOWN + || action == MotionEvent.ACTION_POINTER_DOWN && index == event.getActionIndex()) { return 0; - } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_POINTER_UP && index == event.getActionIndex()) { + } else if (action == MotionEvent.ACTION_UP + || action == MotionEvent.ACTION_POINTER_UP && index == event.getActionIndex()) { return 3; } return 2; @@ -780,6 +782,10 @@ public class QtNative touchEnd(id, 2); break; + case MotionEvent.ACTION_CANCEL: + touchCancel(id); + break; + default: touchEnd(id, 1); } @@ -1364,6 +1370,7 @@ public class QtNative public static native void touchBegin(int winId); public static native void touchAdd(int winId, int pointerId, int action, boolean primary, int x, int y, float major, float minor, float rotation, float pressure); public static native void touchEnd(int winId, int action); + public static native void touchCancel(int winId); public static native void longPress(int winId, int x, int y); // pointer methods diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index eb41ec66568..d4b51d38ba6 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -267,15 +267,11 @@ namespace QtAndroidInput } } - static void touchEnd(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint /*action*/) + static QPointingDevice *getTouchDevice() { - if (m_touchPoints.isEmpty()) - return; - - QMutexLocker lock(QtAndroid::platformInterfaceMutex()); QAndroidPlatformIntegration *platformIntegration = QtAndroid::androidPlatformIntegration(); if (!platformIntegration) - return; + return nullptr; QPointingDevice *touchDevice = platformIntegration->touchDevice(); if (!touchDevice) { @@ -291,10 +287,37 @@ namespace QtAndroidInput platformIntegration->setTouchDevice(touchDevice); } + return touchDevice; + } + + static void touchEnd(JNIEnv * /*env*/, jobject /*thiz*/, jint /*winId*/, jint /*action*/) + { + if (m_touchPoints.isEmpty()) + return; + + QMutexLocker lock(QtAndroid::platformInterfaceMutex()); + QPointingDevice *touchDevice = getTouchDevice(); + if (!touchDevice) + return; + QWindow *window = QtAndroid::topLevelWindowAt(m_touchPoints.at(0).area.center().toPoint()); QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints); } + static void touchCancel(JNIEnv * /*env*/, jobject /*thiz*/, jint /*winId*/) + { + if (m_touchPoints.isEmpty()) + return; + + QMutexLocker lock(QtAndroid::platformInterfaceMutex()); + QPointingDevice *touchDevice = getTouchDevice(); + if (!touchDevice) + return; + + QWindow *window = QtAndroid::topLevelWindowAt(m_touchPoints.at(0).area.center().toPoint()); + QWindowSystemInterface::handleTouchCancelEvent(window, touchDevice); + } + static bool isTabletEventSupported(JNIEnv */*env*/, jobject /*thiz*/) { #if QT_CONFIG(tabletevent) @@ -846,6 +869,7 @@ namespace QtAndroidInput {"touchBegin","(I)V",(void*)touchBegin}, {"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}, {"mouseMove", "(III)V", (void *)mouseMove},