summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/webkit/WebChromeClient.java18
-rw-r--r--core/java/android/webkit/WebView.java278
2 files changed, 201 insertions, 95 deletions
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 1d5aac7..9f642c0 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -320,4 +320,22 @@ public class WebChromeClient {
public void openFileChooser(ValueCallback<Uri> uploadFile) {
uploadFile.onReceiveValue(null);
}
+
+ /**
+ * Tell the client that the selection has been initiated.
+ * @hide
+ */
+ public void onSelectionStart(WebView view) {
+ // By default we cancel the selection again, thus disabling
+ // text selection unless the chrome client supports it.
+ view.notifySelectDialogDismissed();
+ }
+
+ /**
+ * Tell the client that the selection has been copied or canceled.
+ * @hide
+ */
+ public void onSelectionDone(WebView view) {
+ }
+
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 69d9ef4..3e0187d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -459,8 +459,7 @@ public class WebView extends AbsoluteLayout
private static final int TOUCH_SHORTPRESS_MODE = 5;
private static final int TOUCH_DOUBLE_TAP_MODE = 6;
private static final int TOUCH_DONE_MODE = 7;
- private static final int TOUCH_SELECT_MODE = 8;
- private static final int TOUCH_PINCH_DRAG = 9;
+ private static final int TOUCH_PINCH_DRAG = 8;
// Whether to forward the touch events to WebCore
private boolean mForwardTouchEvents = false;
@@ -2693,6 +2692,14 @@ public class WebView extends AbsoluteLayout
nativeSetFindIsUp(isUp);
}
+ /**
+ * @hide
+ */
+ public int findIndex() {
+ if (0 == mNativeClass) return -1;
+ return nativeFindIndex();
+ }
+
// Used to know whether the find dialog is open. Affects whether
// or not we draw the highlights for matches.
private boolean mFindIsUp;
@@ -3309,12 +3316,33 @@ public class WebView extends AbsoluteLayout
// Send the click so that the textfield is in focus
centerKeyPressOnTextField();
rebuildWebTextView();
+ } else {
+ clearTextEntry(true);
}
if (inEditingMode()) {
return mWebTextView.performLongClick();
- } else {
- return super.performLongClick();
}
+ /* if long click brings up a context menu, the super function
+ * returns true and we're done. Otherwise, nothing happened when
+ * the user clicked. */
+ if (super.performLongClick()) {
+ return true;
+ }
+ /* In the case where the application hasn't already handled the long
+ * click action, look for a word under the click. If one is found,
+ * animate the text selection into view.
+ * FIXME: no animation code yet */
+ if (mSelectingText) return false; // long click does nothing on selection
+ int x = viewToContentX((int) mLastTouchX + mScrollX);
+ int y = viewToContentY((int) mLastTouchY + mScrollY);
+ setUpSelect();
+ if (mNativeClass != 0 && nativeWordSelection(x, y)) {
+ nativeSetExtendSelection();
+ getWebChromeClient().onSelectionStart(this);
+ return true;
+ }
+ notifySelectDialogDismissed();
+ return false;
}
boolean inAnimateZoom() {
@@ -3465,19 +3493,12 @@ public class WebView extends AbsoluteLayout
// decide which adornments to draw
int extras = DRAW_EXTRAS_NONE;
if (mFindIsUp) {
- // When the FindDialog is up, only draw the matches if we are not in
- // the process of scrolling them into view.
- if (!animateScroll) {
extras = DRAW_EXTRAS_FIND;
- }
- } else if (mShiftIsPressed && !nativeFocusIsPlugin()) {
- if (!animateZoom && !mPreviewZoomOnly) {
- extras = DRAW_EXTRAS_SELECTION;
- nativeSetSelectionRegion(mTouchSelection || mExtendSelection);
- nativeSetSelectionPointer(!mTouchSelection, mInvActualScale,
- mSelectX, mSelectY - getTitleHeight(),
- mExtendSelection);
- }
+ } else if (mSelectingText) {
+ extras = DRAW_EXTRAS_SELECTION;
+ nativeSetSelectionPointer(mDrawSelectionPointer,
+ mInvActualScale,
+ mSelectX, mSelectY - getTitleHeight());
} else if (drawCursorRing) {
extras = DRAW_EXTRAS_CURSOR_RING;
}
@@ -3486,11 +3507,6 @@ public class WebView extends AbsoluteLayout
if (extras == DRAW_EXTRAS_CURSOR_RING) {
if (mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
mTouchMode = TOUCH_SHORTPRESS_MODE;
- HitTestResult hitTest = getHitTestResult();
- if (hitTest == null
- || hitTest.mType == HitTestResult.UNKNOWN_TYPE) {
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- }
}
}
if (mFocusSizeChanged) {
@@ -3829,8 +3845,8 @@ public class WebView extends AbsoluteLayout
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
if (nativeFocusIsPlugin()) {
mShiftIsPressed = true;
- } else if (!nativeCursorWantsKeyEvents() && !mShiftIsPressed) {
- setUpSelectXY();
+ } else if (!nativeCursorWantsKeyEvents() && !mSelectingText) {
+ setUpSelect();
}
}
@@ -3841,7 +3857,7 @@ public class WebView extends AbsoluteLayout
letPluginHandleNavKey(keyCode, event.getEventTime(), true);
return true;
}
- if (mShiftIsPressed) {
+ if (mSelectingText) {
int xRate = keyCode == KeyEvent.KEYCODE_DPAD_LEFT
? -1 : keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : 0;
int yRate = keyCode == KeyEvent.KEYCODE_DPAD_UP ?
@@ -3861,7 +3877,7 @@ public class WebView extends AbsoluteLayout
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
switchOutDrawHistory();
if (event.getRepeatCount() == 0) {
- if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+ if (mSelectingText) {
return true; // discard press if copy in progress
}
mGotCenterDown = true;
@@ -3879,10 +3895,8 @@ public class WebView extends AbsoluteLayout
if (keyCode != KeyEvent.KEYCODE_SHIFT_LEFT
&& keyCode != KeyEvent.KEYCODE_SHIFT_RIGHT) {
// turn off copy select if a shift-key combo is pressed
- mExtendSelection = mShiftIsPressed = false;
- if (mTouchMode == TOUCH_SELECT_MODE) {
- mTouchMode = TOUCH_INIT_MODE;
- }
+ selectionDone();
+ mShiftIsPressed = false;
}
if (getSettings().getNavDump()) {
@@ -3972,7 +3986,8 @@ public class WebView extends AbsoluteLayout
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
if (nativeFocusIsPlugin()) {
mShiftIsPressed = false;
- } else if (commitCopy()) {
+ } else if (copySelection()) {
+ selectionDone();
return true;
}
}
@@ -3993,11 +4008,13 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
mGotCenterDown = false;
- if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+ if (mSelectingText) {
if (mExtendSelection) {
- commitCopy();
+ copySelection();
+ selectionDone();
} else {
mExtendSelection = true;
+ nativeSetExtendSelection();
invalidate(); // draw the i-beam instead of the arrow
}
return true; // discard press if copy in progress
@@ -4042,9 +4059,18 @@ public class WebView extends AbsoluteLayout
return false;
}
- private void setUpSelectXY() {
+ /**
+ * @hide pending API council approval.
+ */
+ public void setUpSelect() {
+ if (0 == mNativeClass) return; // client isn't initialized
+ if (inFullScreenMode()) return;
+ if (mSelectingText) return;
mExtendSelection = false;
- mShiftIsPressed = true;
+ mSelectingText = mDrawSelectionPointer = true;
+ // don't let the picture change during text selection
+ WebViewCore.pauseUpdatePicture(mWebViewCore);
+ nativeResetSelection();
if (nativeHasCursorNode()) {
Rect rect = nativeCursorNodeBounds();
mSelectX = contentToViewX(rect.left);
@@ -4064,40 +4090,82 @@ public class WebView extends AbsoluteLayout
* Do not rely on this functionality; it will be deprecated in the future.
*/
public void emulateShiftHeld() {
+ setUpSelect();
+ }
+
+ /**
+ * @hide pending API council approval.
+ */
+ public void selectAll() {
if (0 == mNativeClass) return; // client isn't initialized
- setUpSelectXY();
+ if (inFullScreenMode()) return;
+ if (!mSelectingText) setUpSelect();
+ nativeSelectAll();
+ mDrawSelectionPointer = false;
+ mExtendSelection = true;
+ invalidate();
}
- private boolean commitCopy() {
+ /**
+ * @hide pending API council approval.
+ */
+ public boolean selectDialogIsUp() {
+ return mSelectingText;
+ }
+
+ /**
+ * @hide pending API council approval.
+ */
+ public void notifySelectDialogDismissed() {
+ mSelectingText = false;
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
+ }
+
+ /**
+ * @hide pending API council approval.
+ */
+ public void selectionDone() {
+ if (mSelectingText) {
+ getWebChromeClient().onSelectionDone(this);
+ invalidate(); // redraw without selection
+ notifySelectDialogDismissed();
+ }
+ }
+
+ /**
+ * @hide pending API council approval.
+ */
+ public boolean copySelection() {
boolean copiedSomething = false;
- if (mExtendSelection) {
- String selection = nativeGetSelection();
- if (selection != "") {
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "commitCopy \"" + selection + "\"");
- }
- Toast.makeText(mContext
- , com.android.internal.R.string.text_copied
- , Toast.LENGTH_SHORT).show();
- copiedSomething = true;
- try {
- IClipboard clip = IClipboard.Stub.asInterface(
- ServiceManager.getService("clipboard"));
- clip.setClipboardText(selection);
- } catch (android.os.RemoteException e) {
- Log.e(LOGTAG, "Clipboard failed", e);
- }
+ String selection = getSelection();
+ if (selection != "") {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "copySelection \"" + selection + "\"");
+ }
+ Toast.makeText(mContext
+ , com.android.internal.R.string.text_copied
+ , Toast.LENGTH_SHORT).show();
+ copiedSomething = true;
+ try {
+ IClipboard clip = IClipboard.Stub.asInterface(
+ ServiceManager.getService("clipboard"));
+ clip.setClipboardText(selection);
+ } catch (android.os.RemoteException e) {
+ Log.e(LOGTAG, "Clipboard failed", e);
}
- mExtendSelection = false;
}
- mShiftIsPressed = false;
invalidate(); // remove selection region and pointer
- if (mTouchMode == TOUCH_SELECT_MODE) {
- mTouchMode = TOUCH_INIT_MODE;
- }
return copiedSomething;
}
+ /**
+ * @hide pending API council approval.
+ */
+ public String getSelection() {
+ if (mNativeClass == 0) return "";
+ return nativeGetSelection();
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -4672,7 +4740,7 @@ public class WebView extends AbsoluteLayout
private boolean shouldForwardTouchEvent() {
return mFullScreenHolder != null || (mForwardTouchEvents
- && mTouchMode != TOUCH_SELECT_MODE
+ && !mSelectingText
&& mPreventDefault != PREVENT_DEFAULT_IGNORE);
}
@@ -4760,16 +4828,6 @@ public class WebView extends AbsoluteLayout
mTouchMode = TOUCH_DRAG_START_MODE;
mConfirmMove = true;
mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
- } else if (!inFullScreenMode() && mShiftIsPressed) {
- mSelectX = mScrollX + (int) x;
- mSelectY = mScrollY + (int) y;
- mTouchMode = TOUCH_SELECT_MODE;
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "select=" + mSelectX + "," + mSelectY);
- }
- nativeMoveSelection(contentX, contentY, false);
- mTouchSelection = mExtendSelection = true;
- invalidate(); // draw the i-beam instead of the arrow
} else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
@@ -4794,6 +4852,14 @@ public class WebView extends AbsoluteLayout
EventLog.writeEvent(EventLogTags.BROWSER_DOUBLE_TAP_DURATION,
(eventTime - mLastTouchUpTime), eventTime);
}
+ if (mSelectingText) {
+ mDrawSelectionPointer = false;
+ mSelectionStarted = nativeStartSelection(contentX, contentY);
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "select=" + contentX + "," + contentY);
+ }
+ invalidate();
+ }
}
// Trigger the link
if (mTouchMode == TOUCH_INIT_MODE
@@ -4885,17 +4951,17 @@ public class WebView extends AbsoluteLayout
+ " mTouchMode = " + mTouchMode);
}
mVelocityTracker.addMovement(ev);
- if (mTouchMode != TOUCH_DRAG_MODE) {
- if (mTouchMode == TOUCH_SELECT_MODE) {
- mSelectX = mScrollX + (int) x;
- mSelectY = mScrollY + (int) y;
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "xtend=" + mSelectX + "," + mSelectY);
- }
- nativeMoveSelection(contentX, contentY, true);
- invalidate();
- break;
+ if (mSelectingText && mSelectionStarted) {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "extend=" + contentX + "," + contentY);
}
+ nativeExtendSelection(contentX, contentY);
+ invalidate();
+ break;
+ }
+
+ if (mTouchMode != TOUCH_DRAG_MODE) {
+
if (!mConfirmMove) {
break;
}
@@ -5062,10 +5128,6 @@ public class WebView extends AbsoluteLayout
mTouchMode = TOUCH_DONE_MODE;
}
break;
- case TOUCH_SELECT_MODE:
- commitCopy();
- mTouchSelection = false;
- break;
case TOUCH_INIT_MODE: // tap
case TOUCH_SHORTPRESS_START_MODE:
case TOUCH_SHORTPRESS_MODE:
@@ -5096,6 +5158,13 @@ public class WebView extends AbsoluteLayout
break;
}
} else {
+ if (mSelectingText) {
+ // tapping on selection or controls does nothing
+ if (!nativeHitSelection(contentX, contentY)) {
+ selectionDone();
+ }
+ break;
+ }
if (mTouchMode == TOUCH_INIT_MODE) {
mPrivateHandler.sendEmptyMessageDelayed(
RELEASE_SINGLE_TAP, ViewConfiguration
@@ -5266,8 +5335,10 @@ public class WebView extends AbsoluteLayout
private float mTrackballRemainsY = 0.0f;
private int mTrackballXMove = 0;
private int mTrackballYMove = 0;
+ private boolean mSelectingText = false;
+ private boolean mSelectionStarted = false;
private boolean mExtendSelection = false;
- private boolean mTouchSelection = false;
+ private boolean mDrawSelectionPointer = false;
private static final int TRACKBALL_KEY_TIMEOUT = 1000;
private static final int TRACKBALL_TIMEOUT = 200;
private static final int TRACKBALL_WAIT = 100;
@@ -5306,10 +5377,8 @@ public class WebView extends AbsoluteLayout
if (ev.getY() < 0) pageUp(true);
return true;
}
- boolean shiftPressed = mShiftIsPressed && (mNativeClass == 0
- || !nativeFocusIsPlugin());
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (shiftPressed) {
+ if (mSelectingText) {
return true; // discard press if copy in progress
}
mTrackballDown = true;
@@ -5334,11 +5403,13 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
mTrackballDown = false;
mTrackballUpTime = time;
- if (shiftPressed) {
+ if (mSelectingText) {
if (mExtendSelection) {
- commitCopy();
+ copySelection();
+ selectionDone();
} else {
mExtendSelection = true;
+ nativeSetExtendSelection();
invalidate(); // draw the i-beam instead of the arrow
}
return true; // discard press if copy in progress
@@ -5405,8 +5476,7 @@ public class WebView extends AbsoluteLayout
+ " yRate=" + yRate
);
}
- nativeMoveSelection(viewToContentX(mSelectX),
- viewToContentY(mSelectY), mExtendSelection);
+ nativeMoveSelection(viewToContentX(mSelectX), viewToContentY(mSelectY));
int scrollX = mSelectX < mScrollX ? -SELECT_CURSOR_OFFSET
: mSelectX > maxX - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
: 0;
@@ -5472,7 +5542,16 @@ public class WebView extends AbsoluteLayout
float yRate = mTrackballRemainsY * 1000 / elapsed;
int viewWidth = getViewWidth();
int viewHeight = getViewHeight();
- if (mShiftIsPressed && (mNativeClass == 0 || !nativeFocusIsPlugin())) {
+ if (mSelectingText) {
+ if (!mDrawSelectionPointer) {
+ // The last selection was made by touch, disabling drawing the
+ // selection pointer. Allow the trackball to adjust the
+ // position of the touch control.
+ mSelectX = contentToViewX(nativeSelectionX());
+ mSelectY = contentToViewY(nativeSelectionY());
+ mDrawSelectionPointer = mExtendSelection = true;
+ nativeSetExtendSelection();
+ }
moveSelection(scaleTrackballX(xRate, viewWidth),
scaleTrackballY(yRate, viewHeight));
mTrackballRemainsX = mTrackballRemainsY = 0;
@@ -7392,6 +7471,7 @@ public class WebView extends AbsoluteLayout
private native void nativeDebugDump();
private native void nativeDestroy();
private native boolean nativeEvaluateLayersAnimations();
+ private native void nativeExtendSelection(int x, int y);
private native void nativeDrawExtras(Canvas canvas, int extra);
private native void nativeDumpDisplayTree(String urlOrNull);
private native int nativeFindAll(String findLower, String findUpper);
@@ -7420,6 +7500,7 @@ public class WebView extends AbsoluteLayout
private native boolean nativeHasCursorNode();
private native boolean nativeHasFocusNode();
private native void nativeHideCursor();
+ private native boolean nativeHitSelection(int x, int y);
private native String nativeImageURI(int x, int y);
private native void nativeInstrumentReport();
/* package */ native boolean nativeMoveCursorToNextTextInput();
@@ -7429,21 +7510,27 @@ public class WebView extends AbsoluteLayout
private native boolean nativeMoveCursor(int keyCode, int count,
boolean noScroll);
private native int nativeMoveGeneration();
- private native void nativeMoveSelection(int x, int y,
- boolean extendSelection);
+ private native void nativeMoveSelection(int x, int y);
private native boolean nativePointInNavCache(int x, int y, int slop);
// Like many other of our native methods, you must make sure that
// mNativeClass is not null before calling this method.
private native void nativeRecordButtons(boolean focused,
boolean pressed, boolean invalidate);
+ private native void nativeResetSelection();
+ private native void nativeSelectAll();
private native void nativeSelectBestAt(Rect rect);
+ private native int nativeSelectionX();
+ private native int nativeSelectionY();
+ private native int nativeFindIndex();
+ private native void nativeSetExtendSelection();
private native void nativeSetFindIsEmpty();
private native void nativeSetFindIsUp(boolean isUp);
private native void nativeSetFollowedLink(boolean followed);
private native void nativeSetHeightCanMeasure(boolean measure);
private native void nativeSetRootLayer(int layer);
private native void nativeSetSelectionPointer(boolean set,
- float scale, int x, int y, boolean extendSelection);
+ float scale, int x, int y);
+ private native boolean nativeStartSelection(int x, int y);
private native void nativeSetSelectionRegion(boolean set);
private native Rect nativeSubtractLayers(Rect content);
private native int nativeTextGeneration();
@@ -7451,6 +7538,7 @@ public class WebView extends AbsoluteLayout
// we always want to pass in our generation number.
private native void nativeUpdateCachedTextfield(String updatedText,
int generation);
+ private native boolean nativeWordSelection(int x, int y);
// return NO_LEFTEDGE means failure.
private static final int NO_LEFTEDGE = -1;
private native int nativeGetBlockLeftEdge(int x, int y, float scale);