Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc3dd0b7 authored by yingleiw's avatar yingleiw
Browse files

Send TYPE_VIEW_TEXT_CHANGED a11y event when SuggestionSpan is added

When user types space after a word, we receive a text
change event, but the suggestion span is not added to
the text yet. The spell checker adds the span after the
text change event is sent, but currently TextView doesn't send
any notification. This change sends a TYPE_VIEW_TEXT_CHANGED
event with the from and to index of the span, and beforeText
which doesn't have the span and afterText which has the
span.

Bug: b/143378480

Test: tested with talkback.

Change-Id: If16c2c578be5dcae20a9fd7014ff6fba2d487670
parent 62ddf061
Loading
Loading
Loading
Loading
+50 −2
Original line number Diff line number Diff line
@@ -13822,9 +13822,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            TextView.this.handleTextChanged(buffer, start, before, after);
            if (AccessibilityManager.getInstance(mContext).isEnabled()
                    && (isFocused() || isSelected() && isShown())) {
                    && (isFocused() || (isSelected() && isShown()))) {
                sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
                mBeforeText = null;
                mBeforeText = TextUtils.stringOrSpannedString(mTransformed);
            }
        }
@@ -13852,6 +13852,54 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                Log.v(LOG_TAG, "onSpanAdded s=" + s + " e=" + e + " what=" + what + ": " + buf);
            }
            TextView.this.spanChange(buf, what, -1, s, -1, e);
            // Note we don't update mBeforeText here. We look for SuggestionSpans added after the
            // text content changes.
            if (AccessibilityManager.getInstance(mContext).isEnabled()
                    && (isFocused() || (isSelected() && isShown()))
                    && (what instanceof SuggestionSpan)) {
                // When the user types a new word, and SuggestionSpans on the existing words will be
                // removed and added again. We don't need to send out events for existing
                // SuggestionSpans. Multiple spans can be placed on the range.
                if (mBeforeText instanceof SpannedString) {
                    final SpannedString beforeSpannedString = (SpannedString) mBeforeText;
                    if ((beforeSpannedString.getSpanStart(what) == s)
                            && (beforeSpannedString.getSpanEnd(what) == e)) {
                        // Exactly same span is found.
                        return;
                    }
                    // Suggestion span couldn't be found. Try to find a suggestion span that has the
                    // same contents.
                    SuggestionSpan[] suggestionSpans = beforeSpannedString.getSpans(s, e,
                            SuggestionSpan.class);
                    for (final SuggestionSpan suggestionSpan : suggestionSpans) {
                        final int start = beforeSpannedString.getSpanStart(suggestionSpan);
                        if (start != s) {
                            continue;
                        }
                        final int end = beforeSpannedString.getSpanEnd(suggestionSpan);
                        if (end != e) {
                            continue;
                        }
                        if (equalSuggestionSpan(suggestionSpan, (SuggestionSpan) what)) {
                            return;
                        }
                    }
                }
                AccessibilityEvent event =
                        AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
                event.setFromIndex(s);
                event.setToIndex(e);
                event.setBeforeText(mBeforeText);
                sendAccessibilityEventUnchecked(event);
            }
        }
        private boolean equalSuggestionSpan(SuggestionSpan span1, SuggestionSpan span2) {
            // We compare flags because flags will determine the underline color.
            return Arrays.equals(span1.getSuggestions(), span2.getSuggestions())
                    && Objects.equals(span1.getLocaleObject(), span2.getLocaleObject())
                    && span1.getLocale().equals(span2.getLocale())
                    && (span1.getFlags() == span2.getFlags());
        }
        public void onSpanRemoved(Spannable buf, Object what, int s, int e) {