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 2 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
24 changes: 22 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 @@ -480,7 +490,17 @@ boolean performCursorMoveAction(
return true;
}
}
// TODO(goderbauer): support other granularities.
case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the case statements need to end with break to avoid fall-through?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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;
}
}
return false;
}
Expand Down