diff --git a/packages/mixin_markdown_widget/lib/src/render/markdown_document_view.dart b/packages/mixin_markdown_widget/lib/src/render/markdown_document_view.dart index 9bed377f..8c5fd23f 100644 --- a/packages/mixin_markdown_widget/lib/src/render/markdown_document_view.dart +++ b/packages/mixin_markdown_widget/lib/src/render/markdown_document_view.dart @@ -174,7 +174,11 @@ class _MarkdownDocumentViewState extends State { oldWidget.selectable != widget.selectable) { _cachedBlockRows.clear(); } - _syncSelectionParticipant(participantChanged: true); + // Only notify on document changes: the registrar's refresh rebuilds this + // widget, so an unconditional notification never lets frames settle. + _syncSelectionParticipant( + participantChanged: !identical(oldWidget.document, widget.document), + ); } @override diff --git a/packages/mixin_markdown_widget/test/markdown_context_menu_test.dart b/packages/mixin_markdown_widget/test/markdown_context_menu_test.dart index 63e27097..0a6e806c 100644 --- a/packages/mixin_markdown_widget/test/markdown_context_menu_test.dart +++ b/packages/mixin_markdown_widget/test/markdown_context_menu_test.dart @@ -33,21 +33,13 @@ Offset _characterCenter( return renderBox.localToGlobal(box.center); } -Future _rightClick( - WidgetTester tester, - Offset position, { - bool settle = true, -}) async { +Future _rightClick(WidgetTester tester, Offset position) async { await tester.tapAt( position, buttons: kSecondaryMouseButton, kind: PointerDeviceKind.mouse, ); - if (settle) { - await tester.pumpAndSettle(); - } else { - await tester.pump(); - } + await tester.pumpAndSettle(); } Future _doubleClick(WidgetTester tester, Offset position) async { @@ -166,12 +158,10 @@ void main() { ), ); - await tester.pump(); + await tester.pumpAndSettle(); await _rightClick( tester, _characterCenter(tester, containing: 'Hello', character: 'v'), - // MixinSelectionArea keeps scheduling frames, so it never settles. - settle: false, ); expect(selection.selectedPlainText, 'brave'); expect(_menu, findsOneWidget); diff --git a/packages/mixin_markdown_widget/test/mixin_markdown_widget_test.dart b/packages/mixin_markdown_widget/test/mixin_markdown_widget_test.dart index 4be46ea2..952b94ac 100644 --- a/packages/mixin_markdown_widget/test/mixin_markdown_widget_test.dart +++ b/packages/mixin_markdown_widget/test/mixin_markdown_widget_test.dart @@ -7878,6 +7878,36 @@ Tables support varying alignments, complex cell contents, and inline styles. expect(selectionRects, isNotEmpty); }); + testWidgets('MixinSelectionArea with MarkdownWidget settles', (tester) async { + final selectionController = MarkdownSelectionController(); + addTearDown(selectionController.dispose); + + Widget buildApp(String data) { + return MaterialApp( + home: Scaffold( + body: MixinSelectionArea( + controller: selectionController, + child: MarkdownWidget(data: data, useColumn: true), + ), + ), + ); + } + + await tester.pumpWidget(buildApp('Hello brave world')); + await tester.pumpAndSettle(); + + expect(tester.binding.hasScheduledFrame, isFalse); + selectionController.selectAll(); + expect(selectionController.selectedPlainText, 'Hello brave world'); + + await tester.pumpWidget(buildApp('Hello new world')); + await tester.pumpAndSettle(); + + expect(tester.binding.hasScheduledFrame, isFalse); + selectionController.selectAll(); + expect(selectionController.selectedPlainText, 'Hello new world'); + }); + testWidgets('MixinSelectionArea exposes public selectable widgets', (tester) async { final selectionController = MarkdownSelectionController();