Skip to content

Mac context menu #73882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Jan 20, 2021
Merged

Mac context menu #73882

merged 38 commits into from
Jan 20, 2021

Conversation

justinmc
Copy link
Contributor

@justinmc justinmc commented Jan 13, 2021

A minimal Mac context menu.

Native is left, Flutter is right.
Screen Shot 2021-01-13 at 4 58 38 PM

Flutter light mode Flutter dark mode
Screen Shot 2021-01-15 at 10 37 00 AM Screen Shot 2021-01-15 at 10 36 45 AM

Tests

  • Tested that the Mac text selection toolbar shows and works correctly on all text editing widgets (I couldn't just test EditableText because it doesn't set up the text selection controls itself).
  • Tested Mac mouse selection behavior.
  • Stopped testing force press on Mac.

Breaking change

No.

Known limitations

I'm tracking all of these in #74255.

  • We can't draw outside of the current window yet, so this menu moves to always stay inside.
  • The menu items are the same as on mobile. None of the myriad native desktop buttons will appear. However, it is possible to customize the buttons with a little work (similar to how it is on Android/iOS now). Disallowing customization until the menu is done in a more robust way.
  • There is no flash animation when a button is clicked.
  • There is no built-in support for submenus.
  • The menu's hover effect doesn't happen unless the window is focused.
  • Only right clicking on a text field or SelectableText will show the menu, not just anywhere. Same for trying to close the menu by clicking elsewhere.
  • Menu items that are wider than the default width are ellided, but on native the menu grows to accommodate them.

@justinmc justinmc self-assigned this Jan 13, 2021
@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Jan 13, 2021
@google-cla google-cla bot added the cla: yes label Jan 13, 2021
@@ -1784,6 +1784,17 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin {

Offset? _lastTapDownPosition;

/// The position of the most recent tap down event on this text input.
Offset? get lastTapDownPosition => _lastTapDownPosition;
Copy link
Contributor Author

@justinmc justinmc Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to expose this in order to position the menu at the tap position (on mobile, it's positioned centered on the selection). Any objections to this or better ideas?

Ideally I'll be able to clean up RenderEditable stuff like this in my refactor later...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably OK in the short term. We should really be using the existing menu system to show desktop menus.

@justinmc justinmc requested a review from HansMuller January 14, 2021 02:01
@justinmc justinmc force-pushed the desktop-context-menu branch from a3b723d to 343c2ec Compare January 14, 2021 02:02
const double _kToolbarWidth = 222.0;
const Color _kToolbarBorderColor = Color(0xFF505152);
const Radius _kToolbarBorderRadius = Radius.circular(4.0);
const Color _kToolbarBackgroundColor = Color(0xFF2D2E31);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I get this from the theme so that it depends on light/dark mode?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CupertinoDynamicColor values in CupertinoColors resolve to different color values, depending on the theme's CupertinoTheme's brightness. CupertinoDynamicColor.resolve(CupertinoColors.systemBlue, context).

Comment on lines 84 to 93
child: CupertinoButton(
alignment: Alignment.centerLeft,
borderRadius: null,
color: _isHovered ? CupertinoTheme.of(context).primaryColor : null,
minSize: 0.0,
onPressed: widget.onPressed,
padding: _kToolbarButtonPadding,
pressedOpacity: 0.7,
child: widget.child,
),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry that the text may not be vertically centered in these buttons.

Screen Shot 2021-01-13 at 4 58 59 PM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, although we could improve the situation a little by tweaking the padding for now. Part of the root problem is #72521 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've improved it by a pixel or two with padding and it looks noticeably better.


// These values were measured from a screenshot of TextEdit on MacOS 10.15.7 on
// a Macbook Pro.
const double _kToolbarWidth = 222.0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Justin !

It seems that the width is not fixed and depends on the widest menu item according to Apple documentation.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks! I'll make that a minimum width.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not as easy as I thought. I think it might need a custom layout widget. The parent needs to size itself to the biggest intrinsic width of its children, and the children then need to all match that.

I've added this to the "Known limitations" above since this PR is somewhat rushed. Given more time this is definitely doable, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to #72023.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okok perfect!

/// * [TextSelectionToolbar.toolbarBuilder], which is of this type.
/// * [CupertinoTextSelectionToolbar.toolbarBuilder], which is similar, but
/// for a Cupertino-style toolbar.
typedef ToolbarBuilder = Widget Function(BuildContext context, Widget child);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to widgets so it can be shared.

@justinmc
Copy link
Contributor Author

The Google testing failure is just because #73900, which this PR depends on, has not yet been rolled into google3.

@justinmc justinmc marked this pull request as ready for review January 16, 2021 08:09
@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@justinmc
Copy link
Contributor Author

I'm going to merge this even though Google tests are failing because:

CC @HansMuller

@justinmc justinmc merged commit 24e195d into flutter:master Jan 20, 2021
@justinmc justinmc deleted the desktop-context-menu branch January 20, 2021 21:18
@@ -131,6 +142,7 @@ abstract class TextSelectionControls {
List<TextSelectionPoint> endpoints,
TextSelectionDelegate delegate,
ClipboardStatusNotifier clipboardStatus,
Offset? lastSecondaryTapDownPosition,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@justinmc This is a breaking change.

What is the suggested migration?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this breaks flutter_math e.g. - I will link the PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry about that. The migration should be to pass renderObject.lastSecondaryTapDownPosition. See https://github.com/flutter/flutter/pull/73882/files#diff-6f186b82dcb3d864ea23246744ea7a67bcb64d369e0da5495cd0bd0e038f9bd9R600

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, thanks ❤️

@justinmc justinmc added the a: text input Entering text in a text field or keyboard related problems label Feb 23, 2021
@lesnitsky lesnitsky mentioned this pull request Sep 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: text input Entering text in a text field or keyboard related problems f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants