Commit 9b32c079 authored by Tomasz Wiszkowski's avatar Tomasz Wiszkowski Committed by Commit Bot

Announce effect of latest gesture via accessibility.

This change restores functionality of announcing cursor position via
accessibility to users required audible cues, that use gestures to work with
omnibox contents.

The functionality is restored by using explicitly a single source of
accessibility event announcemets for TEXT_CHANGED and
TEXT_SELECTION_CHANGED. This helps us avoid sending multiple repeated
accessibility events to AccessibilityManager, which in turn appears to
be dropping them. These repeated events are originating from both
SpannableAutocompleteEditTextModel and EditText itself, which makes it
difficult to provide consistent and predictable behavior.

This change replaces the above behavior, and introduces a single source of
accessibility events instead: SpannableAutocompleteEditTextModel.

Bug: 935785
Change-Id: I7358d268cc7f21e5a7ed28d9adc26f8e0adf31fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1717783Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarChangwan Ryu <changwan@chromium.org>
Commit-Queue: Ender <ender@google.com>
Cr-Commit-Position: refs/heads/master@{#688634}
parent 5e619aeb
......@@ -71,6 +71,12 @@ public class SpannableAutocompleteEditTextModel implements AutocompleteEditTextM
private int mLastUpdateSelStart;
private int mLastUpdateSelEnd;
// This controls whether AutocompleteEditText is permitted to pass-through specific
// Accessibility announcements, in particular the TEXT_CHANGED and TEXT_SELECTION_CHANGED.
// The only events of the above type that are allowed are ones coming from
// SpannableAutocompleteEditTextModel.
private boolean mDelegateShouldIgnoreAccessibilityEvents = true;
public SpannableAutocompleteEditTextModel(AutocompleteEditTextModelBase.Delegate delegate) {
if (DEBUG) Log.i(TAG, "constructor");
mDelegate = delegate;
......@@ -134,6 +140,8 @@ public class SpannableAutocompleteEditTextModel implements AutocompleteEditTextM
removedCount = oldState.getUserText().length();
fromIndex = 0;
}
mDelegateShouldIgnoreAccessibilityEvents = false;
if (!oldState.getText().equals(newState.getText())
&& (addedCount != 0 || removedCount != 0)) {
AccessibilityEvent event =
......@@ -150,6 +158,7 @@ public class SpannableAutocompleteEditTextModel implements AutocompleteEditTextM
mDelegate.sendAccessibilityEventUnchecked(
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED));
}
mDelegateShouldIgnoreAccessibilityEvents = true;
}
private void sendAccessibilityEventForAppendingAutocomplete(AutocompleteState newState) {
......@@ -161,7 +170,9 @@ public class SpannableAutocompleteEditTextModel implements AutocompleteEditTextM
eventTextChanged.setFromIndex(newState.getUserText().length());
eventTextChanged.setRemovedCount(0);
eventTextChanged.setAddedCount(newState.getAutocompleteText().length());
mDelegateShouldIgnoreAccessibilityEvents = false;
mDelegate.sendAccessibilityEventUnchecked(eventTextChanged);
mDelegateShouldIgnoreAccessibilityEvents = true;
}
private void notifyAccessibilityService() {
......@@ -272,13 +283,21 @@ public class SpannableAutocompleteEditTextModel implements AutocompleteEditTextM
clearAutocompleteTextAndUpdateSpanCursor();
}
}
notifyAutocompleteTextStateChanged();
updateSelectionForTesting();
notifyAutocompleteTextStateChanged();
}
@Override
public void onFocusChanged(boolean focused) {
if (DEBUG) Log.i(TAG, "onFocusChanged: " + focused);
if (!focused) {
// Reset selection now. It will be updated immediately after focus is re-gained.
// We do this to ensure the selection changed announcements are advertised by us
// since we suppress all TEXT_SELECTION_CHANGED announcements coming from EditText.
mPreviouslyNotifiedState.setSelection(-1, -1);
mCurrentState.setSelection(-1, -1);
}
}
@Override
......@@ -399,7 +418,7 @@ public class SpannableAutocompleteEditTextModel implements AutocompleteEditTextM
@Override
public boolean shouldIgnoreAccessibilityEvent() {
return mBatchEditNestCount > 0;
return mDelegateShouldIgnoreAccessibilityEvents;
}
/**
......
......@@ -978,16 +978,13 @@ public class AutocompleteEditTextTest {
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
"hello world", "", 11, 7, 7, -1, -1);
mInOrder.verify(mVerifier).onAutocompleteTextStateChanged(false);
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
"hello world", "", 11, 7, 7, -1, -1);
assertVerifierCallCounts(2, 2);
} else {
mInOrder.verify(mVerifier).onAutocompleteTextStateChanged(false);
mInOrder.verify(mVerifier).onUpdateSelection(7, 7);
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
"hello world", "", 11, 7, 7, -1, -1);
assertVerifierCallCounts(2, 1);
}
assertVerifierCallCounts(2, 1);
mInOrder.verifyNoMoreInteractions();
assertFalse(mAutocomplete.shouldAutocomplete());
assertTexts("hello world", "");
......@@ -1057,9 +1054,7 @@ public class AutocompleteEditTextTest {
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
"hello", "", 5, 3, 3, -1, -1);
mInOrder.verify(mVerifier).onAutocompleteTextStateChanged(false);
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
"hello", "", 5, 3, 3, -1, -1);
assertVerifierCallCounts(2, 3);
assertVerifierCallCounts(2, 2);
} else {
mInOrder.verify(mVerifier).onAutocompleteTextStateChanged(true);
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED, "hello",
......@@ -1170,26 +1165,16 @@ public class AutocompleteEditTextTest {
assertTrue(mAutocomplete.requestFocus());
if (!isUsingSpannableModel()) mInOrder.verify(mVerifier).onUpdateSelection(len, len);
mInOrder.verify(mVerifier).onUpdateSelection(len, len);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED, url, "", 18, 18, 18, -1, -1);
if (isUsingSpannableModel()) {
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
url, "", 18, 0, 18, -1, -1);
}
mInOrder.verify(mVerifier).onUpdateSelection(0, len);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED, url, "", 18, 0, 18, -1, -1);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED, url, "", 2, -1, -1, -1, -1);
if (isUsingSpannableModel()) {
// TODO(https://crbug.com/935785): Remove this exception when double announcement is
// fixed; we expect to see same results as with non-spannable model.
assertVerifierCallCounts(1, 4);
} else {
assertVerifierCallCounts(2, 3);
}
assertVerifierCallCounts(2, 3);
mInOrder.verifyNoMoreInteractions();
}
......@@ -1308,4 +1293,51 @@ public class AutocompleteEditTextTest {
assertEquals("google.com", mAutocomplete.getText().toString());
}
// crbug.com/759876
@Test
@EnableFeatures(ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE)
public void testTextSelectionGetsAnnouncedAgainOnFocusWithSpannableModel() {
internalTestTextSelectionGetsAnnouncedAgainOnFocus();
}
@Test
@DisableFeatures(ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE)
public void testTextSelectionGetsAnnouncedAgainOnFocusWithoutSpannableModel() {
internalTestTextSelectionGetsAnnouncedAgainOnFocus();
}
private void internalTestTextSelectionGetsAnnouncedAgainOnFocus() {
final String text = "hello";
final int len = text.length();
assertTrue(mInputConnection.commitText(text, len));
mAutocomplete.setSelection(0, len);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED, text, "", -1, 0, -1, 0, len);
verifyOnPopulateAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
text, "", len, len, len, -1, -1);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED, text, "", len, 0, len, -1, -1);
mInOrder.verifyNoMoreInteractions();
assertVerifierCallCounts(3, 3);
assertTrue(mFocusPlaceHolder.requestFocus());
mInOrder.verifyNoMoreInteractions();
assertVerifierCallCounts(0, 0);
// We left EditText with selected content. We should get the same event sent again now.
mAutocomplete.setSelectAllOnFocus(true);
assertTrue(mAutocomplete.requestFocus());
mInOrder.verify(mVerifier).onUpdateSelection(0, len);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED, text, "", len, 0, len, -1, -1);
verifyOnPopulateAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED, text, "", 2, -1, -1, -1, -1);
assertVerifierCallCounts(2, 3);
mInOrder.verifyNoMoreInteractions();
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment