Loading core/java/android/widget/Editor.java +60 −22 Original line number Diff line number Diff line Loading @@ -154,6 +154,10 @@ public class Editor { // Specifies whether to use the magnifier when pressing the insertion or selection handles. private static final boolean FLAG_USE_MAGNIFIER = true; // Specifies how far to make the cursor start float when drag the cursor away from the // beginning or end of the line. private static final int CURSOR_START_FLOAT_DISTANCE_PX = 20; private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000; private static final int RECENT_CUT_COPY_DURATION_MS = 15 * 1000; // 15 seconds in millis Loading Loading @@ -289,6 +293,9 @@ public class Editor { private boolean mRenderCursorRegardlessTiming; private Blink mBlink; // Whether to let magnifier draw cursor on its surface. This is for floating cursor effect. // And it can only be true when |mNewMagnifierEnabled| is true. private boolean mDrawCursorOnMagnifier; boolean mCursorVisible = true; boolean mSelectAllOnFocus; boolean mTextIsSelectable; Loading Loading @@ -890,7 +897,7 @@ public class Editor { } boolean enabled = windowSupportsHandles && mTextView.getLayout() != null; mInsertionControllerEnabled = enabled && isCursorVisible(); mInsertionControllerEnabled = enabled && (mDrawCursorOnMagnifier || isCursorVisible()); mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected(); if (!mInsertionControllerEnabled) { Loading Loading @@ -5101,14 +5108,25 @@ public class Editor { final int[] textViewLocationOnScreen = new int[2]; mTextView.getLocationOnScreen(textViewLocationOnScreen); final float touchXInView = event.getRawX() - textViewLocationOnScreen[0]; float leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); float rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) { float leftBound, rightBound; if (mNewMagnifierEnabled) { leftBound = 0; rightBound = mTextView.getWidth(); if (touchXInView < leftBound || touchXInView > rightBound) { // The touch is too far from the current line / selection, so hide the magnifier. return false; } } else { leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) { leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset); } else { leftBound += mTextView.getLayout().getLineLeft(lineNumber); } if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) { if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) { rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset); } else { rightBound += mTextView.getLayout().getLineRight(lineNumber); Loading @@ -5122,6 +5140,7 @@ public class Editor { // The touch is too far from the current line / selection, so hide the magnifier. return false; } } final float scaledTouchXInView; if (mTextViewScaleX == 1f) { Loading Loading @@ -5178,7 +5197,8 @@ public class Editor { final Rect magnifierRect = new Rect(magnifierTopLeft.x, magnifierTopLeft.y, magnifierTopLeft.x + mMagnifierAnimator.mMagnifier.getWidth(), magnifierTopLeft.y + mMagnifierAnimator.mMagnifier.getHeight()); setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect)); setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect) && !mDrawCursorOnMagnifier); final HandleView otherHandle = getOtherSelectionHandle(); if (otherHandle != null) { otherHandle.setVisible(!handleOverlapsMagnifier(otherHandle, magnifierRect)); Loading Loading @@ -5208,7 +5228,20 @@ public class Editor { lineLeft += mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); int lineRight = (int) layout.getLineRight(line); lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight); mDrawCursorOnMagnifier = showPosInView.x < lineLeft - CURSOR_START_FLOAT_DISTANCE_PX || showPosInView.x > lineRight + CURSOR_START_FLOAT_DISTANCE_PX; mMagnifierAnimator.mMagnifier.setDrawCursor( mDrawCursorOnMagnifier, mDrawableForCursor); boolean cursorVisible = mCursorVisible; // Updates cursor visibility, so that the real cursor and the float cursor on // magnifier surface won't appear at the same time. mCursorVisible = !mDrawCursorOnMagnifier; if (mCursorVisible && !cursorVisible) { // When the real cursor is a drawable, hiding/showing it would change its // bounds. So, call updateCursorPosition() to correct its position. updateCursorPosition(); } final int lineHeight = layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line); float zoom = mInitialZoom; Loading @@ -5230,6 +5263,11 @@ public class Editor { if (mMagnifierAnimator != null) { mMagnifierAnimator.dismiss(); mRenderCursorRegardlessTiming = false; mDrawCursorOnMagnifier = false; if (!mCursorVisible) { mCursorVisible = true; mTextView.invalidate(); } resumeBlink(); setVisible(true); final HandleView otherHandle = getOtherSelectionHandle(); Loading core/java/android/widget/Magnifier.java +32 −21 Original line number Diff line number Diff line Loading @@ -149,9 +149,6 @@ public final class Magnifier { private int mLeftCutWidth = 0; // The width of the cut region on the right edge of the pixel copy source rect. private int mRightCutWidth = 0; // The horizontal bounds of the content source in pixels, relative to the view. private int mLeftBound = Integer.MIN_VALUE; private int mRightBound = Integer.MAX_VALUE; // The width of the ramp region in pixels on the left & right sides of the fish-eye effect. private final int mRamp; Loading Loading @@ -243,18 +240,6 @@ public final class Magnifier { sPixelCopyHandlerThread.start(); } /** * Sets the horizontal bounds of the source when showing the magnifier. * This is used for new style magnifier. e.g. limit the source bounds by the text line bounds. * * @param left the left of the bounds, relative to the view. * @param right the right of the bounds, relative to the view. */ void setSourceHorizontalBounds(int left, int right) { mLeftBound = left; mRightBound = right; } /** * Shows the magnifier on the screen. The method takes the coordinates of the center * of the content source going to be magnified and copied to the magnifier. The coordinates Loading @@ -280,6 +265,14 @@ public final class Magnifier { sourceCenterY + mDefaultVerticalSourceToMagnifierOffset); } private Drawable mCursorDrawable; private boolean mDrawCursorEnabled; void setDrawCursor(boolean enabled, Drawable cursorDrawable) { mDrawCursorEnabled = enabled; mCursorDrawable = cursorDrawable; } /** * Shows the magnifier on the screen at a position that is independent from its content * position. The first two arguments represent the coordinates of the center of the Loading Loading @@ -309,8 +302,7 @@ public final class Magnifier { magnifierCenterX = mClampedCenterZoomCoords.x - mViewCoordinatesInSurface[0]; magnifierCenterY = mClampedCenterZoomCoords.y - mViewCoordinatesInSurface[1]; // mLeftBound & mRightBound (typically the text line left/right) is for magnified // content. However the PixelCopy requires the pre-magnified bounds. // PixelCopy requires the pre-magnified bounds. // The below logic calculates the leftBound & rightBound for the pre-magnified bounds. final float rampPre = (mSourceWidth - (mSourceWidth - 2 * mRamp) / mZoom) / 2; Loading @@ -318,7 +310,7 @@ public final class Magnifier { // Calculates the pre-zoomed left edge. // The leftEdge moves from the left of view towards to sourceCenterX, considering the // fisheye-like zooming. final float x0 = sourceCenterX - mSourceWidth / 2; final float x0 = sourceCenterX - mSourceWidth / 2f; final float rampX0 = x0 + mRamp; float leftEdge = 0; if (leftEdge > rampX0) { Loading @@ -330,12 +322,12 @@ public final class Magnifier { // increase per ramp zoom (ramp / rampPre). leftEdge = x0 + rampPre - (rampX0 - leftEdge) * rampPre / mRamp; } int leftBound = Math.min(Math.max((int) leftEdge, mLeftBound), mRightBound); int leftBound = Math.min((int) leftEdge, mView.getWidth()); // Calculates the pre-zoomed right edge. // The rightEdge moves from the right of view towards to sourceCenterX, considering the // fisheye-like zooming. final float x1 = sourceCenterX + mSourceWidth / 2; final float x1 = sourceCenterX + mSourceWidth / 2f; final float rampX1 = x1 - mRamp; float rightEdge = mView.getWidth(); if (rightEdge < rampX1) { Loading @@ -347,7 +339,7 @@ public final class Magnifier { // increase per ramp zoom (ramp / rampPre). rightEdge = x1 - rampPre + (rightEdge - rampX1) * rampPre / mRamp; } int rightBound = Math.max(leftBound, Math.min((int) rightEdge, mRightBound)); int rightBound = Math.max(leftBound, (int) rightEdge); // Gets the startX for new style, which should be bounded by the horizontal bounds. // Also calculates the left/right cut width for pixel copy. Loading Loading @@ -772,6 +764,23 @@ public final class Magnifier { } } private void maybeDrawCursor(Canvas canvas) { if (mDrawCursorEnabled) { if (mCursorDrawable != null) { mCursorDrawable.setBounds( mSourceWidth / 2, 0, mSourceWidth / 2 + mCursorDrawable.getIntrinsicWidth(), mSourceHeight); mCursorDrawable.draw(canvas); } else { Paint paint = new Paint(); paint.setColor(Color.BLACK); // The cursor on magnifier is by default in black. canvas.drawRect( new Rect(mSourceWidth / 2 - 1, 0, mSourceWidth / 2 + 1, mSourceHeight), paint); } } } private void performPixelCopy(final int startXInSurface, final int startYInSurface, final boolean updateWindowPosition) { if (mContentCopySurface.mSurface == null || !mContentCopySurface.mSurface.isValid()) { Loading Loading @@ -827,8 +836,10 @@ public final class Magnifier { final Rect dstRect = new Rect(mLeftCutWidth, 0, mSourceWidth - mRightCutWidth, bitmap.getHeight()); can.drawBitmap(bitmap, null, dstRect, null); maybeDrawCursor(can); mWindow.updateContent(newBitmap); } else { maybeDrawCursor(new Canvas(bitmap)); mWindow.updateContent(bitmap); } } Loading Loading
core/java/android/widget/Editor.java +60 −22 Original line number Diff line number Diff line Loading @@ -154,6 +154,10 @@ public class Editor { // Specifies whether to use the magnifier when pressing the insertion or selection handles. private static final boolean FLAG_USE_MAGNIFIER = true; // Specifies how far to make the cursor start float when drag the cursor away from the // beginning or end of the line. private static final int CURSOR_START_FLOAT_DISTANCE_PX = 20; private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000; private static final int RECENT_CUT_COPY_DURATION_MS = 15 * 1000; // 15 seconds in millis Loading Loading @@ -289,6 +293,9 @@ public class Editor { private boolean mRenderCursorRegardlessTiming; private Blink mBlink; // Whether to let magnifier draw cursor on its surface. This is for floating cursor effect. // And it can only be true when |mNewMagnifierEnabled| is true. private boolean mDrawCursorOnMagnifier; boolean mCursorVisible = true; boolean mSelectAllOnFocus; boolean mTextIsSelectable; Loading Loading @@ -890,7 +897,7 @@ public class Editor { } boolean enabled = windowSupportsHandles && mTextView.getLayout() != null; mInsertionControllerEnabled = enabled && isCursorVisible(); mInsertionControllerEnabled = enabled && (mDrawCursorOnMagnifier || isCursorVisible()); mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected(); if (!mInsertionControllerEnabled) { Loading Loading @@ -5101,14 +5108,25 @@ public class Editor { final int[] textViewLocationOnScreen = new int[2]; mTextView.getLocationOnScreen(textViewLocationOnScreen); final float touchXInView = event.getRawX() - textViewLocationOnScreen[0]; float leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); float rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) { float leftBound, rightBound; if (mNewMagnifierEnabled) { leftBound = 0; rightBound = mTextView.getWidth(); if (touchXInView < leftBound || touchXInView > rightBound) { // The touch is too far from the current line / selection, so hide the magnifier. return false; } } else { leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) { leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset); } else { leftBound += mTextView.getLayout().getLineLeft(lineNumber); } if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) { if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) { rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset); } else { rightBound += mTextView.getLayout().getLineRight(lineNumber); Loading @@ -5122,6 +5140,7 @@ public class Editor { // The touch is too far from the current line / selection, so hide the magnifier. return false; } } final float scaledTouchXInView; if (mTextViewScaleX == 1f) { Loading Loading @@ -5178,7 +5197,8 @@ public class Editor { final Rect magnifierRect = new Rect(magnifierTopLeft.x, magnifierTopLeft.y, magnifierTopLeft.x + mMagnifierAnimator.mMagnifier.getWidth(), magnifierTopLeft.y + mMagnifierAnimator.mMagnifier.getHeight()); setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect)); setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect) && !mDrawCursorOnMagnifier); final HandleView otherHandle = getOtherSelectionHandle(); if (otherHandle != null) { otherHandle.setVisible(!handleOverlapsMagnifier(otherHandle, magnifierRect)); Loading Loading @@ -5208,7 +5228,20 @@ public class Editor { lineLeft += mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); int lineRight = (int) layout.getLineRight(line); lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX(); mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight); mDrawCursorOnMagnifier = showPosInView.x < lineLeft - CURSOR_START_FLOAT_DISTANCE_PX || showPosInView.x > lineRight + CURSOR_START_FLOAT_DISTANCE_PX; mMagnifierAnimator.mMagnifier.setDrawCursor( mDrawCursorOnMagnifier, mDrawableForCursor); boolean cursorVisible = mCursorVisible; // Updates cursor visibility, so that the real cursor and the float cursor on // magnifier surface won't appear at the same time. mCursorVisible = !mDrawCursorOnMagnifier; if (mCursorVisible && !cursorVisible) { // When the real cursor is a drawable, hiding/showing it would change its // bounds. So, call updateCursorPosition() to correct its position. updateCursorPosition(); } final int lineHeight = layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line); float zoom = mInitialZoom; Loading @@ -5230,6 +5263,11 @@ public class Editor { if (mMagnifierAnimator != null) { mMagnifierAnimator.dismiss(); mRenderCursorRegardlessTiming = false; mDrawCursorOnMagnifier = false; if (!mCursorVisible) { mCursorVisible = true; mTextView.invalidate(); } resumeBlink(); setVisible(true); final HandleView otherHandle = getOtherSelectionHandle(); Loading
core/java/android/widget/Magnifier.java +32 −21 Original line number Diff line number Diff line Loading @@ -149,9 +149,6 @@ public final class Magnifier { private int mLeftCutWidth = 0; // The width of the cut region on the right edge of the pixel copy source rect. private int mRightCutWidth = 0; // The horizontal bounds of the content source in pixels, relative to the view. private int mLeftBound = Integer.MIN_VALUE; private int mRightBound = Integer.MAX_VALUE; // The width of the ramp region in pixels on the left & right sides of the fish-eye effect. private final int mRamp; Loading Loading @@ -243,18 +240,6 @@ public final class Magnifier { sPixelCopyHandlerThread.start(); } /** * Sets the horizontal bounds of the source when showing the magnifier. * This is used for new style magnifier. e.g. limit the source bounds by the text line bounds. * * @param left the left of the bounds, relative to the view. * @param right the right of the bounds, relative to the view. */ void setSourceHorizontalBounds(int left, int right) { mLeftBound = left; mRightBound = right; } /** * Shows the magnifier on the screen. The method takes the coordinates of the center * of the content source going to be magnified and copied to the magnifier. The coordinates Loading @@ -280,6 +265,14 @@ public final class Magnifier { sourceCenterY + mDefaultVerticalSourceToMagnifierOffset); } private Drawable mCursorDrawable; private boolean mDrawCursorEnabled; void setDrawCursor(boolean enabled, Drawable cursorDrawable) { mDrawCursorEnabled = enabled; mCursorDrawable = cursorDrawable; } /** * Shows the magnifier on the screen at a position that is independent from its content * position. The first two arguments represent the coordinates of the center of the Loading Loading @@ -309,8 +302,7 @@ public final class Magnifier { magnifierCenterX = mClampedCenterZoomCoords.x - mViewCoordinatesInSurface[0]; magnifierCenterY = mClampedCenterZoomCoords.y - mViewCoordinatesInSurface[1]; // mLeftBound & mRightBound (typically the text line left/right) is for magnified // content. However the PixelCopy requires the pre-magnified bounds. // PixelCopy requires the pre-magnified bounds. // The below logic calculates the leftBound & rightBound for the pre-magnified bounds. final float rampPre = (mSourceWidth - (mSourceWidth - 2 * mRamp) / mZoom) / 2; Loading @@ -318,7 +310,7 @@ public final class Magnifier { // Calculates the pre-zoomed left edge. // The leftEdge moves from the left of view towards to sourceCenterX, considering the // fisheye-like zooming. final float x0 = sourceCenterX - mSourceWidth / 2; final float x0 = sourceCenterX - mSourceWidth / 2f; final float rampX0 = x0 + mRamp; float leftEdge = 0; if (leftEdge > rampX0) { Loading @@ -330,12 +322,12 @@ public final class Magnifier { // increase per ramp zoom (ramp / rampPre). leftEdge = x0 + rampPre - (rampX0 - leftEdge) * rampPre / mRamp; } int leftBound = Math.min(Math.max((int) leftEdge, mLeftBound), mRightBound); int leftBound = Math.min((int) leftEdge, mView.getWidth()); // Calculates the pre-zoomed right edge. // The rightEdge moves from the right of view towards to sourceCenterX, considering the // fisheye-like zooming. final float x1 = sourceCenterX + mSourceWidth / 2; final float x1 = sourceCenterX + mSourceWidth / 2f; final float rampX1 = x1 - mRamp; float rightEdge = mView.getWidth(); if (rightEdge < rampX1) { Loading @@ -347,7 +339,7 @@ public final class Magnifier { // increase per ramp zoom (ramp / rampPre). rightEdge = x1 - rampPre + (rightEdge - rampX1) * rampPre / mRamp; } int rightBound = Math.max(leftBound, Math.min((int) rightEdge, mRightBound)); int rightBound = Math.max(leftBound, (int) rightEdge); // Gets the startX for new style, which should be bounded by the horizontal bounds. // Also calculates the left/right cut width for pixel copy. Loading Loading @@ -772,6 +764,23 @@ public final class Magnifier { } } private void maybeDrawCursor(Canvas canvas) { if (mDrawCursorEnabled) { if (mCursorDrawable != null) { mCursorDrawable.setBounds( mSourceWidth / 2, 0, mSourceWidth / 2 + mCursorDrawable.getIntrinsicWidth(), mSourceHeight); mCursorDrawable.draw(canvas); } else { Paint paint = new Paint(); paint.setColor(Color.BLACK); // The cursor on magnifier is by default in black. canvas.drawRect( new Rect(mSourceWidth / 2 - 1, 0, mSourceWidth / 2 + 1, mSourceHeight), paint); } } } private void performPixelCopy(final int startXInSurface, final int startYInSurface, final boolean updateWindowPosition) { if (mContentCopySurface.mSurface == null || !mContentCopySurface.mSurface.isValid()) { Loading Loading @@ -827,8 +836,10 @@ public final class Magnifier { final Rect dstRect = new Rect(mLeftCutWidth, 0, mSourceWidth - mRightCutWidth, bitmap.getHeight()); can.drawBitmap(bitmap, null, dstRect, null); maybeDrawCursor(can); mWindow.updateContent(newBitmap); } else { maybeDrawCursor(new Canvas(bitmap)); mWindow.updateContent(bitmap); } } Loading