Android: Re-focus focused accessibility node after orientation change
Before this patch the accessibility focus on a selected element could be drawn incorrectly after the screen orientation has changed. The reason for that is that wrong X and Y offsets were used for it. The offsets are used to take the sizes of different panels (like buttons and notifications bar) into account. Normally they are updated only when getNodeForView() is called and the whole accessibility info is reconstructed. However, when the screen orientation changes, we get some getNodeForVirtualViewId(selectedId) calls before the whole accessibility tree is recreated. This is when redrawing happens, and as I understand, this is an internal Android event, so we can't do much about it. The most straightforward fix for the problem would be to query the offsets also in each getNodeForVirtualViewId() call. However, offset calculation seems to be quite heavy operation, and getNodeForVirtualViewId can be called very often (esp. if we have a lot of UI elements). As a result, this fix can't be implemented. In this patch I came up with the second approach - once getNodeForView() is called, and it detects that the offsets have changed, we force re-focus of the currently selected element. This allows us to retain the offsets-caching mechanism. Fixes: QTBUG-93402 Pick-to: 6.3 6.2 5.15 Change-Id: Ic420afe1fe5e80fbdf91b2b2651f2daa71c6e44d Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
parent
0a24e2e984
commit
7c00ad4e9a
@ -89,6 +89,8 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
||||
// this is because the Android platform window does not take
|
||||
// the offset of the view on screen into account (eg status bar on top)
|
||||
private final int[] m_globalOffset = new int[2];
|
||||
private int m_oldOffsetX = 0;
|
||||
private int m_oldOffsetY = 0;
|
||||
|
||||
private class HoverEventListener implements View.OnHoverListener
|
||||
{
|
||||
@ -327,6 +329,22 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
||||
for (int i = 0; i < ids.length; ++i)
|
||||
result.addChild(m_view, ids[i]);
|
||||
|
||||
// The offset values have changed, so we need to re-focus the
|
||||
// currently focused item, otherwise it will have an incorrect
|
||||
// focus frame
|
||||
if ((m_oldOffsetX != offsetX) || (m_oldOffsetY != offsetY)) {
|
||||
m_oldOffsetX = offsetX;
|
||||
m_oldOffsetY = offsetY;
|
||||
if (m_focusedVirtualViewId != INVALID_ID) {
|
||||
m_nodeProvider.performAction(m_focusedVirtualViewId,
|
||||
AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
|
||||
new Bundle());
|
||||
m_nodeProvider.performAction(m_focusedVirtualViewId,
|
||||
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS,
|
||||
new Bundle());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user