Unverified Commit f91ed2a3 authored by chunhtai's avatar chunhtai Committed by GitHub

Adds set text semantics action to render editable (#77024)

* Adds set text semantics action to render editable

* addressing comments

* re-enable test

* fix test

* fix more test

* fix bad merge

* addressing comment

* update dynamic to Object?
parent 406f6bcc
...@@ -987,6 +987,9 @@ class RenderCustomPaint extends RenderProxyBox { ...@@ -987,6 +987,9 @@ class RenderCustomPaint extends RenderProxyBox {
if (properties.onSetSelection != null) { if (properties.onSetSelection != null) {
config.onSetSelection = properties.onSetSelection; config.onSetSelection = properties.onSetSelection;
} }
if (properties.onSetText != null) {
config.onSetText = properties.onSetText;
}
if (properties.onDidGainAccessibilityFocus != null) { if (properties.onDidGainAccessibilityFocus != null) {
config.onDidGainAccessibilityFocus = properties.onDidGainAccessibilityFocus; config.onDidGainAccessibilityFocus = properties.onDidGainAccessibilityFocus;
} }
......
...@@ -1492,6 +1492,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -1492,6 +1492,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
if (hasFocus && selectionEnabled) if (hasFocus && selectionEnabled)
config.onSetSelection = _handleSetSelection; config.onSetSelection = _handleSetSelection;
if (hasFocus && !readOnly)
config.onSetText = _handleSetText;
if (selectionEnabled && selection?.isValid == true) { if (selectionEnabled && selection?.isValid == true) {
config.textSelection = selection; config.textSelection = selection;
if (_textPainter.getOffsetBefore(selection!.extentOffset) != null) { if (_textPainter.getOffsetBefore(selection!.extentOffset) != null) {
...@@ -1507,6 +1510,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -1507,6 +1510,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
} }
} }
void _handleSetText(String text) {
textSelectionDelegate.userUpdateTextEditingValue(
TextEditingValue(
text: text,
selection: TextSelection.collapsed(offset: text.length),
),
SelectionChangedCause.keyboard,
);
}
// TODO(ianh): in theory, [selection] could become null between when // TODO(ianh): in theory, [selection] could become null between when
// we last called describeSemanticsConfiguration and when the // we last called describeSemanticsConfiguration and when the
// callbacks are invoked, in which case the callbacks will crash... // callbacks are invoked, in which case the callbacks will crash...
......
...@@ -3750,6 +3750,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -3750,6 +3750,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
MoveCursorHandler? onMoveCursorForwardByWord, MoveCursorHandler? onMoveCursorForwardByWord,
MoveCursorHandler? onMoveCursorBackwardByWord, MoveCursorHandler? onMoveCursorBackwardByWord,
SetSelectionHandler? onSetSelection, SetSelectionHandler? onSetSelection,
SetTextHandler? onSetText,
VoidCallback? onDidGainAccessibilityFocus, VoidCallback? onDidGainAccessibilityFocus,
VoidCallback? onDidLoseAccessibilityFocus, VoidCallback? onDidLoseAccessibilityFocus,
Map<CustomSemanticsAction, VoidCallback>? customSemanticsActions, Map<CustomSemanticsAction, VoidCallback>? customSemanticsActions,
...@@ -3805,6 +3806,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -3805,6 +3806,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
_onMoveCursorForwardByWord = onMoveCursorForwardByWord, _onMoveCursorForwardByWord = onMoveCursorForwardByWord,
_onMoveCursorBackwardByWord = onMoveCursorBackwardByWord, _onMoveCursorBackwardByWord = onMoveCursorBackwardByWord,
_onSetSelection = onSetSelection, _onSetSelection = onSetSelection,
_onSetText = onSetText,
_onDidGainAccessibilityFocus = onDidGainAccessibilityFocus, _onDidGainAccessibilityFocus = onDidGainAccessibilityFocus,
_onDidLoseAccessibilityFocus = onDidLoseAccessibilityFocus, _onDidLoseAccessibilityFocus = onDidLoseAccessibilityFocus,
_customSemanticsActions = customSemanticsActions, _customSemanticsActions = customSemanticsActions,
...@@ -4540,6 +4542,24 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -4540,6 +4542,24 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
} }
/// The handler for [SemanticsAction.setText].
///
/// This handler is invoked when the user wants to replace the current text in
/// the text field with a new text.
///
/// Voice access users can trigger this handler by speaking "type <text>" to
/// their Android devices.
SetTextHandler? get onSetText => _onSetText;
SetTextHandler? _onSetText;
set onSetText(SetTextHandler? handler) {
if (_onSetText == handler)
return;
final bool hadValue = _onSetText != null;
_onSetText = handler;
if ((handler != null) != hadValue)
markNeedsSemanticsUpdate();
}
/// The handler for [SemanticsAction.didGainAccessibilityFocus]. /// The handler for [SemanticsAction.didGainAccessibilityFocus].
/// ///
/// This handler is invoked when the node annotated with this handler gains /// This handler is invoked when the node annotated with this handler gains
...@@ -4732,6 +4752,8 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -4732,6 +4752,8 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
config.onMoveCursorBackwardByWord = _performMoveCursorBackwardByWord; config.onMoveCursorBackwardByWord = _performMoveCursorBackwardByWord;
if (onSetSelection != null) if (onSetSelection != null)
config.onSetSelection = _performSetSelection; config.onSetSelection = _performSetSelection;
if (onSetText != null)
config.onSetText = _performSetText;
if (onDidGainAccessibilityFocus != null) if (onDidGainAccessibilityFocus != null)
config.onDidGainAccessibilityFocus = _performDidGainAccessibilityFocus; config.onDidGainAccessibilityFocus = _performDidGainAccessibilityFocus;
if (onDidLoseAccessibilityFocus != null) if (onDidLoseAccessibilityFocus != null)
...@@ -4825,6 +4847,11 @@ class RenderSemanticsAnnotations extends RenderProxyBox { ...@@ -4825,6 +4847,11 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
onSetSelection!(selection); onSetSelection!(selection);
} }
void _performSetText(String text) {
if (onSetText != null)
onSetText!(text);
}
void _performDidGainAccessibilityFocus() { void _performDidGainAccessibilityFocus() {
if (onDidGainAccessibilityFocus != null) if (onDidGainAccessibilityFocus != null)
onDidGainAccessibilityFocus!(); onDidGainAccessibilityFocus!();
......
...@@ -36,7 +36,11 @@ typedef MoveCursorHandler = void Function(bool extendSelection); ...@@ -36,7 +36,11 @@ typedef MoveCursorHandler = void Function(bool extendSelection);
/// text selection (or re-position the cursor) to `selection`. /// text selection (or re-position the cursor) to `selection`.
typedef SetSelectionHandler = void Function(TextSelection selection); typedef SetSelectionHandler = void Function(TextSelection selection);
typedef _SemanticsActionHandler = void Function(dynamic args); /// Signature for the [SemanticsAction.setText] handlers to replace the
/// current text with the input `text`.
typedef SetTextHandler = void Function(String text);
typedef _SemanticsActionHandler = void Function(Object? args);
/// A tag for a [SemanticsNode]. /// A tag for a [SemanticsNode].
/// ///
...@@ -626,6 +630,7 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -626,6 +630,7 @@ class SemanticsProperties extends DiagnosticableTree {
this.onMoveCursorForwardByWord, this.onMoveCursorForwardByWord,
this.onMoveCursorBackwardByWord, this.onMoveCursorBackwardByWord,
this.onSetSelection, this.onSetSelection,
this.onSetText,
this.onDidGainAccessibilityFocus, this.onDidGainAccessibilityFocus,
this.onDidLoseAccessibilityFocus, this.onDidLoseAccessibilityFocus,
this.onDismiss, this.onDismiss,
...@@ -1097,6 +1102,15 @@ class SemanticsProperties extends DiagnosticableTree { ...@@ -1097,6 +1102,15 @@ class SemanticsProperties extends DiagnosticableTree {
/// beginning/end" or "Select all" from the local context menu. /// beginning/end" or "Select all" from the local context menu.
final SetSelectionHandler? onSetSelection; final SetSelectionHandler? onSetSelection;
/// The handler for [SemanticsAction.setText].
///
/// This handler is invoked when the user wants to replace the current text in
/// the text field with a new text.
///
/// Voice access users can trigger this handler by speaking "type <text>" to
/// their Android devices.
final SetTextHandler? onSetText;
/// The handler for [SemanticsAction.didGainAccessibilityFocus]. /// The handler for [SemanticsAction.didGainAccessibilityFocus].
/// ///
/// This handler is invoked when the node annotated with this handler gains /// This handler is invoked when the node annotated with this handler gains
...@@ -2684,7 +2698,7 @@ class SemanticsOwner extends ChangeNotifier { ...@@ -2684,7 +2698,7 @@ class SemanticsOwner extends ChangeNotifier {
/// ///
/// If the given `action` requires arguments they need to be passed in via /// If the given `action` requires arguments they need to be passed in via
/// the `args` parameter. /// the `args` parameter.
void performAction(int id, SemanticsAction action, [ dynamic args ]) { void performAction(int id, SemanticsAction action, [ Object? args ]) {
assert(action != null); assert(action != null);
final _SemanticsActionHandler? handler = _getSemanticsActionHandlerForId(id, action); final _SemanticsActionHandler? handler = _getSemanticsActionHandlerForId(id, action);
if (handler != null) { if (handler != null) {
...@@ -2734,7 +2748,7 @@ class SemanticsOwner extends ChangeNotifier { ...@@ -2734,7 +2748,7 @@ class SemanticsOwner extends ChangeNotifier {
/// ///
/// If the given `action` requires arguments they need to be passed in via /// If the given `action` requires arguments they need to be passed in via
/// the `args` parameter. /// the `args` parameter.
void performActionAt(Offset position, SemanticsAction action, [ dynamic args ]) { void performActionAt(Offset position, SemanticsAction action, [ Object? args ]) {
assert(action != null); assert(action != null);
final SemanticsNode? node = rootSemanticsNode; final SemanticsNode? node = rootSemanticsNode;
if (node == null) if (node == null)
...@@ -2848,7 +2862,7 @@ class SemanticsConfiguration { ...@@ -2848,7 +2862,7 @@ class SemanticsConfiguration {
/// `action`. /// `action`.
void _addArgumentlessAction(SemanticsAction action, VoidCallback handler) { void _addArgumentlessAction(SemanticsAction action, VoidCallback handler) {
assert(handler != null); assert(handler != null);
_addAction(action, (dynamic args) { _addAction(action, (Object? args) {
assert(args == null); assert(args == null);
handler(); handler();
}); });
...@@ -3085,9 +3099,8 @@ class SemanticsConfiguration { ...@@ -3085,9 +3099,8 @@ class SemanticsConfiguration {
MoveCursorHandler? _onMoveCursorForwardByCharacter; MoveCursorHandler? _onMoveCursorForwardByCharacter;
set onMoveCursorForwardByCharacter(MoveCursorHandler? value) { set onMoveCursorForwardByCharacter(MoveCursorHandler? value) {
assert(value != null); assert(value != null);
_addAction(SemanticsAction.moveCursorForwardByCharacter, (dynamic args) { _addAction(SemanticsAction.moveCursorForwardByCharacter, (Object? args) {
final bool extentSelection = args as bool; final bool extentSelection = args! as bool;
assert(extentSelection != null);
value!(extentSelection); value!(extentSelection);
}); });
_onMoveCursorForwardByCharacter = value; _onMoveCursorForwardByCharacter = value;
...@@ -3104,9 +3117,8 @@ class SemanticsConfiguration { ...@@ -3104,9 +3117,8 @@ class SemanticsConfiguration {
MoveCursorHandler? _onMoveCursorBackwardByCharacter; MoveCursorHandler? _onMoveCursorBackwardByCharacter;
set onMoveCursorBackwardByCharacter(MoveCursorHandler? value) { set onMoveCursorBackwardByCharacter(MoveCursorHandler? value) {
assert(value != null); assert(value != null);
_addAction(SemanticsAction.moveCursorBackwardByCharacter, (dynamic args) { _addAction(SemanticsAction.moveCursorBackwardByCharacter, (Object? args) {
final bool extentSelection = args as bool; final bool extentSelection = args! as bool;
assert(extentSelection != null);
value!(extentSelection); value!(extentSelection);
}); });
_onMoveCursorBackwardByCharacter = value; _onMoveCursorBackwardByCharacter = value;
...@@ -3123,9 +3135,8 @@ class SemanticsConfiguration { ...@@ -3123,9 +3135,8 @@ class SemanticsConfiguration {
MoveCursorHandler? _onMoveCursorForwardByWord; MoveCursorHandler? _onMoveCursorForwardByWord;
set onMoveCursorForwardByWord(MoveCursorHandler? value) { set onMoveCursorForwardByWord(MoveCursorHandler? value) {
assert(value != null); assert(value != null);
_addAction(SemanticsAction.moveCursorForwardByWord, (dynamic args) { _addAction(SemanticsAction.moveCursorForwardByWord, (Object? args) {
final bool extentSelection = args as bool; final bool extentSelection = args! as bool;
assert(extentSelection != null);
value!(extentSelection); value!(extentSelection);
}); });
_onMoveCursorForwardByCharacter = value; _onMoveCursorForwardByCharacter = value;
...@@ -3142,9 +3153,8 @@ class SemanticsConfiguration { ...@@ -3142,9 +3153,8 @@ class SemanticsConfiguration {
MoveCursorHandler? _onMoveCursorBackwardByWord; MoveCursorHandler? _onMoveCursorBackwardByWord;
set onMoveCursorBackwardByWord(MoveCursorHandler? value) { set onMoveCursorBackwardByWord(MoveCursorHandler? value) {
assert(value != null); assert(value != null);
_addAction(SemanticsAction.moveCursorBackwardByWord, (dynamic args) { _addAction(SemanticsAction.moveCursorBackwardByWord, (Object? args) {
final bool extentSelection = args as bool; final bool extentSelection = args! as bool;
assert(extentSelection != null);
value!(extentSelection); value!(extentSelection);
}); });
_onMoveCursorBackwardByCharacter = value; _onMoveCursorBackwardByCharacter = value;
...@@ -3161,9 +3171,9 @@ class SemanticsConfiguration { ...@@ -3161,9 +3171,9 @@ class SemanticsConfiguration {
SetSelectionHandler? _onSetSelection; SetSelectionHandler? _onSetSelection;
set onSetSelection(SetSelectionHandler? value) { set onSetSelection(SetSelectionHandler? value) {
assert(value != null); assert(value != null);
_addAction(SemanticsAction.setSelection, (dynamic args) { _addAction(SemanticsAction.setSelection, (Object? args) {
assert(args != null && args is Map); assert(args != null && args is Map);
final Map<String, int> selection = (args as Map<dynamic, dynamic>).cast<String, int>(); final Map<String, int> selection = (args! as Map<dynamic, dynamic>).cast<String, int>();
assert(selection != null && selection['base'] != null && selection['extent'] != null); assert(selection != null && selection['base'] != null && selection['extent'] != null);
value!(TextSelection( value!(TextSelection(
baseOffset: selection['base']!, baseOffset: selection['base']!,
...@@ -3173,6 +3183,25 @@ class SemanticsConfiguration { ...@@ -3173,6 +3183,25 @@ class SemanticsConfiguration {
_onSetSelection = value; _onSetSelection = value;
} }
/// The handler for [SemanticsAction.setText].
///
/// This handler is invoked when the user wants to replace the current text in
/// the text field with a new text.
///
/// Voice access users can trigger this handler by speaking "type <text>" to
/// their Android devices.
SetTextHandler? get onSetText => _onSetText;
SetTextHandler? _onSetText;
set onSetText(SetTextHandler? value) {
assert(value != null);
_addAction(SemanticsAction.setText, (Object? args) {
assert(args != null && args is String);
final String text = args! as String;
value!(text);
});
_onSetText = value;
}
/// The handler for [SemanticsAction.didGainAccessibilityFocus]. /// The handler for [SemanticsAction.didGainAccessibilityFocus].
/// ///
/// This handler is invoked when the node annotated with this handler gains /// This handler is invoked when the node annotated with this handler gains
...@@ -3357,8 +3386,8 @@ class SemanticsConfiguration { ...@@ -3357,8 +3386,8 @@ class SemanticsConfiguration {
_actions[SemanticsAction.customAction] = _onCustomSemanticsAction; _actions[SemanticsAction.customAction] = _onCustomSemanticsAction;
} }
void _onCustomSemanticsAction(dynamic args) { void _onCustomSemanticsAction(Object? args) {
final CustomSemanticsAction? action = CustomSemanticsAction.getAction(args as int); final CustomSemanticsAction? action = CustomSemanticsAction.getAction(args! as int);
if (action == null) if (action == null)
return; return;
final VoidCallback? callback = _customSemanticsActions[action]; final VoidCallback? callback = _customSemanticsActions[action];
......
...@@ -6968,6 +6968,7 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -6968,6 +6968,7 @@ class Semantics extends SingleChildRenderObjectWidget {
MoveCursorHandler? onMoveCursorForwardByCharacter, MoveCursorHandler? onMoveCursorForwardByCharacter,
MoveCursorHandler? onMoveCursorBackwardByCharacter, MoveCursorHandler? onMoveCursorBackwardByCharacter,
SetSelectionHandler? onSetSelection, SetSelectionHandler? onSetSelection,
SetTextHandler? onSetText,
VoidCallback? onDidGainAccessibilityFocus, VoidCallback? onDidGainAccessibilityFocus,
VoidCallback? onDidLoseAccessibilityFocus, VoidCallback? onDidLoseAccessibilityFocus,
Map<CustomSemanticsAction, VoidCallback>? customSemanticsActions, Map<CustomSemanticsAction, VoidCallback>? customSemanticsActions,
...@@ -7025,6 +7026,7 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -7025,6 +7026,7 @@ class Semantics extends SingleChildRenderObjectWidget {
onDidLoseAccessibilityFocus: onDidLoseAccessibilityFocus, onDidLoseAccessibilityFocus: onDidLoseAccessibilityFocus,
onDismiss: onDismiss, onDismiss: onDismiss,
onSetSelection: onSetSelection, onSetSelection: onSetSelection,
onSetText: onSetText,
customSemanticsActions: customSemanticsActions, customSemanticsActions: customSemanticsActions,
hintOverrides: onTapHint != null || onLongPressHint != null ? hintOverrides: onTapHint != null || onLongPressHint != null ?
SemanticsHintOverrides( SemanticsHintOverrides(
...@@ -7142,6 +7144,7 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -7142,6 +7144,7 @@ class Semantics extends SingleChildRenderObjectWidget {
onMoveCursorForwardByWord: properties.onMoveCursorForwardByWord, onMoveCursorForwardByWord: properties.onMoveCursorForwardByWord,
onMoveCursorBackwardByWord: properties.onMoveCursorBackwardByWord, onMoveCursorBackwardByWord: properties.onMoveCursorBackwardByWord,
onSetSelection: properties.onSetSelection, onSetSelection: properties.onSetSelection,
onSetText: properties.onSetText,
onDidGainAccessibilityFocus: properties.onDidGainAccessibilityFocus, onDidGainAccessibilityFocus: properties.onDidGainAccessibilityFocus,
onDidLoseAccessibilityFocus: properties.onDidLoseAccessibilityFocus, onDidLoseAccessibilityFocus: properties.onDidLoseAccessibilityFocus,
customSemanticsActions: properties.customSemanticsActions, customSemanticsActions: properties.customSemanticsActions,
...@@ -7214,6 +7217,7 @@ class Semantics extends SingleChildRenderObjectWidget { ...@@ -7214,6 +7217,7 @@ class Semantics extends SingleChildRenderObjectWidget {
..onMoveCursorForwardByWord = properties.onMoveCursorForwardByWord ..onMoveCursorForwardByWord = properties.onMoveCursorForwardByWord
..onMoveCursorBackwardByWord = properties.onMoveCursorBackwardByWord ..onMoveCursorBackwardByWord = properties.onMoveCursorBackwardByWord
..onSetSelection = properties.onSetSelection ..onSetSelection = properties.onSetSelection
..onSetText = properties.onSetText
..onDidGainAccessibilityFocus = properties.onDidGainAccessibilityFocus ..onDidGainAccessibilityFocus = properties.onDidGainAccessibilityFocus
..onDidLoseAccessibilityFocus = properties.onDidLoseAccessibilityFocus ..onDidLoseAccessibilityFocus = properties.onDidLoseAccessibilityFocus
..customSemanticsActions = properties.customSemanticsActions; ..customSemanticsActions = properties.customSemanticsActions;
......
...@@ -254,6 +254,7 @@ void main() { ...@@ -254,6 +254,7 @@ void main() {
isFocused: true, isFocused: true,
value: '01/15/2016', value: '01/15/2016',
hasTapAction: true, hasTapAction: true,
hasSetTextAction: true,
hasSetSelectionAction: true, hasSetSelectionAction: true,
hasCopyAction: true, hasCopyAction: true,
hasCutAction: true, hasCutAction: true,
......
...@@ -628,6 +628,7 @@ void main() { ...@@ -628,6 +628,7 @@ void main() {
actions: <SemanticsAction>[ actions: <SemanticsAction>[
SemanticsAction.tap, SemanticsAction.tap,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
label: 'Search', label: 'Search',
......
...@@ -1198,7 +1198,7 @@ void main() { ...@@ -1198,7 +1198,7 @@ void main() {
flags: <SemanticsFlag>[SemanticsFlag.isTextField, SemanticsFlag.isFocused], flags: <SemanticsFlag>[SemanticsFlag.isTextField, SemanticsFlag.isFocused],
actions: <SemanticsAction>[SemanticsAction.tap, actions: <SemanticsAction>[SemanticsAction.tap,
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.setSelection, SemanticsAction.paste, SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.setSelection, SemanticsAction.paste,
SemanticsAction.moveCursorBackwardByWord], SemanticsAction.setText, SemanticsAction.moveCursorBackwardByWord],
value: 'abcdefghi', value: 'abcdefghi',
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
textSelection: const TextSelection.collapsed(offset: 9), textSelection: const TextSelection.collapsed(offset: 9),
...@@ -5325,6 +5325,7 @@ void main() { ...@@ -5325,6 +5325,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
flags: <SemanticsFlag>[ flags: <SemanticsFlag>[
...@@ -5352,6 +5353,7 @@ void main() { ...@@ -5352,6 +5353,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
flags: <SemanticsFlag>[ flags: <SemanticsFlag>[
...@@ -5378,6 +5380,7 @@ void main() { ...@@ -5378,6 +5380,7 @@ void main() {
SemanticsAction.moveCursorForwardByCharacter, SemanticsAction.moveCursorForwardByCharacter,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
flags: <SemanticsFlag>[ flags: <SemanticsFlag>[
...@@ -5416,6 +5419,7 @@ void main() { ...@@ -5416,6 +5419,7 @@ void main() {
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
actions: <SemanticsAction>[ actions: <SemanticsAction>[
SemanticsAction.tap, SemanticsAction.tap,
SemanticsAction.setText,
// Absent the following because enableInteractiveSelection: false // Absent the following because enableInteractiveSelection: false
// SemanticsAction.moveCursorBackwardByCharacter, // SemanticsAction.moveCursorBackwardByCharacter,
// SemanticsAction.moveCursorBackwardByWord, // SemanticsAction.moveCursorBackwardByWord,
...@@ -5480,6 +5484,7 @@ void main() { ...@@ -5480,6 +5484,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
flags: <SemanticsFlag>[ flags: <SemanticsFlag>[
...@@ -5507,6 +5512,7 @@ void main() { ...@@ -5507,6 +5512,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
SemanticsAction.cut, SemanticsAction.cut,
SemanticsAction.copy, SemanticsAction.copy,
...@@ -5557,6 +5563,7 @@ void main() { ...@@ -5557,6 +5563,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
flags: <SemanticsFlag>[ flags: <SemanticsFlag>[
...@@ -5602,6 +5609,7 @@ void main() { ...@@ -5602,6 +5609,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
SemanticsAction.cut, SemanticsAction.cut,
SemanticsAction.copy, SemanticsAction.copy,
...@@ -5671,6 +5679,7 @@ void main() { ...@@ -5671,6 +5679,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
value: textInTextField, value: textInTextField,
...@@ -5743,6 +5752,7 @@ void main() { ...@@ -5743,6 +5752,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
// No paste option. // No paste option.
], ],
value: textInTextField, value: textInTextField,
...@@ -5939,6 +5949,7 @@ void main() { ...@@ -5939,6 +5949,7 @@ void main() {
actions: <SemanticsAction>[ actions: <SemanticsAction>[
SemanticsAction.tap, SemanticsAction.tap,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
flags: <SemanticsFlag>[ flags: <SemanticsFlag>[
......
...@@ -343,6 +343,7 @@ void _defineTests() { ...@@ -343,6 +343,7 @@ void _defineTests() {
onMoveCursorForwardByWord: (bool _) => performedActions.add(SemanticsAction.moveCursorForwardByWord), onMoveCursorForwardByWord: (bool _) => performedActions.add(SemanticsAction.moveCursorForwardByWord),
onMoveCursorBackwardByWord: (bool _) => performedActions.add(SemanticsAction.moveCursorBackwardByWord), onMoveCursorBackwardByWord: (bool _) => performedActions.add(SemanticsAction.moveCursorBackwardByWord),
onSetSelection: (TextSelection _) => performedActions.add(SemanticsAction.setSelection), onSetSelection: (TextSelection _) => performedActions.add(SemanticsAction.setSelection),
onSetText: (String text) => performedActions.add(SemanticsAction.setText),
onDidGainAccessibilityFocus: () => performedActions.add(SemanticsAction.didGainAccessibilityFocus), onDidGainAccessibilityFocus: () => performedActions.add(SemanticsAction.didGainAccessibilityFocus),
onDidLoseAccessibilityFocus: () => performedActions.add(SemanticsAction.didLoseAccessibilityFocus), onDidLoseAccessibilityFocus: () => performedActions.add(SemanticsAction.didLoseAccessibilityFocus),
), ),
...@@ -387,6 +388,9 @@ void _defineTests() { ...@@ -387,6 +388,9 @@ void _defineTests() {
'extent': 5, 'extent': 5,
}); });
break; break;
case SemanticsAction.setText:
semanticsOwner.performAction(expectedId, action, 'text');
break;
default: default:
semanticsOwner.performAction(expectedId, action); semanticsOwner.performAction(expectedId, action);
} }
...@@ -396,7 +400,7 @@ void _defineTests() { ...@@ -396,7 +400,7 @@ void _defineTests() {
} }
semantics.dispose(); semantics.dispose();
}, skip: true); // disable for soft transition https://github.com/flutter/flutter/issues/77271 });
testWidgets('Supports all flags', (WidgetTester tester) async { testWidgets('Supports all flags', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
......
...@@ -2159,6 +2159,7 @@ void main() { ...@@ -2159,6 +2159,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2178,6 +2179,7 @@ void main() { ...@@ -2178,6 +2179,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2194,6 +2196,7 @@ void main() { ...@@ -2194,6 +2196,7 @@ void main() {
SemanticsAction.moveCursorForwardByCharacter, SemanticsAction.moveCursorForwardByCharacter,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2253,6 +2256,7 @@ void main() { ...@@ -2253,6 +2256,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2279,6 +2283,7 @@ void main() { ...@@ -2279,6 +2283,7 @@ void main() {
SemanticsAction.moveCursorForwardByCharacter, SemanticsAction.moveCursorForwardByCharacter,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2345,6 +2350,7 @@ void main() { ...@@ -2345,6 +2350,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2372,6 +2378,7 @@ void main() { ...@@ -2372,6 +2378,7 @@ void main() {
SemanticsAction.moveCursorForwardByCharacter, SemanticsAction.moveCursorForwardByCharacter,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2446,6 +2453,7 @@ void main() { ...@@ -2446,6 +2453,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2472,6 +2480,7 @@ void main() { ...@@ -2472,6 +2480,7 @@ void main() {
SemanticsAction.moveCursorForwardByCharacter, SemanticsAction.moveCursorForwardByCharacter,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2546,6 +2555,7 @@ void main() { ...@@ -2546,6 +2555,7 @@ void main() {
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2573,6 +2583,7 @@ void main() { ...@@ -2573,6 +2583,7 @@ void main() {
SemanticsAction.moveCursorForwardByCharacter, SemanticsAction.moveCursorForwardByCharacter,
SemanticsAction.moveCursorForwardByWord, SemanticsAction.moveCursorForwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2737,6 +2748,7 @@ void main() { ...@@ -2737,6 +2748,7 @@ void main() {
actions: <SemanticsAction>[ actions: <SemanticsAction>[
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
], ],
value: expectedValue, value: expectedValue,
...@@ -2825,6 +2837,7 @@ void main() { ...@@ -2825,6 +2837,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
], ],
), ),
); );
...@@ -2839,6 +2852,7 @@ void main() { ...@@ -2839,6 +2852,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.copy, SemanticsAction.copy,
], ],
), ),
...@@ -2856,6 +2870,7 @@ void main() { ...@@ -2856,6 +2870,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.paste, SemanticsAction.paste,
], ],
), ),
...@@ -2872,6 +2887,7 @@ void main() { ...@@ -2872,6 +2887,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.cut, SemanticsAction.cut,
], ],
), ),
...@@ -2889,6 +2905,7 @@ void main() { ...@@ -2889,6 +2905,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.cut, SemanticsAction.cut,
SemanticsAction.copy, SemanticsAction.copy,
SemanticsAction.paste, SemanticsAction.paste,
...@@ -2935,6 +2952,7 @@ void main() { ...@@ -2935,6 +2952,7 @@ void main() {
SemanticsAction.moveCursorBackwardByCharacter, SemanticsAction.moveCursorBackwardByCharacter,
SemanticsAction.moveCursorBackwardByWord, SemanticsAction.moveCursorBackwardByWord,
SemanticsAction.setSelection, SemanticsAction.setSelection,
SemanticsAction.setText,
SemanticsAction.copy, SemanticsAction.copy,
SemanticsAction.cut, SemanticsAction.cut,
SemanticsAction.paste, SemanticsAction.paste,
...@@ -2970,6 +2988,73 @@ void main() { ...@@ -2970,6 +2988,73 @@ void main() {
}); });
}); });
testWidgets('can set text with a11y', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
home: EditableText(
backgroundCursorColor: Colors.grey,
controller: controller,
focusNode: focusNode,
style: textStyle,
cursorColor: cursorColor,
),
));
await tester.tap(find.byType(EditableText));
await tester.pump();
final SemanticsOwner owner = tester.binding.pipelineOwner.semanticsOwner!;
const int expectedNodeId = 4;
expect(
semantics,
hasSemantics(
TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
id: 1,
children: <TestSemantics>[
TestSemantics(
id: 2,
children: <TestSemantics>[
TestSemantics(
id: 3,
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
children: <TestSemantics>[
TestSemantics.rootChild(
id: expectedNodeId,
flags: <SemanticsFlag>[
SemanticsFlag.isTextField,
SemanticsFlag.isFocused,
],
actions: <SemanticsAction>[
SemanticsAction.setSelection,
SemanticsAction.setText,
],
value: '',
textSelection: TextSelection.collapsed(
offset: controller.text.length),
textDirection: TextDirection.ltr,
),
],
),
],
),
],
),
],
),
ignoreRect: true,
ignoreTransform: true,
),
);
expect(controller.text, '');
owner.performAction(expectedNodeId, SemanticsAction.setText, 'how are you');
expect(controller.text, 'how are you');
semantics.dispose();
});
testWidgets('allows customizing text style in subclasses', (WidgetTester tester) async { testWidgets('allows customizing text style in subclasses', (WidgetTester tester) async {
controller.text = 'Hello World'; controller.text = 'Hello World';
......
...@@ -451,6 +451,7 @@ void main() { ...@@ -451,6 +451,7 @@ void main() {
onMoveCursorForwardByCharacter: (bool _) => performedActions.add(SemanticsAction.moveCursorForwardByCharacter), onMoveCursorForwardByCharacter: (bool _) => performedActions.add(SemanticsAction.moveCursorForwardByCharacter),
onMoveCursorBackwardByCharacter: (bool _) => performedActions.add(SemanticsAction.moveCursorBackwardByCharacter), onMoveCursorBackwardByCharacter: (bool _) => performedActions.add(SemanticsAction.moveCursorBackwardByCharacter),
onSetSelection: (TextSelection _) => performedActions.add(SemanticsAction.setSelection), onSetSelection: (TextSelection _) => performedActions.add(SemanticsAction.setSelection),
onSetText: (String _) => performedActions.add(SemanticsAction.setText),
onDidGainAccessibilityFocus: () => performedActions.add(SemanticsAction.didGainAccessibilityFocus), onDidGainAccessibilityFocus: () => performedActions.add(SemanticsAction.didGainAccessibilityFocus),
onDidLoseAccessibilityFocus: () => performedActions.add(SemanticsAction.didLoseAccessibilityFocus), onDidLoseAccessibilityFocus: () => performedActions.add(SemanticsAction.didLoseAccessibilityFocus),
), ),
...@@ -489,6 +490,9 @@ void main() { ...@@ -489,6 +490,9 @@ void main() {
'extent': 5, 'extent': 5,
}); });
break; break;
case SemanticsAction.setText:
semanticsOwner.performAction(expectedId, action, 'text');
break;
default: default:
semanticsOwner.performAction(expectedId, action); semanticsOwner.performAction(expectedId, action);
} }
...@@ -498,7 +502,7 @@ void main() { ...@@ -498,7 +502,7 @@ void main() {
} }
semantics.dispose(); semantics.dispose();
}, skip: true); // disable for soft transition https://github.com/flutter/flutter/issues/77271 });
testWidgets('Semantics widget supports all flags', (WidgetTester tester) async { testWidgets('Semantics widget supports all flags', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
......
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