Skip to content

Conversation

@LongCatIsLooong
Copy link
Contributor

Fixes #76349.

Also cleaned up the updateEditingValue/userUpdateEditingValue
paths a bit. Hopefully we will be able to merge the two.

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. You must list at least one issue.

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, 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 feature I am adding, or Hixie said the 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.

selection/cause changes

Fixes flutter#76349.

Also cleaned up the `updateEditingValue`/`userUpdateEditingValue`
paths a bit. Hopefully we will be able to merge the two.
@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Aug 9, 2021
@google-cla google-cla bot added the cla: yes label Aug 9, 2021
@LongCatIsLooong LongCatIsLooong changed the title [EditableText] call onSelectionChanged when there's actual selection/cause changes [EditableText] call onSelectionChanged only when there're actual selection/cause changes Aug 9, 2021
bool _wasSelectingVerticallyWithKeyboard = false;

void _setTextEditingValue(TextEditingValue newValue, SelectionChangedCause cause) {
textSelectionDelegate.textEditingValue = newValue;
Copy link
Contributor

Choose a reason for hiding this comment

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

I kept this for backward compatibility, we should only remove it once we remove the deprecated setter textEditingValue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you elaborate? People are required to implement userUpdateTextEditingValue right? It's part of the TextSelectionDelegate interface.

Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't notice userUpdateTextEditingValue is abstract method. yeah this should be fine.

ScrollController? _scrollController;

late AnimationController _cursorBlinkOpacityController;
late final AnimationController _cursorBlinkOpacityController = AnimationController(vsync: this, duration: _fadeDuration);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we missed this but it should be disposed in the dispose method.
same for _floatingCursorResetController. I think the existing format is cleaner, it is weird the we give a default value in here and then attach listener in initState

Copy link
Contributor

Choose a reason for hiding this comment

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

Whoops good catch about the dispose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These should be fixed in #87973

Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved the addListener to the lazy initializer. My initial goal was to mark the property as final. I'll do the same for other animation controllers in #87973.

? _value.selection != value.selection
: _value != value;
if (shouldShowCaret) {
_scheduleShowCaretOnScreen();
Copy link
Contributor

Choose a reason for hiding this comment

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

I didnt get the logic, the _scheduleShowCaretOnScreen will be called in line 1770 anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I forgot to remove the existing _sheduleShowCaretOnScreen when copied the other one over.

await gesture.moveBy(const Offset(600, 0));
// To the edge of the screen basically.
await tester.pump();
await tester.pumpAndSettle();
Copy link
Contributor

Choose a reason for hiding this comment

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

where do we introduce frame delays?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's no need for these changes. Removed.

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 👍 . This was badly needed, thanks for cleaning this up.

void onDoubleTapDown(TapDownDetails details) {
if (delegate.selectionEnabled) {
renderEditable.selectWord(cause: SelectionChangedCause.tap);
renderEditable.selectWord(cause: SelectionChangedCause.doubleTap);
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch


await testTextEditing(tester, targetPlatform: defaultTargetPlatform);

debugKeyEventSimulatorTransitModeOverride = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you remove this line now that you have the teardown?

Copy link
Contributor

Choose a reason for hiding this comment

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

Same with the next test below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This doesn't seem to work, _verifyInvariants is called before the the tear down callbacks are invoked.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah ok interesting, best to keep both then 👍

index++;
}

expect(
Copy link
Contributor

Choose a reason for hiding this comment

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

Slick 😎

expect(selection, const TextSelection(baseOffset: 1, extentOffset: 2));
expect(cause, SelectionChangedCause.keyboard);

// Selection and cause both changed
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: period here.

Comment on lines -1885 to +1890
_handleSelectionChanged(TextSelection.collapsed(offset: _lastTextPosition!.offset), SelectionChangedCause.forcePress);
final TextEditingValue newValue = _value.copyWith(
selection: TextSelection.fromPosition(_lastTextPosition!),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

The new code preserves the TextAffinity of _lastTextPosition, but the old code didn't. Probably better this way but something to be aware of.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The floating cursor stuff currently doesn't care much about affinity (e.g., final TextPosition currentTextPosition = TextPosition(offset: renderEditable.selection!.baseOffset);). I'm hoping we can take cursor handling out of EditableTextState and maybe clean floating cursor a bit in the process.

Rect? composingRect = renderEditable.getRectForComposingRange(composingRange);
// Send the caret location instead if there's no marked text yet.
if (composingRect == null) {
assert(!composingRange.isValid || composingRange.isCollapsed);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this assert removed?

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 must have thought getRectForComposingRange only returns null only when !composingRange.isValid || composingRange.isCollapsed is true but if getBoxesForSelection returns an empty list that method returns null too. It's triggered in one of the tests so I removed it.

Comment on lines +2533 to +2537
// This method is similar to updateEditingValue, but is used to handle user
// input caused by hardware keyboard events and gesture events, while
// updateEditingValue handles IME/software keyboard input.
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for adding the comment here!

_currentPromptRectRange = null;

if (_hasInputConnection) {
if (widget.obscureText && value.text.length == _value.text.length + 1) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I got really worried about extended grapheme clusters and obscured fields when I saw this + 1 here (even though I know it has nothing to do with this PR). Indeed they show up as multiple characters when entered into an obscured field and don't have a delay, but it turns out that's the behavior on native too 🤷 . All is well.

ScrollController? _scrollController;

late AnimationController _cursorBlinkOpacityController;
late final AnimationController _cursorBlinkOpacityController = AnimationController(vsync: this, duration: _fadeDuration);
Copy link
Contributor

Choose a reason for hiding this comment

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

Whoops good catch about the dispose.

@LongCatIsLooong LongCatIsLooong force-pushed the remove-excessive-onSelectionChanged-calls branch from b04b362 to d751b73 Compare August 12, 2021 07:16
@LongCatIsLooong LongCatIsLooong force-pushed the remove-excessive-onSelectionChanged-calls branch from d751b73 to f674e17 Compare August 12, 2021 21:29
@fluttergithubbot fluttergithubbot merged commit 6e224ee into flutter:master Aug 13, 2021
@LongCatIsLooong LongCatIsLooong deleted the remove-excessive-onSelectionChanged-calls branch August 13, 2021 00:34
LongCatIsLooong added a commit that referenced this pull request Aug 13, 2021
…ctual selection/cause changes (#87971)"

This reverts commit 6e224ee.
fluttergithubbot pushed a commit that referenced this pull request Aug 14, 2021
blasten pushed a commit to blasten/flutter that referenced this pull request Aug 19, 2021
blasten pushed a commit to blasten/flutter that referenced this pull request Aug 19, 2021
@HansMuller HansMuller changed the title [EditableText] call onSelectionChanged only when there're actual selection/cause changes [EditableText] call onSelectionChanged only when there are actual selection/cause changes Aug 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EditableText calls onSelectionChanged even if the selection does not change.

4 participants