diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart index 1258e285f3..778aff0e26 100644 --- a/packages/flutter/lib/src/material/tooltip.dart +++ b/packages/flutter/lib/src/material/tooltip.dart @@ -46,6 +46,7 @@ class _ExclusiveMouseRegion extends MouseRegion { const _ExclusiveMouseRegion({ super.onEnter, super.onExit, + super.cursor, super.child, }); @@ -54,6 +55,7 @@ class _ExclusiveMouseRegion extends MouseRegion { return _RenderExclusiveMouseRegion( onEnter: onEnter, onExit: onExit, + cursor: cursor, ); } } @@ -62,6 +64,7 @@ class _RenderExclusiveMouseRegion extends RenderMouseRegion { _RenderExclusiveMouseRegion({ super.onEnter, super.onExit, + super.cursor, }); static bool isOutermostMouseRegion = true; @@ -195,6 +198,7 @@ class Tooltip extends StatefulWidget { this.triggerMode, this.enableFeedback, this.onTriggered, + this.mouseCursor, this.child, }) : assert((message == null) != (richMessage == null), 'Either `message` or `richMessage` must be specified'), assert( @@ -363,6 +367,12 @@ class Tooltip extends StatefulWidget { /// or after a long press when [triggerMode] is [TooltipTriggerMode.longPress]. final TooltipTriggeredCallback? onTriggered; + /// The cursor for a mouse pointer when it enters or is hovering over the + /// widget. + /// + /// If this property is null, [MouseCursor.defer] will be used. + final MouseCursor? mouseCursor; + static final List _openedTooltips = []; /// Dismiss all of the tooltips that are currently shown on the screen, @@ -839,6 +849,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { result = _ExclusiveMouseRegion( onEnter: _handleMouseEnter, onExit: _handleMouseExit, + cursor: widget.mouseCursor ?? MouseCursor.defer, child: Listener( onPointerDown: _handlePointerDown, behavior: HitTestBehavior.opaque, diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart index e9046f7f6a..70f6e9a5b4 100644 --- a/packages/flutter/test/material/tooltip_test.dart +++ b/packages/flutter/test/material/tooltip_test.dart @@ -3091,6 +3091,38 @@ void main() { expect(selectedText, isNot(contains('A'))); }); + + testWidgets('Tooltip mouse cursor behavior', (WidgetTester tester) async { + const SystemMouseCursor customCursor = SystemMouseCursors.grab; + + await tester.pumpWidget( + const MaterialApp( + home: Center( + child: Tooltip( + message: tooltipText, + mouseCursor: customCursor, + child: SizedBox.square(dimension: 50), + ), + ), + ), + ); + + final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1); + await gesture.addPointer(location: const Offset(10, 10)); + await tester.pump(); + expect( + RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), + SystemMouseCursors.basic, + ); + + final Offset chip = tester.getCenter(find.byType(Tooltip)); + await gesture.moveTo(chip); + await tester.pump(); + expect( + RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), + customCursor, + ); + }); } Future setWidgetForTooltipMode(