From 21b8224ae12d94e00fc621d2a15160a0539c4b69 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Tue, 8 Oct 2019 16:54:17 -0700 Subject: [PATCH] Send AccessibilityEvent.TYPE_VIEW_FOCUSED when input focus is set. (#12746) When the focus changes, we should be sending a TYPE_VIEW_FOCUSED event. This enables that. --- .../io/flutter/view/AccessibilityBridge.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index 1679d96869d95..24584f9f599fa 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -190,6 +190,14 @@ public class AccessibilityBridge extends AccessibilityNodeProvider { @Nullable private SemanticsNode inputFocusedSemanticsNode; + // Keeps track of the last semantics node that had the input focus. + // + // This is used to determine if the input focus has changed since the last time the + // {@code inputFocusSemanticsNode} has been set, so that we can send a {@code TYPE_VIEW_FOCUSED} + // event when it changes. + @Nullable + private SemanticsNode lastInputFocusedSemanticsNode; + // The widget within Flutter that currently sits beneath a cursor, e.g, // beneath a stylus or mouse cursor. @Nullable @@ -1377,6 +1385,20 @@ void updateSemantics(@NonNull ByteBuffer buffer, @NonNull String[] strings) { event.getText().add(object.label); sendAccessibilityEvent(event); } + + // If the object is the input-focused node, then tell the reader about it, but only if + // it has changed since the last update. + if (inputFocusedSemanticsNode != null && inputFocusedSemanticsNode.id == object.id && + (lastInputFocusedSemanticsNode == null || lastInputFocusedSemanticsNode.id != inputFocusedSemanticsNode.id)) { + lastInputFocusedSemanticsNode = inputFocusedSemanticsNode; + sendAccessibilityEvent(obtainAccessibilityEvent(object.id, AccessibilityEvent.TYPE_VIEW_FOCUSED)); + } else if (inputFocusedSemanticsNode == null) { + // There's no TYPE_VIEW_CLEAR_FOCUSED event, so if the current input focus becomes + // null, then we just set the last one to null too, so that it sends the event again + // when something regains focus. + lastInputFocusedSemanticsNode = null; + } + if (inputFocusedSemanticsNode != null && inputFocusedSemanticsNode.id == object.id && object.hadFlag(Flag.IS_TEXT_FIELD) && object.hasFlag(Flag.IS_TEXT_FIELD) // If we have a TextField that has InputFocus, we should avoid announcing it if something