diff --git a/packages/flutter/lib/src/widgets/selectable_region.dart b/packages/flutter/lib/src/widgets/selectable_region.dart index eb3d556616d79..dad2580caae6c 100644 --- a/packages/flutter/lib/src/widgets/selectable_region.dart +++ b/packages/flutter/lib/src/widgets/selectable_region.dart @@ -444,6 +444,10 @@ class SelectableRegionState extends State final _SelectableRegionSelectionStatusNotifier _selectionStatusNotifier = _SelectableRegionSelectionStatusNotifier._(); + /// Preserves the selection status scope and root selection container when the + /// desktop web context menu wrapper is added or removed. + final GlobalKey _selectionStatusScopeKey = GlobalKey(debugLabel: 'selectionStatusScopeKey'); + @protected @override void initState() { @@ -1949,6 +1953,7 @@ class SelectableRegionState extends State Widget build(BuildContext context) { assert(debugCheckHasOverlay(context)); Widget result = SelectableRegionSelectionStatusScope._( + key: _selectionStatusScopeKey, selectionStatusNotifier: _selectionStatusNotifier, child: SelectionContainer(registrar: this, delegate: _selectionDelegate, child: widget.child), ); @@ -3506,6 +3511,7 @@ final class _SelectableRegionSelectionStatusNotifier extends ChangeNotifier /// does not change. final class SelectableRegionSelectionStatusScope extends InheritedWidget { const SelectableRegionSelectionStatusScope._({ + super.key, required this.selectionStatusNotifier, required super.child, }); diff --git a/packages/flutter/test/widgets/selectable_region_test.dart b/packages/flutter/test/widgets/selectable_region_test.dart index be04530eeb7eb..91d7d78519cbc 100644 --- a/packages/flutter/test/widgets/selectable_region_test.dart +++ b/packages/flutter/test/widgets/selectable_region_test.dart @@ -6572,6 +6572,38 @@ void main() { skip: !kIsWeb, // [intended] This test verifies web behavior. ); + testWidgets( + 'web can rebuild SelectableRegion after disabling the browser context menu', + (WidgetTester tester) async { + debugDefaultTargetPlatformOverride = TargetPlatform.macOS; + try { + await BrowserContextMenu.enableContextMenu(); + + late StateSetter rebuild; + await tester.pumpWidget( + TestWidgetsApp( + home: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + rebuild = setState; + return _selectableRegion(child: const Text('How are you?')); + }, + ), + ), + ); + + await BrowserContextMenu.disableContextMenu(); + rebuild(() {}); + await tester.pump(); + + final Object? exception = tester.takeException(); + expect(exception, isNull, reason: exception?.toString()); + } finally { + debugDefaultTargetPlatformOverride = null; + } + }, + skip: !kIsWeb, // [intended] This test verifies web desktop behavior. + ); + testWidgets( 'uses contextMenuBuilder by default on Android and iOS web', (WidgetTester tester) async {