From 0bda633509e9874fa0ce4e884ddb38c0806a45d8 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 2 Jun 2020 12:27:11 -0700 Subject: [PATCH] InkWell uses MaterialStateMouseCursor and defaults to clickable (#58448) * Adds support for material state mouse cursor to InkWell and InkResponse * Set their default cursors to be MaterialStateMouseCursor.clickable. --- .../flutter/lib/src/material/ink_well.dart | 38 +++++++++++++------ .../flutter/test/material/ink_well_test.dart | 34 ++++++++++++++++- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 9a4f1c0e4c1..f2c8c5cc528 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -13,6 +13,7 @@ import 'debug.dart'; import 'feedback.dart'; import 'ink_highlight.dart'; import 'material.dart'; +import 'material_state.dart'; import 'theme.dart'; /// An ink feature that displays a [color] "splash" in response to a user @@ -296,7 +297,7 @@ class InkResponse extends StatelessWidget { this.onLongPress, this.onHighlightChanged, this.onHover, - this.mouseCursor = MouseCursor.defer, + this.mouseCursor, this.containedInkWell = false, this.highlightShape = BoxShape.circle, this.radius, @@ -313,8 +314,7 @@ class InkResponse extends StatelessWidget { this.canRequestFocus = true, this.onFocusChange, this.autofocus = false, - }) : assert(mouseCursor != null), - assert(containedInkWell != null), + }) : assert(containedInkWell != null), assert(highlightShape != null), assert(enableFeedback != null), assert(excludeFromSemantics != null), @@ -367,8 +367,17 @@ class InkResponse extends StatelessWidget { /// The cursor for a mouse pointer when it enters or is hovering over the /// widget. /// - /// The [cursor] defaults to [MouseCursor.defer], deferring the choice of - /// cursor to the next region behing it in hit-test order. + /// If [mouseCursor] is a [MaterialStateProperty], + /// [MaterialStateProperty.resolve] is used for the following [MaterialState]s: + /// + /// * [MaterialState.hovered]. + /// * [MaterialState.focused]. + /// * [MaterialState.disabled]. + /// + /// When [value] is null and [tristate] is true, [MaterialState.selected] is + /// included as a state. + /// + /// If this property is null, [MaterialStateMouseCursor.clickable] will be used. final MouseCursor mouseCursor; /// Whether this ink response should be clipped its bounds. @@ -601,7 +610,7 @@ class _InkResponseStateWidget extends StatefulWidget { this.onLongPress, this.onHighlightChanged, this.onHover, - this.mouseCursor = MouseCursor.defer, + this.mouseCursor, this.containedInkWell = false, this.highlightShape = BoxShape.circle, this.radius, @@ -626,8 +635,7 @@ class _InkResponseStateWidget extends StatefulWidget { assert(enableFeedback != null), assert(excludeFromSemantics != null), assert(autofocus != null), - assert(canRequestFocus != null), - assert(mouseCursor != null); + assert(canRequestFocus != null); final Widget child; final GestureTapCallback onTap; @@ -672,7 +680,7 @@ class _InkResponseStateWidget extends StatefulWidget { if (onTapCancel != null) 'tap cancel', ]; properties.add(IterableProperty('gestures', gestures, ifEmpty: '')); - properties.add(DiagnosticsProperty('mouseCursor', mouseCursor, defaultValue: MouseCursor.defer)); + properties.add(DiagnosticsProperty('mouseCursor', mouseCursor)); properties.add(DiagnosticsProperty('containedInkWell', containedInkWell, level: DiagnosticLevel.fine)); properties.add(DiagnosticsProperty( 'highlightShape', @@ -1025,6 +1033,14 @@ class _InkResponseState extends State<_InkResponseStateWidget> _highlights[type]?.color = getHighlightColorForType(type); } _currentSplash?.color = widget.splashColor ?? Theme.of(context).splashColor; + final MouseCursor effectiveMouseCursor = MaterialStateProperty.resolveAs( + widget.mouseCursor ?? MaterialStateMouseCursor.clickable, + { + if (!enabled) MaterialState.disabled, + if (_hovering) MaterialState.hovered, + if (_hasFocus) MaterialState.focused, + }, + ); return _ParentInkResponseProvider( state: this, child: Actions( @@ -1035,7 +1051,7 @@ class _InkResponseState extends State<_InkResponseStateWidget> onFocusChange: _handleFocusUpdate, autofocus: widget.autofocus, child: MouseRegion( - cursor: widget.mouseCursor, + cursor: effectiveMouseCursor, onEnter: enabled ? _handleMouseEnter : null, onExit: enabled ? _handleMouseExit : null, child: GestureDetector( @@ -1160,7 +1176,7 @@ class InkWell extends InkResponse { GestureTapCancelCallback onTapCancel, ValueChanged onHighlightChanged, ValueChanged onHover, - MouseCursor mouseCursor = MouseCursor.defer, + MouseCursor mouseCursor, Color focusColor, Color hoverColor, Color highlightColor, diff --git a/packages/flutter/test/material/ink_well_test.dart b/packages/flutter/test/material/ink_well_test.dart index bd957c9ee3f..927c92d144c 100644 --- a/packages/flutter/test/material/ink_well_test.dart +++ b/packages/flutter/test/material/ink_well_test.dart @@ -227,7 +227,22 @@ void main() { ), ); - expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + + // Test disabled + await tester.pumpWidget( + const Material( + child: Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: InkWell(), + ), + ), + ), + ); + + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); // Test default of InkResponse() await tester.pumpWidget( @@ -244,7 +259,22 @@ void main() { ), ); - expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + + // Test disabled + await tester.pumpWidget( + const Material( + child: Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: InkResponse(), + ), + ), + ), + ); + + expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); group('feedback', () {