Chromium Code Reviews| Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| index a8d204192d9b66c5e572b92c0fe2ec629079797b..622b62b4eec710ff351aa0c25fd0eac07844219a 100644 |
| --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| @@ -7,6 +7,7 @@ package org.chromium.content.browser; |
| import android.annotation.SuppressLint; |
| import android.app.Activity; |
| import android.app.SearchManager; |
| +import android.content.ClipboardManager; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.Intent; |
| @@ -62,16 +63,18 @@ import org.chromium.content.browser.accessibility.AccessibilityInjector; |
| import org.chromium.content.browser.accessibility.BrowserAccessibilityManager; |
| import org.chromium.content.browser.input.AdapterInputConnection; |
| import org.chromium.content.browser.input.GamepadList; |
| -import org.chromium.content.browser.input.HandleView; |
| import org.chromium.content.browser.input.ImeAdapter; |
| import org.chromium.content.browser.input.ImeAdapter.AdapterInputConnectionFactory; |
| import org.chromium.content.browser.input.InputMethodManagerWrapper; |
| -import org.chromium.content.browser.input.InsertionHandleController; |
| +import org.chromium.content.browser.input.PastePopupMenu; |
| +import org.chromium.content.browser.input.PastePopupMenu.PastePopupMenuDelegate; |
| +import org.chromium.content.browser.input.PopupTouchHandleDrawable; |
| +import org.chromium.content.browser.input.PopupTouchHandleDrawable.PopupTouchHandleDrawableDelegate; |
| import org.chromium.content.browser.input.SelectPopup; |
| import org.chromium.content.browser.input.SelectPopupDialog; |
| import org.chromium.content.browser.input.SelectPopupDropdown; |
| import org.chromium.content.browser.input.SelectPopupItem; |
| -import org.chromium.content.browser.input.SelectionHandleController; |
| +import org.chromium.content.browser.input.SelectionEventType; |
| import org.chromium.content.common.ContentSwitches; |
| import org.chromium.content_public.browser.GestureStateListener; |
| import org.chromium.content_public.browser.WebContents; |
| @@ -108,9 +111,6 @@ public class ContentViewCore |
| private static final int IS_LONG_PRESS = 1; |
| private static final int IS_LONG_TAP = 2; |
| - // Length of the delay (in ms) before fading in handles after the last page movement. |
| - private static final int TEXT_HANDLE_FADE_IN_DELAY = 300; |
| - |
| // If the embedder adds a JavaScript interface object that contains an indirect reference to |
| // the ContentViewCore, then storing a strong ref to the interface object on the native |
| // side would prevent garbage collection of the ContentViewCore (as that strong ref would |
| @@ -263,13 +263,13 @@ public class ContentViewCore |
| private AdapterInputConnection mInputConnection; |
| private InputMethodManagerWrapper mInputMethodManagerWrapper; |
| - private SelectionHandleController mSelectionHandleController; |
| - private InsertionHandleController mInsertionHandleController; |
| + // Lazily created paste popup menu, triggered either via long press in an |
| + // editable region or from tapping the insertion handle. |
| + private PastePopupMenu mPastePopupMenu; |
| - private Runnable mDeferredHandleFadeInRunnable; |
| + private PopupTouchHandleDrawableDelegate mTouchHandleDelegate; |
| private PositionObserver mPositionObserver; |
| - private PositionObserver.Listener mPositionListener; |
| // Size of the viewport in physical pixels as set from onSizeChanged. |
| private int mViewportWidthPix; |
| @@ -283,13 +283,10 @@ public class ContentViewCore |
| // Cached copy of all positions and scales as reported by the renderer. |
| private final RenderCoordinates mRenderCoordinates; |
| - private final RenderCoordinates.NormalizedPoint mStartHandlePoint; |
| - private final RenderCoordinates.NormalizedPoint mEndHandlePoint; |
| - private final RenderCoordinates.NormalizedPoint mInsertionHandlePoint; |
| - |
| // Tracks whether a selection is currently active. When applied to selected text, indicates |
| // whether the last selected text is still highlighted. |
| private boolean mHasSelection; |
| + private boolean mHasInsertion; |
| private String mLastSelectedText; |
| private boolean mFocusedNodeEditable; |
| private ActionMode mActionMode; |
| @@ -383,9 +380,6 @@ public class ContentViewCore |
| deviceScaleFactor = Float.valueOf(forceScaleFactor); |
| } |
| mRenderCoordinates.setDeviceScaleFactor(deviceScaleFactor); |
| - mStartHandlePoint = mRenderCoordinates.createNormalizedPoint(); |
| - mEndHandlePoint = mRenderCoordinates.createNormalizedPoint(); |
| - mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint(); |
| mAccessibilityManager = (AccessibilityManager) |
| getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); |
| mGestureStateListeners = new ObserverList<GestureStateListener>(); |
| @@ -543,7 +537,7 @@ public class ContentViewCore |
| public void onImeEvent(boolean isFinish) { |
| getContentViewClient().onImeEvent(); |
| if (!isFinish) { |
| - hideHandles(); |
| + hideTextHandles(); |
| } |
| } |
| @@ -606,15 +600,6 @@ public class ContentViewCore |
| long nativeWebContents, WindowAndroid windowAndroid) { |
| setContainerView(containerView); |
| - mPositionListener = new PositionObserver.Listener() { |
| - @Override |
| - public void onPositionChanged(int x, int y) { |
| - if (isSelectionHandleShowing() || isInsertionHandleShowing()) { |
| - temporarilyHideTextHandles(); |
| - } |
| - } |
| - }; |
| - |
| long windowNativePointer = windowAndroid != null ? windowAndroid.getNativePointer() : 0; |
| long viewAndroidNativePointer = 0; |
| @@ -686,9 +671,7 @@ public class ContentViewCore |
| public void setContainerView(ViewGroup containerView) { |
| TraceEvent.begin(); |
| if (mContainerView != null) { |
| - mPositionObserver.removeListener(mPositionListener); |
| - mSelectionHandleController = null; |
| - mInsertionHandleController = null; |
| + mPastePopupMenu = null; |
| mInputConnection = null; |
| } |
| @@ -1128,23 +1111,17 @@ public class ContentViewCore |
| * @see View#onTouchEvent(MotionEvent) |
| */ |
| public boolean onTouchEvent(MotionEvent event) { |
| + final boolean isTouchHandleEvent = false; |
| + return onTouchEventImpl(event, isTouchHandleEvent); |
| + } |
| + |
| + private boolean onTouchEventImpl(MotionEvent event, boolean isTouchHandleEvent) { |
| TraceEvent.begin("onTouchEvent"); |
| try { |
| cancelRequestToScrollFocusedEditableNodeIntoView(); |
| final int eventAction = event.getActionMasked(); |
| - |
| - // Only these actions have any effect on gesture detection. Other |
| - // actions have no corresponding WebTouchEvent type and may confuse the |
| - // touch pipline, so we ignore them entirely. |
| - if (eventAction != MotionEvent.ACTION_DOWN |
| - && eventAction != MotionEvent.ACTION_UP |
| - && eventAction != MotionEvent.ACTION_CANCEL |
| - && eventAction != MotionEvent.ACTION_MOVE |
| - && eventAction != MotionEvent.ACTION_POINTER_DOWN |
| - && eventAction != MotionEvent.ACTION_POINTER_UP) { |
| - return false; |
| - } |
| + if (!isValidTouchEventActionForNative(eventAction)) return false; |
| if (mNativeContentViewCore == 0) return false; |
| @@ -1167,7 +1144,8 @@ public class ContentViewCore |
| event.getRawX(), event.getRawY(), |
| event.getToolType(0), |
| pointerCount > 1 ? event.getToolType(1) : MotionEvent.TOOL_TYPE_UNKNOWN, |
| - event.getButtonState()); |
| + event.getButtonState(), |
| + isTouchHandleEvent); |
| if (offset != null) offset.recycle(); |
| return consumed; |
| @@ -1176,6 +1154,18 @@ public class ContentViewCore |
| } |
| } |
| + private static boolean isValidTouchEventActionForNative(int eventAction) { |
| + // Only these actions have any effect on gesture detection. Other |
| + // actions have no corresponding WebTouchEvent type and may confuse the |
| + // touch pipline, so we ignore them entirely. |
| + return eventAction == MotionEvent.ACTION_DOWN |
| + || eventAction == MotionEvent.ACTION_UP |
| + || eventAction == MotionEvent.ACTION_CANCEL |
| + || eventAction == MotionEvent.ACTION_MOVE |
| + || eventAction == MotionEvent.ACTION_POINTER_DOWN |
| + || eventAction == MotionEvent.ACTION_POINTER_UP; |
| + } |
| + |
| public void setIgnoreRemainingTouchEvents() { |
| resetGestureDetection(); |
| } |
| @@ -1189,7 +1179,6 @@ public class ContentViewCore |
| private void onFlingStartEventConsumed(int vx, int vy) { |
| mTouchScrollInProgress = false; |
| mPotentiallyActiveFlingCount++; |
| - temporarilyHideTextHandles(); |
| for (mGestureStateListenersIterator.rewind(); |
| mGestureStateListenersIterator.hasNext();) { |
| mGestureStateListenersIterator.next().onFlingStartGesture( |
| @@ -1216,8 +1205,8 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void onScrollBeginEventAck() { |
| + hidePastePopup(); |
| mTouchScrollInProgress = true; |
| - temporarilyHideTextHandles(); |
| mZoomControlsDelegate.invokeZoomPicker(); |
| updateGestureStateListener(GestureEventType.SCROLL_START); |
| } |
| @@ -1243,7 +1232,6 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void onPinchBeginEventAck() { |
| - temporarilyHideTextHandles(); |
| updateGestureStateListener(GestureEventType.PINCH_BEGIN); |
| } |
| @@ -1262,12 +1250,6 @@ public class ContentViewCore |
| } |
| } |
| - @SuppressWarnings("unused") |
| - @CalledByNative |
| - private void onDoubleTapEventAck() { |
| - temporarilyHideTextHandles(); |
| - } |
| - |
| /** |
| * Called just prior to a tap or press gesture being forwarded to the renderer. |
| */ |
| @@ -1433,9 +1415,11 @@ public class ContentViewCore |
| } |
| private void hidePopups() { |
| - hideSelectPopup(); |
| - hideHandles(); |
| + mUnselectAllOnActionModeDismiss = true; |
| hideSelectActionBar(); |
| + hidePastePopup(); |
| + hideSelectPopup(); |
| + hideTextHandles(); |
| } |
| public void hideSelectActionBar() { |
| @@ -1889,14 +1873,6 @@ public class ContentViewCore |
| mLastTapX = (int) xPix; |
| mLastTapY = (int) yPix; |
| - |
| - if (type == GestureEventType.LONG_PRESS |
| - || type == GestureEventType.LONG_TAP) { |
| - getInsertionHandleController().allowAutomaticShowing(); |
| - getSelectionHandleController().allowAutomaticShowing(); |
| - } else { |
| - if (mFocusedNodeEditable) getInsertionHandleController().allowAutomaticShowing(); |
| - } |
| } |
| /** |
| @@ -1959,101 +1935,6 @@ public class ContentViewCore |
| return mDownloadDelegate; |
| } |
| - private SelectionHandleController getSelectionHandleController() { |
| - if (mSelectionHandleController == null) { |
| - mSelectionHandleController = new SelectionHandleController( |
| - getContainerView(), mPositionObserver) { |
| - @Override |
| - public void selectBetweenCoordinates(int x1, int y1, int x2, int y2) { |
| - if (mNativeContentViewCore != 0 && !(x1 == x2 && y1 == y2)) { |
| - nativeSelectBetweenCoordinates(mNativeContentViewCore, |
| - x1, y1 - mRenderCoordinates.getContentOffsetYPix(), |
| - x2, y2 - mRenderCoordinates.getContentOffsetYPix()); |
| - } |
| - } |
| - |
| - @Override |
| - public void showHandles(int startDir, int endDir) { |
| - final boolean wasShowing = isShowing(); |
| - super.showHandles(startDir, endDir); |
| - if (!wasShowing || mActionMode == null) showSelectActionBar(); |
| - } |
| - |
| - }; |
| - |
| - mSelectionHandleController.hideAndDisallowAutomaticShowing(); |
| - } |
| - |
| - return mSelectionHandleController; |
| - } |
| - |
| - private InsertionHandleController getInsertionHandleController() { |
| - if (mInsertionHandleController == null) { |
| - mInsertionHandleController = new InsertionHandleController( |
| - getContainerView(), mPositionObserver) { |
| - private static final int AVERAGE_LINE_HEIGHT = 14; |
| - |
| - @Override |
| - public void setCursorPosition(int x, int y) { |
| - if (mNativeContentViewCore != 0) { |
| - nativeMoveCaret(mNativeContentViewCore, |
| - x, y - mRenderCoordinates.getContentOffsetYPix()); |
| - } |
| - } |
| - |
| - @Override |
| - public void paste() { |
| - mImeAdapter.paste(); |
| - hideHandles(); |
| - } |
| - |
| - @Override |
| - public int getLineHeight() { |
| - return (int) Math.ceil( |
| - mRenderCoordinates.fromLocalCssToPix(AVERAGE_LINE_HEIGHT)); |
| - } |
| - }; |
| - |
| - mInsertionHandleController.hideAndDisallowAutomaticShowing(); |
| - } |
| - |
| - return mInsertionHandleController; |
| - } |
| - |
| - @VisibleForTesting |
| - public InsertionHandleController getInsertionHandleControllerForTest() { |
| - return mInsertionHandleController; |
| - } |
| - |
| - @VisibleForTesting |
| - public SelectionHandleController getSelectionHandleControllerForTest() { |
| - return mSelectionHandleController; |
| - } |
| - |
| - private void updateHandleScreenPositions() { |
| - if (isSelectionHandleShowing()) { |
| - mSelectionHandleController.setStartHandlePosition( |
| - mStartHandlePoint.getXPix(), mStartHandlePoint.getYPix()); |
| - mSelectionHandleController.setEndHandlePosition( |
| - mEndHandlePoint.getXPix(), mEndHandlePoint.getYPix()); |
| - } |
| - |
| - if (isInsertionHandleShowing()) { |
| - mInsertionHandleController.setHandlePosition( |
| - mInsertionHandlePoint.getXPix(), mInsertionHandlePoint.getYPix()); |
| - } |
| - } |
| - |
| - private void hideHandles() { |
| - if (mSelectionHandleController != null) { |
| - mSelectionHandleController.hideAndDisallowAutomaticShowing(); |
| - } |
| - if (mInsertionHandleController != null) { |
| - mInsertionHandleController.hideAndDisallowAutomaticShowing(); |
| - } |
| - mPositionObserver.removeListener(mPositionListener); |
| - } |
| - |
| private void showSelectActionBar() { |
| if (mActionMode != null) { |
| mActionMode.invalidate(); |
| @@ -2183,6 +2064,54 @@ public class ContentViewCore |
| } |
| } |
| + private void hidePastePopup() { |
| + if (mPastePopupMenu == null) return; |
| + mPastePopupMenu.hide(); |
| + } |
| + |
| + @CalledByNative |
| + private void onSelectionEvent(int eventType, float posXDip, float posYDip) { |
| + switch (eventType) { |
| + case SelectionEventType.SELECTION_SHOWN: |
| + mHasSelection = true; |
| + // TODO(cjhopman): Remove this when there is a better signal that long press caused |
| + // a selection. See http://crbug.com/150151. |
| + mContainerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); |
| + showSelectActionBar(); |
| + break; |
| + |
| + case SelectionEventType.SELECTION_CLEARED: |
| + mHasSelection = false; |
| + mUnselectAllOnActionModeDismiss = false; |
| + hideSelectActionBar(); |
| + break; |
| + |
| + case SelectionEventType.INSERTION_SHOWN: |
| + mHasInsertion = true; |
| + break; |
| + |
| + case SelectionEventType.INSERTION_MOVED: |
| + // TODO(jdduke): Handle case where movement triggered by focus. |
| + hidePastePopup(); |
| + break; |
| + |
| + case SelectionEventType.INSERTION_TAPPED: |
| + if (getPastePopup().isShowing()) |
| + mPastePopupMenu.hide(); |
| + else |
| + showPastePopup((int) posXDip, (int) posYDip); |
| + break; |
| + |
| + case SelectionEventType.INSERTION_CLEARED: |
| + mHasInsertion = false; |
| + hidePastePopup(); |
| + break; |
| + |
| + default: |
| + assert false : "Invalid selection event type."; |
| + } |
| + } |
| + |
| public boolean getUseDesktopUserAgent() { |
| if (mNativeContentViewCore != 0) { |
| return nativeGetUseDesktopUserAgent(mNativeContentViewCore); |
| @@ -2205,59 +2134,10 @@ public class ContentViewCore |
| if (mNativeContentViewCore != 0) nativeClearSslPreferences(mNativeContentViewCore); |
| } |
| - private boolean isSelectionHandleShowing() { |
| - return mSelectionHandleController != null && mSelectionHandleController.isShowing(); |
| - } |
| - |
| - private boolean isInsertionHandleShowing() { |
| - return mInsertionHandleController != null && mInsertionHandleController.isShowing(); |
| - } |
| - |
| - // Makes the insertion/selection handles invisible. They will fade back in shortly after the |
| - // last call to scheduleTextHandleFadeIn (or temporarilyHideTextHandles). |
| - private void temporarilyHideTextHandles() { |
| - if (isSelectionHandleShowing() && !mSelectionHandleController.isDragging()) { |
| - mSelectionHandleController.setHandleVisibility(HandleView.INVISIBLE); |
| - } |
| - if (isInsertionHandleShowing() && !mInsertionHandleController.isDragging()) { |
| - mInsertionHandleController.setHandleVisibility(HandleView.INVISIBLE); |
| - } |
| - scheduleTextHandleFadeIn(); |
| - } |
| - |
| - private boolean allowTextHandleFadeIn() { |
| - if (mTouchScrollInProgress) return false; |
| - |
| - if (mPopupZoomer.isShowing()) return false; |
| - |
| - return true; |
| - } |
| - |
| - // Cancels any pending fade in and schedules a new one. |
| - private void scheduleTextHandleFadeIn() { |
| - if (!isInsertionHandleShowing() && !isSelectionHandleShowing()) return; |
| - |
| - if (mDeferredHandleFadeInRunnable == null) { |
| - mDeferredHandleFadeInRunnable = new Runnable() { |
| - @Override |
| - public void run() { |
| - if (!allowTextHandleFadeIn()) { |
| - // Delay fade in until it is allowed. |
| - scheduleTextHandleFadeIn(); |
| - } else { |
| - if (isSelectionHandleShowing()) { |
| - mSelectionHandleController.beginHandleFadeIn(); |
| - } |
| - if (isInsertionHandleShowing()) { |
| - mInsertionHandleController.beginHandleFadeIn(); |
| - } |
| - } |
| - } |
| - }; |
| - } |
| - |
| - mContainerView.removeCallbacks(mDeferredHandleFadeInRunnable); |
| - mContainerView.postDelayed(mDeferredHandleFadeInRunnable, TEXT_HANDLE_FADE_IN_DELAY); |
| + private void hideTextHandles() { |
| + mHasSelection = false; |
| + mHasInsertion = false; |
| + if (mNativeContentViewCore != 0) nativeHideTextHandles(mNativeContentViewCore); |
| } |
| /** |
| @@ -2321,7 +2201,6 @@ public class ContentViewCore |
| final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged; |
| final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged; |
| - final boolean needTemporarilyHideHandles = scrollChanged; |
| if (needHidePopupZoomer) mPopupZoomer.hide(true); |
| @@ -2349,9 +2228,7 @@ public class ContentViewCore |
| } |
| } |
| - if (needTemporarilyHideHandles) temporarilyHideTextHandles(); |
| if (needUpdateZoomControls) mZoomControlsDelegate.updateZoomControls(); |
| - if (contentOffsetChanged) updateHandleScreenPositions(); |
| // Update offsets for fullscreen. |
| final float controlsOffsetPix = controlsOffsetYCss * deviceScale; |
| @@ -2371,6 +2248,7 @@ public class ContentViewCore |
| boolean isNonImeChange) { |
| TraceEvent.begin(); |
| mFocusedNodeEditable = (textInputType != ImeAdapter.getTextInputTypeNone()); |
| + if (!mFocusedNodeEditable) hidePastePopup(); |
| mImeAdapter.updateKeyboardVisibility( |
| nativeImeAdapterAndroid, textInputType, showImeIfNeeded); |
| @@ -2440,7 +2318,6 @@ public class ContentViewCore |
| private void showDisambiguationPopup(Rect targetRect, Bitmap zoomedBitmap) { |
| mPopupZoomer.setBitmap(zoomedBitmap); |
| mPopupZoomer.show(targetRect); |
| - temporarilyHideTextHandles(); |
| } |
| @SuppressWarnings("unused") |
| @@ -2451,69 +2328,24 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| - private void onSelectionChanged(String text) { |
| - mLastSelectedText = text; |
| - getContentViewClient().onSelectionChanged(text); |
| - } |
| - |
| - @SuppressWarnings("unused") |
| - @CalledByNative |
| - private void showSelectionHandlesAutomatically() { |
| - getSelectionHandleController().allowAutomaticShowing(); |
| + private PopupTouchHandleDrawable createPopupTouchHandleDrawable() { |
| + if (mTouchHandleDelegate == null) { |
| + mTouchHandleDelegate = new PopupTouchHandleDrawableDelegate() { |
| + public boolean onTouchHandleEvent(MotionEvent event) { |
| + final boolean isTouchHandleEvent = true; |
| + return onTouchEventImpl(event, isTouchHandleEvent); |
| + } |
| + }; |
| + } |
| + return new PopupTouchHandleDrawable( |
|
jdduke (slow)
2014/07/10 21:11:28
So, I think the one major remaining issue is WebVi
cjhopman
2014/07/14 18:23:52
Yeah, this whole structure (not this change specif
|
| + mTouchHandleDelegate, getContainerView(), mPositionObserver); |
| } |
| @SuppressWarnings("unused") |
| @CalledByNative |
| - private void onSelectionBoundsChanged( |
| - float startXDip, float startYDip, float endXDip, float endYDip, |
| - int startDir, int endDir) { |
| - if (endXDip != startXDip || endYDip != startYDip || |
| - (mSelectionHandleController != null && mSelectionHandleController.isDragging())) { |
| - if (mInsertionHandleController != null) { |
| - mInsertionHandleController.hide(); |
| - } |
| - mStartHandlePoint.setLocalDip(startXDip, startYDip); |
| - mEndHandlePoint.setLocalDip(endXDip, endYDip); |
| - |
| - boolean wereSelectionHandlesShowing = getSelectionHandleController().isShowing(); |
| - |
| - getSelectionHandleController().onSelectionChanged(startDir, endDir); |
| - updateHandleScreenPositions(); |
| - mHasSelection = true; |
| - |
| - if (!wereSelectionHandlesShowing && getSelectionHandleController().isShowing()) { |
| - // TODO(cjhopman): Remove this when there is a better signal that long press caused |
| - // a selection. See http://crbug.com/150151. |
| - mContainerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); |
| - } |
| - |
| - } else { |
| - mUnselectAllOnActionModeDismiss = false; |
| - hideSelectActionBar(); |
| - if (startXDip != 0 && startYDip != 0 && mFocusedNodeEditable) { |
| - // Selection is a caret, and a text field is focused. |
| - if (mSelectionHandleController != null) { |
| - mSelectionHandleController.hide(); |
| - } |
| - mInsertionHandlePoint.setLocalDip(startXDip, startYDip); |
| - |
| - getInsertionHandleController().onCursorPositionChanged(); |
| - updateHandleScreenPositions(); |
| - if (mInputMethodManagerWrapper.isWatchingCursor(mContainerView)) { |
| - final int xPix = (int) mInsertionHandlePoint.getXPix(); |
| - final int yPix = (int) mInsertionHandlePoint.getYPix(); |
| - mInputMethodManagerWrapper.updateCursor( |
| - mContainerView, xPix, yPix, xPix, yPix); |
| - } |
| - } else { |
| - // Deselection |
| - hideHandles(); |
| - } |
| - mHasSelection = false; |
| - } |
| - if (isSelectionHandleShowing() || isInsertionHandleShowing()) { |
| - mPositionObserver.addListener(mPositionListener); |
| - } |
| + private void onSelectionChanged(String text) { |
| + mLastSelectedText = text; |
| + getContentViewClient().onSelectionChanged(text); |
| } |
| @SuppressWarnings("unused") |
| @@ -2526,10 +2358,27 @@ public class ContentViewCore |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void showPastePopup(int xDip, int yDip) { |
| - mInsertionHandlePoint.setLocalDip(xDip, yDip); |
| - getInsertionHandleController().showHandle(); |
| - updateHandleScreenPositions(); |
| - getInsertionHandleController().showHandleWithPastePopup(); |
| + final float contentOffsetYPix = mRenderCoordinates.getContentOffsetYPix(); |
| + getPastePopup().showAt( |
| + (int) mRenderCoordinates.fromDipToPix(xDip), |
| + (int) (mRenderCoordinates.fromDipToPix(yDip) + contentOffsetYPix)); |
| + } |
| + |
| + private PastePopupMenu getPastePopup() { |
| + if (mPastePopupMenu == null) { |
| + mPastePopupMenu = new PastePopupMenu(getContainerView(), |
| + new PastePopupMenuDelegate() { |
| + public void paste() { |
| + mImeAdapter.paste(); |
| + } |
| + public boolean canPaste() { |
| + if (!mFocusedNodeEditable) return false; |
| + return ((ClipboardManager) mContext.getSystemService( |
| + Context.CLIPBOARD_SERVICE)).hasPrimaryClip(); |
| + } |
| + }); |
| + } |
| + return mPastePopupMenu; |
| } |
| @SuppressWarnings("unused") |
| @@ -3218,7 +3067,8 @@ public class ContentViewCore |
| int pointerId0, int pointerId1, |
| float touchMajor0, float touchMajor1, |
| float rawX, float rawY, |
| - int androidToolType0, int androidToolType1, int androidButtonState); |
| + int androidToolType0, int androidToolType1, int androidButtonState, |
| + boolean isTouchHandleEvent); |
| private native int nativeSendMouseMoveEvent( |
| long nativeContentViewCoreImpl, long timeMs, float x, float y); |
| @@ -3263,6 +3113,8 @@ public class ContentViewCore |
| private native void nativeMoveCaret(long nativeContentViewCoreImpl, float x, float y); |
| + private native void nativeHideTextHandles(long nativeContentViewCoreImpl); |
| + |
| private native void nativeResetGestureDetection(long nativeContentViewCoreImpl); |
| private native void nativeSetDoubleTapSupportEnabled( |
| long nativeContentViewCoreImpl, boolean enabled); |