Skip to content

Commit 7c023fa

Browse files
yukawaAndroid (Google) Code Review
authored andcommitted
Merge "Fix handling of line-end and RTL characters in CursorAnchorInfo" into lmp-dev
2 parents 01db916 + 987eb3f commit 7c023fa

1 file changed

Lines changed: 23 additions & 16 deletions

File tree

core/java/android/widget/Editor.java

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3080,40 +3080,47 @@ public void updatePosition(int parentPositionX, int parentPositionY,
30803080
composingTextEnd);
30813081
builder.setComposingText(composingTextStart, composingText);
30823082
}
3083+
// TODO: Optimize this loop by caching the result.
30833084
for (int offset = composingTextStart; offset < composingTextEnd; offset++) {
30843085
if (offset < 0) {
30853086
continue;
30863087
}
3088+
final boolean isRtl = layout.isRtlCharAt(offset);
30873089
final int line = layout.getLineForOffset(offset);
3088-
final float left = layout.getPrimaryHorizontal(offset)
3090+
final int nextCharIndex = offset + 1;
3091+
final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset);
3092+
final float localTrailingEdgeX;
3093+
if (nextCharIndex != layout.getLineEnd(line)) {
3094+
localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex);
3095+
} else if (isRtl) {
3096+
localTrailingEdgeX = layout.getLineLeft(line);
3097+
} else {
3098+
localTrailingEdgeX = layout.getLineRight(line);
3099+
}
3100+
final float leadingEdgeX = localLeadingEdgeX
30893101
+ viewportToContentHorizontalOffset;
3090-
final float top = layout.getLineTop(line) + viewportToContentVerticalOffset;
3091-
// Here we are tentatively passing offset + 1 to calculate the other side of
3092-
// the primary horizontal to preserve as many positions as possible so that
3093-
// the IME can reconstruct the layout entirely. However, we should revisit this
3094-
// to have a clear specification about the relationship between the index of
3095-
// the character and its bounding box. See also the TODO comment below.
3096-
final float right = layout.getPrimaryHorizontal(offset + 1)
3102+
final float trailingEdgeX = localTrailingEdgeX
30973103
+ viewportToContentHorizontalOffset;
3104+
final float top = layout.getLineTop(line) + viewportToContentVerticalOffset;
30983105
final float bottom = layout.getLineBottom(line)
30993106
+ viewportToContentVerticalOffset;
3100-
// Take TextView's padding and scroll into account.
31013107
// TODO: Check right-top and left-bottom as well.
3102-
final boolean leftTopVisible = isPositionVisible(left, top);
3103-
final boolean rightBottomVisible = isPositionVisible(right, bottom);
3108+
final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
3109+
final boolean isTrailingEdgeBottomVisible =
3110+
isPositionVisible(trailingEdgeX, bottom);
31043111
final int characterRectFlags;
3105-
if (leftTopVisible && rightBottomVisible) {
3112+
if (isLeadingEdgeTopVisible && isTrailingEdgeBottomVisible) {
31063113
characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
3107-
} else if (leftTopVisible || rightBottomVisible) {
3114+
} else if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
31083115
characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
31093116
} else {
31103117
characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
31113118
}
31123119
// Here offset is the index in Java chars.
31133120
// TODO: We must have a well-defined specification. For example, how
3114-
// RTL, surrogate pairs, and composition letters are handled must be
3115-
// documented.
3116-
builder.addCharacterRect(offset, left, top, right, bottom, characterRectFlags);
3121+
// surrogate pairs and composition letters are handled must be documented.
3122+
builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom,
3123+
characterRectFlags);
31173124
}
31183125
}
31193126

0 commit comments

Comments
 (0)