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); |