Skip to content

Conversation

@gspencergoog
Copy link
Contributor

Description

This re-implements keyboard text selection so that it will work on platforms other than Android (e.g. macOS, Linux, etc.).

Also, fixed a number of bugs in editing selection via a hardware keyboard (unable to select backwards, incorrect conversion to ASCII when cutting to clipboard, lack of support for CTRL-SHIFT-ARROW word selection, etc.).

Did not address the keyboard locale issues that remain, or add platform specific switches for the bindings. All that will need some more design work before implementing them.

Related Issues

Fixes #31951

Tests

  • Added a large number of test scenarios for text selection, and cut/copy/paste.

Breaking Change

  • No, this is not a breaking change.

@fluttergithubbot fluttergithubbot added the framework flutter/packages/flutter repository. See also f: labels. label Oct 17, 2019
@gspencergoog gspencergoog force-pushed the keyboard_text_selection branch from 665a38d to d4c5f3c Compare October 17, 2019 00:21
@gspencergoog gspencergoog requested a review from justinmc October 17, 2019 00:31
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍

There is an existing issue about Gboard's directional soft keyboard not working: #9419. It looks like this PR will make it easier to get that sort of thing working, would you agree? Just making sure you're aware that we'll have to support that at some point.

onSelectionChanged(nextSelection, this, cause);
}

// TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404).
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this TODO obsolete now or should we keep it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, you're right, this does still apply, but only because some parts of this code depend upon the length of a string in code points instead of extended grapheme clusters. I'll restore it and add more info.

/// It is used, for example, to make sets of keys with members like
/// [controlRight] and [controlLeft] and convert that set to contain just
/// [control], so that the question "is any control key down?" can be asked.
static Set<LogicalKeyboardKey> collapseSynonyms(Set<LogicalKeyboardKey> input) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I love static methods. This could even be directly unit tested if you want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

LOL! Yeah, ok, added a test. Very subtle. :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

😄

),
cause,
);
if (onSelectionChanged == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do all of these checks if onSelectionChanged exist here instead of one check inside of _handleSelectionChanged?

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 think the idea was to avoid doing the work needed to get to _handleSelectionChanged, but I think I'll move this up to _handleKeyEvent, and also a check in _handleSelectionChanged, since there are other call sites for it that aren't protected.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good.


await tester.pump(); // Wait for autofocus to take effect.

Future<void> sendKeys(List<LogicalKeyboardKey> keys, {bool shift = false, bool control = false}) async {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was wondering if we had a good way to test hardware keyboard keys 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes! I added that stuff last month because it was missing. It's turning out to be very useful.

@gspencergoog
Copy link
Contributor Author

Yes, it could make it easier to implement a fix for #9419, but we'd have to convert those events into calls to a method here. Probably we'd have to subscribe to some listener for those events, and refactor this class to handle either those or key events. In any case, it shouldn't be too bad.

@gspencergoog gspencergoog force-pushed the keyboard_text_selection branch from 012c244 to 739b5c8 Compare October 17, 2019 20:16
@justinmc
Copy link
Contributor

Sounds good about #9419. I'm going to add some notes in there about this for when I get to it.

@gspencergoog gspencergoog force-pushed the keyboard_text_selection branch from 739b5c8 to 38c1485 Compare October 17, 2019 21:27
@gspencergoog gspencergoog merged commit a7aa661 into flutter:master Oct 17, 2019
@gspencergoog gspencergoog deleted the keyboard_text_selection branch October 18, 2019 00:57
@pchampio
Copy link

pchampio commented Oct 28, 2019

Just to be sure.

If I understand correctly, this code handles text selection at the flutter framework level using RawKeyEvent.

Embedders have control over the text input (and text selection/position). And existing embedders are making use of the flutter/textinput method channel to send text, cursor position, and in our case text selection & copy/paste.

On go-flutter, work has been done to implement keyboard selection/copy/paste at the embedder level. textinput.go.

My question is, should go-flutter stop using the flutter/textinput channel for text selection/copy/paste? (implies delete of textinput_{darwin.,linux,windows}.go that were used to distinguish platform specific bindings)

The linux shell also uses flutter/textinput method channel for cursor position text_input_plugin.cc.

This PR isn't aligned with embedders, and handles are duplicate.
Other than #31951, there seems to be another related issue: #36316

My very personal opinion, I think putting these handles in the flutter framework makes embedders lighter which is a good thing. Waiting for #31366 to be merged so that platform specific bindings can be addressed.
I feel like the flutter/keyevent method channel is doing a lot, maybe add documentation on https://api.flutter.dev/flutter/services/SystemChannels/keyEvent-constant.html ?

gspencergoog added a commit that referenced this pull request Nov 18, 2019
…4130)

This adds support for the command key for text selection/editing on macOS. I had ported the text editing code (in #42879), but forgot to add support for the command key itself. This also adds a test that tests the text editing on multiple platforms instead of just testing Android.

There appears to still be a bug (filed #44135) where we're losing key events sometimes on macOS, leaving some keys "stuck" on, but this PR at least allows the right key combinations to be used.
Inconnu08 pushed a commit to Inconnu08/flutter that referenced this pull request Nov 26, 2019
This re-implements keyboard text selection so that it will work on platforms other than Android (e.g. macOS, Linux, etc.).

Also, fixed a number of bugs in editing selection via a hardware keyboard (unable to select backwards, incorrect conversion to ASCII when cutting to clipboard, lack of support for CTRL-SHIFT-ARROW word selection, etc.).

Did not address the keyboard locale issues that remain, or add platform specific switches for the bindings. All that will need some more design work before implementing them.

Related Issues
Fixes flutter#31951
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support text selection via keyboard

5 participants