Skip to content

Conversation

@nate-thegrate
Copy link
Contributor

@nate-thegrate nate-thegrate commented Feb 5, 2024

fixes #87061

It doesn't matter whether I'm using Google Chrome, VS Code, Discord, or a Terminal window: any time a text cursor is blinking, it means that the characters I type will show up there.

And this isn't limited to text fields: if I repeatedly press Tab to navigate through a website, there's a visual indicator that goes away if I click away from the window, and it comes back if I click or Alt+Tab back into it.

Example (Chrome):

focus node

This PR adds the same functionality to Flutter apps:

Flutter demo

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, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

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

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact "@test-exemption-reviewer" in the #hackers channel in Chat (don't just cc them here, they won't see it! Use Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: focus Focus traversal, gaining or losing focus labels Feb 5, 2024
@nate-thegrate nate-thegrate marked this pull request as draft February 5, 2024 18:31
@flutter-dashboard
Copy link

This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@nate-thegrate nate-thegrate marked this pull request as ready for review February 5, 2024 20:37
@nate-thegrate
Copy link
Contributor Author

@gspencergoog the FocusManager class is updated, and I added a test to cover detaching a suspended node.

Thanks for your help, and let me know if we need anything else!

} else if (_primaryFocus != rootScope) {
assert(_focusDebug(() => 'suspending $_primaryFocus'));
_markedForFocus = rootScope;
_suspendedNode = _primaryFocus;
Copy link
Contributor

Choose a reason for hiding this comment

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

What should happen if something changes the focus while the app is not in "resumed" mode? (Imagine a timer being set to return focus to something at a later time.) Should setting the primary focus to something other than the rootScope modify the _suspendedNode, or should it clear it and set the primary focus?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a really good question. I'm not aware of an app that changes focus on a timer, so there probably isn't a precedent to follow.

But if a developer implements a feature that can change the focus without user input, it probably makes sense to just let it happen, i.e. null out the _suspendedNode and set the primary focus. I'll update this function accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, it doesn't have to be as simple as a timer, I was just thinking of the simplest way to describe the issue. For a more real-world case, Imagine a slide-in animation that sets the focus on a text field when the animation is done. If you switch the focus away during the animation, this would also cause the same problem.

Your solution looks good, though.

Copy link
Contributor

@gspencergoog gspencergoog Feb 12, 2024

Choose a reason for hiding this comment

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

One thing just occurred to me, though: we might not want to expose didChangeAppLifecycleState as a public function on the FocusManager, since it's not really something that should be called outside of the binding. Perhaps it would be better to aggregate instead of inherit here: create a private class that extends WidgetsBindingObserver and let the FocusManager have a private instance of that class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

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

32384589-a60f0e74-c078-11e7-9bc1-e5b5287aea9d

Thanks for doing this!

Copy link
Member

@loic-sharma loic-sharma left a comment

Choose a reason for hiding this comment

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

Thanks for the excellent contribution!

@gspencergoog gspencergoog added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 13, 2024
@auto-submit auto-submit bot merged commit f01ce9f into flutter:master Feb 13, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 14, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 14, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 15, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 15, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 15, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 16, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 16, 2024
auto-submit bot pushed a commit that referenced this pull request Feb 20, 2024
Previously we merged #142930, to solve issue #87061.

Since then, I discovered that the keyboard input wasn't being captured after the app had been paused and resumed. After some digging, I realized that the problem was due to [a line in editable_text.dart](https://github.com/flutter/flutter/blob/d4b1b6e744ba6196e14fb49904f07a4aea4d5869/packages/flutter/lib/src/widgets/editable_text.dart#L3589) that called the `focusNode.consumeKeyboardToken()` method.

Luckily, it's a very easy fix: we just use `requestFocus()` instead of `applyFocusChangesIfNeeded()`. @gspencergoog could you take a look when you have a chance?
@gspencergoog
Copy link
Contributor

gspencergoog commented Mar 6, 2024

This PR appears to be causing problems on some mobile devices where trying to type on the keyboard causes the text field to lose focus, and then the keyboard goes away.

We may need to revert this until we figure out the cause.

I'll see if I can get more information and a reproducible test case.

(b/327733085)

@nate-thegrate
Copy link
Contributor Author

That's unfortunate to hear.

If the keyboard can trigger a lifecycle state change on some devices but not on others, hopefully that can get fixed soon.

I agree that for now it makes sense to revert this merge, or maybe add a platform check when activating the listener.

@gspencergoog
Copy link
Contributor

I like the idea of a platform check more than just reverting it. This is a good change for desktop platforms especially.

Let's wait and see what the team comes up with for a reproduction case so we can see what the extent of it is. So far it seems to be on specific mobile devices only. My suspicion is that there's an OEM onscreen keyboard that isn't coded similarly to other keyboards, and acts more like a separate app, causing a lifecycle change when it takes focus.

auto-submit bot pushed a commit that referenced this pull request Mar 12, 2024
This PR implements a temporary fix for the mobile device keyboard bug reported in [this comment](#142930 (comment)).

CC @gspencergoog
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 14, 2024
auto-submit bot pushed a commit that referenced this pull request May 20, 2024
…us (#148067)

This change fixes an issue where SelectionArea would clear its selection when the application window lost focus by first checking if the application is running. This is needed because `FocusManager` is aware of the application lifecycle as of #142930 , and triggers a focus lost if the application is not active.

Also fixes an issue where the `FocusManager` was not being reset on tests at the right time, causing it always to build with `TargetPlatform.android` as its context.
flutteractionsbot pushed a commit to flutteractionsbot/flutter that referenced this pull request Jul 11, 2024
…us (flutter#148067)

This change fixes an issue where SelectionArea would clear its selection when the application window lost focus by first checking if the application is running. This is needed because `FocusManager` is aware of the application lifecycle as of flutter#142930 , and triggers a focus lost if the application is not active.

Also fixes an issue where the `FocusManager` was not being reset on tests at the right time, causing it always to build with `TargetPlatform.android` as its context.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App f: focus Focus traversal, gaining or losing focus framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Even if desktop app is inactive, the cursor is still blinking

3 participants