summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Trillmann <jens.trillmann@governikus.de>2022-05-24 08:57:45 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-09-11 14:06:35 +0000
commita5241da0d100ac74e745d70c6b3476ffc8941f11 (patch)
tree2db26c51bc468b8f498e6cc859c47b6caa329c43
parent43406f04adb788a56cc0450fd7fb53b877927c7a (diff)
Android A11Y: Fix TalkBack scrolling behavior
* Add CollectionInfo to scrollable nodes. Every scrollable node will get a CollectionInfo attached to signal the number of (possibly invisible) children. This is necessary as TalkBack on Android doesn't scroll to items not visible on screen if the number of further child nodes is not communicated to TalkBack. * Return success of scroll to TalkBack. TalkBack needs the result of the scroll to decide if it should leave the current element or stay after a scroll was successful. Success of a scroll action is measured as the successful movement of the children of the scrolled element. This is a workaround for the Qt Accessibility API not returning the success of failure of a performed action. Task-number: QTBUG-103499 Change-Id: Ie2c51d0b77fb5030973a0f93c42e0db3082be45e Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> (cherry picked from commit 56c4d183ec30c7f40ece09de1c483829eedc299b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java9
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp28
2 files changed, 33 insertions, 4 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java
index 9bf84b5d5a..c035e20e98 100644
--- a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java
@@ -43,6 +43,7 @@ package org.qtproject.qt.android.accessibility;
import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -51,6 +52,7 @@ import android.view.ViewParent;
import android.text.TextUtils;
import android.view.accessibility.*;
+import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
import android.view.MotionEvent;
import android.view.View.OnHoverListener;
@@ -444,6 +446,13 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(virtualViewId);
for (int i = 0; i < ids.length; ++i)
node.addChild(m_view, ids[i]);
+ if (node.isScrollable()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ node.setCollectionInfo(new CollectionInfo(ids.length, 1, false));
+ } else {
+ node.setCollectionInfo(CollectionInfo.obtain(ids.length, 1, false));
+ }
+ }
return node;
}
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 86377af5e8..99b6869daf 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -221,7 +221,7 @@ namespace QtAndroidAccessibility
return result;
}
- static QRect screenRect_helper(int objectId)
+ static QRect screenRect_helper(int objectId, bool clip = true)
{
QRect rect;
QAccessibleInterface *iface = interfaceFromId(objectId);
@@ -229,7 +229,7 @@ namespace QtAndroidAccessibility
rect = QHighDpi::toNativePixels(iface->rect(), iface->window());
}
// If the widget is not fully in-bound in its parent then we have to clip the rectangle to draw
- if (iface && iface->parent() && iface->parent()->isValid()) {
+ if (clip && iface && iface->parent() && iface->parent()->isValid()) {
const auto parentRect = QHighDpi::toNativePixels(iface->parent()->rect(), iface->parent()->window());
rect = rect.intersected(parentRect);
}
@@ -331,23 +331,43 @@ namespace QtAndroidAccessibility
static jboolean scrollForward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
{
bool result = false;
+
+ const auto& ids = childIdListForAccessibleObject_helper(objectId);
+ if (ids.isEmpty())
+ return false;
+
+ const int firstChildId = ids.first();
+ const QRect oldPosition = screenRect_helper(firstChildId, false);
+
if (m_accessibilityContext) {
runInObjectContext(m_accessibilityContext, [objectId]() {
return scroll_helper(objectId, QAccessibleActionInterface::increaseAction());
}, &result);
}
- return result;
+
+ // Don't check for position change if the call was not successful
+ return result && oldPosition != screenRect_helper(firstChildId, false);
}
static jboolean scrollBackward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
{
bool result = false;
+
+ const auto& ids = childIdListForAccessibleObject_helper(objectId);
+ if (ids.isEmpty())
+ return false;
+
+ const int firstChildId = ids.first();
+ const QRect oldPosition = screenRect_helper(firstChildId, false);
+
if (m_accessibilityContext) {
runInObjectContext(m_accessibilityContext, [objectId]() {
return scroll_helper(objectId, QAccessibleActionInterface::decreaseAction());
}, &result);
}
- return result;
+
+ // Don't check for position change if the call was not successful
+ return result && oldPosition != screenRect_helper(firstChildId, false);
}