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

Right aligned backspace bug #25229

Merged
merged 7 commits into from
Dec 20, 2018

Conversation

justinmc
Copy link
Contributor

@justinmc justinmc commented Dec 11, 2018

Closes #25199

In an input with textAlign: TextAlign.right with the cursor in the middle of the text:

    133333344444444448|4

Deleting until the end of the line caused the cursor to jump to the far right:

...
                    13|4
                     1|4
                       4|

This PR fixes it so the cursor stays in the correct place, so in this example it would be:

                      |4

I also encountered related bugs with multiline inputs while working on this. When going to an empty new line with text align set to right, the cursor would jump back over to the far left. These bugs seem to be fixed with this change as well.

@justinmc justinmc self-assigned this Dec 11, 2018
@justinmc justinmc requested a review from HansMuller December 11, 2018 19:25
@justinmc
Copy link
Contributor Author

@HansMuller Does it seem reasonable that this could just be an off by one error as in my code change? Can you explain what _getOffsetFromDownstream and _getOffsetFromUpstream are supposed to calculate exactly if you know? I'm worried that I misunderstand how simple this is and my fix will break other things.

@zoechi zoechi added a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels. labels Dec 12, 2018
@justinmc justinmc force-pushed the text-field-right-backspace branch 2 times, most recently from 48c436d to 27f788e Compare December 14, 2018 16:43
@justinmc justinmc changed the title WIP right aligned backspace bug Right aligned backspace bug Dec 14, 2018
@justinmc
Copy link
Contributor Author

@HansMuller This is ready for a real review now. Several tests were expecting incorrect behavior, so that's what all the lines changed in the test are.

@justinmc justinmc force-pushed the text-field-right-backspace branch from 27f788e to 73a3110 Compare December 14, 2018 17:07
Copy link
Contributor

@HansMuller HansMuller left a comment

Choose a reason for hiding this comment

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

As far as I can tell, this all looks correct. LGTM

It would be helpful to add some additional explanation to the TextAffinity enum doc, particularly about white space, implicit newlines ("forced line breaks"), genuine newlines, and bidi text. Many of the corner cases covered by the tests probably deserve a sentence or two. Given that, other places that would benefit from the clarification, like the TextPosition class, could remind readers to "See Also" the TextAfinity class for more information about cursor positioning...

Updating the TextAffinity et al docs could be a separate PR.


// When text wraps on its own, getOffsetForCaret disambiguates between the
// end of one line and start of next using affinity.
text = 'aaaaaaaa'; // Just enough to wrap one character down to second line
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume that this wraps because SIZE_OF_A * 8 (112) is wider than the layout width of 100, specified below. Maybe add a comment on the painter.layout line explaining what's up here.

// Correctly moves through second line with upstream affinity.
caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 4, affinity: TextAffinity.upstream), ui.Rect.zero);
expect(caretOffset.dx, closeTo(42.0, 0.0001));
// Check that getOffsetForCaret handles being at the end when affinity is
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 it would be better to explain what the test is checking, like the previous test does (and the next one as well). Something like: Given a one-line right aligned string, positioning the cursor at offset 0 means that it appears at the "end" of the string, at x = 0.


// Correctly handles multiple trailing newlines.
// Correctly handles multiple trailing newlines with the same offset
Copy link
Contributor

Choose a reason for hiding this comment

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

As before, best to explain what we expect here.

@justinmc
Copy link
Contributor Author

@HansMuller I just improved the comments and cleaned the tests up a bit. I'll open a PR in the engine to improve the TextAffinity docs and reference it here.

@justinmc
Copy link
Contributor Author

@GaryQian Heads up that I'm changing similar code in text_painter.dart to what you just changed. I just merged your changes into this PR and I think it went well though. I think you and I were partially fixing the same bug in _getOffsetFromDownstream. I really just added this check for an edge case and cleaned up the tests a bit. They seemed to be mistaking newline characters and wrapping, which has different behavior with TextAffinity.

final double caretEnd = box.end;
final double dx = box.direction == TextDirection.rtl ? caretEnd - caretPrototype.width : caretEnd;
return Offset(dx, box.top);
}
return null;
}

// Get the Offset of the cursor (in pixels) based off the near edge of the
Copy link
Contributor

Choose a reason for hiding this comment

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

May want to distinguish between logical vs physical pixels, as 'pixels' may be ambiguous. In this case I think everything should be logical pixels.

@@ -417,12 +417,15 @@ class TextPainter {
// Unicode value for a zero width joiner character.
static const int _zwjUtf16 = 0x200d;

// Get the Offset of the cursor (in pixels) based off the near edge of the
Copy link
Contributor

Choose a reason for hiding this comment

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

See below

@justinmc
Copy link
Contributor Author

@GaryQian I clarified "logical pixels" in the docs like you mentioned, but I couldn't find a better way to check for newlines other than the integer value 10. It looks like \r is also a typical newline value for example, but it is displayed as a space in our text fields and not as a newline, so we shouldn't match it here. Let me know if you can think of anything else though.

@justinmc justinmc merged commit ca8ba58 into flutter:master Dec 20, 2018
@justinmc justinmc deleted the text-field-right-backspace branch December 20, 2018 19:03
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TextField and TextFormField could not clear all the text in some situation
5 participants