Android: remove a11y methods from QtNative, call a11y delegate direct
Remove yet another two layers of delegation, QtNative calling QtActivityDelegate and that in turn calls QtAccessibilityDelegate. Now from c++ native code, acquire the a11y delegate and use it to call a11y operations that live in QtAccessibilityDelegate. Task-number: QTBUG-118077 Change-Id: I9e84520c2caa281a6f786a687b0106d702f92a67 Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
This commit is contained in:
parent
ddb1c75afe
commit
0f3dbd6dc7
@ -342,7 +342,14 @@ public class QtActivityDelegate
|
|||||||
|
|
||||||
public void initializeAccessibility()
|
public void initializeAccessibility()
|
||||||
{
|
{
|
||||||
m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity, m_layout, this);
|
final QtActivityDelegate currentDelegate = this;
|
||||||
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity, m_layout,
|
||||||
|
currentDelegate);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleUiModeChange(int uiMode)
|
void handleUiModeChange(int uiMode)
|
||||||
|
@ -239,7 +239,7 @@ public class QtNative
|
|||||||
updateApplicationState(state);
|
updateApplicationState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void runAction(Runnable action)
|
public static void runAction(Runnable action)
|
||||||
{
|
{
|
||||||
synchronized (m_mainActivityMutex) {
|
synchronized (m_mainActivityMutex) {
|
||||||
final Looper mainLooper = Looper.getMainLooper();
|
final Looper mainLooper = Looper.getMainLooper();
|
||||||
@ -364,66 +364,6 @@ public class QtNative
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void notifyAccessibilityLocationChange(final int viewId)
|
|
||||||
{
|
|
||||||
runAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (m_activityDelegate != null) {
|
|
||||||
m_activityDelegate.notifyAccessibilityLocationChange(viewId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void notifyObjectHide(final int viewId, final int parentId)
|
|
||||||
{
|
|
||||||
runAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (m_activityDelegate != null) {
|
|
||||||
m_activityDelegate.notifyObjectHide(viewId, parentId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void notifyObjectFocus(final int viewId)
|
|
||||||
{
|
|
||||||
runAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (m_activityDelegate != null) {
|
|
||||||
m_activityDelegate.notifyObjectFocus(viewId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void notifyValueChanged(int viewId, String value)
|
|
||||||
{
|
|
||||||
runAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (m_activityDelegate != null) {
|
|
||||||
m_activityDelegate.notifyValueChanged(viewId, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void notifyScrolledEvent(final int viewId)
|
|
||||||
{
|
|
||||||
runAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (m_activityDelegate != null) {
|
|
||||||
m_activityDelegate.notifyScrolledEvent(viewId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void notifyQtAndroidPluginRunning(final boolean running)
|
public static void notifyQtAndroidPluginRunning(final boolean running)
|
||||||
{
|
{
|
||||||
if (m_activityDelegate != null)
|
if (m_activityDelegate != null)
|
||||||
@ -569,17 +509,6 @@ public class QtNative
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initializeAccessibility()
|
|
||||||
{
|
|
||||||
runAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (m_activityDelegate != null)
|
|
||||||
m_activityDelegate.initializeAccessibility();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void hideSplashScreen(final int duration)
|
private static void hideSplashScreen(final int duration)
|
||||||
{
|
{
|
||||||
runAction(new Runnable() {
|
runAction(new Runnable() {
|
||||||
|
@ -27,6 +27,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.qtproject.qt.android.QtActivityDelegate;
|
import org.qtproject.qt.android.QtActivityDelegate;
|
||||||
|
import org.qtproject.qt.android.QtNative;
|
||||||
|
|
||||||
public class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
public class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
||||||
{
|
{
|
||||||
@ -164,75 +165,100 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
|
|
||||||
public void notifyScrolledEvent(int viewId)
|
public void notifyScrolledEvent(int viewId)
|
||||||
{
|
{
|
||||||
sendEventForVirtualViewId(viewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sendEventForVirtualViewId(viewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyLocationChange(int viewId)
|
public void notifyLocationChange(int viewId)
|
||||||
{
|
{
|
||||||
if (m_focusedVirtualViewId == viewId)
|
QtNative.runAction(new Runnable() {
|
||||||
invalidateVirtualViewId(m_focusedVirtualViewId);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (m_focusedVirtualViewId == viewId)
|
||||||
|
invalidateVirtualViewId(m_focusedVirtualViewId);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyObjectHide(int viewId, int parentId)
|
public void notifyObjectHide(int viewId, int parentId)
|
||||||
{
|
{
|
||||||
// If the object had accessibility focus, we need to clear it.
|
QtNative.runAction(new Runnable() {
|
||||||
// Note: This code is mostly copied from
|
@Override
|
||||||
// AccessibilityNodeProvider::performAction, but we remove the
|
public void run() {
|
||||||
// focus only if the focused view id matches the one that was hidden.
|
// If the object had accessibility focus, we need to clear it.
|
||||||
if (m_focusedVirtualViewId == viewId) {
|
// Note: This code is mostly copied from
|
||||||
m_focusedVirtualViewId = INVALID_ID;
|
// AccessibilityNodeProvider::performAction, but we remove the
|
||||||
m_view.invalidate();
|
// focus only if the focused view id matches the one that was hidden.
|
||||||
sendEventForVirtualViewId(viewId,
|
if (m_focusedVirtualViewId == viewId) {
|
||||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
m_focusedVirtualViewId = INVALID_ID;
|
||||||
}
|
m_view.invalidate();
|
||||||
// When the object is hidden, we need to notify its parent about
|
sendEventForVirtualViewId(viewId,
|
||||||
// content change, not the hidden object itself
|
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
||||||
invalidateVirtualViewId(parentId);
|
}
|
||||||
|
// When the object is hidden, we need to notify its parent about
|
||||||
|
// content change, not the hidden object itself
|
||||||
|
invalidateVirtualViewId(parentId);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyObjectFocus(int viewId)
|
public void notifyObjectFocus(int viewId)
|
||||||
{
|
{
|
||||||
if (m_view == null)
|
QtNative.runAction(new Runnable() {
|
||||||
return;
|
@Override
|
||||||
m_focusedVirtualViewId = viewId;
|
public void run() {
|
||||||
m_view.invalidate();
|
if (m_view == null)
|
||||||
sendEventForVirtualViewId(viewId,
|
return;
|
||||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
m_focusedVirtualViewId = viewId;
|
||||||
|
m_view.invalidate();
|
||||||
|
sendEventForVirtualViewId(viewId,
|
||||||
|
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyValueChanged(int viewId, String value)
|
public void notifyValueChanged(int viewId, String value)
|
||||||
{
|
{
|
||||||
// Send a TYPE_ANNOUNCEMENT event with the new value
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Send a TYPE_ANNOUNCEMENT event with the new value
|
||||||
|
|
||||||
if ((viewId == INVALID_ID) || !m_manager.isEnabled()) {
|
if ((viewId == INVALID_ID) || !m_manager.isEnabled()) {
|
||||||
Log.w(TAG, "notifyValueChanged() for invalid view");
|
Log.w(TAG, "notifyValueChanged() for invalid view");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ViewGroup group = (ViewGroup)m_view.getParent();
|
final ViewGroup group = (ViewGroup) m_view.getParent();
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
Log.w(TAG, "Could not announce value because ViewGroup was null.");
|
Log.w(TAG, "Could not announce value because ViewGroup was null.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final AccessibilityEvent event =
|
final AccessibilityEvent event =
|
||||||
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT);
|
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT);
|
||||||
|
|
||||||
event.setEnabled(true);
|
event.setEnabled(true);
|
||||||
event.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
|
event.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
|
||||||
|
|
||||||
event.setContentDescription(value);
|
event.setContentDescription(value);
|
||||||
|
|
||||||
if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) {
|
if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) {
|
||||||
Log.w(TAG, "No value to announce for " + event.getClassName());
|
Log.w(TAG, "No value to announce for " + event.getClassName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.setPackageName(m_view.getContext().getPackageName());
|
event.setPackageName(m_view.getContext().getPackageName());
|
||||||
event.setSource(m_view, viewId);
|
event.setSource(m_view, viewId);
|
||||||
|
|
||||||
if (!group.requestSendAccessibilityEvent(m_view, event))
|
if (!group.requestSendAccessibilityEvent(m_view, event))
|
||||||
Log.w(TAG, "Failed to send value change announcement for " + event.getClassName());
|
Log.w(TAG, "Failed to send value change announcement for " + event.getClassName());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean sendEventForVirtualViewId(int virtualViewId, int eventType)
|
public boolean sendEventForVirtualViewId(int virtualViewId, int eventType)
|
||||||
|
@ -82,8 +82,7 @@ namespace QtAndroidAccessibility
|
|||||||
|
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(QtAndroid::applicationClass(),
|
QtAndroid::qtActivityDelegate().callMethod<void>("initializeAccessibility");
|
||||||
"initializeAccessibility");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isActive()
|
bool isActive()
|
||||||
|
@ -23,8 +23,6 @@ Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods");
|
|||||||
|
|
||||||
using namespace QtAndroid;
|
using namespace QtAndroid;
|
||||||
|
|
||||||
Q_DECLARE_JNI_CLASS(QtInputDelegate, "org/qtproject/qt/android/QtInputDelegate")
|
|
||||||
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
|
|
||||||
Q_DECLARE_JNI_CLASS(QtLayout, "org/qtproject/qt/android/QtLayout")
|
Q_DECLARE_JNI_CLASS(QtLayout, "org/qtproject/qt/android/QtLayout")
|
||||||
|
|
||||||
namespace QtAndroidInput
|
namespace QtAndroidInput
|
||||||
@ -96,18 +94,6 @@ namespace QtAndroidInput
|
|||||||
g_keyEventListeners()->listeners.removeOne(listener);
|
g_keyEventListeners()->listeners.removeOne(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: avoid direct access to QtActivityDelegate
|
|
||||||
QJniObject qtActivityDelegate()
|
|
||||||
{
|
|
||||||
return QtAndroidPrivate::activity().callMethod<QtJniTypes::QtActivityDelegate>(
|
|
||||||
"getActivityDelegate");
|
|
||||||
}
|
|
||||||
|
|
||||||
QJniObject qtInputDelegate()
|
|
||||||
{
|
|
||||||
return qtActivityDelegate().callMethod<QtJniTypes::QtInputDelegate>("getInputDelegate");
|
|
||||||
}
|
|
||||||
|
|
||||||
QJniObject qtLayout()
|
QJniObject qtLayout()
|
||||||
{
|
{
|
||||||
return qtActivityDelegate().callMethod<QtJniTypes::QtLayout>("getQtLayout");
|
return qtActivityDelegate().callMethod<QtJniTypes::QtLayout>("getQtLayout");
|
||||||
|
@ -49,6 +49,9 @@ static jmethodID m_createSurfaceMethodID = nullptr;
|
|||||||
static jmethodID m_setSurfaceGeometryMethodID = nullptr;
|
static jmethodID m_setSurfaceGeometryMethodID = nullptr;
|
||||||
static jmethodID m_destroySurfaceMethodID = nullptr;
|
static jmethodID m_destroySurfaceMethodID = nullptr;
|
||||||
|
|
||||||
|
static QtJniTypes::QtActivityDelegate m_activityDelegate = nullptr;
|
||||||
|
static QtJniTypes::QtInputDelegate m_inputDelegate = nullptr;
|
||||||
|
|
||||||
static int m_pendingApplicationState = -1;
|
static int m_pendingApplicationState = -1;
|
||||||
static QBasicMutex m_platformMutex;
|
static QBasicMutex m_platformMutex;
|
||||||
|
|
||||||
@ -165,33 +168,52 @@ namespace QtAndroid
|
|||||||
QJniObject::callStaticMethod<void>(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility));
|
QJniObject::callStaticMethod<void>(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: avoid direct access to QtActivityDelegate
|
||||||
|
QtJniTypes::QtActivityDelegate qtActivityDelegate()
|
||||||
|
{
|
||||||
|
if (!m_activityDelegate.isValid()) {
|
||||||
|
auto activity = QtAndroidPrivate::activity();
|
||||||
|
m_activityDelegate = activity.callMethod<QtJniTypes::QtActivityDelegate>(
|
||||||
|
"getActivityDelegate");
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_activityDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtJniTypes::QtInputDelegate qtInputDelegate()
|
||||||
|
{
|
||||||
|
if (!m_inputDelegate.isValid()) {
|
||||||
|
m_inputDelegate = qtActivityDelegate().callMethod<QtJniTypes::QtInputDelegate>(
|
||||||
|
"getInputDelegate");
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_inputDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
void notifyAccessibilityLocationChange(uint accessibilityObjectId)
|
void notifyAccessibilityLocationChange(uint accessibilityObjectId)
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(m_applicationClass, "notifyAccessibilityLocationChange",
|
qtActivityDelegate().callMethod<void>("notifyLocationChange", accessibilityObjectId);
|
||||||
"(I)V", accessibilityObjectId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyObjectHide(uint accessibilityObjectId, uint parentObjectId)
|
void notifyObjectHide(uint accessibilityObjectId, uint parentObjectId)
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(m_applicationClass, "notifyObjectHide", "(II)V",
|
qtActivityDelegate().callMethod<void>("notifyObjectHide",
|
||||||
accessibilityObjectId, parentObjectId);
|
accessibilityObjectId, parentObjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyObjectFocus(uint accessibilityObjectId)
|
void notifyObjectFocus(uint accessibilityObjectId)
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(m_applicationClass, "notifyObjectFocus","(I)V", accessibilityObjectId);
|
qtActivityDelegate().callMethod<void>("notifyObjectFocus", accessibilityObjectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyValueChanged(uint accessibilityObjectId, jstring value)
|
void notifyValueChanged(uint accessibilityObjectId, jstring value)
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(m_applicationClass, "notifyValueChanged",
|
qtActivityDelegate().callMethod<void>("notifyValueChanged", accessibilityObjectId, value);
|
||||||
"(ILjava/lang/String;)V", accessibilityObjectId, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyScrolledEvent(uint accessibilityObjectId)
|
void notifyScrolledEvent(uint accessibilityObjectId)
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(m_applicationClass, "notifyScrolledEvent", "(I)V",
|
qtActivityDelegate().callMethod<void>("notifyScrolledEvent", accessibilityObjectId);
|
||||||
accessibilityObjectId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyQtAndroidPluginRunning(bool running)
|
void notifyQtAndroidPluginRunning(bool running)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <private/qjnihelpers_p.h>
|
#include <private/qjnihelpers_p.h>
|
||||||
|
#include <QtCore/QJniObject>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -25,6 +26,9 @@ class QWindow;
|
|||||||
class AndroidSurfaceClient;
|
class AndroidSurfaceClient;
|
||||||
class QBasicMutex;
|
class QBasicMutex;
|
||||||
|
|
||||||
|
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
|
||||||
|
Q_DECLARE_JNI_CLASS(QtInputDelegate, "org/qtproject/qt/android/QtInputDelegate")
|
||||||
|
|
||||||
namespace QtAndroid
|
namespace QtAndroid
|
||||||
{
|
{
|
||||||
QBasicMutex *platformInterfaceMutex();
|
QBasicMutex *platformInterfaceMutex();
|
||||||
@ -32,7 +36,6 @@ namespace QtAndroid
|
|||||||
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
|
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
|
||||||
void setQtThread(QThread *thread);
|
void setQtThread(QThread *thread);
|
||||||
|
|
||||||
|
|
||||||
int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop, int imageDepth);
|
int createSurface(AndroidSurfaceClient * client, const QRect &geometry, bool onTop, int imageDepth);
|
||||||
int insertNativeView(jobject view, const QRect &geometry);
|
int insertNativeView(jobject view, const QRect &geometry);
|
||||||
void setViewVisibility(jobject view, bool visible);
|
void setViewVisibility(jobject view, bool visible);
|
||||||
@ -51,6 +54,9 @@ namespace QtAndroid
|
|||||||
AAssetManager *assetManager();
|
AAssetManager *assetManager();
|
||||||
jclass applicationClass();
|
jclass applicationClass();
|
||||||
|
|
||||||
|
QtJniTypes::QtActivityDelegate qtActivityDelegate();
|
||||||
|
QtJniTypes::QtInputDelegate qtInputDelegate();
|
||||||
|
|
||||||
// Keep synchronized with flags in ActivityDelegate.java
|
// Keep synchronized with flags in ActivityDelegate.java
|
||||||
enum SystemUiVisibility {
|
enum SystemUiVisibility {
|
||||||
SYSTEM_UI_VISIBILITY_NORMAL = 0,
|
SYSTEM_UI_VISIBILITY_NORMAL = 0,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user