Merge change 2713
* changes:
in the browser, make the trackball more like a mouse
diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java
index 6fe64ee..85f3cff 100644
--- a/core/java/android/webkit/TextDialog.java
+++ b/core/java/android/webkit/TextDialog.java
@@ -121,6 +121,10 @@
if (isPopupShowing()) {
return super.dispatchKeyEvent(event);
}
+ if (!mWebView.nativeCursorMatchesFocus()) {
+ return down ? mWebView.onKeyDown(keyCode, event) : mWebView
+ .onKeyUp(keyCode, event);
+ }
// Center key should be passed to a potential onClick
if (!down) {
mWebView.shortPressOnTextField();
@@ -128,6 +132,20 @@
// Pass to super to handle longpress.
return super.dispatchKeyEvent(event);
}
+ boolean isArrowKey = false;
+ switch(keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (!mWebView.nativeCursorMatchesFocus()) {
+ return down ? mWebView.onKeyDown(keyCode, event) : mWebView
+ .onKeyUp(keyCode, event);
+
+ }
+ isArrowKey = true;
+ break;
+ }
// Ensure there is a layout so arrow keys are handled properly.
if (getLayout() == null) {
@@ -157,22 +175,11 @@
// so do not pass down to javascript, and instead
// return true. If it is an arrow key or a delete key, we can go
// ahead and pass it down.
- boolean isArrowKey;
- switch(keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- isArrowKey = true;
- break;
- case KeyEvent.KEYCODE_ENTER:
- // For multi-line text boxes, newlines will
- // trigger onTextChanged for key down (which will send both
- // key up and key down) but not key up.
- mGotEnterDown = true;
- default:
- isArrowKey = false;
- break;
+ if (KeyEvent.KEYCODE_ENTER == keyCode) {
+ // For multi-line text boxes, newlines will
+ // trigger onTextChanged for key down (which will send both
+ // key up and key down) but not key up.
+ mGotEnterDown = true;
}
if (maxedOut && !isArrowKey && keyCode != KeyEvent.KEYCODE_DEL) {
if (oldEnd == oldStart) {
@@ -216,10 +223,7 @@
return true;
}
// if it is a navigation key, pass it to WebView
- if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT
- || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
- || keyCode == KeyEvent.KEYCODE_DPAD_UP
- || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (isArrowKey) {
// WebView check the trackballtime in onKeyDown to avoid calling
// native from both trackball and key handling. As this is called
// from TextDialog, we always want WebView to check with native.
@@ -333,6 +337,11 @@
if (event.getAction() != MotionEvent.ACTION_MOVE) {
return false;
}
+ // If the Cursor is not on the text input, webview should handle the
+ // trackball
+ if (!mWebView.nativeCursorMatchesFocus()) {
+ return mWebView.onTrackballEvent(event);
+ }
Spannable text = (Spannable) getText();
MovementMethod move = getMovementMethod();
if (move != null && getLayout() != null &&
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index eef128b..69254c0 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -84,7 +84,7 @@
import java.util.List;
/**
- * <p>A View that displays web pages. This class is the basis upon which you
+ * <p>A View that displays web pages. This class is the basis upon which you
* can roll your own web browser or simply display some online content within your Activity.
* It uses the WebKit rendering engine to display
* web pages and includes methods to navigate forward and backward
@@ -93,7 +93,7 @@
* {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)}
* (introduced in API version 3).
* <p>Note that, in order for your Activity to access the Internet and load web pages
- * in a WebView, you must add the <var>INTERNET</var> permissions to your
+ * in a WebView, you must add the <var>INTERNET</var> permissions to your
* Android Manifest file:</p>
* <pre><uses-permission android:name="android.permission.INTERNET" /></pre>
*
@@ -195,7 +195,7 @@
* changes, and then just leave the WebView alone. It'll automatically
* re-orient itself as appropriate.</p>
*/
-public class WebView extends AbsoluteLayout
+public class WebView extends AbsoluteLayout
implements ViewTreeObserver.OnGlobalFocusChangeListener,
ViewGroup.OnHierarchyChangeListener {
@@ -219,40 +219,40 @@
mZoomControls = (ZoomControls) findViewById(com.android.internal.R.id.zoomControls);
mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify);
}
-
+
public void show(boolean showZoom, boolean canZoomOut) {
mZoomControls.setVisibility(showZoom ? View.VISIBLE : View.GONE);
mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE);
fade(View.VISIBLE, 0.0f, 1.0f);
}
-
+
public void hide() {
fade(View.GONE, 1.0f, 0.0f);
}
-
+
private void fade(int visibility, float startAlpha, float endAlpha) {
AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha);
anim.setDuration(500);
startAnimation(anim);
setVisibility(visibility);
}
-
+
public void setIsZoomMagnifyEnabled(boolean isEnabled) {
mZoomMagnify.setEnabled(isEnabled);
}
-
+
public boolean hasFocus() {
return mZoomControls.hasFocus() || mZoomMagnify.hasFocus();
}
-
+
public void setOnZoomInClickListener(OnClickListener listener) {
mZoomControls.setOnZoomInClickListener(listener);
}
-
+
public void setOnZoomOutClickListener(OnClickListener listener) {
mZoomControls.setOnZoomOutClickListener(listener);
}
-
+
public void setOnZoomMagnifyClickListener(OnClickListener listener) {
mZoomMagnify.setOnClickListener(listener);
}
@@ -260,7 +260,7 @@
ZoomControls mZoomControls;
ImageView mZoomMagnify;
}
-
+
/**
* Transportation object for returning WebView across thread boundaries.
*/
@@ -363,12 +363,12 @@
// take control of touch events unless it says no for touch down event.
private boolean mPreventDrag;
- // If updateTextEntry gets called while we are out of focus, use this
+ // If updateTextEntry gets called while we are out of focus, use this
// variable to remember to do it next time we gain focus.
private boolean mNeedsUpdateTextEntry = false;
-
- // Whether or not to draw the focus ring.
- private boolean mDrawFocusRing = true;
+
+ // Whether or not to draw the cursor ring.
+ private boolean mDrawCursorRing = true;
// true if onPause has been called (and not onResume)
private boolean mIsPaused;
@@ -391,7 +391,7 @@
// needed to avoid flinging after a pause of no movement
private static final int MIN_FLING_TIME = 250;
// The time that the Zoom Controls are visible before fading away
- private static final long ZOOM_CONTROLS_TIMEOUT =
+ private static final long ZOOM_CONTROLS_TIMEOUT =
ViewConfiguration.getZoomControlsTimeout();
// The amount of content to overlap between two screens when going through
// pages with the space bar, in pixels.
@@ -412,7 +412,7 @@
private int mContentWidth; // cache of value from WebViewCore
private int mContentHeight; // cache of value from WebViewCore
- // Need to have the separate control for horizontal and vertical scrollbar
+ // Need to have the separate control for horizontal and vertical scrollbar
// style than the View's single scrollbar style
private boolean mOverlayHorizontalScrollbar = true;
private boolean mOverlayVerticalScrollbar = false;
@@ -427,9 +427,6 @@
private boolean mWrapContent;
- // true if we should call webcore to draw the content, false means we have
- // requested something but it isn't ready to draw yet.
- private WebViewCore.FocusData mFocusData;
/**
* Private message ids
*/
@@ -438,7 +435,7 @@
private static final int SWITCH_TO_SHORTPRESS = 3;
private static final int SWITCH_TO_LONGPRESS = 4;
private static final int UPDATE_TEXT_ENTRY_ADAPTER = 6;
- private static final int SWITCH_TO_ENTER = 7;
+ private static final int SWITCH_TO_CLICK = 7;
private static final int RESUME_WEBCORE_UPDATE = 8;
//! arg1=x, arg2=y
@@ -454,7 +451,7 @@
static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17;
static final int DID_FIRST_LAYOUT_MSG_ID = 18;
static final int RECOMPUTE_FOCUS_MSG_ID = 19;
- static final int NOTIFY_FOCUS_SET_MSG_ID = 20;
+
static final int MARK_NODE_INVALID_ID = 21;
static final int UPDATE_CLIPBOARD = 22;
static final int LONG_PRESS_ENTER = 23;
@@ -462,7 +459,7 @@
static final int WEBCORE_NEED_TOUCH_EVENTS = 25;
// obj=Rect in doc coordinates
static final int INVAL_RECT_MSG_ID = 26;
-
+
static final String[] HandlerDebugString = {
"REMEMBER_PASSWORD", // = 1;
"NEVER_REMEMBER_PASSWORD", // = 2;
@@ -470,7 +467,7 @@
"SWITCH_TO_LONGPRESS", // = 4;
"5",
"UPDATE_TEXT_ENTRY_ADAPTER", // = 6;
- "SWITCH_TO_ENTER", // = 7;
+ "SWITCH_TO_CLICK", // = 7;
"RESUME_WEBCORE_UPDATE", // = 8;
"9",
"SCROLL_TO_MSG_ID", // = 10;
@@ -483,7 +480,7 @@
"UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
"DID_FIRST_LAYOUT_MSG_ID", // = 18;
"RECOMPUTE_FOCUS_MSG_ID", // = 19;
- "NOTIFY_FOCUS_SET_MSG_ID", // = 20;
+ "20",
"MARK_NODE_INVALID_ID", // = 21;
"UPDATE_CLIPBOARD", // = 22;
"LONG_PRESS_ENTER", // = 23;
@@ -527,7 +524,7 @@
private static final int SNAP_X_LOCK = 4;
private static final int SNAP_Y_LOCK = 5;
private boolean mSnapPositive;
-
+
// Used to match key downs and key ups
private boolean mGotKeyDown;
@@ -550,7 +547,7 @@
* URI scheme for map address
*/
public static final String SCHEME_GEO = "geo:0,0?q=";
-
+
private int mBackgroundColor = Color.WHITE;
// Used to notify listeners of a new picture.
@@ -638,7 +635,7 @@
private ExtendedZoomControls mZoomControls;
private Runnable mZoomControlRunnable;
- private ZoomButtonsController mZoomButtonsController;
+ private ZoomButtonsController mZoomButtonsController;
private ImageView mZoomOverviewButton;
private ImageView mZoomFitPageButton;
@@ -663,11 +660,11 @@
} else {
zoomOut();
}
-
+
updateZoomButtonsEnabled();
}
};
-
+
/**
* Construct a new WebView with a Context object.
* @param context A Context object used to access application assets.
@@ -698,11 +695,6 @@
mCallbackProxy = new CallbackProxy(context, this);
mWebViewCore = new WebViewCore(context, this, mCallbackProxy);
mDatabase = WebViewDatabase.getInstance(context);
- mFocusData = new WebViewCore.FocusData();
- mFocusData.mFrame = 0;
- mFocusData.mNode = 0;
- mFocusData.mX = 0;
- mFocusData.mY = 0;
mScroller = new Scroller(context);
initZoomController(context);
@@ -969,7 +961,7 @@
clearTextEntry();
if (mWebViewCore != null) {
// Set the handlers to null before destroying WebViewCore so no
- // more messages will be posted.
+ // more messages will be posted.
mCallbackProxy.setWebViewClient(null);
mCallbackProxy.setWebChromeClient(null);
// Tell WebViewCore to destroy itself
@@ -1005,7 +997,7 @@
public static void disablePlatformNotifications() {
Network.disablePlatformNotifications();
}
-
+
/**
* Inform WebView of the network state. This is used to set
* the javascript property window.navigator.isOnline and
@@ -1018,7 +1010,7 @@
}
/**
- * Save the state of this WebView used in
+ * Save the state of this WebView used in
* {@link android.app.Activity#onSaveInstanceState}. Please note that this
* method no longer stores the display data for this WebView. The previous
* behavior could potentially leak files if {@link #restoreState} was never
@@ -1149,10 +1141,10 @@
/**
* Restore the state of this WebView from the given map used in
- * {@link android.app.Activity#onRestoreInstanceState}. This method should
- * be called to restore the state of the WebView before using the object. If
- * it is called after the WebView has had a chance to build state (load
- * pages, create a back/forward list, etc.) there may be undesirable
+ * {@link android.app.Activity#onRestoreInstanceState}. This method should
+ * be called to restore the state of the WebView before using the object. If
+ * it is called after the WebView has had a chance to build state (load
+ * pages, create a back/forward list, etc.) there may be undesirable
* side-effects. Please note that this method no longer restores the
* display data for this WebView. See {@link #savePicture} and {@link
* #restorePicture} for saving and restoring the display data.
@@ -1222,10 +1214,10 @@
* Load the url with postData using "POST" method into the WebView. If url
* is not a network url, it will be loaded with {link
* {@link #loadUrl(String)} instead.
- *
+ *
* @param url The url of the resource to load.
* @param postData The data will be passed to "POST" request.
- *
+ *
* @hide pending API solidification
*/
public void postUrl(String url, byte[] postData) {
@@ -1267,7 +1259,7 @@
* able to access asset files. If the baseUrl is anything other than
* http(s)/ftp(s)/about/javascript as scheme, you can access asset files for
* sub resources.
- *
+ *
* @param baseUrl Url to resolve relative paths with, if null defaults to
* "about:blank"
* @param data A String of data in the given encoding.
@@ -1278,7 +1270,7 @@
*/
public void loadDataWithBaseURL(String baseUrl, String data,
String mimeType, String encoding, String failUrl) {
-
+
if (baseUrl != null && baseUrl.toLowerCase().startsWith("data:")) {
loadData(data, mimeType, encoding);
return;
@@ -1399,7 +1391,7 @@
ignoreSnapshot ? 1 : 0);
}
}
-
+
private boolean extendScroll(int y) {
int finalY = mScroller.getFinalY();
int newY = pinLocY(finalY + y);
@@ -1408,7 +1400,7 @@
mScroller.extendDuration(computeDuration(0, y));
return true;
}
-
+
/**
* Scroll the contents of the view up by half the view size
* @param top true to jump to the top of the page
@@ -1432,10 +1424,10 @@
y = -h / 2;
}
mUserScroll = true;
- return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
+ return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
: extendScroll(y);
}
-
+
/**
* Scroll the contents of the view down by half the page size
* @param bottom true to jump to bottom of page
@@ -1458,7 +1450,7 @@
y = h / 2;
}
mUserScroll = true;
- return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
+ return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
: extendScroll(y);
}
@@ -1471,7 +1463,7 @@
mContentHeight = 0;
mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
}
-
+
/**
* Return a new picture that captures the current display of the webview.
* This is a copy of the display, and will be unaffected if the webview
@@ -1482,7 +1474,7 @@
* bounds of the view.
*/
public Picture capturePicture() {
- if (null == mWebViewCore) return null; // check for out of memory tab
+ if (null == mWebViewCore) return null; // check for out of memory tab
return mWebViewCore.copyContentPicture();
}
@@ -1500,7 +1492,7 @@
}
}
- /**
+ /**
* Return the current scale of the WebView
* @return The current scale.
*/
@@ -1564,26 +1556,26 @@
}
HitTestResult result = new HitTestResult();
-
- if (nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- if (node.mIsTextField || node.mIsTextArea) {
+ if (nativeHasCursorNode()) {
+ if (nativeCursorIsTextInput()) {
result.setType(HitTestResult.EDIT_TEXT_TYPE);
- } else if (node.mText != null) {
- String text = node.mText;
- if (text.startsWith(SCHEME_TEL)) {
- result.setType(HitTestResult.PHONE_TYPE);
- result.setExtra(text.substring(SCHEME_TEL.length()));
- } else if (text.startsWith(SCHEME_MAILTO)) {
- result.setType(HitTestResult.EMAIL_TYPE);
- result.setExtra(text.substring(SCHEME_MAILTO.length()));
- } else if (text.startsWith(SCHEME_GEO)) {
- result.setType(HitTestResult.GEO_TYPE);
- result.setExtra(URLDecoder.decode(text
- .substring(SCHEME_GEO.length())));
- } else if (node.mIsAnchor) {
- result.setType(HitTestResult.SRC_ANCHOR_TYPE);
- result.setExtra(text);
+ } else {
+ String text = nativeCursorText();
+ if (text != null) {
+ if (text.startsWith(SCHEME_TEL)) {
+ result.setType(HitTestResult.PHONE_TYPE);
+ result.setExtra(text.substring(SCHEME_TEL.length()));
+ } else if (text.startsWith(SCHEME_MAILTO)) {
+ result.setType(HitTestResult.EMAIL_TYPE);
+ result.setExtra(text.substring(SCHEME_MAILTO.length()));
+ } else if (text.startsWith(SCHEME_GEO)) {
+ result.setType(HitTestResult.GEO_TYPE);
+ result.setExtra(URLDecoder.decode(text
+ .substring(SCHEME_GEO.length())));
+ } else if (nativeCursorIsAnchor()) {
+ result.setType(HitTestResult.SRC_ANCHOR_TYPE);
+ result.setExtra(text);
+ }
}
}
}
@@ -1595,8 +1587,8 @@
int contentY = viewToContent((int) mLastTouchY + mScrollY);
String text = nativeImageURI(contentX, contentY);
if (text != null) {
- result.setType(type == HitTestResult.UNKNOWN_TYPE ?
- HitTestResult.IMAGE_TYPE :
+ result.setType(type == HitTestResult.UNKNOWN_TYPE ?
+ HitTestResult.IMAGE_TYPE :
HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
result.setExtra(text);
}
@@ -1608,7 +1600,7 @@
* Request the href of an anchor element due to getFocusNodePath returning
* "href." If hrefMsg is null, this method returns immediately and does not
* dispatch hrefMsg to its target.
- *
+ *
* @param hrefMsg This message will be dispatched with the result of the
* request as the data member with "url" as key. The result can
* be null.
@@ -1617,22 +1609,20 @@
if (hrefMsg == null || mNativeClass == 0) {
return;
}
- if (nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- if (node.mIsAnchor) {
- // NOTE: We may already have the url of the anchor stored in
- // node.mText but it may be out of date or the caller may want
- // to know about javascript urls.
- mWebViewCore.sendMessage(EventHub.REQUEST_FOCUS_HREF,
- node.mFramePointer, node.mNodePointer, hrefMsg);
- }
+ if (nativeCursorIsAnchor()) {
+ // NOTE: We may already have the url of the anchor stored in
+ // node.mText but it may be out of date or the caller may want
+ // to know about javascript urls.
+ mWebViewCore.sendMessage(EventHub.REQUEST_FOCUS_HREF,
+ nativeCursorFramePointer(), nativeCursorNodePointer(),
+ hrefMsg);
}
}
-
+
/**
* Request the url of the image last touched by the user. msg will be sent
* to its target with a String representing the url as its object.
- *
+ *
* @param msg This message will be dispatched with the result of the request
* as the data member with "url" as key. The result can be null.
*/
@@ -1707,7 +1697,7 @@
if ((w | h) == 0) {
return;
}
-
+
// don't abort a scroll animation if we didn't change anything
if (mContentWidth != w || mContentHeight != h) {
// record new dimensions
@@ -1767,7 +1757,7 @@
mActualScale = scale;
mInvActualScale = 1 / scale;
- // as we don't have animation for scaling, don't do animation
+ // as we don't have animation for scaling, don't do animation
// for scrolling, as it causes weird intermediate state
// pinScrollTo(Math.round(sx), Math.round(sy));
mScrollX = pinLocX(Math.round(sx));
@@ -1891,10 +1881,10 @@
WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
return h != null ? h.getUrl() : null;
}
-
+
/**
- * Get the original url for the current page. This is not always the same
- * as the url passed to WebViewClient.onPageStarted because although the
+ * Get the original url for the current page. This is not always the same
+ * as the url passed to WebViewClient.onPageStarted because although the
* load for that url has begun, the current page may not have changed.
* Also, there may have been redirects resulting in a different url to that
* originally requested.
@@ -1932,7 +1922,7 @@
public int getProgress() {
return mCallbackProxy.getProgress();
}
-
+
/**
* @return the height of the HTML content.
*/
@@ -2048,7 +2038,7 @@
/*
* Highlight and scroll to the next occurance of String in findAll.
- * Wraps the page infinitely, and scrolls. Must be called after
+ * Wraps the page infinitely, and scrolls. Must be called after
* calling findAll.
*
* @param forward Direction to search.
@@ -2074,11 +2064,8 @@
// or not we draw the highlights for matches.
private boolean mFindIsUp;
- private native int nativeFindAll(String findLower, String findUpper);
- private native void nativeFindNext(boolean forward);
-
/**
- * Return the first substring consisting of the address of a physical
+ * Return the first substring consisting of the address of a physical
* location. Currently, only addresses in the United States are detected,
* and consist of:
* - a house number
@@ -2091,7 +2078,7 @@
* All names must be correctly capitalized, and the zip code, if present,
* must be valid for the state. The street type must be a standard USPS
* spelling or abbreviation. The state or territory must also be spelled
- * or abbreviated using USPS standards. The house number may not exceed
+ * or abbreviated using USPS standards. The house number may not exceed
* five digits.
* @param addr The string to search for addresses.
*
@@ -2396,7 +2383,7 @@
protected void finalize() throws Throwable {
destroy();
}
-
+
@Override
protected void onDraw(Canvas canvas) {
// if mNativeClass is 0, the WebView has been destroyed. Do nothing.
@@ -2405,7 +2392,7 @@
}
if (mWebViewCore.mEndScaleZoom) {
mWebViewCore.mEndScaleZoom = false;
- if (mTouchMode >= FIRST_SCROLL_ZOOM
+ if (mTouchMode >= FIRST_SCROLL_ZOOM
&& mTouchMode <= LAST_SCROLL_ZOOM) {
setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(true);
@@ -2428,10 +2415,10 @@
nativeRecordButtons(hasFocus() && hasWindowFocus(),
mTouchMode == TOUCH_SHORTPRESS_START_MODE
|| mTrackballDown || mGotEnterDown, false);
- drawCoreAndFocusRing(canvas, mBackgroundColor, mDrawFocusRing);
+ drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
}
canvas.restoreToCount(sc);
-
+
if (AUTO_REDRAW_HACK && mAutoRedraw) {
invalidate();
}
@@ -2454,7 +2441,7 @@
}
}
- private void drawCoreAndFocusRing(Canvas canvas, int color,
+ private void drawCoreAndCursorRing(Canvas canvas, int color,
boolean drawFocus) {
if (mDrawHistory) {
canvas.scale(mActualScale, mActualScale);
@@ -2463,14 +2450,14 @@
}
boolean animateZoom = mZoomScale != 0;
- boolean animateScroll = !mScroller.isFinished()
+ boolean animateScroll = !mScroller.isFinished()
|| mVelocityTracker != null;
if (animateZoom) {
float zoomScale;
int interval = (int) (SystemClock.uptimeMillis() - mZoomStart);
if (interval < ZOOM_ANIMATION_LENGTH) {
float ratio = (float) interval / ZOOM_ANIMATION_LENGTH;
- zoomScale = 1.0f / (mInvInitialZoomScale
+ zoomScale = 1.0f / (mInvInitialZoomScale
+ (mInvFinalZoomScale - mInvInitialZoomScale) * ratio);
invalidate();
} else {
@@ -2510,7 +2497,7 @@
if (mTouchSelection) {
nativeDrawSelectionRegion(canvas);
} else {
- nativeDrawSelection(canvas, mSelectX, mSelectY,
+ nativeDrawSelection(canvas, mSelectX, mSelectY,
mExtendSelection);
}
} else if (drawFocus) {
@@ -2524,7 +2511,7 @@
LONG_PRESS_TIMEOUT);
}
}
- nativeDrawFocusRing(canvas);
+ nativeDrawCursorRing(canvas);
}
// When the FindDialog is up, only draw the matches if we are not in
// the process of scrolling them into view.
@@ -2533,14 +2520,12 @@
}
}
- private native void nativeDrawMatches(Canvas canvas);
-
private float scrollZoomGridScale(float invScale) {
- float griddedInvScale = (int) (invScale * SCROLL_ZOOM_GRID)
+ float griddedInvScale = (int) (invScale * SCROLL_ZOOM_GRID)
/ (float) SCROLL_ZOOM_GRID;
return 1.0f / griddedInvScale;
}
-
+
private float scrollZoomX(float scale) {
int width = getViewWidth();
float maxScrollZoomX = mContentWidth * scale - width;
@@ -2556,7 +2541,7 @@
return -(maxScrollZoomY > 0 ? mZoomScrollY * maxScrollZoomY / maxY
: maxScrollZoomY / 2);
}
-
+
private void drawMagnifyFrame(Canvas canvas, Rect frame, Paint paint) {
final float ADORNMENT_LEN = 16.0f;
float width = frame.width();
@@ -2577,13 +2562,13 @@
path.offset(frame.left, frame.top);
canvas.drawPath(path, paint);
}
-
- // Returns frame surrounding magified portion of screen while
+
+ // Returns frame surrounding magified portion of screen while
// scroll-zoom is enabled. The frame is also used to center the
// zoom-in zoom-out points at the start and end of the animation.
private Rect scrollZoomFrame(int width, int height, float halfScale) {
Rect scrollFrame = new Rect();
- scrollFrame.set(mZoomScrollX, mZoomScrollY,
+ scrollFrame.set(mZoomScrollX, mZoomScrollY,
mZoomScrollX + width, mZoomScrollY + height);
if (mContentWidth * mZoomScrollLimit < width) {
float scale = zoomFrameScaleX(width, halfScale, 1.0f);
@@ -2599,37 +2584,37 @@
}
return scrollFrame;
}
-
+
private float zoomFrameScaleX(int width, float halfScale, float noScale) {
// mContentWidth > width > mContentWidth * mZoomScrollLimit
if (mContentWidth <= width) {
return halfScale;
}
- float part = (width - mContentWidth * mZoomScrollLimit)
+ float part = (width - mContentWidth * mZoomScrollLimit)
/ (width * (1 - mZoomScrollLimit));
return halfScale * part + noScale * (1.0f - part);
}
-
+
private float zoomFrameScaleY(int height, float halfScale, float noScale) {
if (mContentHeight <= height) {
return halfScale;
}
- float part = (height - mContentHeight * mZoomScrollLimit)
+ float part = (height - mContentHeight * mZoomScrollLimit)
/ (height * (1 - mZoomScrollLimit));
return halfScale * part + noScale * (1.0f - part);
}
-
+
private float scrollZoomMagScale(float invScale) {
return (invScale * 2 + mInvActualScale) / 3;
}
-
+
private void scrollZoomDraw(Canvas canvas) {
- float invScale = mZoomScrollInvLimit;
+ float invScale = mZoomScrollInvLimit;
int elapsed = 0;
if (mTouchMode != SCROLL_ZOOM_OUT) {
- elapsed = (int) Math.min(System.currentTimeMillis()
+ elapsed = (int) Math.min(System.currentTimeMillis()
- mZoomScrollStart, SCROLL_ZOOM_DURATION);
- float transitionScale = (mZoomScrollInvLimit - mInvActualScale)
+ float transitionScale = (mZoomScrollInvLimit - mInvActualScale)
* elapsed / SCROLL_ZOOM_DURATION;
if (mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
invScale = mInvActualScale + transitionScale;
@@ -2648,8 +2633,8 @@
setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(true);
updateTextEntry();
- scrollTo((int) (scrollFrame.centerX() * mActualScale)
- - (width >> 1), (int) (scrollFrame.centerY()
+ scrollTo((int) (scrollFrame.centerX() * mActualScale)
+ - (width >> 1), (int) (scrollFrame.centerY()
* mActualScale) - (height >> 1));
mTouchMode = TOUCH_DONE_MODE;
} else {
@@ -2661,7 +2646,7 @@
if (LOGV_ENABLED) {
Log.v(LOGTAG, "scrollZoomDraw scale=" + scale + " + (" + newX
+ ", " + newY + ") mZoomScroll=(" + mZoomScrollX + ", "
- + mZoomScrollY + ")" + " invScale=" + invScale + " scale="
+ + mZoomScrollY + ")" + " invScale=" + invScale + " scale="
+ scale);
}
canvas.translate(newX, newY);
@@ -2706,7 +2691,7 @@
canvas.scale(halfScale, halfScale, mZoomScrollX + width * halfX
, mZoomScrollY + height * halfY);
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "scrollZoomDraw halfScale=" + halfScale + " w/h=("
+ Log.v(LOGTAG, "scrollZoomDraw halfScale=" + halfScale + " w/h=("
+ width + ", " + height + ") half=(" + halfX + ", "
+ halfY + ")");
}
@@ -2766,7 +2751,7 @@
return mContentWidth >= width * limit
|| mContentHeight >= height * limit;
}
-
+
private void startZoomScrollOut() {
setHorizontalScrollBarEnabled(false);
setVerticalScrollBarEnabled(false);
@@ -2792,18 +2777,18 @@
mZoomScrollStart = System.currentTimeMillis();
Rect zoomFrame = scrollZoomFrame(width, height
, scrollZoomMagScale(mZoomScrollInvLimit));
- mZoomScrollX = Math.max(0, (int) ((mScrollX + halfW) * mInvActualScale)
+ mZoomScrollX = Math.max(0, (int) ((mScrollX + halfW) * mInvActualScale)
- (zoomFrame.width() >> 1));
- mZoomScrollY = Math.max(0, (int) ((mScrollY + halfH) * mInvActualScale)
+ mZoomScrollY = Math.max(0, (int) ((mScrollY + halfH) * mInvActualScale)
- (zoomFrame.height() >> 1));
scrollTo(0, 0); // triggers inval, starts animation
clearTextEntry();
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "startZoomScrollOut mZoomScroll=("
+ Log.v(LOGTAG, "startZoomScrollOut mZoomScroll=("
+ mZoomScrollX + ", " + mZoomScrollY +")");
}
}
-
+
private void zoomScrollOut() {
if (canZoomScrollOut() == false) {
mTouchMode = TOUCH_DONE_MODE;
@@ -2815,7 +2800,7 @@
}
private void moveZoomScrollWindow(float x, float y) {
- if (Math.abs(x - mLastZoomScrollRawX) < 1.5f
+ if (Math.abs(x - mLastZoomScrollRawX) < 1.5f
&& Math.abs(y - mLastZoomScrollRawY) < 1.5f) {
return;
}
@@ -2827,12 +2812,12 @@
int height = getViewHeight();
int maxZoomX = mContentWidth - width;
if (maxZoomX > 0) {
- int maxScreenX = width - (int) Math.ceil(width
+ int maxScreenX = width - (int) Math.ceil(width
* mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveZoomScrollWindow-X"
+ Log.v(LOGTAG, "moveZoomScrollWindow-X"
+ " maxScreenX=" + maxScreenX + " width=" + width
- + " mZoomScrollLimit=" + mZoomScrollLimit + " x=" + x);
+ + " mZoomScrollLimit=" + mZoomScrollLimit + " x=" + x);
}
x += maxScreenX * mLastScrollX / maxZoomX - mLastTouchX;
x *= Math.max(maxZoomX / maxScreenX, mZoomScrollInvLimit);
@@ -2840,12 +2825,12 @@
}
int maxZoomY = mContentHeight - height;
if (maxZoomY > 0) {
- int maxScreenY = height - (int) Math.ceil(height
+ int maxScreenY = height - (int) Math.ceil(height
* mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveZoomScrollWindow-Y"
+ Log.v(LOGTAG, "moveZoomScrollWindow-Y"
+ " maxScreenY=" + maxScreenY + " height=" + height
- + " mZoomScrollLimit=" + mZoomScrollLimit + " y=" + y);
+ + " mZoomScrollLimit=" + mZoomScrollLimit + " y=" + y);
}
y += maxScreenY * mLastScrollY / maxZoomY - mLastTouchY;
y *= Math.max(maxZoomY / maxScreenY, mZoomScrollInvLimit);
@@ -2855,11 +2840,11 @@
invalidate();
}
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveZoomScrollWindow"
- + " scrollTo=(" + mZoomScrollX + ", " + mZoomScrollY + ")"
- + " mLastTouch=(" + mLastTouchX + ", " + mLastTouchY + ")"
- + " maxZoom=(" + maxZoomX + ", " + maxZoomY + ")"
- + " last=("+mLastScrollX+", "+mLastScrollY+")"
+ Log.v(LOGTAG, "moveZoomScrollWindow"
+ + " scrollTo=(" + mZoomScrollX + ", " + mZoomScrollY + ")"
+ + " mLastTouch=(" + mLastTouchX + ", " + mLastTouchY + ")"
+ + " maxZoom=(" + maxZoomX + ", " + maxZoomY + ")"
+ + " last=("+mLastScrollX+", "+mLastScrollY+")"
+ " x=" + x + " y=" + y);
}
}
@@ -2920,64 +2905,20 @@
}
}
- /**
- * Class representing the node which is focused.
- */
- private static class FocusNode {
- public FocusNode() {
- mBounds = new Rect();
- }
- // Only to be called by JNI
- private void setAll(boolean isTextField, boolean isTextArea, boolean
- isPassword, boolean isAnchor, boolean isRtlText, int maxLength,
- int textSize, int boundsX, int boundsY, int boundsRight, int
- boundsBottom, int nodePointer, int framePointer, String text,
- String name, int rootTextGeneration) {
- mIsTextField = isTextField;
- mIsTextArea = isTextArea;
- mIsPassword = isPassword;
- mIsAnchor = isAnchor;
- mIsRtlText = isRtlText;
-
- mMaxLength = maxLength;
- mTextSize = textSize;
-
- mBounds.set(boundsX, boundsY, boundsRight, boundsBottom);
-
-
- mNodePointer = nodePointer;
- mFramePointer = framePointer;
- mText = text;
- mName = name;
- mRootTextGeneration = rootTextGeneration;
- }
- public boolean mIsTextField;
- public boolean mIsTextArea;
- public boolean mIsPassword;
- public boolean mIsAnchor;
- public boolean mIsRtlText;
-
- public int mSelectionStart;
- public int mSelectionEnd;
- public int mMaxLength;
- public int mTextSize;
-
- public Rect mBounds;
-
- public int mNodePointer;
- public int mFramePointer;
- public String mText;
- public String mName;
- public int mRootTextGeneration;
+ WebViewCore.CursorData cursorData() {
+ WebViewCore.CursorData result = new WebViewCore.CursorData();
+ result.mMoveGeneration = nativeMoveGeneration();
+ result.mFrame = nativeCursorFramePointer();
+ result.mNode = nativeCursorNodePointer();
+ Rect bounds = nativeCursorNodeBounds();
+ result.mX = bounds.centerX();
+ result.mY = bounds.centerY();
+ return result;
}
-
- // Warning: ONLY use mFocusNode AFTER calling nativeUpdateFocusNode(),
- // and ONLY if it returns true;
- private FocusNode mFocusNode = new FocusNode();
-
+
/**
* Delete text from start to end in the focused textfield. If there is no
- * focus, or if start == end, silently fail. If start and end are out of
+ * focus, or if start == end, silently fail. If start and end are out of
* order, swap them.
* @param start Beginning of selection to delete.
* @param end End of selection to delete.
@@ -2985,7 +2926,7 @@
/* package */ void deleteSelection(int start, int end) {
mTextGeneration++;
mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, start, end,
- new WebViewCore.FocusData(mFocusData));
+ cursorData());
}
/**
@@ -2996,7 +2937,7 @@
*/
/* package */ void setSelection(int start, int end) {
mWebViewCore.sendMessage(EventHub.SET_SELECTION, start, end,
- new WebViewCore.FocusData(mFocusData));
+ cursorData());
}
// Called by JNI when a touch event puts a textfield into focus.
@@ -3021,7 +2962,7 @@
private void updateTextEntry() {
// If we do not have focus, do nothing until we gain focus.
if (!hasFocus() && (null == mTextEntry || !mTextEntry.hasFocus())
- || (mTouchMode >= FIRST_SCROLL_ZOOM
+ || (mTouchMode >= FIRST_SCROLL_ZOOM
&& mTouchMode <= LAST_SCROLL_ZOOM)) {
mNeedsUpdateTextEntry = true;
return;
@@ -3029,14 +2970,8 @@
boolean alreadyThere = inEditingMode();
// inEditingMode can only return true if mTextEntry is non-null,
// so we can safely call remove() if (alreadyThere)
- if (0 == mNativeClass || !nativeUpdateFocusNode()) {
- if (alreadyThere) {
- mTextEntry.remove();
- }
- return;
- }
- FocusNode node = mFocusNode;
- if (!node.mIsTextField && !node.mIsTextArea) {
+ if (0 == mNativeClass || (!nativeFocusIsTextInput()
+ && !nativeCursorIsTextInput())) {
if (alreadyThere) {
mTextEntry.remove();
}
@@ -3049,19 +2984,18 @@
// Initialize our generation number.
mTextGeneration = 0;
}
- mTextEntry.setTextSize(contentToView(node.mTextSize));
+ mTextEntry.setTextSize(contentToView(nativeFocusTextSize()));
Rect visibleRect = sendOurVisibleRect();
// Note that sendOurVisibleRect calls viewToContent, so the coordinates
// should be in content coordinates.
- if (!Rect.intersects(node.mBounds, visibleRect)) {
+ Rect bounds = nativeFocusNodeBounds();
+ if (!Rect.intersects(bounds, visibleRect)) {
// Node is not on screen, so do not bother.
return;
}
- int x = node.mBounds.left;
- int y = node.mBounds.top;
- int width = node.mBounds.width();
- int height = node.mBounds.height();
- if (alreadyThere && mTextEntry.isSameTextField(node.mNodePointer)) {
+ String text = nativeFocusText();
+ int nodePointer = nativeFocusNodePointer();
+ if (alreadyThere && mTextEntry.isSameTextField(nodePointer)) {
// It is possible that we have the same textfield, but it has moved,
// i.e. In the case of opening/closing the screen.
// In that case, we need to set the dimensions, but not the other
@@ -3071,36 +3005,37 @@
Spannable spannable = (Spannable) mTextEntry.getText();
int start = Selection.getSelectionStart(spannable);
int end = Selection.getSelectionEnd(spannable);
- setTextEntryRect(x, y, width, height);
// If the text has been changed by webkit, update it. However, if
// there has been more UI text input, ignore it. We will receive
// another update when that text is recognized.
- if (node.mText != null && !node.mText.equals(spannable.toString())
- && node.mRootTextGeneration == mTextGeneration) {
- mTextEntry.setTextAndKeepSelection(node.mText);
+ if (text != null && !text.equals(spannable.toString())
+ && nativeTextGeneration() == mTextGeneration) {
+ mTextEntry.setTextAndKeepSelection(text);
} else {
Selection.setSelection(spannable, start, end);
}
} else {
- String text = node.mText;
- setTextEntryRect(x, y, width, height);
- mTextEntry.setGravity(node.mIsRtlText ? Gravity.RIGHT :
+ Rect vBox = contentToView(bounds);
+ mTextEntry.setRect(vBox.left, vBox.top, vBox.width(), vBox.height());
+ mTextEntry.setGravity(nativeFocusIsRtlText() ? Gravity.RIGHT :
Gravity.NO_GRAVITY);
// this needs to be called before update adapter thread starts to
// ensure the mTextEntry has the same node pointer
- mTextEntry.setNodePointer(node.mNodePointer);
+ mTextEntry.setNodePointer(nodePointer);
int maxLength = -1;
- if (node.mIsTextField) {
- maxLength = node.mMaxLength;
+ boolean isTextField = nativeFocusIsTextField();
+ if (isTextField) {
+ maxLength = nativeFocusMaxLength();
+ String name = nativeFocusName();
if (mWebViewCore.getSettings().getSaveFormData()
- && node.mName != null) {
+ && name != null) {
HashMap data = new HashMap();
- data.put("text", node.mText);
+ data.put("text", text);
Message update = mPrivateHandler.obtainMessage(
- UPDATE_TEXT_ENTRY_ADAPTER, node.mNodePointer, 0,
+ UPDATE_TEXT_ENTRY_ADAPTER, nodePointer, 0,
data);
UpdateTextEntryAdapter updater = new UpdateTextEntryAdapter(
- node.mName, getUrl(), update);
+ name, getUrl(), update);
Thread t = new Thread(updater);
t.start();
}
@@ -3108,8 +3043,8 @@
mTextEntry.setMaxLength(maxLength);
AutoCompleteAdapter adapter = null;
mTextEntry.setAdapterCustom(adapter);
- mTextEntry.setSingleLine(node.mIsTextField);
- mTextEntry.setInPassword(node.mIsPassword);
+ mTextEntry.setSingleLine(isTextField);
+ mTextEntry.setInPassword(nativeFocusIsPassword());
if (null == text) {
mTextEntry.setText("", 0, 0);
} else {
@@ -3123,7 +3058,7 @@
// selection at the end, and textareas at the beginning.
if (false) {
mTextEntry.setText(text, 0, text.length());
- } else if (node.mIsTextField) {
+ } else if (isTextField) {
int length = text.length();
mTextEntry.setText(text, length, length);
} else {
@@ -3156,14 +3091,6 @@
}
}
- private void setTextEntryRect(int x, int y, int width, int height) {
- x = contentToView(x);
- y = contentToView(y);
- width = contentToView(width);
- height = contentToView(height);
- mTextEntry.setRect(x, y, width, height);
- }
-
// This is used to determine long press with the enter key, or
// a center key. Does not affect long press with the trackball/touch.
private boolean mGotEnterDown = false;
@@ -3199,14 +3126,14 @@
}
if (mShiftIsPressed == false && nativeFocusNodeWantsKeyEvents() == false
- && (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
+ && (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT)) {
mExtendSelection = false;
mShiftIsPressed = true;
- if (nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- mSelectX = contentToView(node.mBounds.left);
- mSelectY = contentToView(node.mBounds.top);
+ if (nativeHasCursorNode()) {
+ Rect rect = nativeCursorNodeBounds();
+ mSelectX = contentToView(rect.left);
+ mSelectY = contentToView(rect.top);
} else {
mSelectX = mScrollX + (int) mLastTouchX;
mSelectY = mScrollY + (int) mLastTouchY;
@@ -3305,10 +3232,9 @@
}
// special CALL handling when focus node's href is "tel:XXX"
- if (keyCode == KeyEvent.KEYCODE_CALL && nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- String text = node.mText;
- if (!node.mIsTextField && !node.mIsTextArea && text != null
+ if (keyCode == KeyEvent.KEYCODE_CALL && nativeHasCursorNode()) {
+ String text = nativeCursorText();
+ if (!nativeCursorIsTextInput() && text != null
&& text.startsWith(SCHEME_TEL)) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(text));
getContext().startActivity(intent);
@@ -3335,7 +3261,7 @@
return false;
}
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
+ if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
if (commitCopy()) {
return true;
@@ -3367,7 +3293,7 @@
Log.v(LOGTAG, "TOUCH_DOUBLECLICK_MODE");
}
mPrivateHandler.sendMessageDelayed(mPrivateHandler
- .obtainMessage(SWITCH_TO_ENTER), TAP_TIMEOUT);
+ .obtainMessage(SWITCH_TO_CLICK), TAP_TIMEOUT);
mTouchMode = TOUCH_DOUBLECLICK_MODE;
}
return true;
@@ -3377,19 +3303,14 @@
Rect visibleRect = sendOurVisibleRect();
// Note that sendOurVisibleRect calls viewToContent, so the
// coordinates should be in content coordinates.
- if (nativeUpdateFocusNode()) {
- if (Rect.intersects(mFocusNode.mBounds, visibleRect)) {
- nativeSetFollowedLink(true);
- mWebViewCore.sendMessage(EventHub.SET_FINAL_FOCUS,
- EventHub.BLOCK_FOCUS_CHANGE_UNTIL_KEY_UP, 0,
- new WebViewCore.FocusData(mFocusData));
- playSoundEffect(SoundEffectConstants.CLICK);
- if (!mCallbackProxy.uiOverrideUrlLoading(mFocusNode.mText)) {
- // use CLICK instead of KEY_DOWN/KEY_UP so that we can
- // trigger mouse click events
- mWebViewCore.sendMessage(EventHub.CLICK);
- }
- }
+ if (nativeCursorIntersects(visibleRect)) {
+ nativeSetFollowedLink(true);
+ mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE,
+ EventHub.BLOCK_FOCUS_CHANGE_UNTIL_KEY_UP, 0,
+ cursorData());
+ playSoundEffect(SoundEffectConstants.CLICK);
+ return true;
+ } else if (nativeHasCursorNode()) {
return true;
}
// Bubble up the key event as WebView doesn't handle it
@@ -3407,7 +3328,7 @@
// Bubble up the key event as WebView doesn't handle it
return false;
}
-
+
/**
* @hide
*/
@@ -3464,10 +3385,10 @@
// Clean up the zoom controller
mZoomButtonsController.setVisible(false);
}
-
+
// Implementation for OnHierarchyChangeListener
public void onChildViewAdded(View parent, View child) {}
-
+
public void onChildViewRemoved(View p, View child) {
if (child == this) {
if (inEditingMode()) {
@@ -3486,16 +3407,16 @@
public void onGlobalFocusChanged(View oldFocus, View newFocus) {
}
- // To avoid drawing the focus ring, and remove the TextView when our window
+ // To avoid drawing the cursor ring, and remove the TextView when our window
// loses focus.
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (hasWindowFocus) {
if (hasFocus()) {
// If our window regained focus, and we have focus, then begin
- // drawing the focus ring, and restore the TextView if
+ // drawing the cursor ring, and restore the TextView if
// necessary.
- mDrawFocusRing = true;
+ mDrawCursorRing = true;
if (mNeedsUpdateTextEntry) {
updateTextEntry();
}
@@ -3505,8 +3426,8 @@
setFocusControllerActive(true);
} else {
// If our window gained focus, but we do not have it, do not
- // draw the focus ring.
- mDrawFocusRing = false;
+ // draw the cursor ring.
+ mDrawCursorRing = false;
// We do not call nativeRecordButtons here because we assume
// that when we lost focus, or window focus, it got called with
// false for the first parameter
@@ -3515,13 +3436,13 @@
if (getSettings().getBuiltInZoomControls() && !mZoomButtonsController.isVisible()) {
/*
* The zoom controls come in their own window, so our window
- * loses focus. Our policy is to not draw the focus ring if
+ * loses focus. Our policy is to not draw the cursor ring if
* our window is not focused, but this is an exception since
* the user can still navigate the web page with the zoom
* controls showing.
*/
- // If our window has lost focus, stop drawing the focus ring
- mDrawFocusRing = false;
+ // If our window has lost focus, stop drawing the cursor ring
+ mDrawCursorRing = false;
}
mGotKeyDown = false;
mShiftIsPressed = false;
@@ -3552,9 +3473,9 @@
}
if (focused) {
// When we regain focus, if we have window focus, resume drawing
- // the focus ring, and add the TextView if necessary.
+ // the cursor ring, and add the TextView if necessary.
if (hasWindowFocus()) {
- mDrawFocusRing = true;
+ mDrawCursorRing = true;
if (mNeedsUpdateTextEntry) {
updateTextEntry();
mNeedsUpdateTextEntry = false;
@@ -3573,9 +3494,9 @@
}
} else {
// When we lost focus, unless focus went to the TextView (which is
- // true if we are in editing mode), stop drawing the focus ring.
+ // true if we are in editing mode), stop drawing the cursor ring.
if (!inEditingMode()) {
- mDrawFocusRing = false;
+ mDrawCursorRing = false;
if (mNativeClass != 0) {
nativeRecordButtons(false, false, true);
}
@@ -3610,8 +3531,8 @@
super.onScrollChanged(l, t, oldl, oldt);
sendOurVisibleRect();
}
-
-
+
+
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
boolean dispatch = true;
@@ -3680,7 +3601,7 @@
if (mForwardTouchEvents && mTouchMode != SCROLL_ZOOM_OUT
&& mTouchMode != SCROLL_ZOOM_ANIMATION_IN
&& mTouchMode != SCROLL_ZOOM_ANIMATION_OUT
- && (action != MotionEvent.ACTION_MOVE ||
+ && (action != MotionEvent.ACTION_MOVE ||
eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
ted.mAction = action;
@@ -3739,7 +3660,7 @@
break;
}
case MotionEvent.ACTION_MOVE: {
- if (mTouchMode == TOUCH_DONE_MODE
+ if (mTouchMode == TOUCH_DONE_MODE
|| mTouchMode == SCROLL_ZOOM_ANIMATION_IN
|| mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
// no dragging during scroll zoom animation
@@ -3801,7 +3722,7 @@
if (settings.supportZoom()
&& settings.getBuiltInZoomControls()
&& !mZoomButtonsController.isVisible()
- && (canZoomScrollOut() ||
+ && (canZoomScrollOut() ||
mMinZoomScale < mMaxZoomScale)) {
mZoomButtonsController.setVisible(true);
}
@@ -3827,7 +3748,7 @@
}
// reverse direction means lock in the snap mode
if ((ax > MAX_SLOPE_FOR_DIAG * ay) &&
- ((mSnapPositive &&
+ ((mSnapPositive &&
deltaX < -mMinLockSnapReverseDistance)
|| (!mSnapPositive &&
deltaX > mMinLockSnapReverseDistance))) {
@@ -3841,9 +3762,9 @@
}
// reverse direction means lock in the snap mode
if ((ay > MAX_SLOPE_FOR_DIAG * ax) &&
- ((mSnapPositive &&
+ ((mSnapPositive &&
deltaY < -mMinLockSnapReverseDistance)
- || (!mSnapPositive &&
+ || (!mSnapPositive &&
deltaY > mMinLockSnapReverseDistance))) {
mSnapScrollMode = SNAP_Y_LOCK;
}
@@ -3974,7 +3895,7 @@
}
return true;
}
-
+
private long mTrackballFirstTime = 0;
private long mTrackballLastTime = 0;
private float mTrackballRemainsX = 0.0f;
@@ -4000,10 +3921,10 @@
private Rect mLastFocusBounds;
// Set by default; BrowserActivity clears to interpret trackball data
- // directly for movement. Currently, the framework only passes
+ // directly for movement. Currently, the framework only passes
// arrow key events, not trackball events, from one child to the next
private boolean mMapTrackballToArrowKeys = true;
-
+
public void setMapTrackballToArrowKeys(boolean setMap) {
mMapTrackballToArrowKeys = setMap;
}
@@ -4021,23 +3942,23 @@
return true;
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mPrivateHandler.removeMessages(SWITCH_TO_ENTER);
+ mPrivateHandler.removeMessages(SWITCH_TO_CLICK);
mTrackballDown = true;
if (mNativeClass != 0) {
nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
}
if (time - mLastFocusTime <= TRACKBALL_TIMEOUT
- && !mLastFocusBounds.equals(nativeGetFocusRingBounds())) {
+ && !mLastFocusBounds.equals(nativeGetCursorRingBounds())) {
nativeSelectBestAt(mLastFocusBounds);
}
if (LOGV_ENABLED) {
Log.v(LOGTAG, "onTrackballEvent down ev=" + ev
- + " time=" + time
+ + " time=" + time
+ " mLastFocusTime=" + mLastFocusTime);
}
if (isInTouchMode()) requestFocusFromTouch();
return false; // let common code in onKeyDown at it
- }
+ }
if (ev.getAction() == MotionEvent.ACTION_UP) {
// LONG_PRESS_ENTER is set in common onKeyDown
mPrivateHandler.removeMessages(LONG_PRESS_ENTER);
@@ -4052,7 +3973,7 @@
}
if (LOGV_ENABLED) {
Log.v(LOGTAG, "onTrackballEvent up ev=" + ev
- + " time=" + time
+ + " time=" + time
);
}
return false; // let common code in onKeyUp at it
@@ -4061,7 +3982,7 @@
if (LOGV_ENABLED) Log.v(LOGTAG, "onTrackballEvent gmail quit");
return false;
}
- // no move if we're still waiting on SWITCH_TO_ENTER timeout
+ // no move if we're still waiting on SWITCH_TO_CLICK timeout
if (mTouchMode == TOUCH_DOUBLECLICK_MODE) {
if (LOGV_ENABLED) Log.v(LOGTAG, "onTrackballEvent 2 click quit");
return true;
@@ -4078,7 +3999,7 @@
switchOutDrawHistory();
if (time - mTrackballLastTime > TRACKBALL_TIMEOUT) {
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "onTrackballEvent time="
+ Log.v(LOGTAG, "onTrackballEvent time="
+ time + " last=" + mTrackballLastTime);
}
mTrackballFirstTime = time;
@@ -4093,7 +4014,7 @@
doTrackball(time);
return true;
}
-
+
void moveSelection(float xRate, float yRate) {
if (mNativeClass == 0)
return;
@@ -4108,7 +4029,7 @@
mSelectY = Math.min(maxY, Math.max(mScrollY - SELECT_CURSOR_OFFSET
, mSelectY));
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "moveSelection"
+ Log.v(LOGTAG, "moveSelection"
+ " mSelectX=" + mSelectX
+ " mSelectY=" + mSelectY
+ " mScrollX=" + mScrollX
@@ -4120,10 +4041,10 @@
nativeMoveSelection(viewToContent(mSelectX)
, viewToContent(mSelectY), mExtendSelection);
int scrollX = mSelectX < mScrollX ? -SELECT_CURSOR_OFFSET
- : mSelectX > maxX - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
+ : mSelectX > maxX - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
: 0;
int scrollY = mSelectY < mScrollY ? -SELECT_CURSOR_OFFSET
- : mSelectY > maxY - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
+ : mSelectY > maxY - SELECT_CURSOR_OFFSET ? SELECT_CURSOR_OFFSET
: 0;
pinScrollBy(scrollX, scrollY, true, 0);
Rect select = new Rect(mSelectX, mSelectY, mSelectX + 1, mSelectY + 1);
@@ -4180,7 +4101,7 @@
if (elapsed == 0) {
elapsed = TRACKBALL_TIMEOUT;
}
- float xRate = mTrackballRemainsX * 1000 / elapsed;
+ float xRate = mTrackballRemainsX * 1000 / elapsed;
float yRate = mTrackballRemainsY * 1000 / elapsed;
if (mShiftIsPressed) {
moveSelection(xRate, yRate);
@@ -4209,7 +4130,7 @@
mZoomScrollY += scaleTrackballY(yRate, maxWH);
if (LOGV_ENABLED) {
Log.v(LOGTAG, "doTrackball SCROLL_ZOOM_OUT"
- + " mZoomScrollX=" + mZoomScrollX
+ + " mZoomScrollX=" + mZoomScrollX
+ " mZoomScrollY=" + mZoomScrollY);
}
mZoomScrollX = Math.min(width, Math.max(0, mZoomScrollX));
@@ -4227,13 +4148,13 @@
int oldScrollX = mScrollX;
int oldScrollY = mScrollY;
if (count > 0) {
- int selectKeyCode = ax < ay ? mTrackballRemainsY < 0 ?
- KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN :
+ int selectKeyCode = ax < ay ? mTrackballRemainsY < 0 ?
+ KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN :
mTrackballRemainsX < 0 ? KeyEvent.KEYCODE_DPAD_LEFT :
KeyEvent.KEYCODE_DPAD_RIGHT;
count = Math.min(count, TRACKBALL_MOVE_COUNT);
if (LOGV_ENABLED) {
- Log.v(LOGTAG, "doTrackball keyCode=" + selectKeyCode
+ Log.v(LOGTAG, "doTrackball keyCode=" + selectKeyCode
+ " count=" + count
+ " mTrackballRemainsX=" + mTrackballRemainsX
+ " mTrackballRemainsY=" + mTrackballRemainsY);
@@ -4250,8 +4171,8 @@
Log.v(LOGTAG, "doTrackball pinScrollBy"
+ " count=" + count
+ " xMove=" + xMove + " yMove=" + yMove
- + " mScrollX-oldScrollX=" + (mScrollX-oldScrollX)
- + " mScrollY-oldScrollY=" + (mScrollY-oldScrollY)
+ + " mScrollX-oldScrollX=" + (mScrollX-oldScrollX)
+ + " mScrollY-oldScrollY=" + (mScrollY-oldScrollY)
);
}
if (Math.abs(mScrollX - oldScrollX) > Math.abs(xMove)) {
@@ -4264,18 +4185,18 @@
pinScrollBy(xMove, yMove, true, 0);
}
mUserScroll = true;
- }
- mWebViewCore.sendMessage(EventHub.UNBLOCK_FOCUS);
+ }
+ mWebViewCore.sendMessage(EventHub.UNBLOCK_FOCUS);
}
public void flingScroll(int vx, int vy) {
int maxX = Math.max(computeHorizontalScrollRange() - getViewWidth(), 0);
int maxY = Math.max(computeVerticalScrollRange() - getViewHeight(), 0);
-
+
mScroller.fling(mScrollX, mScrollY, vx, vy, 0, maxX, 0, maxY);
invalidate();
}
-
+
private void doFling() {
if (mVelocityTracker == null) {
return;
@@ -4294,7 +4215,7 @@
vx = 0;
}
}
-
+
if (true /* EMG release: make our fling more like Maps' */) {
// maps cuts their velocity in half
vx = vx * 3 / 4;
@@ -4355,7 +4276,7 @@
}
if (mZoomControls == null) {
mZoomControls = createZoomControls();
-
+
/*
* need to be set to VISIBLE first so that getMeasuredHeight() in
* {@link #onSizeChanged()} can return the measured value for proper
@@ -4364,7 +4285,7 @@
mZoomControls.setVisibility(View.VISIBLE);
mZoomControlRunnable = new Runnable() {
public void run() {
-
+
/* Don't dismiss the controls if the user has
* focus on them. Wait and check again later.
*/
@@ -4416,7 +4337,7 @@
/**
* Gets the {@link ZoomButtonsController} which can be used to add
* additional buttons to the zoom controls window.
- *
+ *
* @return The instance of {@link ZoomButtonsController} used by this class,
* or null if it is unavailable.
* @hide
@@ -4480,8 +4401,7 @@
Checkin.Stats.Tag.BROWSER_SNAP_CENTER, 1, 0.0);
}
}
- if (nativeUpdateFocusNode() && !mFocusNode.mIsTextField
- && !mFocusNode.mIsTextArea) {
+ if (nativeHasCursorNode() && !nativeCursorIsTextInput()) {
playSoundEffect(SoundEffectConstants.CLICK);
}
}
@@ -4520,7 +4440,7 @@
default:
return result;
}
- if (mNativeClass != 0 && !nativeUpdateFocusNode()) {
+ if (mNativeClass != 0 && !nativeHasCursorNode()) {
navHandledKey(fakeKeyDirection, 1, true, 0);
}
}
@@ -4626,11 +4546,11 @@
return false;
}
-
+
/* package */ void replaceTextfieldText(int oldStart, int oldEnd,
String replace, int newStart, int newEnd) {
HashMap arg = new HashMap();
- arg.put("focusData", new WebViewCore.FocusData(mFocusData));
+ arg.put("focusData", cursorData());
arg.put("replace", replace);
arg.put("start", Integer.valueOf(newStart));
arg.put("end", Integer.valueOf(newEnd));
@@ -4640,19 +4560,19 @@
/* package */ void passToJavaScript(String currentText, KeyEvent event) {
HashMap arg = new HashMap();
- arg.put("focusData", new WebViewCore.FocusData(mFocusData));
+ arg.put("focusData", cursorData());
arg.put("event", event);
arg.put("currentText", currentText);
// Increase our text generation number, and pass it to webcore thread
mTextGeneration++;
mWebViewCore.sendMessage(EventHub.PASS_TO_JS, mTextGeneration, 0, arg);
// WebKit's document state is not saved until about to leave the page.
- // To make sure the host application, like Browser, has the up to date
- // document state when it goes to background, we force to save the
+ // To make sure the host application, like Browser, has the up to date
+ // document state when it goes to background, we force to save the
// document state.
mWebViewCore.removeMessages(EventHub.SAVE_DOCUMENT_STATE);
mWebViewCore.sendMessageDelayed(EventHub.SAVE_DOCUMENT_STATE,
- new WebViewCore.FocusData(mFocusData), 1000);
+ cursorData(), 1000);
}
/* package */ WebViewCore getWebViewCore() {
@@ -4671,8 +4591,8 @@
@Override
public void handleMessage(Message msg) {
if (LOGV_ENABLED) {
- Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
- > INVAL_RECT_MSG_ID ? Integer.toString(msg.what)
+ Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
+ > INVAL_RECT_MSG_ID ? Integer.toString(msg.what)
: HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
}
switch (msg.what) {
@@ -4703,19 +4623,28 @@
updateTextEntry();
break;
}
- case SWITCH_TO_ENTER:
- if (LOGV_ENABLED) Log.v(LOGTAG, "SWITCH_TO_ENTER");
+ case SWITCH_TO_CLICK:
mTouchMode = TOUCH_DONE_MODE;
- onKeyUp(KeyEvent.KEYCODE_ENTER
- , new KeyEvent(KeyEvent.ACTION_UP
- , KeyEvent.KEYCODE_ENTER));
+ Rect visibleRect = sendOurVisibleRect();
+ // Note that sendOurVisibleRect calls viewToContent, so the
+ // coordinates should be in content coordinates.
+ if (!nativeCursorIntersects(visibleRect)) {
+ break;
+ }
+ nativeSetFollowedLink(true);
+ mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE,
+ cursorData());
+ playSoundEffect(SoundEffectConstants.CLICK);
+ if (!mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
+ mWebViewCore.sendMessage(EventHub.CLICK);
+ }
break;
case SCROLL_BY_MSG_ID:
setContentScrollBy(msg.arg1, msg.arg2, (Boolean) msg.obj);
break;
case SYNC_SCROLL_TO_MSG_ID:
if (mUserScroll) {
- // if user has scrolled explicitly, don't sync the
+ // if user has scrolled explicitly, don't sync the
// scroll position any more
mUserScroll = false;
break;
@@ -4724,7 +4653,7 @@
case SCROLL_TO_MSG_ID:
if (setContentScrollTo(msg.arg1, msg.arg2)) {
// if we can't scroll to the exact position due to pin,
- // send a message to WebCore to re-scroll when we get a
+ // send a message to WebCore to re-scroll when we get a
// new picture
mUserScroll = false;
mWebViewCore.sendMessage(EventHub.SYNC_SCROLL,
@@ -4736,7 +4665,7 @@
break;
case NEW_PICTURE_MSG_ID:
// called for new content
- final WebViewCore.DrawData draw =
+ final WebViewCore.DrawData draw =
(WebViewCore.DrawData) msg.obj;
final Point viewSize = draw.mViewPoint;
if (mZoomScale > 0) {
@@ -4759,7 +4688,7 @@
// received in the fixed dimension.
final boolean updateLayout = viewSize.x == mLastWidthSent
&& viewSize.y == mLastHeightSent;
- recordNewContentSize(draw.mWidthHeight.x,
+ recordNewContentSize(draw.mWidthHeight.x,
draw.mWidthHeight.y, updateLayout);
if (LOGV_ENABLED) {
Rect b = draw.mInvalRegion.getBounds();
@@ -4777,8 +4706,8 @@
break;
case UPDATE_TEXTFIELD_TEXT_MSG_ID:
// Make sure that the textfield is currently focused
- // and representing the same node as the pointer.
- if (inEditingMode() &&
+ // and representing the same node as the pointer.
+ if (inEditingMode() &&
mTextEntry.isSameTextField(msg.arg1)) {
if (msg.getData().getBoolean("password")) {
Spannable text = (Spannable) mTextEntry.getText();
@@ -4802,7 +4731,7 @@
break;
}
// Do not reset the focus or clear the text; the user may have already
-// navigated or entered text at this point. The focus should have gotten
+// navigated or entered text at this point. The focus should have gotten
// reset, if need be, when the focus cache was built. Similarly, the text
// view should already be torn down and rebuilt if needed.
// nativeResetFocus();
@@ -4858,20 +4787,11 @@
case MARK_NODE_INVALID_ID:
nativeMarkNodeInvalid(msg.arg1);
break;
- case NOTIFY_FOCUS_SET_MSG_ID:
- if (mNativeClass != 0) {
- nativeNotifyFocusSet(inEditingMode());
- }
- break;
case UPDATE_TEXT_ENTRY_MSG_ID:
- // this is sent after finishing resize in WebViewCore. Make
+ // this is sent after finishing resize in WebViewCore. Make
// sure the text edit box is still on the screen.
- boolean alreadyThere = inEditingMode();
- if (alreadyThere && nativeUpdateFocusNode()) {
- FocusNode node = mFocusNode;
- if (node.mIsTextField || node.mIsTextArea) {
- mTextEntry.bringIntoView();
- }
+ if (inEditingMode() && nativeCursorIsTextInput()) {
+ mTextEntry.bringIntoView();
}
updateTextEntry();
break;
@@ -4957,7 +4877,7 @@
// Passed in to a list with multiple selection to tell
// which items are selected.
private int[] mSelectedArray;
- // Passed in to a list with single selection to tell
+ // Passed in to a list with single selection to tell
// where the initial selection is.
private int mSelection;
@@ -4976,14 +4896,14 @@
}
/**
- * Subclass ArrayAdapter so we can disable OptionGroupLabels,
+ * Subclass ArrayAdapter so we can disable OptionGroupLabels,
* and allow filtering.
*/
private class MyArrayListAdapter extends ArrayAdapter<Container> {
public MyArrayListAdapter(Context context, Container[] objects, boolean multiple) {
- super(context,
+ super(context,
multiple ? com.android.internal.R.layout.select_dialog_multichoice :
- com.android.internal.R.layout.select_dialog_singlechoice,
+ com.android.internal.R.layout.select_dialog_singlechoice,
objects);
}
@@ -5041,7 +4961,7 @@
}
}
- private InvokeListBox(String[] array, boolean[] enabled, int
+ private InvokeListBox(String[] array, boolean[] enabled, int
selection) {
mSelection = selection;
mMultiple = false;
@@ -5104,17 +5024,17 @@
public void run() {
final ListView listView = (ListView) LayoutInflater.from(mContext)
.inflate(com.android.internal.R.layout.select_dialog, null);
- final MyArrayListAdapter adapter = new
+ final MyArrayListAdapter adapter = new
MyArrayListAdapter(mContext, mContainers, mMultiple);
AlertDialog.Builder b = new AlertDialog.Builder(mContext)
.setView(listView).setCancelable(true)
.setInverseBackgroundForced(true);
-
+
if (mMultiple) {
b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mWebViewCore.sendMessage(
- EventHub.LISTBOX_CHOICES,
+ EventHub.LISTBOX_CHOICES,
adapter.getCount(), 0,
listView.getCheckedItemPositions());
}});
@@ -5130,10 +5050,10 @@
listView.setFocusableInTouchMode(true);
// There is a bug (1250103) where the checks in a ListView with
// multiple items selected are associated with the positions, not
- // the ids, so the items do not properly retain their checks when
+ // the ids, so the items do not properly retain their checks when
// filtered. Do not allow filtering on multiple lists until
// that bug is fixed.
-
+
listView.setTextFilterEnabled(!mMultiple);
if (mMultiple) {
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
@@ -5196,47 +5116,26 @@
}
// called by JNI
- private void sendFinalFocus(int frame, int node, int x, int y) {
- WebViewCore.FocusData focusData = new WebViewCore.FocusData();
- focusData.mFrame = frame;
- focusData.mNode = node;
- focusData.mX = x;
- focusData.mY = y;
- mWebViewCore.sendMessage(EventHub.SET_FINAL_FOCUS,
- EventHub.NO_FOCUS_CHANGE_BLOCK, 0, focusData);
+ private void sendMoveMouse(int frame, int node, int x, int y) {
+ mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE,
+ new WebViewCore.CursorData(frame, node, x, y));
}
// called by JNI
- private void setFocusData(int moveGeneration, int buildGeneration,
- int frame, int node, int x, int y, boolean ignoreNullFocus) {
- mFocusData.mMoveGeneration = moveGeneration;
- mFocusData.mBuildGeneration = buildGeneration;
- mFocusData.mFrame = frame;
- mFocusData.mNode = node;
- mFocusData.mX = x;
- mFocusData.mY = y;
- mFocusData.mIgnoreNullFocus = ignoreNullFocus;
- }
-
- // called by JNI
- private void sendKitFocus() {
- WebViewCore.FocusData focusData = new WebViewCore.FocusData(mFocusData);
- mWebViewCore.sendMessage(EventHub.SET_KIT_FOCUS, focusData);
+ private void sendMoveMouseIfLatest() {
+ mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE_IF_LATEST, cursorData());
}
// called by JNI
- private void sendMotionUp(int touchGeneration, int buildGeneration,
- int frame, int node, int x, int y, int size,
- boolean retry) {
+ private void sendMotionUp(int touchGeneration,
+ int frame, int node, int x, int y, int size) {
WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
touchUpData.mMoveGeneration = touchGeneration;
- touchUpData.mBuildGeneration = buildGeneration;
touchUpData.mSize = size;
- touchUpData.mRetry = retry;
- mFocusData.mFrame = touchUpData.mFrame = frame;
- mFocusData.mNode = touchUpData.mNode = node;
- mFocusData.mX = touchUpData.mX = x;
- mFocusData.mY = touchUpData.mY = y;
+ touchUpData.mFrame = frame;
+ touchUpData.mNode = node;
+ touchUpData.mX = x;
+ touchUpData.mY = y;
mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
}
@@ -5275,7 +5174,7 @@
private void viewInvalidate() {
invalidate();
}
-
+
// return true if the key was handled
private boolean navHandledKey(int keyCode, int count, boolean noScroll
, long time) {
@@ -5283,7 +5182,7 @@
return false;
}
mLastFocusTime = time;
- mLastFocusBounds = nativeGetFocusRingBounds();
+ mLastFocusBounds = nativeGetCursorRingBounds();
boolean keyHandled = nativeMoveFocus(keyCode, count, noScroll) == false;
if (LOGV_ENABLED) {
Log.v(LOGTAG, "navHandledKey mLastFocusBounds=" + mLastFocusBounds
@@ -5293,7 +5192,7 @@
if (keyHandled == false || mHeightCanMeasure == false) {
return keyHandled;
}
- Rect contentFocus = nativeGetFocusRingBounds();
+ Rect contentFocus = nativeGetCursorRingBounds();
if (contentFocus.isEmpty()) return keyHandled;
Rect viewFocus = contentToView(contentFocus);
Rect visRect = new Rect();
@@ -5324,7 +5223,7 @@
mUserScroll = true;
return keyHandled;
}
-
+
/**
* Set the background color. It's white by default. Pass
* zero to make the view transparent.
@@ -5339,7 +5238,7 @@
nativeDebugDump();
mWebViewCore.sendMessage(EventHub.DUMP_NAVTREE);
}
-
+
/**
* Update our cache with updatedText.
* @param updatedText The new text to put in our cache.
@@ -5349,52 +5248,70 @@
// we recognize that it is up to date.
nativeUpdateCachedTextfield(updatedText, mTextGeneration);
}
-
- // Never call this version except by updateCachedTextfield(String) -
- // we always want to pass in our generation number.
- private native void nativeUpdateCachedTextfield(String updatedText,
- int generation);
+
private native void nativeClearFocus(int x, int y);
private native void nativeCreate(int ptr);
+ private native int nativeCursorFramePointer();
+ private native Rect nativeCursorNodeBounds();
+ /* package */ native int nativeCursorNodePointer();
+ /* package */ native boolean nativeCursorMatchesFocus();
+ private native boolean nativeCursorIntersects(Rect visibleRect);
+ private native boolean nativeCursorIsAnchor();
+ private native boolean nativeCursorIsTextInput();
+ private native String nativeCursorText();
private native void nativeDebugDump();
private native void nativeDestroy();
- private native void nativeDrawFocusRing(Canvas content);
+ private native void nativeDrawCursorRing(Canvas content);
+ private native void nativeDrawMatches(Canvas canvas);
private native void nativeDrawSelection(Canvas content
, int x, int y, boolean extendSelection);
private native void nativeDrawSelectionRegion(Canvas content);
- private native boolean nativeUpdateFocusNode();
- private native Rect nativeGetFocusRingBounds();
- private native Rect nativeGetNavBounds();
- private native void nativeInstrumentReport();
- private native void nativeMarkNodeInvalid(int node);
- // return true if the page has been scrolled
- private native boolean nativeMotionUp(int x, int y, int slop);
- // returns false if it handled the key
- private native boolean nativeMoveFocus(int keyCode, int count,
- boolean noScroll);
- private native void nativeNotifyFocusSet(boolean inEditingMode);
- private native void nativeRecomputeFocus();
- // 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 nativeResetFocus();
- private native void nativeResetNavClipBounds();
- private native void nativeSelectBestAt(Rect rect);
- private native void nativeSetFindIsDown();
- private native void nativeSetFollowedLink(boolean followed);
- private native void nativeSetHeightCanMeasure(boolean measure);
- private native void nativeSetNavBounds(Rect rect);
- private native void nativeSetNavClipBounds(Rect rect);
- private native String nativeImageURI(int x, int y);
+ private native void nativeDumpDisplayTree(String urlOrNull);
+ private native int nativeFindAll(String findLower, String findUpper);
+ private native void nativeFindNext(boolean forward);
+ private native boolean nativeFocusIsPassword();
+ private native boolean nativeFocusIsRtlText();
+ private native boolean nativeFocusIsTextField();
+ private native boolean nativeFocusIsTextInput();
+ private native int nativeFocusMaxLength();
+ private native String nativeFocusName();
+ private native Rect nativeFocusNodeBounds();
+ /* package */ native int nativeFocusNodePointer();
+ private native String nativeFocusText();
+ private native int nativeFocusTextSize();
/**
* Returns true if the native focus nodes says it wants to handle key events
* (ala plugins). This can only be called if mNativeClass is non-zero!
*/
private native boolean nativeFocusNodeWantsKeyEvents();
- private native void nativeMoveSelection(int x, int y
- , boolean extendSelection);
+ private native Rect nativeGetCursorRingBounds();
private native Region nativeGetSelection();
+ private native boolean nativeHasCursorNode();
+ private native boolean nativeHasFocusNode();
+ private native String nativeImageURI(int x, int y);
+ private native void nativeInstrumentReport();
+ private native void nativeMarkNodeInvalid(int node);
+ // return true if the page has been scrolled
+ private native boolean nativeMotionUp(int x, int y, int slop);
+ // returns false if it handled the key
+ private native boolean nativeMoveFocus(int keyCode, int count,
+ boolean noScroll);
+ private native int nativeMoveGeneration();
+ private native void nativeMoveSelection(int x, int y,
+ boolean extendSelection);
+ private native void nativeRecomputeFocus();
+ // 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 nativeSelectBestAt(Rect rect);
+ private native void nativeSetFindIsDown();
+ private native void nativeSetFollowedLink(boolean followed);
+ private native void nativeSetHeightCanMeasure(boolean measure);
+ private native int nativeTextGeneration();
+ // Never call this version except by updateCachedTextfield(String) -
+ // we always want to pass in our generation number.
+ private native void nativeUpdateCachedTextfield(String updatedText,
+ int generation);
- private native void nativeDumpDisplayTree(String urlOrNull);
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index f9bbc31..1d91f52 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -96,7 +96,7 @@
private int mViewportMaximumScale = 0;
private boolean mViewportUserScalable = true;
-
+
private int mRestoredScale = 100;
private int mRestoredX = 0;
private int mRestoredY = 0;
@@ -308,15 +308,15 @@
* Empty the picture set.
*/
private native void nativeClearContent();
-
+
/**
* Create a flat picture from the set of pictures.
*/
private native void nativeCopyContentToPicture(Picture picture);
-
+
/**
* Draw the picture set with a background color. Returns true
- * if some individual picture took too long to draw and can be
+ * if some individual picture took too long to draw and can be
* split into parts. Called from the UI thread.
*/
private native boolean nativeDrawContent(Canvas canvas, int color);
@@ -325,13 +325,13 @@
* check to see if picture is blank and in progress
*/
private native boolean nativePictureReady();
-
+
/**
* Redraw a portion of the picture set. The Point wh returns the
* width and height of the overall picture.
*/
private native boolean nativeRecordContent(Region invalRegion, Point wh);
-
+
/**
* Splits slow parts of the picture set. Called from the webkit
* thread after nativeDrawContent returns true.
@@ -359,10 +359,10 @@
float scale, int realScreenWidth, int screenHeight);
private native int nativeGetContentMinPrefWidth();
-
+
// Start: functions that deal with text editing
- private native void nativeReplaceTextfieldText(int frame, int node, int x,
- int y, int oldStart, int oldEnd, String replace, int newStart,
+ private native void nativeReplaceTextfieldText(int frame, int node, int x,
+ int y, int oldStart, int oldEnd, String replace, int newStart,
int newEnd);
private native void passToJs(int frame, int node, int x, int y, int gen,
@@ -373,31 +373,31 @@
private native void nativeSaveDocumentState(int frame);
- private native void nativeSetFinalFocus(int framePtr, int nodePtr, int x,
- int y, boolean block);
+ private native void nativeMoveMouse(int framePtr, int nodePtr, int x,
+ int y);
- private native void nativeSetKitFocus(int moveGeneration,
- int buildGeneration, int framePtr, int nodePtr, int x, int y,
+ private native void nativeMoveMouseIfLatest(int moveGeneration,
+ int framePtr, int nodePtr, int x, int y,
boolean ignoreNullFocus);
private native String nativeRetrieveHref(int framePtr, int nodePtr);
-
- private native void nativeTouchUp(int touchGeneration,
- int buildGeneration, int framePtr, int nodePtr, int x, int y,
- int size, boolean retry);
+
+ private native void nativeTouchUp(int touchGeneration,
+ int framePtr, int nodePtr, int x, int y,
+ int size);
private native boolean nativeHandleTouchEvent(int action, int x, int y);
private native void nativeUnblockFocus();
-
+
private native void nativeUpdateFrameCache();
-
+
private native void nativeSetSnapAnchor(int x, int y);
-
+
private native void nativeSnapToAnchor();
-
+
private native void nativeSetBackgroundColor(int color);
-
+
private native void nativeDumpDomTree(boolean useFile);
private native void nativeDumpRenderTree(boolean useFile);
@@ -406,7 +406,7 @@
/**
* Delete text from start to end in the focused textfield. If there is no
- * focus, or if start == end, silently fail. If start and end are out of
+ * focus, or if start == end, silently fail. If start and end are out of
* order, swap them.
* @param start Beginning of selection to delete.
* @param end End of selection to delete.
@@ -424,7 +424,7 @@
int start, int end);
private native String nativeGetSelection(Region sel);
-
+
// Register a scheme to be treated as local scheme so that it can access
// local asset files for resources
private native void nativeRegisterURLSchemeAsLocal(String scheme);
@@ -485,7 +485,7 @@
CacheManager.endCacheTransaction();
CacheManager.startCacheTransaction();
sendMessageDelayed(
- obtainMessage(CACHE_TICKER),
+ obtainMessage(CACHE_TICKER),
CACHE_TICKER_INTERVAL);
}
break;
@@ -510,19 +510,15 @@
}
}
- static class FocusData {
- FocusData() {}
- FocusData(FocusData d) {
- mMoveGeneration = d.mMoveGeneration;
- mBuildGeneration = d.mBuildGeneration;
- mFrame = d.mFrame;
- mNode = d.mNode;
- mX = d.mX;
- mY = d.mY;
- mIgnoreNullFocus = d.mIgnoreNullFocus;
+ static class CursorData {
+ CursorData() {}
+ CursorData(int frame, int node, int x, int y) {
+ mFrame = frame;
+ mNode = node;
+ mX = x;
+ mY = y;
}
int mMoveGeneration;
- int mBuildGeneration;
int mFrame;
int mNode;
int mX;
@@ -532,13 +528,11 @@
static class TouchUpData {
int mMoveGeneration;
- int mBuildGeneration;
int mFrame;
int mNode;
int mX;
int mY;
int mSize;
- boolean mRetry;
}
static class TouchEventData {
@@ -583,8 +577,8 @@
"POST_URL", // = 132;
"SPLIT_PICTURE_SET", // = 133;
"CLEAR_CONTENT", // = 134;
- "SET_FINAL_FOCUS", // = 135;
- "SET_KIT_FOCUS", // = 136;
+ "SET_MOVE_MOUSE", // = 135;
+ "SET_MOVE_MOUSE_IF_LATEST", // = 136;
"REQUEST_FOCUS_HREF", // = 137;
"ADD_JS_INTERFACE", // = 138;
"LOAD_DATA", // = 139;
@@ -632,10 +626,10 @@
static final int POST_URL = 132;
static final int SPLIT_PICTURE_SET = 133;
static final int CLEAR_CONTENT = 134;
-
+
// UI nav messages
- static final int SET_FINAL_FOCUS = 135;
- static final int SET_KIT_FOCUS = 136;
+ static final int SET_MOVE_MOUSE = 135;
+ static final int SET_MOVE_MOUSE_IF_LATEST = 136;
static final int REQUEST_FOCUS_HREF = 137;
static final int ADD_JS_INTERFACE = 138;
static final int LOAD_DATA = 139;
@@ -668,7 +662,7 @@
// private message ids
private static final int DESTROY = 200;
-
+
// flag values passed to message SET_FINAL_FOCUS
static final int NO_FOCUS_CHANGE_BLOCK = 0;
static final int BLOCK_FOCUS_CHANGE_UNTIL_KEY_UP = 1;
@@ -701,7 +695,7 @@
@Override
public void handleMessage(Message msg) {
if (LOGV_ENABLED) {
- Log.v(LOGTAG, msg.what < LOAD_URL || msg.what
+ Log.v(LOGTAG, msg.what < LOAD_URL || msg.what
> SET_ACTIVE ? Integer.toString(msg.what)
: HandlerDebugString[msg.what - LOAD_URL]);
}
@@ -744,7 +738,7 @@
* we automatically add the scheme of the
* baseUrl for local access as long as it is
* not http(s)/ftp(s)/about/javascript
- */
+ */
String scheme = baseUrl.substring(0, i);
if (!scheme.startsWith("http") &&
!scheme.startsWith("ftp") &&
@@ -762,9 +756,9 @@
break;
case STOP_LOADING:
- // If the WebCore has committed the load, but not
- // finished the first layout yet, we need to set
- // first layout done to trigger the interpreted side sync
+ // If the WebCore has committed the load, but not
+ // finished the first layout yet, we need to set
+ // first layout done to trigger the interpreted side sync
// up with native side
if (mBrowserFrame.committed()
&& !mBrowserFrame.firstLayoutDone()) {
@@ -800,7 +794,7 @@
// (inv-zoom)
nativeSetScrollOffset(msg.arg1, msg.arg2);
break;
-
+
case SET_GLOBAL_BOUNDS:
Rect r = (Rect) msg.obj;
nativeSetGlobalBounds(r.left, r.top, r.width(),
@@ -811,7 +805,7 @@
// If it is a standard load and the load is not
// committed yet, we interpret BACK as RELOAD
if (!mBrowserFrame.committed() && msg.arg1 == -1 &&
- (mBrowserFrame.loadType() ==
+ (mBrowserFrame.loadType() ==
BrowserFrame.FRAME_LOADTYPE_STANDARD)) {
mBrowserFrame.reload(true);
} else {
@@ -877,13 +871,13 @@
close(mBrowserFrame.mNativeFrame);
break;
- case REPLACE_TEXT:
+ case REPLACE_TEXT:
HashMap jMap = (HashMap) msg.obj;
- FocusData fData = (FocusData) jMap.get("focusData");
+ CursorData fData = (CursorData) jMap.get("focusData");
String replace = (String) jMap.get("replace");
- int newStart =
+ int newStart =
((Integer) jMap.get("start")).intValue();
- int newEnd =
+ int newEnd =
((Integer) jMap.get("end")).intValue();
nativeReplaceTextfieldText(fData.mFrame,
fData.mNode, fData.mX, fData.mY, msg.arg1,
@@ -892,7 +886,7 @@
case PASS_TO_JS: {
HashMap jsMap = (HashMap) msg.obj;
- FocusData fDat = (FocusData) jsMap.get("focusData");
+ CursorData fDat = (CursorData) jsMap.get("focusData");
KeyEvent evt = (KeyEvent) jsMap.get("event");
int keyCode = evt.getKeyCode();
int keyValue = evt.getUnicodeChar();
@@ -909,7 +903,7 @@
}
case SAVE_DOCUMENT_STATE: {
- FocusData fDat = (FocusData) msg.obj;
+ CursorData fDat = (CursorData) msg.obj;
nativeSaveDocumentState(fDat.mFrame);
break;
}
@@ -922,11 +916,9 @@
case TOUCH_UP:
TouchUpData touchUpData = (TouchUpData) msg.obj;
nativeTouchUp(touchUpData.mMoveGeneration,
- touchUpData.mBuildGeneration,
touchUpData.mFrame, touchUpData.mNode,
- touchUpData.mX, touchUpData.mY,
- touchUpData.mSize,
- touchUpData.mRetry);
+ touchUpData.mX, touchUpData.mY,
+ touchUpData.mSize);
break;
case TOUCH_EVENT: {
@@ -961,22 +953,20 @@
mBrowserFrame.documentAsText((Message) msg.obj);
break;
- case SET_FINAL_FOCUS:
- FocusData finalData = (FocusData) msg.obj;
- nativeSetFinalFocus(finalData.mFrame,
- finalData.mNode, finalData.mX,
- finalData.mY, msg.arg1
- != EventHub.NO_FOCUS_CHANGE_BLOCK);
+ case SET_MOVE_MOUSE:
+ CursorData finalData = (CursorData) msg.obj;
+ nativeMoveMouse(finalData.mFrame,
+ finalData.mNode, finalData.mX,
+ finalData.mY);
break;
case UNBLOCK_FOCUS:
nativeUnblockFocus();
break;
- case SET_KIT_FOCUS:
- FocusData focusData = (FocusData) msg.obj;
- nativeSetKitFocus(focusData.mMoveGeneration,
- focusData.mBuildGeneration,
+ case SET_MOVE_MOUSE_IF_LATEST:
+ CursorData focusData = (CursorData) msg.obj;
+ nativeMoveMouseIfLatest(focusData.mMoveGeneration,
focusData.mFrame, focusData.mNode,
focusData.mX, focusData.mY,
focusData.mIgnoreNullFocus);
@@ -989,7 +979,7 @@
hrefMsg.sendToTarget();
break;
}
-
+
case UPDATE_CACHE_AND_TEXT_ENTRY:
nativeUpdateFrameCache();
// FIXME: this should provide a minimal rectangle
@@ -1009,21 +999,21 @@
case SET_SNAP_ANCHOR:
nativeSetSnapAnchor(msg.arg1, msg.arg2);
break;
-
+
case DELETE_SELECTION:
- FocusData delData = (FocusData) msg.obj;
+ CursorData delData = (CursorData) msg.obj;
nativeDeleteSelection(delData.mFrame,
- delData.mNode, delData.mX,
+ delData.mNode, delData.mX,
delData.mY, msg.arg1, msg.arg2);
break;
case SET_SELECTION:
- FocusData selData = (FocusData) msg.obj;
+ CursorData selData = (CursorData) msg.obj;
nativeSetSelection(selData.mFrame,
- selData.mNode, selData.mX,
+ selData.mNode, selData.mX,
selData.mY, msg.arg1, msg.arg2);
break;
-
+
case LISTBOX_CHOICES:
SparseBooleanArray choices = (SparseBooleanArray)
msg.obj;
@@ -1032,18 +1022,18 @@
for (int c = 0; c < choicesSize; c++) {
choicesArray[c] = choices.get(c);
}
- nativeSendListBoxChoices(choicesArray,
+ nativeSendListBoxChoices(choicesArray,
choicesSize);
break;
case SINGLE_LISTBOX_CHOICE:
nativeSendListBoxChoice(msg.arg1);
break;
-
+
case SET_BACKGROUND_COLOR:
nativeSetBackgroundColor(msg.arg1);
break;
-
+
case GET_SELECTION:
String str = nativeGetSelection((Region) msg.obj);
Message.obtain(mWebView.mPrivateHandler
@@ -1072,7 +1062,7 @@
nativeSplitContent();
mSplitPictureIsScheduled = false;
break;
-
+
case CLEAR_CONTENT:
// Clear the view so that onDraw() will draw nothing
// but white background
@@ -1282,7 +1272,7 @@
&& (w < mViewportWidth || mViewportWidth == -1)) {
int width = mViewportWidth;
if (mViewportWidth == -1) {
- if (mSettings.getLayoutAlgorithm() ==
+ if (mSettings.getLayoutAlgorithm() ==
WebSettings.LayoutAlgorithm.NORMAL) {
width = WebView.ZOOM_OUT_WIDTH;
} else {
@@ -1329,7 +1319,7 @@
// Used to avoid posting more than one draw message.
private boolean mDrawIsScheduled;
-
+
// Used to avoid posting more than one split picture message.
private boolean mSplitPictureIsScheduled;
@@ -1338,7 +1328,7 @@
// Used to end scale+scroll mode, accessed by both threads
boolean mEndScaleZoom = false;
-
+
public class DrawData {
public DrawData() {
mInvalRegion = new Region();
@@ -1348,12 +1338,12 @@
public Point mViewPoint;
public Point mWidthHeight;
}
-
+
private void webkitDraw() {
mDrawIsScheduled = false;
DrawData draw = new DrawData();
if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw start");
- if (nativeRecordContent(draw.mInvalRegion, draw.mWidthHeight)
+ if (nativeRecordContent(draw.mInvalRegion, draw.mWidthHeight)
== false) {
if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw abort");
return;
@@ -1427,9 +1417,9 @@
sWebCoreHandler.sendMessageAtFrontOfQueue(sWebCoreHandler
.obtainMessage(WebCoreThread.REDUCE_PRIORITY));
// Note: there is one possible failure mode. If pauseUpdate() is called
- // from UI thread while in webcore thread WEBKIT_DRAW is just pulled out
- // of the queue and about to be executed. mDrawIsScheduled may be set to
- // false in webkitDraw(). So update won't be blocked. But at least the
+ // from UI thread while in webcore thread WEBKIT_DRAW is just pulled out
+ // of the queue and about to be executed. mDrawIsScheduled may be set to
+ // false in webkitDraw(). So update won't be blocked. But at least the
// webcore thread priority is still lowered.
if (core != null) {
synchronized (core) {
@@ -1498,7 +1488,7 @@
mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
}
}
-
+
// called by JNI
private void contentScrollBy(int dx, int dy, boolean animate) {
if (!mBrowserFrame.firstLayoutDone()) {
@@ -1574,14 +1564,6 @@
}
// called by JNI
- private void sendNotifyFocusSet() {
- if (mWebView != null) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.NOTIFY_FOCUS_SET_MSG_ID).sendToTarget();
- }
- }
-
- // called by JNI
private void sendNotifyProgressFinished() {
sendUpdateTextEntry();
// as CacheManager can behave based on database transaction, we need to
@@ -1617,12 +1599,12 @@
}
private native void setViewportSettingsFromNative();
-
+
// called by JNI
private void didFirstLayout(boolean standardLoad) {
// Trick to ensure that the Picture has the exact height for the content
// by forcing to layout with 0 height after the page is ready, which is
- // indicated by didFirstLayout. This is essential to get rid of the
+ // indicated by didFirstLayout. This is essential to get rid of the
// white space in the GMail which uses WebView for message view.
if (mWebView != null && mWebView.mHeightCanMeasure) {
mWebView.mLastHeightSent = 0;
@@ -1667,7 +1649,7 @@
mViewportMaximumScale = mViewportInitialScale;
} else if (mViewportInitialScale == 0) {
mViewportInitialScale = mViewportMaximumScale;
- }
+ }
}
if (mViewportWidth < 0 && mViewportInitialScale == 100) {
mViewportWidth = 0;
@@ -1737,7 +1719,7 @@
String text, int textGeneration) {
if (mWebView != null) {
Message msg = Message.obtain(mWebView.mPrivateHandler,
- WebView.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
+ WebView.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
textGeneration, text);
msg.getData().putBoolean("password", changeToPassword);
msg.sendToTarget();
@@ -1763,7 +1745,7 @@
if (mWebView != null) {
mWebView.requestListBox(array, enabledArray, selection);
}
-
+
}
private native void nativePause();
diff --git a/preloaded-classes b/preloaded-classes
index e72c6af..8ee015f 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -503,12 +503,11 @@
android.webkit.WebSyncManager$SyncHandler
android.webkit.WebView
android.webkit.WebView$ExtendedZoomControls
-android.webkit.WebView$FocusNode
android.webkit.WebView$PrivateHandler
android.webkit.WebViewCore
+android.webkit.WebViewCore$CursorData
android.webkit.WebViewCore$EventHub
android.webkit.WebViewCore$EventHub$1
-android.webkit.WebViewCore$FocusData
android.webkit.WebViewCore$WebCoreThread
android.webkit.WebViewCore$WebCoreThread$1
android.webkit.WebViewDatabase