From 236d633a497b2de9bb6d14c5168240ab012a8e95 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 30 Jul 2018 17:53:17 -0700 Subject: [PATCH] Add word movement granularities to android (#5902) --- lib/ui/semantics.dart | 24 +++++++++++++++++ .../io/flutter/view/AccessibilityBridge.java | 26 +++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/ui/semantics.dart b/lib/ui/semantics.dart index 7e58c93d71..0b77a2e480 100644 --- a/lib/ui/semantics.dart +++ b/lib/ui/semantics.dart @@ -28,6 +28,8 @@ class SemanticsAction { static const int _kDidLoseAccessibilityFocusIndex = 1 << 16; static const int _kCustomAction = 1 << 17; static const int _kDismissIndex = 1 << 18; + static const int _kMoveCursorForwardByWordIndex = 1 << 19; + static const int _kMoveCursorBackwardByWordIndex = 1 << 20; /// The numerical value for this action. /// @@ -163,6 +165,22 @@ class SemanticsAction { /// (with VoiceOver) users can perform a standard gesture to dismiss it. static const SemanticsAction dismiss = const SemanticsAction._(_kDismissIndex); + /// Move the cursor forward by one word. + /// + /// This is for example used by the cursor control in text fields. + /// + /// The action includes a boolean argument, which indicates whether the cursor + /// movement should extend (or start) a selection. + static const SemanticsAction moveCursorForwardByWord = const SemanticsAction._(_kMoveCursorForwardByWordIndex); + + /// Move the cursor backward by one word. + /// + /// This is for example used by the cursor control in text fields. + /// + /// The action includes a boolean argument, which indicates whether the cursor + /// movement should extend (or start) a selection. + static const SemanticsAction moveCursorBackwardByWord = const SemanticsAction._(_kMoveCursorBackwardByWordIndex); + /// The possible semantics actions. /// /// The map's key is the [index] of the action and the value is the action @@ -187,6 +205,8 @@ class SemanticsAction { _kDidLoseAccessibilityFocusIndex: didLoseAccessibilityFocus, _kCustomAction: customAction, _kDismissIndex: dismiss, + _kMoveCursorForwardByWordIndex: moveCursorForwardByWord, + _kMoveCursorBackwardByWordIndex: moveCursorBackwardByWord, }; @override @@ -230,6 +250,10 @@ class SemanticsAction { return 'SemanticsAction.customAction'; case _kDismissIndex: return 'SemanticsAction.dismiss'; + case _kMoveCursorForwardByWordIndex: + return 'SemanticsAction.moveCursorForwardByWord'; + case _kMoveCursorBackwardByWordIndex: + return 'SemanticsAction.moveCursorBackwardByWord'; } return null; } diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index 01302abbd1..9c7f9bef0e 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -63,7 +63,9 @@ class AccessibilityBridge DID_GAIN_ACCESSIBILITY_FOCUS(1 << 15), DID_LOSE_ACCESSIBILITY_FOCUS(1 << 16), CUSTOM_ACTION(1 << 17), - DISMISS(1 << 18); + DISMISS(1 << 18), + MOVE_CURSOR_FORWARD_BY_WORD(1 << 19), + MOVE_CURSOR_BACKWARD_BY_WORD(1 << 20); Action(int value) { this.value = value; @@ -172,6 +174,14 @@ class AccessibilityBridge result.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); granularities |= AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER; } + if (object.hasAction(Action.MOVE_CURSOR_FORWARD_BY_WORD)) { + result.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); + granularities |= AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD; + } + if (object.hasAction(Action.MOVE_CURSOR_BACKWARD_BY_WORD)) { + result.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); + granularities |= AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD; + } result.setMovementGranularities(granularities); } if (object.hasAction(Action.SET_SELECTION)) { @@ -479,8 +489,20 @@ class AccessibilityBridge Action.MOVE_CURSOR_BACKWARD_BY_CHARACTER, extendSelection); return true; } + break; } - // TODO(goderbauer): support other granularities. + case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: + if (forward && object.hasAction(Action.MOVE_CURSOR_FORWARD_BY_WORD)) { + mOwner.dispatchSemanticsAction(virtualViewId, + Action.MOVE_CURSOR_FORWARD_BY_WORD, extendSelection); + return true; + } + if (!forward && object.hasAction(Action.MOVE_CURSOR_BACKWARD_BY_WORD)) { + mOwner.dispatchSemanticsAction(virtualViewId, + Action.MOVE_CURSOR_BACKWARD_BY_WORD, extendSelection); + return true; + } + break; } return false; } -- GitLab