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.
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.
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 |
| // 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.
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.
What exactly does the affinity mean here?
There was a problem hiding this comment.
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 |
| // 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.
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.
"_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.
"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.
Nit: Consider linking/creating a GitHub issue here.
There was a problem hiding this comment.
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.
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.
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.
Why did you change this to both return and assign?
There was a problem hiding this comment.
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. |
| return _cachedCaretMetrics; | ||
| } | ||
| final InlineSpan text = _text!; | ||
| // Special case: the text is emtpy. ui.Paragraph returns a TextBox located |
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.