Android: move QtAccessibilityDelegate instance to QtActivityDelegateBase

Similar to the display manager and the input delegate, keep the
accessibility delegate under the base class. Also, following the same
pattern as in the parent patch, assign a default instance for this in
the delegate in the constructor, and initialize anything later when
needed. Also, make sure calls for various objects under the
QtAccessibilityDelegate are safe and guarded.

Task-number: QTBUG-129704
Change-Id: I14a57d8e0916127ae8fa00acb3265b92803087dc
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
(cherry picked from commit af73c7a99eeea346efb65bed1d6e643e74ef33a6)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Assam Boudjelthia 2024-10-25 16:22:24 +03:00 committed by Qt Cherry-pick Bot
parent 6c6f456987
commit 2d88b05376
3 changed files with 46 additions and 33 deletions

View File

@ -35,8 +35,8 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
private static final String DEFAULT_CLASS_NAME = "$VirtualChild";
private View m_view = null;
private final AccessibilityManager m_manager;
private final QtLayout m_layout;
private AccessibilityManager m_manager;
private QtLayout m_layout;
// The accessible object that currently has the "accessibility focus"
// usually indicated by a yellow rectangle on screen.
@ -63,11 +63,16 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
// e.g. one per window?
// FIXME make QtAccessibilityDelegate window based or verify current way works
// also for child windows: QTBUG-120685
QtAccessibilityDelegate(QtLayout layout)
QtAccessibilityDelegate() { }
void initLayoutAccessibility(QtLayout layout)
{
if (m_layout == null)
Log.w(TAG, "Unable to initialize the accessibility delegate with a null layout");
m_layout = layout;
m_manager = (AccessibilityManager) m_layout.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
m_manager = m_layout.getContext().getSystemService(AccessibilityManager.class);
if (m_manager != null) {
AccessibilityManagerListener accServiceListener = new AccessibilityManagerListener();
if (!m_manager.addAccessibilityStateChangeListener(accServiceListener))
@ -82,7 +87,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
@Override
public void onAccessibilityStateChanged(boolean enabled)
{
if (Os.getenv("QT_ANDROID_DISABLE_ACCESSIBILITY") != null)
if (m_layout == null || Os.getenv("QT_ANDROID_DISABLE_ACCESSIBILITY") != null)
return;
if (enabled) {
try {
@ -136,7 +141,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
// (user moves finger over screen to discover items on screen).
private boolean dispatchHoverEvent(MotionEvent event)
{
if (!m_manager.isTouchExplorationEnabled()) {
if (m_manager == null || !m_manager.isTouchExplorationEnabled()) {
return false;
}
@ -177,7 +182,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
// Note: This code is mostly copied from
// AccessibilityNodeProvider::performAction, but we remove the
// focus only if the focused view id matches the one that was hidden.
if (m_focusedVirtualViewId == viewId) {
if (m_view != null && m_focusedVirtualViewId == viewId) {
m_focusedVirtualViewId = INVALID_ID;
m_view.invalidate();
sendEventForVirtualViewId(viewId,
@ -212,7 +217,13 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
void notifyValueChanged(int viewId, String value)
{
if (m_manager == null)
return;
QtNative.runAction(() -> {
if (m_view == null)
return;
// Send a TYPE_ANNOUNCEMENT event with the new value
if ((viewId == INVALID_ID) || !m_manager.isEnabled()) {
@ -255,7 +266,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
void sendAccessibilityEvent(AccessibilityEvent event)
{
if (event == null)
if (m_view == null || event == null)
return;
final ViewGroup group = (ViewGroup) m_view.getParent();
@ -292,12 +303,13 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
private AccessibilityEvent getEventForVirtualViewId(int virtualViewId, int eventType)
{
if ((virtualViewId == INVALID_ID) || !m_manager.isEnabled()) {
final boolean isManagerEnabled = m_manager != null && m_manager.isEnabled();
if (m_view == null || !isManagerEnabled || (virtualViewId == INVALID_ID)) {
Log.w(TAG, "getEventForVirtualViewId for invalid view");
return null;
}
if (m_layout.getChildCount() == 0)
if (m_layout == null || m_layout.getChildCount() == 0)
return null;
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
@ -330,6 +342,9 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
private AccessibilityNodeInfo getNodeForView()
{
if (m_view == null || m_layout == null)
return AccessibilityNodeInfo.obtain();
// Since we don't want the parent to be focusable, but we can't remove
// actions from a node, copy over the necessary fields.
final AccessibilityNodeInfo result = AccessibilityNodeInfo.obtain(m_view);
@ -391,6 +406,9 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
private AccessibilityNodeInfo getNodeForVirtualViewId(int virtualViewId)
{
if (m_view == null || m_layout == null)
return AccessibilityNodeInfo.obtain();
final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain();
node.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
@ -456,6 +474,11 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
@Override
public boolean performAction(int virtualViewId, int action, Bundle arguments)
{
if (m_view == null) {
Log.e(TAG, "Unable to perform action with a null view");
return false;
}
boolean handled = false;
//Log.i(TAG, "PERFORM ACTION: " + action + " on " + virtualViewId);
switch (action) {

View File

@ -43,7 +43,6 @@ class QtActivityDelegate extends QtActivityDelegateBase
private View m_dummyView = null;
private final HashMap<Integer, View> m_nativeViews = new HashMap<>();
private QtAccessibilityDelegate m_accessibilityDelegate = null;
QtActivityDelegate(Activity activity)
{
@ -248,49 +247,37 @@ class QtActivityDelegate extends QtActivityDelegateBase
@Override
public void notifyLocationChange(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyLocationChange(viewId);
getAccessibilityDelegate().notifyLocationChange(viewId);
}
@Override
public void notifyObjectHide(int viewId, int parentId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
getAccessibilityDelegate().notifyObjectHide(viewId, parentId);
}
@Override
public void notifyObjectShow(int parentId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectShow(parentId);
getAccessibilityDelegate().notifyObjectShow(parentId);
}
@Override
public void notifyObjectFocus(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectFocus(viewId);
getAccessibilityDelegate().notifyObjectFocus(viewId);
}
@Override
public void notifyValueChanged(int viewId, String value)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyValueChanged(viewId, value);
getAccessibilityDelegate().notifyValueChanged(viewId, value);
}
@Override
public void notifyScrolledEvent(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyScrolledEvent(viewId);
getAccessibilityDelegate().notifyScrolledEvent(viewId);
}
@Override
@ -298,10 +285,7 @@ class QtActivityDelegate extends QtActivityDelegateBase
{
QtNative.runAction(() -> {
// FIXME make QtAccessibilityDelegate window based
if (m_layout != null)
m_accessibilityDelegate = new QtAccessibilityDelegate(m_layout);
else
Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
getAccessibilityDelegate().initLayoutAccessibility(m_layout);
});
}

View File

@ -41,6 +41,7 @@ abstract class QtActivityDelegateBase
protected final HashMap<Integer, QtWindow> m_topLevelWindows = new HashMap<>();
protected final QtDisplayManager m_displayManager;
protected final QtInputDelegate m_inputDelegate;
private final QtAccessibilityDelegate m_accessibilityDelegate;
private boolean m_membersInitialized = false;
private boolean m_contextMenuVisible = false;
@ -60,6 +61,7 @@ abstract class QtActivityDelegateBase
QtNative.setActivity(m_activity);
m_displayManager = new QtDisplayManager(m_activity);
m_inputDelegate = new QtInputDelegate(m_displayManager::updateFullScreen);
m_accessibilityDelegate = new QtAccessibilityDelegate();
}
QtDisplayManager displayManager() {
@ -70,6 +72,10 @@ abstract class QtActivityDelegateBase
return m_inputDelegate;
}
QtAccessibilityDelegate getAccessibilityDelegate() {
return m_accessibilityDelegate;
}
void setContextMenuVisible(boolean contextMenuVisible)
{
m_contextMenuVisible = contextMenuVisible;