Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions lib/ui/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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
Expand All @@ -187,6 +205,8 @@ class SemanticsAction {
_kDidLoseAccessibilityFocusIndex: didLoseAccessibilityFocus,
_kCustomAction: customAction,
_kDismissIndex: dismiss,
_kMoveCursorForwardByWordIndex: moveCursorForwardByWord,
_kMoveCursorBackwardByWordIndex: moveCursorBackwardByWord,
};

@override
Expand Down Expand Up @@ -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;
}
Expand Down
26 changes: 24 additions & 2 deletions shell/platform/android/io/flutter/view/AccessibilityBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ enum Action {
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;
Expand Down Expand Up @@ -172,6 +174,14 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
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)) {
Expand Down Expand Up @@ -479,8 +489,20 @@ boolean performCursorMoveAction(
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;
}
Expand Down