From 72df4801c81547fc8e9da642efcb989610f04ed2 Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Thu, 13 Jan 2022 17:08:35 -0800 Subject: [PATCH] Land Set "basic" mouse cursor for disabled buttons, PR #89346 (#96561) --- .../lib/src/material/elevated_button.dart | 4 +- .../flutter/lib/src/material/icon_button.dart | 4 +- .../lib/src/material/outlined_button.dart | 4 +- .../flutter/lib/src/material/text_button.dart | 4 +- .../test/material/elevated_button_test.dart | 79 +++++++++++++++++++ .../test/material/icon_button_test.dart | 4 +- .../test/material/outlined_button_test.dart | 79 +++++++++++++++++++ .../test/material/text_button_test.dart | 78 ++++++++++++++++++ 8 files changed, 246 insertions(+), 10 deletions(-) diff --git a/packages/flutter/lib/src/material/elevated_button.dart b/packages/flutter/lib/src/material/elevated_button.dart index 7afb26a158..6b163549f2 100644 --- a/packages/flutter/lib/src/material/elevated_button.dart +++ b/packages/flutter/lib/src/material/elevated_button.dart @@ -255,7 +255,7 @@ class ElevatedButton extends ButtonStyleButton { /// * `side` - null /// * `shape` - RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)) /// * `mouseCursor` - /// * disabled - SystemMouseCursors.forbidden + /// * disabled - SystemMouseCursors.basic /// * others - SystemMouseCursors.click /// * `visualDensity` - theme.visualDensity /// * `tapTargetSize` - theme.materialTapTargetSize @@ -300,7 +300,7 @@ class ElevatedButton extends ButtonStyleButton { maximumSize: Size.infinite, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))), enabledMouseCursor: SystemMouseCursors.click, - disabledMouseCursor: SystemMouseCursors.forbidden, + disabledMouseCursor: SystemMouseCursors.basic, visualDensity: theme.visualDensity, tapTargetSize: theme.materialTapTargetSize, animationDuration: kThemeChangeDuration, diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart index 1515149532..1d15f1caff 100644 --- a/packages/flutter/lib/src/material/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -256,7 +256,7 @@ class IconButton extends StatelessWidget { /// {@macro flutter.material.RawMaterialButton.mouseCursor} /// /// If set to null, will default to - /// - [SystemMouseCursors.forbidden], if [onPressed] is null + /// - [SystemMouseCursors.basic], if [onPressed] is null /// - [SystemMouseCursors.click], otherwise final MouseCursor? mouseCursor; @@ -357,7 +357,7 @@ class IconButton extends StatelessWidget { autofocus: autofocus, canRequestFocus: onPressed != null, onTap: onPressed, - mouseCursor: mouseCursor ?? (onPressed == null ? SystemMouseCursors.forbidden : SystemMouseCursors.click), + mouseCursor: mouseCursor ?? (onPressed == null ? SystemMouseCursors.basic : SystemMouseCursors.click), enableFeedback: enableFeedback, focusColor: focusColor ?? theme.focusColor, hoverColor: hoverColor ?? theme.hoverColor, diff --git a/packages/flutter/lib/src/material/outlined_button.dart b/packages/flutter/lib/src/material/outlined_button.dart index 8e28ea3fd4..5badea5f93 100644 --- a/packages/flutter/lib/src/material/outlined_button.dart +++ b/packages/flutter/lib/src/material/outlined_button.dart @@ -240,7 +240,7 @@ class OutlinedButton extends ButtonStyleButton { /// * `side` - BorderSide(width: 1, color: Theme.colorScheme.onSurface(0.12)) /// * `shape` - RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)) /// * `mouseCursor` - /// * disabled - SystemMouseCursors.forbidden + /// * disabled - SystemMouseCursors.basic /// * others - SystemMouseCursors.click /// * `visualDensity` - theme.visualDensity /// * `tapTargetSize` - theme.materialTapTargetSize @@ -275,7 +275,7 @@ class OutlinedButton extends ButtonStyleButton { ), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))), enabledMouseCursor: SystemMouseCursors.click, - disabledMouseCursor: SystemMouseCursors.forbidden, + disabledMouseCursor: SystemMouseCursors.basic, visualDensity: theme.visualDensity, tapTargetSize: theme.materialTapTargetSize, animationDuration: kThemeChangeDuration, diff --git a/packages/flutter/lib/src/material/text_button.dart b/packages/flutter/lib/src/material/text_button.dart index fb3aa74024..fcb27dc355 100644 --- a/packages/flutter/lib/src/material/text_button.dart +++ b/packages/flutter/lib/src/material/text_button.dart @@ -244,7 +244,7 @@ class TextButton extends ButtonStyleButton { /// * `side` - null /// * `shape` - RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)) /// * `mouseCursor` - /// * disabled - SystemMouseCursors.forbidden + /// * disabled - SystemMouseCursors.basic /// * others - SystemMouseCursors.click /// * `visualDensity` - theme.visualDensity /// * `tapTargetSize` - theme.materialTapTargetSize @@ -288,7 +288,7 @@ class TextButton extends ButtonStyleButton { maximumSize: Size.infinite, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))), enabledMouseCursor: SystemMouseCursors.click, - disabledMouseCursor: SystemMouseCursors.forbidden, + disabledMouseCursor: SystemMouseCursors.basic, visualDensity: theme.visualDensity, tapTargetSize: theme.materialTapTargetSize, animationDuration: kThemeChangeDuration, diff --git a/packages/flutter/test/material/elevated_button_test.dart b/packages/flutter/test/material/elevated_button_test.dart index e29c6142cd..f58613d6de 100644 --- a/packages/flutter/test/material/elevated_button_test.dart +++ b/packages/flutter/test/material/elevated_button_test.dart @@ -1418,6 +1418,85 @@ void main() { expect(tester.getSize(find.widgetWithText(ElevatedButton, '200x200')), const Size(200, 200)); expect(tester.getSize(find.widgetWithText(ElevatedButton, '200,200')), const Size(200, 200)); }); + + testWidgets('ElevatedButton changes mouse cursor when hovered', (WidgetTester tester) async { + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + enabledMouseCursor: SystemMouseCursors.text, + disabledMouseCursor: SystemMouseCursors.grab, + ), + onPressed: () {}, + child: const Text('button'), + ), + ), + ), + ); + + final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1); + await gesture.addPointer(location: Offset.zero); + addTearDown(gesture.removePointer); + + await tester.pump(); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + + // Test cursor when disabled + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + enabledMouseCursor: SystemMouseCursors.text, + disabledMouseCursor: SystemMouseCursors.grab, + ), + onPressed: null, + child: const Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); + + // Test default cursor + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: ElevatedButton( + onPressed: () {}, + child: const Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + + // Test default cursor when disabled + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: ElevatedButton( + onPressed: null, + child: Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + }); } TextStyle _iconStyle(WidgetTester tester, IconData icon) { diff --git a/packages/flutter/test/material/icon_button_test.dart b/packages/flutter/test/material/icon_button_test.dart index 1ad4a4da53..675862cc12 100644 --- a/packages/flutter/test/material/icon_button_test.dart +++ b/packages/flutter/test/material/icon_button_test.dart @@ -793,7 +793,7 @@ void main() { expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); }); - testWidgets('disabled IconButton has forbidden mouse cursor', (WidgetTester tester) async { + testWidgets('disabled IconButton has basic mouse cursor', (WidgetTester tester) async { await tester.pumpWidget( const Material( child: Directionality( @@ -814,7 +814,7 @@ void main() { await tester.pump(); - expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden); + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); }); testWidgets('IconButton.mouseCursor overrides implicit setting of mouse cursor', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/outlined_button_test.dart b/packages/flutter/test/material/outlined_button_test.dart index ef30649472..8f1367a543 100644 --- a/packages/flutter/test/material/outlined_button_test.dart +++ b/packages/flutter/test/material/outlined_button_test.dart @@ -1593,6 +1593,85 @@ void main() { expect(tester.getSize(find.widgetWithText(OutlinedButton, '200x200')), const Size(200, 200)); expect(tester.getSize(find.widgetWithText(OutlinedButton, '200,200')), const Size(200, 200)); }); + + testWidgets('OutlinedButton changes mouse cursor when hovered', (WidgetTester tester) async { + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + enabledMouseCursor: SystemMouseCursors.text, + disabledMouseCursor: SystemMouseCursors.grab, + ), + onPressed: () {}, + child: const Text('button'), + ), + ), + ), + ); + + final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1); + await gesture.addPointer(location: Offset.zero); + addTearDown(gesture.removePointer); + + await tester.pump(); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + + // Test cursor when disabled + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + enabledMouseCursor: SystemMouseCursors.text, + disabledMouseCursor: SystemMouseCursors.grab, + ), + onPressed: null, + child: const Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); + + // Test default cursor + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: OutlinedButton( + onPressed: () {}, + child: const Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + + // Test default cursor when disabled + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: OutlinedButton( + onPressed: null, + child: Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + }); } PhysicalModelLayer _findPhysicalLayer(Element element) { diff --git a/packages/flutter/test/material/text_button_test.dart b/packages/flutter/test/material/text_button_test.dart index 45a3a9c8fe..c8b4b6cc18 100644 --- a/packages/flutter/test/material/text_button_test.dart +++ b/packages/flutter/test/material/text_button_test.dart @@ -1391,6 +1391,84 @@ void main() { expect(tester.getSize(find.widgetWithText(TextButton, '200,200')), const Size(200, 200)); }); + testWidgets('TextButton changes mouse cursor when hovered', (WidgetTester tester) async { + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: TextButton( + style: TextButton.styleFrom( + enabledMouseCursor: SystemMouseCursors.text, + disabledMouseCursor: SystemMouseCursors.grab, + ), + onPressed: () {}, + child: const Text('button'), + ), + ), + ), + ); + + final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1); + await gesture.addPointer(location: Offset.zero); + addTearDown(gesture.removePointer); + + await tester.pump(); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text); + + // Test cursor when disabled + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: TextButton( + style: TextButton.styleFrom( + enabledMouseCursor: SystemMouseCursors.text, + disabledMouseCursor: SystemMouseCursors.grab, + ), + onPressed: null, + child: const Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab); + + // Test default cursor + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: TextButton( + onPressed: () {}, + child: const Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); + + // Test default cursor when disabled + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: MouseRegion( + cursor: SystemMouseCursors.forbidden, + child: TextButton( + onPressed: null, + child: Text('button'), + ), + ), + ), + ); + + expect(RendererBinding.instance!.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); + }); } TextStyle? _iconStyle(WidgetTester tester, IconData icon) {