flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
163.4k stars 26.89k forks source link

`DesktopTextSelectionToolbar` doesn't support keyboard navigation #125476

Open TahaTesser opened 1 year ago

TahaTesser commented 1 year ago

Is there an existing issue for this?

Steps to reproduce

  1. Run the code sample on a desktop platform.
  2. Type some text, select it, and right-click to open the desktop text selection toolbar.
  3. Try to navigate the toolbar with a keyboard. e.g. press the up/down arrow keys.

Expected results

Be able to navigate the desktop text selection toolbar with a keyboard.

Actual results

When trying to navigate with a keyboard, the toolbar changes, and is unable to navigate with a keyboard.

Code sample

Code sample ```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, theme: ThemeData(useMaterial3: true), home: const Example(), ); } } class Example extends StatelessWidget { const Example({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('DesktopTextSelectionToolbar'), ), body: const Center( child: TextField( style: TextStyle(fontSize: 24.0), ), ), ); } } ```

Screenshots or Video

macOS (Keyboard navigation when hovering the toolbar)

https://user-images.githubusercontent.com/48603081/234251221-27e1069c-6048-4e3e-b59c-2d3e49a798e2.mov

Flutter (Keyboard navigation when not hovered)

https://user-images.githubusercontent.com/48603081/234251250-405298b1-c27a-4af0-a55c-9bd86eb6fa33.mov

macOS (Keyboard navigation when not hovering the toolbar)

https://user-images.githubusercontent.com/48603081/234251337-aa91ec3c-1cff-40b1-9808-86c313927da1.mov

Flutter (Keyboard navigation when not hovering the toolbar)

https://user-images.githubusercontent.com/48603081/234251394-003f22d2-c66e-4b87-9c1f-8a7773371da6.mov

Logs

Logs ```console [Paste your logs here] ```

Flutter Doctor output

Doctor output ```console [!] Flutter (Channel master, 3.10.0-12.0.pre.50, on macOS 13.3.1 22E261 darwin-arm64, locale en-EE) • Flutter version 3.10.0-12.0.pre.50 on channel master at /Users/tahatesser/Code/flutter ! Upstream repository git@github.com:TahaTesser/flutter.git is not the same as FLUTTER_GIT_URL • FLUTTER_GIT_URL = git@github.com:NevercodeHQ/flutter.git • Framework revision 8395a2b2a1 (3 hours ago), 2023-04-25 04:00:07 -0400 • Engine revision a26a479e86 • Dart version 3.1.0 (build 3.1.0-38.0.dev) • DevTools version 2.23.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2) • Android SDK at /Users/tahatesser/Code/android-sdk • Platform android-33, build-tools 33.0.2 • ANDROID_SDK_ROOT = /Users/tahatesser/Code/android-sdk • Java binary at: /Applications/Android Studio Preview.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b653.34-9746777) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14E222b • CocoaPods version 1.12.0 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio • Android Studio at /Applications/Android Studio Preview.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b653.34-9746777) [✓] VS Code (version 1.77.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.62.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-arm64 • macOS 13.3.1 22E261 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 112.0.5615.137 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. ```
huycozy commented 1 year ago

Thanks for the detailed report, Taha! This issue is reproducible on the latest stable and master channels.

It would be great if it also supports navigating to boundary items (top/bottom) by combination keys (Cmd + Up/Down) as well.

