Unverified Commit d2c85529 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix disabled `DropdownMenu` doesn't defer the mouse cursor (#145686)

fixes [DropdownMenu cursor in disabled state](https://github.com/flutter/flutter/issues/144611)

This was added in https://github.com/flutter/flutter/pull/121353

### Code sample

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              const Spacer(),
              const Text('enabled: true,\nrequestFocusOnTap: true,'),
              const SizedBox(height: 16),
              DropdownMenu<String>(
                enabled: true,
                initialSelection: 'First',
                requestFocusOnTap: true,
                width: 200,
                dropdownMenuEntries: ['First', 'Second', 'Third']
                    .map((e) => DropdownMenuEntry(value: e, label: e))
                    .toList(),
              ),
              const Text('Expected: text cursor'),
              const Spacer(),
              const Text('enabled: true,\nrequestFocusOnTap: false,'),
              const SizedBox(height: 16),
              DropdownMenu<String>(
                enabled: true,
                initialSelection: 'First',
                requestFocusOnTap: false,
                width: 200,
                dropdownMenuEntries: ['First', 'Second', 'Third']
                    .map((e) => DropdownMenuEntry(value: e, label: e))
                    .toList(),
                // label: const Text('requestFocusOnTap: false'),
              ),
              const Text('Expected: clickable cursor'),
              const Spacer(),
              const Text('enabled: false,\nrequestFocusOnTap: true,'),
              const SizedBox(height: 16),
              DropdownMenu<String>(
                enabled: false,
                initialSelection: 'First',
                requestFocusOnTap: true,
                width: 200,
                dropdownMenuEntries: ['First', 'Second', 'Third']
                    .map((e) => DropdownMenuEntry(value: e, label: e))
                    .toList(),
              ),
              const Text('Expected: deferred cursor'),
              const Spacer(),
              const Text('enabled: false,\nrequestFocusOnTap: false,'),
              const SizedBox(height: 16),
              DropdownMenu<String>(
                enabled: false,
                initialSelection: 'First',
                requestFocusOnTap: false,
                width: 200,
                dropdownMenuEntries: ['First', 'Second', 'Third']
                    .map((e) => DropdownMenuEntry(value: e, label: e))
                    .toList(),
              ),
              const Text('Expected: deferred cursor'),
              const Spacer(),
            ],
          ),
        ),
      ),
    );
  }
}
```

</details>

### Preview
![Screenshot 2024-03-25 at 14 52 31](https://github.com/flutter/flutter/assets/48603081/cf4361a5-d3bb-4635-9825-5eefa4efe6cc)
parent 8d31c583
...@@ -699,7 +699,10 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> { ...@@ -699,7 +699,10 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
?? theme.inputDecorationTheme ?? theme.inputDecorationTheme
?? defaults.inputDecorationTheme!; ?? defaults.inputDecorationTheme!;
final MouseCursor effectiveMouseCursor = canRequestFocus() ? SystemMouseCursors.text : SystemMouseCursors.click; final MouseCursor? effectiveMouseCursor = switch (widget.enabled) {
true => canRequestFocus() ? SystemMouseCursors.text : SystemMouseCursors.click,
false => null,
};
Widget menuAnchor = MenuAnchor( Widget menuAnchor = MenuAnchor(
style: effectiveMenuStyle, style: effectiveMenuStyle,
......
...@@ -1342,6 +1342,68 @@ void main() { ...@@ -1342,6 +1342,68 @@ void main() {
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click); expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
}); });
testWidgets('If enabled is false, the mouse cursor should be deferred when hovered', (WidgetTester tester) async {
Widget buildDropdownMenu({ bool enabled = true, bool? requestFocusOnTap }) {
return MaterialApp(
home: Scaffold(
body: Column(
children: <Widget>[
DropdownMenu<TestMenu>(
enabled: enabled,
requestFocusOnTap: requestFocusOnTap,
dropdownMenuEntries: menuChildren,
),
],
),
),
);
}
// Check mouse cursor dropdown menu is disabled and requestFocusOnTap is true.
await tester.pumpWidget(buildDropdownMenu(enabled: false, requestFocusOnTap: true));
await tester.pumpAndSettle();
Finder textFieldFinder = find.byType(TextField);
TextField textField = tester.widget<TextField>(textFieldFinder);
expect(textField.canRequestFocus, true);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
await gesture.moveTo(tester.getCenter(textFieldFinder));
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
// Remove the pointer.
await gesture.removePointer();
// Check mouse cursor dropdown menu is disabled and requestFocusOnTap is false.
await tester.pumpWidget(buildDropdownMenu(enabled: false, requestFocusOnTap: false));
await tester.pumpAndSettle();
textFieldFinder = find.byType(TextField);
textField = tester.widget<TextField>(textFieldFinder);
expect(textField.canRequestFocus, false);
// Add a new pointer.
await gesture.addPointer();
await gesture.moveTo(tester.getCenter(textFieldFinder));
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
// Remove the pointer.
await gesture.removePointer();
// Check enabled dropdown menu updates the mouse cursor when hovered.
await tester.pumpWidget(buildDropdownMenu(requestFocusOnTap: true));
await tester.pumpAndSettle();
textFieldFinder = find.byType(TextField);
textField = tester.widget<TextField>(textFieldFinder);
expect(textField.canRequestFocus, true);
// Add a new pointer.
await gesture.addPointer();
await gesture.moveTo(tester.getCenter(textFieldFinder));
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
});
testWidgets('The menu has the same width as the input field in ListView', (WidgetTester tester) async { testWidgets('The menu has the same width as the input field in ListView', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/123631 // Regression test for https://github.com/flutter/flutter/issues/123631
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment