Loading core/java/android/text/Layout.java +48 −9 Original line number Diff line number Diff line Loading @@ -792,8 +792,17 @@ public abstract class Layout { * the paragraph's primary direction. */ public float getPrimaryHorizontal(int offset) { return getPrimaryHorizontal(offset, false /* not clamped */); } /** * Get the primary horizontal position for the specified text offset, but * optionally clamp it so that it doesn't exceed the width of the layout. * @hide */ public float getPrimaryHorizontal(int offset, boolean clamped) { boolean trailing = primaryIsTrailingPrevious(offset); return getHorizontal(offset, trailing); return getHorizontal(offset, trailing, clamped); } /** Loading @@ -802,17 +811,26 @@ public abstract class Layout { * the direction other than the paragraph's primary direction. */ public float getSecondaryHorizontal(int offset) { return getSecondaryHorizontal(offset, false /* not clamped */); } /** * Get the secondary horizontal position for the specified text offset, but * optionally clamp it so that it doesn't exceed the width of the layout. * @hide */ public float getSecondaryHorizontal(int offset, boolean clamped) { boolean trailing = primaryIsTrailingPrevious(offset); return getHorizontal(offset, !trailing); return getHorizontal(offset, !trailing, clamped); } private float getHorizontal(int offset, boolean trailing) { private float getHorizontal(int offset, boolean trailing, boolean clamped) { int line = getLineForOffset(offset); return getHorizontal(offset, trailing, line); return getHorizontal(offset, trailing, line, clamped); } private float getHorizontal(int offset, boolean trailing, int line) { private float getHorizontal(int offset, boolean trailing, int line, boolean clamped) { int start = getLineStart(line); int end = getLineEnd(line); int dir = getParagraphDirection(line); Loading @@ -834,6 +852,9 @@ public abstract class Layout { float wid = tl.measure(offset - start, trailing, null); TextLine.recycle(tl); if (clamped && wid > mWidth) { wid = mWidth; } int left = getParagraphLeft(line); int right = getParagraphRight(line); Loading Loading @@ -1256,6 +1277,23 @@ public abstract class Layout { return offset; } /** * Determine whether we should clamp cursor position. Currently it's * only robust for left-aligned displays. * @hide */ public boolean shouldClampCursor(int line) { // Only clamp cursor position in left-aligned displays. switch (getParagraphAlignment(line)) { case ALIGN_LEFT: return true; case ALIGN_NORMAL: return getParagraphDirection(line) > 0; default: return false; } } /** * Fills in the specified Path with a representation of a cursor * at the specified offset. This will often be a vertical line Loading @@ -1270,8 +1308,9 @@ public abstract class Layout { int top = getLineTop(line); int bottom = getLineTop(line+1); float h1 = getPrimaryHorizontal(point) - 0.5f; float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point) - 0.5f : h1; boolean clamped = shouldClampCursor(line); float h1 = getPrimaryHorizontal(point, clamped) - 0.5f; float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point, clamped) - 0.5f : h1; int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) | TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING); Loading Loading @@ -1357,8 +1396,8 @@ public abstract class Layout { int en = Math.min(end, there); if (st != en) { float h1 = getHorizontal(st, false, line); float h2 = getHorizontal(en, true, line); float h1 = getHorizontal(st, false, line, false /* not clamped */); float h2 = getHorizontal(en, true, line, false /* not clamped */); float left = Math.min(h1, h2); float right = Math.max(h1, h2); Loading core/java/android/widget/Editor.java +9 −5 Original line number Diff line number Diff line Loading @@ -1468,20 +1468,24 @@ public class Editor { middle = (top + bottom) >> 1; } updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset)); boolean clamped = layout.shouldClampCursor(line); updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset, clamped)); if (mCursorCount == 2) { updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset)); updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset, clamped)); } } private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset) { private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset, boolean clamped) { if (TextUtils.isEmpty(layout.getText()) && hintLayout != null && !TextUtils.isEmpty(hintLayout.getText())) { return hintLayout.getPrimaryHorizontal(offset); return hintLayout.getPrimaryHorizontal(offset, clamped); } else { return layout.getPrimaryHorizontal(offset); return layout.getPrimaryHorizontal(offset, clamped); } } Loading core/java/android/widget/TextView.java +24 −9 Original line number Diff line number Diff line Loading @@ -6553,15 +6553,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int line = layout.getLineForOffset(offset); // FIXME: Is it okay to truncate this, or should we round? final int x = (int)layout.getPrimaryHorizontal(offset); final int top = layout.getLineTop(line); final int bottom = layout.getLineTop(line + 1); int left = (int) FloatMath.floor(layout.getLineLeft(line)); int right = (int) FloatMath.ceil(layout.getLineRight(line)); int ht = layout.getHeight(); int grav; switch (layout.getParagraphAlignment(line)) { Loading @@ -6583,8 +6574,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; } // We only want to clamp the cursor to fit within the layout width // in left-to-right modes, because in a right to left alignment, // we want to scroll to keep the line-right on the screen, as other // lines are likely to have text flush with the right margin, which // we want to keep visible. // A better long-term solution would probably be to measure both // the full line and a blank-trimmed version, and, for example, use // the latter measurement for centering and right alignment, but for // the time being we only implement the cursor clamping in left to // right where it is most likely to be annoying. final boolean clamped = grav > 0; // FIXME: Is it okay to truncate this, or should we round? final int x = (int)layout.getPrimaryHorizontal(offset, clamped); final int top = layout.getLineTop(line); final int bottom = layout.getLineTop(line + 1); int left = (int) FloatMath.floor(layout.getLineLeft(line)); int right = (int) FloatMath.ceil(layout.getLineRight(line)); int ht = layout.getHeight(); int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(); int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom(); if (!mHorizontallyScrolling && right - left > hspace && right > x) { // If cursor has been clamped, make sure we don't scroll. right = Math.max(x, left + hspace); } int hslack = (bottom - top) / 2; int vslack = hslack; Loading Loading
core/java/android/text/Layout.java +48 −9 Original line number Diff line number Diff line Loading @@ -792,8 +792,17 @@ public abstract class Layout { * the paragraph's primary direction. */ public float getPrimaryHorizontal(int offset) { return getPrimaryHorizontal(offset, false /* not clamped */); } /** * Get the primary horizontal position for the specified text offset, but * optionally clamp it so that it doesn't exceed the width of the layout. * @hide */ public float getPrimaryHorizontal(int offset, boolean clamped) { boolean trailing = primaryIsTrailingPrevious(offset); return getHorizontal(offset, trailing); return getHorizontal(offset, trailing, clamped); } /** Loading @@ -802,17 +811,26 @@ public abstract class Layout { * the direction other than the paragraph's primary direction. */ public float getSecondaryHorizontal(int offset) { return getSecondaryHorizontal(offset, false /* not clamped */); } /** * Get the secondary horizontal position for the specified text offset, but * optionally clamp it so that it doesn't exceed the width of the layout. * @hide */ public float getSecondaryHorizontal(int offset, boolean clamped) { boolean trailing = primaryIsTrailingPrevious(offset); return getHorizontal(offset, !trailing); return getHorizontal(offset, !trailing, clamped); } private float getHorizontal(int offset, boolean trailing) { private float getHorizontal(int offset, boolean trailing, boolean clamped) { int line = getLineForOffset(offset); return getHorizontal(offset, trailing, line); return getHorizontal(offset, trailing, line, clamped); } private float getHorizontal(int offset, boolean trailing, int line) { private float getHorizontal(int offset, boolean trailing, int line, boolean clamped) { int start = getLineStart(line); int end = getLineEnd(line); int dir = getParagraphDirection(line); Loading @@ -834,6 +852,9 @@ public abstract class Layout { float wid = tl.measure(offset - start, trailing, null); TextLine.recycle(tl); if (clamped && wid > mWidth) { wid = mWidth; } int left = getParagraphLeft(line); int right = getParagraphRight(line); Loading Loading @@ -1256,6 +1277,23 @@ public abstract class Layout { return offset; } /** * Determine whether we should clamp cursor position. Currently it's * only robust for left-aligned displays. * @hide */ public boolean shouldClampCursor(int line) { // Only clamp cursor position in left-aligned displays. switch (getParagraphAlignment(line)) { case ALIGN_LEFT: return true; case ALIGN_NORMAL: return getParagraphDirection(line) > 0; default: return false; } } /** * Fills in the specified Path with a representation of a cursor * at the specified offset. This will often be a vertical line Loading @@ -1270,8 +1308,9 @@ public abstract class Layout { int top = getLineTop(line); int bottom = getLineTop(line+1); float h1 = getPrimaryHorizontal(point) - 0.5f; float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point) - 0.5f : h1; boolean clamped = shouldClampCursor(line); float h1 = getPrimaryHorizontal(point, clamped) - 0.5f; float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point, clamped) - 0.5f : h1; int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) | TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING); Loading Loading @@ -1357,8 +1396,8 @@ public abstract class Layout { int en = Math.min(end, there); if (st != en) { float h1 = getHorizontal(st, false, line); float h2 = getHorizontal(en, true, line); float h1 = getHorizontal(st, false, line, false /* not clamped */); float h2 = getHorizontal(en, true, line, false /* not clamped */); float left = Math.min(h1, h2); float right = Math.max(h1, h2); Loading
core/java/android/widget/Editor.java +9 −5 Original line number Diff line number Diff line Loading @@ -1468,20 +1468,24 @@ public class Editor { middle = (top + bottom) >> 1; } updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset)); boolean clamped = layout.shouldClampCursor(line); updateCursorPosition(0, top, middle, getPrimaryHorizontal(layout, hintLayout, offset, clamped)); if (mCursorCount == 2) { updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset)); updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset, clamped)); } } private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset) { private float getPrimaryHorizontal(Layout layout, Layout hintLayout, int offset, boolean clamped) { if (TextUtils.isEmpty(layout.getText()) && hintLayout != null && !TextUtils.isEmpty(hintLayout.getText())) { return hintLayout.getPrimaryHorizontal(offset); return hintLayout.getPrimaryHorizontal(offset, clamped); } else { return layout.getPrimaryHorizontal(offset); return layout.getPrimaryHorizontal(offset, clamped); } } Loading
core/java/android/widget/TextView.java +24 −9 Original line number Diff line number Diff line Loading @@ -6553,15 +6553,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int line = layout.getLineForOffset(offset); // FIXME: Is it okay to truncate this, or should we round? final int x = (int)layout.getPrimaryHorizontal(offset); final int top = layout.getLineTop(line); final int bottom = layout.getLineTop(line + 1); int left = (int) FloatMath.floor(layout.getLineLeft(line)); int right = (int) FloatMath.ceil(layout.getLineRight(line)); int ht = layout.getHeight(); int grav; switch (layout.getParagraphAlignment(line)) { Loading @@ -6583,8 +6574,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; } // We only want to clamp the cursor to fit within the layout width // in left-to-right modes, because in a right to left alignment, // we want to scroll to keep the line-right on the screen, as other // lines are likely to have text flush with the right margin, which // we want to keep visible. // A better long-term solution would probably be to measure both // the full line and a blank-trimmed version, and, for example, use // the latter measurement for centering and right alignment, but for // the time being we only implement the cursor clamping in left to // right where it is most likely to be annoying. final boolean clamped = grav > 0; // FIXME: Is it okay to truncate this, or should we round? final int x = (int)layout.getPrimaryHorizontal(offset, clamped); final int top = layout.getLineTop(line); final int bottom = layout.getLineTop(line + 1); int left = (int) FloatMath.floor(layout.getLineLeft(line)); int right = (int) FloatMath.ceil(layout.getLineRight(line)); int ht = layout.getHeight(); int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(); int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom(); if (!mHorizontallyScrolling && right - left > hspace && right > x) { // If cursor has been clamped, make sure we don't scroll. right = Math.max(x, left + hspace); } int hslack = (bottom - top) / 2; int vslack = hslack; Loading