Skip to content

[flutter] prevent errant text field clicks from losing focus - #86041

Merged
fluttergithubbot merged 12 commits into
flutter:masterfrom
jonahwilliams:merged_focus_node
Jul 13, 2021
Merged

fluttergithubbot merged 12 commits into
flutter:masterfrom
jonahwilliams:merged_focus_node

Conversation

@jonahwilliams

@jonahwilliams jonahwilliams commented Jul 7, 2021 •

Copy link
Copy Markdown
Contributor

Without making dramatic adjustments to the focus system, attempts to support the text field / editable text nesting while still preventing clicks from text field decoration from removing focus from the editable text.

Fixes #86154

@flutter-dashboard flutter-dashboard Bot added p: material_ui material_ui package in flutter/packages framework flutter/packages/flutter repository. See also f: labels. labels Jul 7, 2021
@google-cla google-cla Bot added the cla: yes label Jul 7, 2021
@jonahwilliams

Copy link
Copy Markdown
Contributor Author

@gspencergoog @chunhtai this is an attempt to fix one of the side effects from the focus removal change; since the "focused" part of the text field is just the tiny editable text portion it is too easy to lose focus by clicking on the decorative parts. This introduces another context that can be attached to a focus node to detect this.

focusScopeNode.addListener(_currentFocusListener);
}

void _currentFocusListener() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For some reason this wasn't giving up to date results when using tab navigation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am not so certain about why we need to remove this code. If this is indeed a bug fixes, we should have a test for this.

@jonahwilliams
jonahwilliams marked this pull request as ready for review July 7, 2021 22:48
@flutter-dashboard

Copy link
Copy Markdown

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 Hixie on the #hackers channel in Chat.

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.

@jonahwilliams

Copy link
Copy Markdown
Contributor Author

ahh, need to port over my old tests

BuildContext? _context;

/// An optional parent context that determines whether or not a primary pointer
/// gesture that missed the actual [context] should remove focus from the node.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you also document on when will this focus manager will remove focus from the node? will it do it when the parent context = null or will it do it when the parent context != null?

Also where the focus will go if this happen

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

expanded the comments here a bit

_clipboardStatus?.addListener(_onChangedClipboardStatus);
widget.controller.addListener(_didChangeTextEditingValue);
_focusAttachment = widget.focusNode.attach(context);
_focusAttachment = widget.focusNode.attach(context, contextBounds: widget.parentContext);

@chunhtai chunhtai Jul 7, 2021 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It looks like the hittest prioritizes context bounds to determine hittest rect, I wonder can it directly attach to the widget.parentContext if it is not null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thinking about this more, we might have some issues if editable text migrates to use a regular focus node since we won't have the attachment available.

Attaching to the parent context might work, but thinking about it more I'm not sure if we need to worry about reparenting. Surely you'd never re-parent the text field decoration apart from an editable text right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

third party libraries does crazy thing around editable text, I wouldn't be surprised if the editabletext gets reparented. but I think we should be able to reparent the attachment in didUpdateWidget?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Currently focus will be lost (at least according to my test cases)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yes, focusAttachment.detach will call unfocus on the focusnode. I think this is probably fine because this will be an edgy case where people keep swapping out the parent focus. We can fix it later if that actually cause issue.

@jonahwilliams
jonahwilliams requested a review from chunhtai July 8, 2021 18:44
focusScopeNode.addListener(_currentFocusListener);
}

void _currentFocusListener() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am not so certain about why we need to remove this code. If this is indeed a bug fixes, we should have a test for this.

/// than 1.
final ScrollBehavior? scrollBehavior;

/// Optionally, the parent build context if this editable text was built as part of

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Optionally, the parent build context if this editable text was built as part of
/// The optional parent build context if this editable text was built as part of

/// a larger text field.
///
/// If this is provided then focus will be attached to the parent context instead of
/// the editable text. If the [parentContext] is later modified while the editable text

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe also explain what's the different consequences to attach to this context vs parent context, and why developer may want to do that

@chunhtai

chunhtai commented Jul 8, 2021

Copy link
Copy Markdown
Contributor

The overall approach looks good to me, just some nits

@jonahwilliams

Copy link
Copy Markdown
Contributor Author

Good point, i need to investigate a bit more. i might be working around a focus bug, so finding the root cause first is probably ideal.

@jonahwilliams

Copy link
Copy Markdown
Contributor Author

moved the listener change to #86141

@jonahwilliams

Copy link
Copy Markdown
Contributor Author

I wasn't able to make the parent context work - it changed how actions/shortcuts were looked up in some non-obvious ways. I've gone back to tagging render objects with the focus node.

@jonahwilliams

Copy link
Copy Markdown
Contributor Author

This is ready for review

/// This area is conceptually part of the editable text, but not attached to the
/// focus context. The [FocusTrapArea] is used to inform the framework of this
/// relationship, so that primary pointer contact inside of this region but above
/// the editable text focus will not trigger loss of focus.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You might add a reference/description here for the focus trap and when it comes into play, etc. If I pretend that I just happened upon the API docs page for this widget, it feels like if I wasn't writing my own text widget I wouldn't quite know when to use it, or what it affects.

Since _FocusTrap isn't a public class, there's probably not much mention of it in other docs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I could make it public, no need to keep it private really

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

that would require me to document it a bit more, but no harm there

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The other option would be to make FocusTrapArea private, if you don't think anyone will need it outside of the text field (but it seems like they might).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

probably the cupertino text field needs it as well, as would other like the macos ui package - depending on whether or not they are editable text widget based

@jonahwilliams

Copy link
Copy Markdown
Contributor Author

I've updated the documentation and made focus trap/ focus area stuff public. ptAL @gspencergoog

@gspencergoog gspencergoog left a comment

Copy link
Copy Markdown
Contributor

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

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[desktop/web] TextField loses focus when pressing prefix or suffix button

4 participants