Unverified Commit 36f73cf6 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Disable context menu (#128365)

## Description

Changes the context menu example for `MenuAnchor` so that it uses right-click, or (on macOS and iOS only) ctrl-left-click, for the context menu. Also disables the browser context menu on web platforms.

## Tests
 - Updated test to reflect new triggers.
parent 5328bd9a
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -41,6 +42,7 @@ class _MyContextMenuState extends State<MyContextMenu> { ...@@ -41,6 +42,7 @@ class _MyContextMenuState extends State<MyContextMenu> {
final FocusNode _buttonFocusNode = FocusNode(debugLabel: 'Menu Button'); final FocusNode _buttonFocusNode = FocusNode(debugLabel: 'Menu Button');
final MenuController _menuController = MenuController(); final MenuController _menuController = MenuController();
ShortcutRegistryEntry? _shortcutsEntry; ShortcutRegistryEntry? _shortcutsEntry;
bool _menuWasEnabled = false;
Color get backgroundColor => _backgroundColor; Color get backgroundColor => _backgroundColor;
Color _backgroundColor = Colors.red; Color _backgroundColor = Colors.red;
...@@ -62,6 +64,12 @@ class _MyContextMenuState extends State<MyContextMenu> { ...@@ -62,6 +64,12 @@ class _MyContextMenuState extends State<MyContextMenu> {
} }
} }
@override
void initState() {
super.initState();
_disableContextMenu();
}
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
...@@ -84,15 +92,38 @@ class _MyContextMenuState extends State<MyContextMenu> { ...@@ -84,15 +92,38 @@ class _MyContextMenuState extends State<MyContextMenu> {
void dispose() { void dispose() {
_shortcutsEntry?.dispose(); _shortcutsEntry?.dispose();
_buttonFocusNode.dispose(); _buttonFocusNode.dispose();
_reenableContextMenu();
super.dispose(); super.dispose();
} }
Future<void> _disableContextMenu() async {
if (!kIsWeb) {
// Does nothing on non-web platforms.
return;
}
_menuWasEnabled = BrowserContextMenu.enabled;
if (_menuWasEnabled) {
await BrowserContextMenu.disableContextMenu();
}
}
void _reenableContextMenu() {
if (!kIsWeb) {
// Does nothing on non-web platforms.
return;
}
if (_menuWasEnabled && !BrowserContextMenu.enabled) {
BrowserContextMenu.enableContextMenu();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.all(50), padding: const EdgeInsets.all(50),
child: GestureDetector( child: GestureDetector(
onTapDown: _handleTapDown, onTapDown: _handleTapDown,
onSecondaryTapDown: _handleSecondaryTapDown,
child: MenuAnchor( child: MenuAnchor(
controller: _menuController, controller: _menuController,
anchorTapClosesMenu: true, anchorTapClosesMenu: true,
...@@ -142,7 +173,7 @@ class _MyContextMenuState extends State<MyContextMenu> { ...@@ -142,7 +173,7 @@ class _MyContextMenuState extends State<MyContextMenu> {
children: <Widget>[ children: <Widget>[
const Padding( const Padding(
padding: EdgeInsets.all(8.0), padding: EdgeInsets.all(8.0),
child: Text('Ctrl-click anywhere on the background to show the menu.'), child: Text('Right-click anywhere on the background to show the menu.'),
), ),
Padding( Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
...@@ -185,12 +216,28 @@ class _MyContextMenuState extends State<MyContextMenu> { ...@@ -185,12 +216,28 @@ class _MyContextMenuState extends State<MyContextMenu> {
} }
} }
void _handleSecondaryTapDown(TapDownDetails details) {
_menuController.open(position: details.localPosition);
}
void _handleTapDown(TapDownDetails details) { void _handleTapDown(TapDownDetails details) {
if (!HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlLeft) && switch (defaultTargetPlatform) {
!HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlRight)) { case TargetPlatform.android:
return; case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
// Don't open the menu on these platforms with a Ctrl-tap (or a
// tap).
break;
case TargetPlatform.iOS:
case TargetPlatform.macOS:
// Only open the menu on these platforms if the control button is down
// when the tap occurs.
if (HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlLeft) ||
HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlRight)) {
_menuController.open(position: details.localPosition);
}
} }
_menuController.open(position: details.localPosition);
} }
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_api_samples/material/menu_anchor/menu_anchor.1.dart' as example; import 'package:flutter_api_samples/material/menu_anchor/menu_anchor.1.dart' as example;
...@@ -18,15 +19,13 @@ void main() { ...@@ -18,15 +19,13 @@ void main() {
await tester.pumpWidget(const example.ContextMenuApp()); await tester.pumpWidget(const example.ContextMenuApp());
await tester.sendKeyDownEvent(LogicalKeyboardKey.controlRight); await tester.tapAt(const Offset(100, 200), buttons: kSecondaryButton);
await tester.tapAt(const Offset(100, 200));
await tester.pump(); await tester.pump();
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(100.0, 200.0, 433.0, 360.0))); expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(100.0, 200.0, 433.0, 360.0)));
// Make sure tapping in a different place causes the menu to move. // Make sure tapping in a different place causes the menu to move.
await tester.tapAt(const Offset(200, 100)); await tester.tapAt(const Offset(200, 100), buttons: kSecondaryButton);
await tester.pump(); await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlRight);
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(200.0, 100.0, 533.0, 260.0))); expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(200.0, 100.0, 533.0, 260.0)));
...@@ -67,8 +66,7 @@ void main() { ...@@ -67,8 +66,7 @@ void main() {
); );
// Open the menu so we can look for state changes reflected in the menu. // Open the menu so we can look for state changes reflected in the menu.
await tester.sendKeyDownEvent(LogicalKeyboardKey.controlRight); await tester.tapAt(const Offset(100, 200), buttons: kSecondaryButton);
await tester.tapAt(const Offset(100, 200));
await tester.pump(); await tester.pump();
expect(find.text(example.MenuEntry.showMessage.label), findsOneWidget); expect(find.text(example.MenuEntry.showMessage.label), findsOneWidget);
......
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