Skip to content
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

[macOS] Put FlutterTextInputPlugin in view hierarchy #33827

Merged
merged 14 commits into from
Jun 15, 2022

Conversation

knopp
Copy link
Member

@knopp knopp commented Jun 4, 2022

Before After
Screenshot 2022-06-04 at 22 16 32 Screenshot 2022-06-04 at 22 16 59

Emoji picker is different than the other IME popovers. In order for the picker to be attached properly, FlutterTextInputPlugin must be in view hierarchy and first responder.

Notable changes in this PR:

  • FlutterTextInputPlugin is added to hierarchy in TextInput.show, removed in TextInput.hide.
  • Manual [TextInputContext activate] and deactivate calls are not needed anymore and were removed. The context gets activated automatically now. I also removed the TestTextInputContextIsKeptAlive unit test. Unfortunately I wasn't able to get the context to activate in "headless" unit test environment, but in actual application the context gets activated/deactivated as expected (tested by overriding the activate/deactivate methods on context).
  • I've removed key up event synthesising in performKeyEquivalent:. The keyUp event monitor in FlutterViewController takes care of this. It needed to be modified to allow TextInputPlugin as first responder (which is also works with accessibility text field)
  • [FlutterTestInputPlugin performKeyEquivalent:] now simply calls [FlutterViewController keyDown:]. With one caveat: When the CMD+CTRL+SPACE emoji picker shortcut event gets redispached to nextResponder by FlutterKeyboardManager, the nextResponder is usually NSWindow and it routes the event to [FlutterTestInputPlugin performKeyEquivalent:]. Sending it again to controller would result in endless cycle, so the FlutterTextInputPlugin checks if the event in question is currently being redispatched by manager and if it is, it will not handle it. Not handling the event is also required for the emoji picker to actually show up.
  • I've replaced calls to becomeFirstResponder with [NSWindow makeFirstResponder:]. Unlike UIKit, in AppKit the becomeFirstResponder documentation explicitely says not to call this method directly and in some cases it leads to crash with unhandled NSInternalInconsistencyException.
  • [FlutterTextField becomeFirstResponder], which was called directly has been replaced by [FlutterTextField startEditing]. This method sets FlutterTextPlugin as field editor to the FlutterTextField. This was previously happening as a side effect of becomeFirstResponder calling selectText.

Partially fixes flutter/flutter#85328

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See testing the engine for instructions on
    writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@knopp knopp force-pushed the text_input_plugin_in_view_hierarchy branch from eef9255 to 3f51a94 Compare June 4, 2022 20:28
@knopp knopp changed the title WIP: [macOs] Put FlutterTextInputPlugin in view hierarchy [macOs] Put FlutterTextInputPlugin in view hierarchy Jun 4, 2022
@knopp knopp changed the title [macOs] Put FlutterTextInputPlugin in view hierarchy [macOS] Put FlutterTextInputPlugin in view hierarchy Jun 4, 2022
@knopp knopp force-pushed the text_input_plugin_in_view_hierarchy branch from 00a82f0 to f50304a Compare June 5, 2022 19:45
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

/cc @cbracken

@@ -262,11 +268,22 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
_activeModel = std::make_unique<flutter::TextInputModel>();
}
} else if ([method isEqualToString:kShowMethod]) {
// Ensure the plugin is in hierarchy.
// When accessibility text field becomes first responder AppKit sometimes
// removes the plugin from hierarchy.
Copy link
Contributor

Choose a reason for hiding this comment

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

I couldn't find the place where the text input plugin is added to the view hierarchy. You mean with this change the accessibility text field still causes the text input plugin to be removed as a subview when it has the focus?

Copy link
Member Author

Choose a reason for hiding this comment

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

When FlutterTextField has focus and FlutterTextInputPlugin becomes the field editor of ([FlutterTextField startEditing]) the input plugin gets reparented inside the text field.

@@ -362,7 +379,9 @@ - (void)setEditingState:(NSDictionary*)state {
if (composing_range.collapsed() && wasComposing) {
[_textInputContext discardMarkedText];
}
[_client becomeFirstResponder];
if (_client != nil) {
[self.window makeFirstResponder:_client];
Copy link
Contributor

Choose a reason for hiding this comment

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

thanks for fixing this! 👍

Copy link
Member Author

@knopp knopp Jun 7, 2022

Choose a reason for hiding this comment

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

This was the wrong fix. The TextInputField is actually not meant to be first responder. Instead the FlutterTextInputPlugin is supposed to be the first responder. What the original becomeFirstResponder did was not making the text field first responder, it made FlutterTextInputPlugin current field editor for the text field. It happened as a sideeffect of becomeFirstResponder calling selectText, which sets the field editor as current editor.

So instead of overriding becomeFirstResponder and calling it directly (which shouldn't be done) I replaced it with [FlutterTextField startEditing], which makes the text input plugin current field editor.

@knopp knopp force-pushed the text_input_plugin_in_view_hierarchy branch 2 times, most recently from 75fdba0 to eb2b414 Compare June 7, 2022 14:38
@cbracken cbracken self-requested a review June 8, 2022 20:42
@knopp knopp force-pushed the text_input_plugin_in_view_hierarchy branch 2 times, most recently from 252ba98 to 4c8aa84 Compare June 13, 2022 14:08
Copy link
Contributor

@dkwingsmt dkwingsmt left a comment

Choose a reason for hiding this comment

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

LGTM

@knopp
Copy link
Member Author

knopp commented Jun 14, 2022

@cbracken, @LongCatIsLooong, any objections to getting this merged?

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 16, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 17, 2022
houhuayong pushed a commit to houhuayong/engine that referenced this pull request Jun 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't navigate composing candidates list with arrow keys on Mac
3 participants