Update clipboard status on cut (#92167)
Cut now explicitly updates the clipboard status.
diff --git a/packages/flutter/lib/src/cupertino/desktop_text_selection.dart b/packages/flutter/lib/src/cupertino/desktop_text_selection.dart
index c0c76c1..6b1f89b 100644
--- a/packages/flutter/lib/src/cupertino/desktop_text_selection.dart
+++ b/packages/flutter/lib/src/cupertino/desktop_text_selection.dart
@@ -55,7 +55,7 @@
clipboardStatus: clipboardStatus,
endpoints: endpoints,
globalEditableRegion: globalEditableRegion,
- handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
+ handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
diff --git a/packages/flutter/lib/src/cupertino/text_selection.dart b/packages/flutter/lib/src/cupertino/text_selection.dart
index 45e88a8..6b3ddde 100644
--- a/packages/flutter/lib/src/cupertino/text_selection.dart
+++ b/packages/flutter/lib/src/cupertino/text_selection.dart
@@ -236,7 +236,7 @@
clipboardStatus: clipboardStatus,
endpoints: endpoints,
globalEditableRegion: globalEditableRegion,
- handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
+ handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
diff --git a/packages/flutter/lib/src/material/desktop_text_selection.dart b/packages/flutter/lib/src/material/desktop_text_selection.dart
index dde0640..e24f4db 100644
--- a/packages/flutter/lib/src/material/desktop_text_selection.dart
+++ b/packages/flutter/lib/src/material/desktop_text_selection.dart
@@ -41,7 +41,7 @@
clipboardStatus: clipboardStatus,
endpoints: endpoints,
globalEditableRegion: globalEditableRegion,
- handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
+ handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
diff --git a/packages/flutter/lib/src/material/text_selection.dart b/packages/flutter/lib/src/material/text_selection.dart
index f1def2a..ca1d892 100644
--- a/packages/flutter/lib/src/material/text_selection.dart
+++ b/packages/flutter/lib/src/material/text_selection.dart
@@ -45,7 +45,7 @@
endpoints: endpoints,
delegate: delegate,
clipboardStatus: clipboardStatus,
- handleCut: canCut(delegate) ? () => handleCut(delegate) : null,
+ handleCut: canCut(delegate) ? () => handleCut(delegate, clipboardStatus) : null,
handleCopy: canCopy(delegate) ? () => handleCopy(delegate, clipboardStatus) : null,
handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null,
handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null,
diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart
index 2995b5b..a0cb911 100644
--- a/packages/flutter/lib/src/widgets/editable_text.dart
+++ b/packages/flutter/lib/src/widgets/editable_text.dart
@@ -2808,7 +2808,7 @@
VoidCallback? _semanticsOnCut(TextSelectionControls? controls) {
return widget.selectionEnabled && cutEnabled && _hasFocus && controls?.canCut(this) == true
- ? () => controls!.handleCut(this)
+ ? () => controls!.handleCut(this, _clipboardStatus)
: null;
}
diff --git a/packages/flutter/lib/src/widgets/text_selection.dart b/packages/flutter/lib/src/widgets/text_selection.dart
index 971d9c9..9feb7fe 100644
--- a/packages/flutter/lib/src/widgets/text_selection.dart
+++ b/packages/flutter/lib/src/widgets/text_selection.dart
@@ -204,8 +204,9 @@
///
/// This is called by subclasses when their cut affordance is activated by
/// the user.
- void handleCut(TextSelectionDelegate delegate) {
+ void handleCut(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
delegate.cutSelection(SelectionChangedCause.toolbar);
+ clipboardStatus?.update();
}
/// Call [TextSelectionDelegate.copySelection] to copy current selection.
diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart
index 7f28c9d..3ccb3c2 100644
--- a/packages/flutter/test/widgets/editable_text_test.dart
+++ b/packages/flutter/test/widgets/editable_text_test.dart
@@ -8724,7 +8724,7 @@
}
@override
- void handleCut(TextSelectionDelegate delegate) {
+ void handleCut(TextSelectionDelegate delegate, ClipboardStatusNotifier? clipboardStatus) {
cutCount += 1;
}
diff --git a/packages/flutter/test/widgets/text_selection_test.dart b/packages/flutter/test/widgets/text_selection_test.dart
index ba3b28f..04f7327 100644
--- a/packages/flutter/test/widgets/text_selection_test.dart
+++ b/packages/flutter/test/widgets/text_selection_test.dart
@@ -759,6 +759,28 @@
});
});
});
+
+ group('TextSelectionControls', () {
+ test('ClipboardStatusNotifier is updated on handleCut', () async {
+ final FakeClipboardStatusNotifier clipboardStatus = FakeClipboardStatusNotifier();
+ final FakeTextSelectionDelegate delegate = FakeTextSelectionDelegate();
+ final CustomTextSelectionControls textSelectionControls = CustomTextSelectionControls();
+
+ expect(clipboardStatus.updateCalled, false);
+ textSelectionControls.handleCut(delegate, clipboardStatus);
+ expect(clipboardStatus.updateCalled, true);
+ });
+
+ test('ClipboardStatusNotifier is updated on handleCopy', () async {
+ final FakeClipboardStatusNotifier clipboardStatus = FakeClipboardStatusNotifier();
+ final FakeTextSelectionDelegate delegate = FakeTextSelectionDelegate();
+ final CustomTextSelectionControls textSelectionControls = CustomTextSelectionControls();
+
+ expect(clipboardStatus.updateCalled, false);
+ textSelectionControls.handleCopy(delegate, clipboardStatus);
+ expect(clipboardStatus.updateCalled, true);
+ });
+ });
}
class FakeTextSelectionGestureDetectorBuilderDelegate implements TextSelectionGestureDetectorBuilderDelegate {
@@ -872,3 +894,55 @@
selectWordCalled = true;
}
}
+
+class CustomTextSelectionControls extends TextSelectionControls {
+ @override
+ Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Widget buildToolbar(
+ BuildContext context,
+ Rect globalEditableRegion,
+ double textLineHeight,
+ Offset position,
+ List<TextSelectionPoint> endpoints,
+ TextSelectionDelegate delegate,
+ ClipboardStatusNotifier clipboardStatus,
+ Offset? lastSecondaryTapDownPosition,
+ ) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) {
+ throw UnimplementedError();
+ }
+
+ @override
+ Size getHandleSize(double textLineHeight) {
+ throw UnimplementedError();
+ }
+}
+
+class FakeClipboardStatusNotifier extends ClipboardStatusNotifier {
+ FakeClipboardStatusNotifier() : super(value: ClipboardStatus.unknown);
+
+ @override
+ bool get disposed => false;
+
+ bool updateCalled = false;
+ @override
+ Future<void> update() async {
+ updateCalled = true;
+ }
+}
+
+class FakeTextSelectionDelegate extends Fake implements TextSelectionDelegate {
+ @override
+ void cutSelection(SelectionChangedCause cause) { }
+
+ @override
+ void copySelection(SelectionChangedCause cause) { }
+}