From 9b6eb6939e894df3a7a7bea3a41dfd7e2e91cbae Mon Sep 17 00:00:00 2001 From: George Mount Date: Tue, 5 Jun 2012 09:19:51 -0700 Subject: [PATCH] Hide handles when clipped by layer or edit region. Bug 6590742 Separated base and extent handle alpha so that they can be hidden individually. Added visiblity check and animations to show and hide the handles. Change-Id: I08ce7f870bbb8e059550797afa18c2db39394caf --- core/java/android/webkit/WebViewClassic.java | 127 ++++++++++++++++++--------- 1 file changed, 87 insertions(+), 40 deletions(-) diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 5314e47230df..e456a64354d5 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -679,6 +679,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // after resize. static private final int EDIT_RECT_BUFFER = 10; + static private final long SELECTION_HANDLE_ANIMATION_MS = 150; + // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK private boolean mAutoRedraw; @@ -3305,6 +3307,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } if (mTouchMode == TOUCH_DRAG_LAYER_MODE) { scrollLayerTo(scrollX, scrollY); + animateHandles(); return; } mInOverScrollMode = false; @@ -3325,6 +3328,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mWebViewPrivate.super_scrollTo(scrollX, scrollY); + animateHandles(); + if (mOverScrollGlow != null) { mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY); } @@ -3827,9 +3832,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mSelectCursorExtent.offset(dx, dy); mSelectCursorExtentTextQuad.offset(dx, dy); } - } else if (mHandleAlpha.getAlpha() > 0) { - // stop fading as we're not going to move with the layer. - mHandleAlphaAnimator.end(); } if (mAutoCompletePopup != null && mCurrentScrollingLayerId == mEditTextLayerId) { @@ -4445,9 +4447,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } private void onZoomAnimationStart() { - if (!mSelectingText && mHandleAlpha.getAlpha() > 0) { - mHandleAlphaAnimator.end(); - } } private void onZoomAnimationEnd() { @@ -4480,34 +4479,63 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private class SelectionHandleAlpha { private int mAlpha = 0; + private int mTargetAlpha = 0; + public void setAlpha(int alpha) { mAlpha = alpha; - if (mSelectHandleCenter != null) { - mSelectHandleCenter.setAlpha(alpha); - mSelectHandleLeft.setAlpha(alpha); - mSelectHandleRight.setAlpha(alpha); - // TODO: Use partial invalidate - invalidate(); - } + // TODO: Use partial invalidate + invalidate(); } public int getAlpha() { return mAlpha; } + public void setTargetAlpha(int alpha) { + mTargetAlpha = alpha; + } + + public int getTargetAlpha() { + return mTargetAlpha; + } + } private void startSelectingText() { mSelectingText = true; mShowTextSelectionExtra = true; - mHandleAlphaAnimator.setIntValues(255); - mHandleAlphaAnimator.start(); + animateHandles(); + } + + private void animateHandle(boolean canShow, ObjectAnimator animator, + Point selectionPoint, int selectionLayerId, + SelectionHandleAlpha alpha) { + boolean isVisible = canShow && mSelectingText + && ((mSelectionStarted && mSelectDraggingCursor == selectionPoint) + || isHandleVisible(selectionPoint, selectionLayerId)); + int targetValue = isVisible ? 255 : 0; + if (targetValue != alpha.getTargetAlpha()) { + alpha.setTargetAlpha(targetValue); + animator.setIntValues(targetValue); + animator.setDuration(SELECTION_HANDLE_ANIMATION_MS); + animator.start(); + } } + + private void animateHandles() { + boolean canShowBase = mSelectingText; + boolean canShowExtent = mSelectingText && !mIsCaretSelection; + animateHandle(canShowBase, mBaseHandleAlphaAnimator, mSelectCursorBase, + mSelectCursorBaseLayerId, mBaseAlpha); + animateHandle(canShowExtent, mExtentHandleAlphaAnimator, + mSelectCursorExtent, mSelectCursorExtentLayerId, + mExtentAlpha); + } + private void endSelectingText() { mSelectingText = false; mShowTextSelectionExtra = false; - mHandleAlphaAnimator.setIntValues(0); - mHandleAlphaAnimator.start(); + animateHandles(); } private void ensureSelectionHandles() { @@ -4518,7 +4546,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc com.android.internal.R.drawable.text_select_handle_left); mSelectHandleRight = mContext.getResources().getDrawable( com.android.internal.R.drawable.text_select_handle_right); - mHandleAlpha.setAlpha(mHandleAlpha.getAlpha()); // All handles have the same height, so we can save effort with // this assumption. mSelectOffset = new Point(0, @@ -4527,7 +4554,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } private void drawHandle(Point point, int handleId, Rect bounds, - Canvas canvas) { + int alpha, Canvas canvas) { int offset; int width; int height; @@ -4550,32 +4577,45 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc int y = contentToViewDimension(point.y); bounds.set(x - offset, y, x - offset + width, y + height); drawable.setBounds(bounds); + drawable.setAlpha(alpha); drawable.draw(canvas); } private void drawTextSelectionHandles(Canvas canvas) { - if (mHandleAlpha.getAlpha() == 0) { + if (mBaseAlpha.getAlpha() == 0 && mExtentAlpha.getAlpha() == 0) { return; } ensureSelectionHandles(); - if (mSelectingText) { - if (mIsCaretSelection) { - // Caret handle is centered - int x = contentToViewDimension(mSelectCursorBase.x) - - (mSelectHandleCenter.getIntrinsicWidth() / 2); - int y = contentToViewDimension(mSelectCursorBase.y); - mSelectHandleBaseBounds.set(x, y, - x + mSelectHandleCenter.getIntrinsicWidth(), - y + mSelectHandleCenter.getIntrinsicHeight()); - mSelectHandleCenter.setBounds(mSelectHandleBaseBounds); - mSelectHandleCenter.draw(canvas); - } else { - drawHandle(mSelectCursorBase, HANDLE_ID_BASE, - mSelectHandleBaseBounds, canvas); - drawHandle(mSelectCursorExtent, HANDLE_ID_EXTENT, - mSelectHandleExtentBounds, canvas); - } + if (mIsCaretSelection) { + // Caret handle is centered + int x = contentToViewDimension(mSelectCursorBase.x) - + (mSelectHandleCenter.getIntrinsicWidth() / 2); + int y = contentToViewDimension(mSelectCursorBase.y); + mSelectHandleBaseBounds.set(x, y, + x + mSelectHandleCenter.getIntrinsicWidth(), + y + mSelectHandleCenter.getIntrinsicHeight()); + mSelectHandleCenter.setBounds(mSelectHandleBaseBounds); + mSelectHandleCenter.setAlpha(mBaseAlpha.getAlpha()); + mSelectHandleCenter.draw(canvas); + } else { + drawHandle(mSelectCursorBase, HANDLE_ID_BASE, + mSelectHandleBaseBounds, mBaseAlpha.getAlpha(), canvas); + drawHandle(mSelectCursorExtent, HANDLE_ID_EXTENT, + mSelectHandleExtentBounds, mExtentAlpha.getAlpha(), canvas); + } + } + + private boolean isHandleVisible(Point selectionPoint, int layerId) { + boolean isVisible = true; + if (mIsEditingText) { + isVisible = mEditTextContentBounds.contains(selectionPoint.x, + selectionPoint.y); + } + if (isVisible) { + isVisible = nativeIsPointVisible(mNativeClass, layerId, + selectionPoint.x, selectionPoint.y); } + return isVisible; } /** @@ -6429,9 +6469,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private long mTrackballUpTime = 0; private long mLastCursorTime = 0; private Rect mLastCursorBounds; - private SelectionHandleAlpha mHandleAlpha = new SelectionHandleAlpha(); - private ObjectAnimator mHandleAlphaAnimator = - ObjectAnimator.ofInt(mHandleAlpha, "alpha", 0); + private SelectionHandleAlpha mBaseAlpha = new SelectionHandleAlpha(); + private SelectionHandleAlpha mExtentAlpha = new SelectionHandleAlpha(); + private ObjectAnimator mBaseHandleAlphaAnimator = + ObjectAnimator.ofInt(mBaseAlpha, "alpha", 0); + private ObjectAnimator mExtentHandleAlphaAnimator = + ObjectAnimator.ofInt(mExtentAlpha, "alpha", 0); // Set by default; BrowserActivity clears to interpret trackball data // directly for movement. Currently, the framework only passes @@ -7946,6 +7989,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } else { syncSelectionCursors(); } + animateHandles(); if (mIsCaretSelection) { resetCaretTimer(); } @@ -7964,6 +8008,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mWebViewCore.removeMessages(EventHub.SCROLL_TEXT_INPUT); mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, 0, scrollY, (Float)scrollPercentX); + animateHandles(); } private void beginTextBatch() { @@ -8613,4 +8658,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private static native void nativeFindMaxVisibleRect(int instance, int layerId, Rect visibleContentRect); private static native boolean nativeIsHandleLeft(int instance, int handleId); + private static native boolean nativeIsPointVisible(int instance, + int layerId, int contentX, int contentY); } -- 2.11.0