flutter doctor -v (stable and master) ```bash [✓] Flutter (Channel stable, 3.7.12, on macOS 13.0.1 22A400 darwin-x64, locale en-VN) • Flutter version 3.7.12 on channel stable at /Users/huynq/Documents/GitHub/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 4d9e56e694 (2 days ago), 2023-04-17 21:47:46 -0400 • Engine revision 1a65d409c7 • Dart version 2.19.6 • DevTools version 2.20.1 [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0) • Android SDK at /Users/huynq/Library/Android/sdk • Platform android-33, build-tools 32.0.0 • ANDROID_HOME = /Users/huynq/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14E222b • CocoaPods version 1.11.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.1) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301) [✓] IntelliJ IDEA Community Edition (version 2022.1.1) • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart [✓] VS Code (version 1.77.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.62.0 [✓] Connected device (3 available) • SM T225 (mobile) • R9JT3004VRJ • android-arm64 • Android 13 (API 33) • macOS (desktop) • macos • darwin-x64 • macOS 13.0.1 22A400 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 112.0.5615.137 [✓] HTTP Host Availability • All required HTTP hosts are available • No issues found! ``` ```bash [!] Flutter (Channel master, 3.10.0-12.0.pre.55, on macOS 13.0.1 22A400 darwin-x64, locale en-VN) • Flutter version 3.10.0-12.0.pre.55 on channel master at /Users/huynq/Documents/GitHub/flutter_master ! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path. ! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision aad9fd2d77 (19 minutes ago), 2023-04-25 07:53:24 -0400 • Engine revision 54ddef68b1 • Dart version 3.1.0 (build 3.1.0-39.0.dev) • DevTools version 2.23.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0) • Android SDK at /Users/huynq/Library/Android/sdk • Platform android-33, build-tools 32.0.0 • ANDROID_HOME = /Users/huynq/Library/Android/sdk • Java binary at: /Applications/Android Studio Flamingo.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 14.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 14E222b • CocoaPods version 1.11.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.1) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301) [✓] Android Studio (version 2022.2) • Android Studio at /Applications/Android Studio Flamingo.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) [✓] IntelliJ IDEA Community Edition (version 2022.1.1) • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart [✓] VS Code (version 1.77.3) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.62.0 [✓] Connected device (4 available) • SM T225 (mobile) • R9JT3004VRJ • android-arm64 • Android 13 (API 33) • iPhone (mobile) • d9a94afe2b649fef56ba0bfeb052f0f2a7dae95e • ios • iOS 15.7.2 19H218 • macOS (desktop) • macos • darwin-x64 • macOS 13.0.1 22A400 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 112.0.5615.137 [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. ```
Renzo-Olivares commented 1 year ago

cc @justinmc from triage.

justinmc commented 1 year ago

@gspencergoog Weren't we talking about this at some point? I remember brainstorming with you how to keep a TextField focused while some buttons also have focus. Do you know if that's currently possible?

gspencergoog commented 1 year ago

Yes, I think so, I added the ability to supply a parentNode to the Focus widget, which should allow you to make the focus nodes in the toolbar be descendants of the text field, meaning that the focus tree doesn't match the widget tree, but If they're focused, the text field will still think it has focus.

justinmc commented 1 year ago

@gspencergoog That seems to be exactly what I need, but I just tried it and the problem I'm having is that Shortcuts traversals always seem to start from the parent Focus.

In this app, if I tap the button and press "Z", the top CallbackShortcuts is always triggered ```dart CallbackShortcuts( bindings: { const SingleActivator(LogicalKeyboardKey.keyZ): () { print('justin Z: top'); // always logged }, }, child: Focus( focusNode: focusNodeTop, child: CallbackShortcuts( bindings: { const SingleActivator(LogicalKeyboardKey.keyZ): () { print('justin Z: bottom'); // never logged }, }, child: Focus( parentNode: focusNodeTop, // If I remove this line, the bottom one is logged instead. focusNode: focusNodeBottom, child: TextButton( onPressed: () { focusNodeBottom.requestFocus(); }, child: const Text('clickme'), ), ), ), ), ), ```

This is a simplified version of the problem at hand, where the top Focus would be the EditableText and the bottom would be the context menu.

Is this desired or a bug? I want to be able to receive key events from the child Focus.

gspencergoog commented 1 year ago

Yeah, because by specifying the parent node, you're bypassing the focus node that is embedded in the middle CallbackShortcuts widget. You've restructured the focus tree so that it is a second leaf node under the focusTopNode node.

Try printing the focus tree with debugDumpFocusTree() and you'll see what I mean.

gspencergoog commented 1 year ago

What you probably want to do is wrap the subtree with a Focus widget that has the parentNode set, but is unfocusable and not traversable, to act as a bridge to the parent. Then all the children will find that Focus widget and parent from it.

flutter-triage-bot[bot] commented 1 month ago

The triaged-desktop label is irrelevant if there is no team-desktop label or fyi-desktop label.