diff --git a/packages/flutter/lib/src/widgets/selectable_region.dart b/packages/flutter/lib/src/widgets/selectable_region.dart index d84a72cceab8..06f17c0216a7 100644 --- a/packages/flutter/lib/src/widgets/selectable_region.dart +++ b/packages/flutter/lib/src/widgets/selectable_region.dart @@ -780,6 +780,7 @@ class _SelectableRegionState extends State with TextSelectionD child: Actions( actions: _actions, child: Focus( + includeSemantics: false, focusNode: widget.focusNode, child: SelectionContainer( registrar: this, diff --git a/packages/flutter/test/widgets/selectable_region_test.dart b/packages/flutter/test/widgets/selectable_region_test.dart index 4c083ca295f3..0450525df7a1 100644 --- a/packages/flutter/test/widgets/selectable_region_test.dart +++ b/packages/flutter/test/widgets/selectable_region_test.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import '../widgets/clipboard_utils.dart'; +import 'semantics_tester.dart'; Offset textOffsetToPosition(RenderParagraph paragraph, int offset) { const Rect caret = Rect.fromLTWH(0.0, 0.0, 2.0, 20.0); @@ -34,7 +35,7 @@ void main() { TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); }); - group('SelectionArea', () { + group('SelectableRegion', () { testWidgets('mouse selection sends correct events', (WidgetTester tester) async { final UniqueKey spy = UniqueKey(); await tester.pumpWidget( @@ -94,6 +95,81 @@ void main() { ); }); + testWidgets('does not merge semantics node of the children', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + await tester.pumpWidget( + MaterialApp( + home: SelectableRegion( + focusNode: FocusNode(), + selectionControls: materialTextSelectionControls, + child: Scaffold( + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('Line one'), + const Text('Line two'), + ElevatedButton( + onPressed: () {}, + child: const Text('Button'), + ) + ], + ), + ), + ), + ), + ), + ); + + expect( + semantics, + hasSemantics( + TestSemantics.root( + children: [ + TestSemantics( + textDirection: TextDirection.ltr, + children: [ + TestSemantics( + children: [ + TestSemantics( + flags: [SemanticsFlag.scopesRoute], + children: [ + TestSemantics( + label: 'Line one', + textDirection: TextDirection.ltr, + ), + TestSemantics( + label: 'Line two', + textDirection: TextDirection.ltr, + ), + TestSemantics( + flags: [ + SemanticsFlag.isButton, + SemanticsFlag.hasEnabledState, + SemanticsFlag.isEnabled, + SemanticsFlag.isFocusable + ], + actions: [SemanticsAction.tap], + label: 'Button', + textDirection: TextDirection.ltr, + ), + ], + ), + ], + ), + ], + ), + ], + ), + ignoreRect: true, + ignoreTransform: true, + ignoreId: true, + ), + ); + + semantics.dispose(); + }); + testWidgets('mouse selection always cancels previous selection', (WidgetTester tester) async { final UniqueKey spy = UniqueKey(); await tester.pumpWidget(