-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Caret location improvements #113268
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
Caret location improvements #113268
Conversation
| const _CaretMetrics({required this.offset, required this.fullHeight}); | ||
| /// The offset of the top start corner of the caret from the top left | ||
| /// corner of the paragraph. | ||
| final Offset offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're currently always painting to the right of this offset regardless of the writing direction. That's probably not right.
|
Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change). If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. Changes reported for pull request #113268 at sha 67a99e9a35e11c279db4d901b59c485ec129af16 |
|
4.1K scuba changes but nothing stood out. |
67a99e9 to
d03f6fc
Compare
justinmc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know what's going on with the scuba changes? I see that you changed a few pixel values in the tests. Should the caret height be the only thing that changed visually?
| } | ||
|
|
||
| // Returns true iff the given value is a valid UTF-16 surrogate. The value | ||
| // Returns true iff the given value is a valid UTF-16 high surrogate. The value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
| // Returns null when the range [start, end) does not contain a full grapheme | ||
| // in the paragrah. | ||
| static _CaretMetrics? _caretMetricsFromTextBox(int start, int end, TextAffinity affinity, ui.Paragraph paragraph) { | ||
| assert(end > start, '$end > $start'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Maybe '$end must be greater than $start'.
| // | ||
| // Returns null when the range [start, end) does not contain a full grapheme | ||
| // in the paragrah. | ||
| static _CaretMetrics? _caretMetricsFromTextBox(int start, int end, TextAffinity affinity, ui.Paragraph paragraph) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly does the affinity mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see it's used to indicate direction elsewhere in this PR. Maybe it's a standard thing or maybe it requires a little bit more description in these comments.
| final int? nextCodeUnit = _text!.codeUnitAt(min(offset, flattenedText.length - 1)); | ||
| if (nextCodeUnit == null) { | ||
| // Search for graphemes in the paragraph in the given range, and exponentially | ||
| // expands the search range if there are no graphemes in the current range |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"expands" => "expand"
| // Search for graphemes in the paragraph in the given range, and exponentially | ||
| // expands the search range if there are no graphemes in the current range | ||
| // until a grapheme is found. Return the _CaretMetrics based on the TextBox | ||
| // of that grapheme. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Maybe mention that this can also be expensive if that's true. I see it calls _caretMetricsFromTextBox.
| /// | ||
| /// Valid only after [layout] has been called. | ||
| Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) { | ||
| return (_computeCaretMetrics(position) ?? _fallbakCaretMetrics).offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"_fallbak" => "_fallback"
| // Checks if the [position] and [caretPrototype] have changed from the cached | ||
| // version and recomputes the metrics required to position the caret. | ||
| void _computeCaretMetrics(TextPosition position, Rect caretPrototype) { | ||
| // the metrics required to position the caret. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"the" => "The"
Or maybe I'm reading this wrong with all of the deletions.
| // TODO(LongCatIsLooong): introduce ui.Paragraph-level api for this. The | ||
| // exponential search using getBoxesForRange isn't necessary and does not | ||
| // work well for certian edge cases (e.g., when the position is inside a | ||
| // glyph, and the previous character is a newline character). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Consider linking/creating a GitHub issue here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be taken care of in the new paragraph api. But I don't think there's a github issue.
| // TODO(LongCatIsLooong): ui.Paragraph.width always reports the input | ||
| // width. The double layout keeps the two width in sync so TextPainter | ||
| // does not have to work with a non-zero paint offset. SkParagraph | ||
| // invalidates the layout entirely in this case so this is expensive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we create an issue for this? Or maybe it's not possible or easy to reproduce a userland bug caused by this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one important use case that has to be covered in the new paragraph API. I'll describe that in the design doc instead.
| // Cache the input parameters to prevent repeat work later. | ||
| _previousCaretPosition = position; | ||
| _previousCaretPrototype = caretPrototype; | ||
| return _cachedCaretMetrics = caretMetrics; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you change this to both return and assign?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
caretPrototype doesn't affect the anchoring of the caret and it's not expensive at all to compute, there's no need to invalidate the cache over that.
| final bool done = (searchStep > 0 || start <= 0) | ||
| && (searchStep < 0 || text.codeUnitAt(end) == null); | ||
|
|
||
| // Exapnds the search region exponentially if we need to keep searching. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exapnds -> Expands
| return _cachedCaretMetrics; | ||
| } | ||
| final InlineSpan text = _text!; | ||
| // Special case: the text is emtpy. ui.Paragraph returns a TextBox located |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
emtpy -> empty
d28cd63 to
de812d0
Compare
de812d0 to
c815d6e
Compare
|
This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
|
I think this also fixes #64072 |
|
@LongCatIsLooong Are you still planning to merge this? Sorry I never gave a final review. Looks like it needs to be merged with master now. |
|
I'll get back to this once needed lower-level APIs are exposed in ui.Paragraph. |
toPlainText, as it could be expensive.getLocalRectForCaretnow reports the real rect that will be painted.Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.