| 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 6f22fcf9811528abd9d58739344be7b401c1f721..831f9e1691a06034b7758c7a004287350c6849f8 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;
|
| -
|
| // These values are obtained from Samsung.
|
| private static final int SPEN_ACTION_DOWN = 211;
|
| private static final int SPEN_ACTION_UP = 212;
|
| @@ -270,13 +270,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;
|
| @@ -290,13 +290,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;
|
| @@ -390,9 +387,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>();
|
| @@ -550,7 +544,7 @@ public class ContentViewCore
|
| public void onImeEvent(boolean isFinish) {
|
| getContentViewClient().onImeEvent();
|
| if (!isFinish) {
|
| - hideHandles();
|
| + hideTextHandles();
|
| }
|
| }
|
|
|
| @@ -613,15 +607,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.getNativePointer();
|
| assert windowNativePointer != 0;
|
| mViewAndroid = new ViewAndroid(windowAndroid, getViewAndroidDelegate());
|
| @@ -691,10 +676,9 @@ public class ContentViewCore
|
| public void setContainerView(ViewGroup containerView) {
|
| TraceEvent.begin();
|
| if (mContainerView != null) {
|
| - mPositionObserver.removeListener(mPositionListener);
|
| - mSelectionHandleController = null;
|
| - mInsertionHandleController = null;
|
| + mPastePopupMenu = null;
|
| mInputConnection = null;
|
| + hidePopups();
|
| }
|
|
|
| mContainerView = containerView;
|
| @@ -1166,6 +1150,11 @@ 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 {
|
| int eventAction = event.getActionMasked();
|
| @@ -1176,18 +1165,7 @@ public class ContentViewCore
|
|
|
| if (isSPenSupported(mContext))
|
| eventAction = convertSPenEventAction(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.
|
| - 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;
|
|
|
| @@ -1210,7 +1188,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;
|
| @@ -1219,6 +1198,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();
|
| }
|
| @@ -1232,7 +1223,6 @@ public class ContentViewCore
|
| private void onFlingStartEventConsumed(int vx, int vy) {
|
| mTouchScrollInProgress = false;
|
| mPotentiallyActiveFlingCount++;
|
| - temporarilyHideTextHandles();
|
| for (mGestureStateListenersIterator.rewind();
|
| mGestureStateListenersIterator.hasNext();) {
|
| mGestureStateListenersIterator.next().onFlingStartGesture(
|
| @@ -1260,7 +1250,7 @@ public class ContentViewCore
|
| @CalledByNative
|
| private void onScrollBeginEventAck() {
|
| mTouchScrollInProgress = true;
|
| - temporarilyHideTextHandles();
|
| + hidePastePopup();
|
| mZoomControlsDelegate.invokeZoomPicker();
|
| updateGestureStateListener(GestureEventType.SCROLL_START);
|
| }
|
| @@ -1286,7 +1276,6 @@ public class ContentViewCore
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| private void onPinchBeginEventAck() {
|
| - temporarilyHideTextHandles();
|
| updateGestureStateListener(GestureEventType.PINCH_BEGIN);
|
| }
|
|
|
| @@ -1305,12 +1294,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.
|
| */
|
| @@ -1494,9 +1477,11 @@ public class ContentViewCore
|
| }
|
|
|
| private void hidePopups() {
|
| - hideSelectPopup();
|
| - hideHandles();
|
| + mUnselectAllOnActionModeDismiss = true;
|
| hideSelectActionBar();
|
| + hidePastePopup();
|
| + hideSelectPopup();
|
| + hideTextHandles();
|
| }
|
|
|
| public void hideSelectActionBar() {
|
| @@ -1947,14 +1932,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();
|
| - }
|
| }
|
|
|
| /**
|
| @@ -2017,106 +1994,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));
|
| - }
|
| -
|
| - @Override
|
| - public void showHandle() {
|
| - super.showHandle();
|
| - }
|
| - };
|
| -
|
| - 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();
|
| @@ -2203,7 +2080,7 @@ public class ContentViewCore
|
| public void onDestroyActionMode() {
|
| mActionMode = null;
|
| if (mUnselectAllOnActionModeDismiss) {
|
| - hideHandles();
|
| + hideTextHandles();
|
| if (isSelectionEditable()) {
|
| int selectionEnd = Selection.getSelectionEnd(mEditable);
|
| mInputConnection.setSelection(selectionEnd, selectionEnd);
|
| @@ -2247,6 +2124,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);
|
| @@ -2269,59 +2194,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);
|
| }
|
|
|
| /**
|
| @@ -2386,7 +2262,6 @@ public class ContentViewCore
|
|
|
| final boolean needHidePopupZoomer = contentSizeChanged || scrollChanged;
|
| final boolean needUpdateZoomControls = scaleLimitsChanged || scrollChanged;
|
| - final boolean needTemporarilyHideHandles = scrollChanged;
|
|
|
| if (needHidePopupZoomer) mPopupZoomer.hide(true);
|
|
|
| @@ -2414,9 +2289,7 @@ public class ContentViewCore
|
| }
|
| }
|
|
|
| - if (needTemporarilyHideHandles) temporarilyHideTextHandles();
|
| if (needUpdateZoomControls) mZoomControlsDelegate.updateZoomControls();
|
| - if (contentOffsetChanged) updateHandleScreenPositions();
|
|
|
| // Update offsets for fullscreen.
|
| final float controlsOffsetPix = controlsOffsetYCss * deviceScale;
|
| @@ -2436,6 +2309,7 @@ public class ContentViewCore
|
| boolean isNonImeChange) {
|
| TraceEvent.begin();
|
| mFocusedNodeEditable = (textInputType != ImeAdapter.getTextInputTypeNone());
|
| + if (!mFocusedNodeEditable) hidePastePopup();
|
|
|
| mImeAdapter.updateKeyboardVisibility(
|
| nativeImeAdapterAndroid, textInputType, showImeIfNeeded);
|
| @@ -2505,7 +2379,6 @@ public class ContentViewCore
|
| private void showDisambiguationPopup(Rect targetRect, Bitmap zoomedBitmap) {
|
| mPopupZoomer.setBitmap(zoomedBitmap);
|
| mPopupZoomer.show(targetRect);
|
| - temporarilyHideTextHandles();
|
| }
|
|
|
| @SuppressWarnings("unused")
|
| @@ -2516,84 +2389,31 @@ public class ContentViewCore
|
|
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| - private void onSelectionChanged(String text) {
|
| - mLastSelectedText = text;
|
| - getContentViewClient().onSelectionChanged(text);
|
| - }
|
| + private PopupTouchHandleDrawable createPopupTouchHandleDrawable() {
|
| + if (mTouchHandleDelegate == null) {
|
| + mTouchHandleDelegate = new PopupTouchHandleDrawableDelegate() {
|
| + public View getParent() {
|
| + return getContainerView();
|
| + }
|
|
|
| - @SuppressWarnings("unused")
|
| - @CalledByNative
|
| - private void showSelectionHandlesAutomatically() {
|
| - getSelectionHandleController().allowAutomaticShowing();
|
| + public PositionObserver getParentPositionObserver() {
|
| + return mPositionObserver;
|
| + }
|
| +
|
| + public boolean onTouchHandleEvent(MotionEvent event) {
|
| + final boolean isTouchHandleEvent = true;
|
| + return onTouchEventImpl(event, isTouchHandleEvent);
|
| + }
|
| + };
|
| + }
|
| + return new PopupTouchHandleDrawable(mTouchHandleDelegate);
|
| }
|
|
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| - private void onSelectionBoundsChanged(Rect anchorRectDip, int anchorDir, Rect focusRectDip,
|
| - int focusDir, boolean isAnchorFirst) {
|
| - // All coordinates are in DIP.
|
| - int x1 = anchorRectDip.left;
|
| - int y1 = anchorRectDip.bottom;
|
| - int x2 = focusRectDip.left;
|
| - int y2 = focusRectDip.bottom;
|
| -
|
| - if (x1 != x2 || y1 != y2 ||
|
| - (mSelectionHandleController != null && mSelectionHandleController.isDragging())) {
|
| - if (mInsertionHandleController != null) {
|
| - mInsertionHandleController.hide();
|
| - }
|
| - if (isAnchorFirst) {
|
| - mStartHandlePoint.setLocalDip(x1, y1);
|
| - mEndHandlePoint.setLocalDip(x2, y2);
|
| - } else {
|
| - mStartHandlePoint.setLocalDip(x2, y2);
|
| - mEndHandlePoint.setLocalDip(x1, y1);
|
| - }
|
| -
|
| - boolean wereSelectionHandlesShowing = getSelectionHandleController().isShowing();
|
| -
|
| - getSelectionHandleController().onSelectionChanged(anchorDir, focusDir);
|
| - 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 (x1 != 0 && y1 != 0 && mFocusedNodeEditable) {
|
| - // Selection is a caret, and a text field is focused.
|
| - if (mSelectionHandleController != null) {
|
| - mSelectionHandleController.hide();
|
| - }
|
| - mInsertionHandlePoint.setLocalDip(x1, y1);
|
| -
|
| - 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
|
| - if (mSelectionHandleController != null) {
|
| - mSelectionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| - if (mInsertionHandleController != null) {
|
| - mInsertionHandleController.hideAndDisallowAutomaticShowing();
|
| - }
|
| - }
|
| - mHasSelection = false;
|
| - }
|
| - if (isSelectionHandleShowing() || isInsertionHandleShowing()) {
|
| - mPositionObserver.addListener(mPositionListener);
|
| - }
|
| + private void onSelectionChanged(String text) {
|
| + mLastSelectedText = text;
|
| + getContentViewClient().onSelectionChanged(text);
|
| }
|
|
|
| @SuppressWarnings("unused")
|
| @@ -2606,10 +2426,28 @@ 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();
|
| + hideTextHandles();
|
| + }
|
| + public boolean canPaste() {
|
| + if (!mFocusedNodeEditable) return false;
|
| + return ((ClipboardManager) mContext.getSystemService(
|
| + Context.CLIPBOARD_SERVICE)).hasPrimaryClip();
|
| + }
|
| + });
|
| + }
|
| + return mPastePopupMenu;
|
| }
|
|
|
| @SuppressWarnings("unused")
|
| @@ -3294,7 +3132,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);
|
| @@ -3339,6 +3178,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);
|
|
|