summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-07-28 13:45:58 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-07-28 13:45:58 -0700
commit10e85ba98771608542e2fc1de9efadb07a62e1fa (patch)
tree3ec6ef1160085dc2cc6b83b25792030de59c918d /core
parent3cbaf0087f4bbed5a5f711d1a588e5ec9d369005 (diff)
parent8b97e4b0fe4a89a76b47a8df422d0d3ea5b70754 (diff)
downloadframeworks_base-10e85ba98771608542e2fc1de9efadb07a62e1fa.zip
frameworks_base-10e85ba98771608542e2fc1de9efadb07a62e1fa.tar.gz
frameworks_base-10e85ba98771608542e2fc1de9efadb07a62e1fa.tar.bz2
Merge change 8437
* changes: Re-add double tap to the Browser. It only works if WebView uses wide viewport. It is also controlled by ENABLE_DOUBLETAP_ZOOM flag. Currently the default is on.
Diffstat (limited to 'core')
-rw-r--r--core/java/android/webkit/WebView.java186
-rw-r--r--core/java/android/webkit/WebViewCore.java42
2 files changed, 203 insertions, 25 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 19df87f..358fc9e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -351,6 +351,9 @@ public class WebView extends AbsoluteLayout
VelocityTracker mVelocityTracker;
private int mMaximumFling;
+ // use this flag to control whether enabling the new double tap zoom
+ static final boolean ENABLE_DOUBLETAP_ZOOM = true;
+
/**
* Touch mode
*/
@@ -370,6 +373,7 @@ public class WebView extends AbsoluteLayout
private static final int SCROLL_ZOOM_OUT = 11;
private static final int LAST_SCROLL_ZOOM = 11;
// end of touch mode values specific to scale+scroll
+ private static final int TOUCH_DOUBLE_TAP_MODE = 12;
// Whether to forward the touch events to WebCore
private boolean mForwardTouchEvents = false;
@@ -394,6 +398,8 @@ public class WebView extends AbsoluteLayout
*/
// pre-computed square of ViewConfiguration.getScaledTouchSlop()
private int mTouchSlopSquare;
+ // pre-computed square of ViewConfiguration.getScaledDoubleTapSlop()
+ private int mDoubleTapSlopSquare;
// pre-computed density adjusted navigation slop
private int mNavSlop;
// This should be ViewConfiguration.getTapTimeout()
@@ -450,6 +456,7 @@ public class WebView extends AbsoluteLayout
private static final int NEVER_REMEMBER_PASSWORD = 2;
private static final int SWITCH_TO_SHORTPRESS = 3;
private static final int SWITCH_TO_LONGPRESS = 4;
+ private static final int RELEASE_SINGLE_TAP = 5;
private static final int REQUEST_FORM_DATA = 6;
private static final int SWITCH_TO_CLICK = 7;
private static final int RESUME_WEBCORE_UPDATE = 8;
@@ -482,7 +489,7 @@ public class WebView extends AbsoluteLayout
"NEVER_REMEMBER_PASSWORD", // = 2;
"SWITCH_TO_SHORTPRESS", // = 3;
"SWITCH_TO_LONGPRESS", // = 4;
- "5",
+ "RELEASE_SINGLE_TAP", // = 5;
"REQUEST_FORM_DATA", // = 6;
"SWITCH_TO_CLICK", // = 7;
"RESUME_WEBCORE_UPDATE", // = 8;
@@ -521,6 +528,16 @@ public class WebView extends AbsoluteLayout
// initial scale in percent. 0 means using default.
private int mInitialScale = 0;
+ // while in the zoom overview mode, the page's width is fully fit to the
+ // current window. The page is alive, in another words, you can click to
+ // follow the links. Double tap will toggle between zoom overview mode and
+ // the last zoom scale.
+ boolean mInZoomOverview = false;
+ // ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
+ // engadget always have wider mContentWidth no matter what viewport size is.
+ int mZoomOverviewWidth = 0;
+ float mLastScale;
+
// default scale. Depending on the display density.
static int DEFAULT_SCALE_PERCENT;
private float mDefaultScale;
@@ -762,9 +779,11 @@ public class WebView extends AbsoluteLayout
setLongClickable(true);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
- final int slop = configuration.getScaledTouchSlop();
+ int slop = configuration.getScaledTouchSlop();
mTouchSlopSquare = slop * slop;
mMinLockSnapReverseDistance = slop;
+ slop = configuration.getScaledDoubleTapSlop();
+ mDoubleTapSlopSquare = slop * slop;
final float density = getContext().getResources().getDisplayMetrics().density;
// use one line height, 16 based on our current default font, for how
// far we allow a touch be away from the edge of a link
@@ -1124,6 +1143,9 @@ public class WebView extends AbsoluteLayout
b.putInt("scrollX", mScrollX);
b.putInt("scrollY", mScrollY);
b.putFloat("scale", mActualScale);
+ if (mInZoomOverview) {
+ b.putFloat("lastScale", mLastScale);
+ }
return true;
}
return false;
@@ -1168,6 +1190,13 @@ public class WebView extends AbsoluteLayout
// onSizeChanged() is called, the rest will be set
// correctly
mActualScale = scale;
+ float lastScale = b.getFloat("lastScale", -1.0f);
+ if (lastScale > 0) {
+ mInZoomOverview = true;
+ mLastScale = lastScale;
+ } else {
+ mInZoomOverview = false;
+ }
invalidate();
return true;
}
@@ -3060,6 +3089,11 @@ public class WebView extends AbsoluteLayout
float y = mLastTouchY + (float) (mScrollY - lp.y);
mWebTextView.fakeTouchEvent(x, y);
}
+ if (mInZoomOverview) {
+ // if in zoom overview mode, call doDoubleTap() to bring it back
+ // to normal mode so that user can enter text.
+ doDoubleTap();
+ }
}
else { // used by plugins
imm.showSoftInput(this, 0);
@@ -3634,7 +3668,9 @@ public class WebView extends AbsoluteLayout
// update mMinZoomScale if the minimum zoom scale is not fixed
if (!mMinZoomScaleFixed) {
mMinZoomScale = (float) getViewWidth()
- / Math.max(ZOOM_OUT_WIDTH, mContentWidth);
+ / Math.max(ZOOM_OUT_WIDTH, mDrawHistory ? mHistoryPicture
+ .getWidth() : (mZoomOverviewWidth > 0 ?
+ mZoomOverviewWidth : mContentWidth));
}
// we always force, in case our height changed, in which case we still
@@ -3755,6 +3791,15 @@ public class WebView extends AbsoluteLayout
nativeMoveSelection(viewToContent(mSelectX)
, viewToContent(mSelectY), false);
mTouchSelection = mExtendSelection = true;
+ } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
+ mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
+ if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
+ mTouchMode = TOUCH_DOUBLE_TAP_MODE;
+ } else {
+ // commit the short press action for the previous tap
+ doShortPress();
+ // continue, mTouchMode should be still TOUCH_INIT_MODE
+ }
} else {
mTouchMode = TOUCH_INIT_MODE;
mPreventDrag = mForwardTouchEvents;
@@ -3764,7 +3809,8 @@ public class WebView extends AbsoluteLayout
}
}
// Trigger the link
- if (mTouchMode == TOUCH_INIT_MODE) {
+ if (mTouchMode == TOUCH_INIT_MODE
+ || mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mPrivateHandler.sendMessageDelayed(mPrivateHandler
.obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
}
@@ -3810,7 +3856,8 @@ public class WebView extends AbsoluteLayout
if (mTouchMode == TOUCH_SHORTPRESS_MODE
|| mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- } else if (mTouchMode == TOUCH_INIT_MODE) {
+ } else if (mTouchMode == TOUCH_INIT_MODE
+ || mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
}
@@ -3836,7 +3883,7 @@ public class WebView extends AbsoluteLayout
.sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0);
}
WebSettings settings = getSettings();
- if (settings.supportZoom()
+ if (settings.supportZoom() && !mInZoomOverview
&& settings.getBuiltInZoomControls()
&& !mZoomButtonsController.isVisible()
&& (canZoomScrollOut() ||
@@ -3905,7 +3952,7 @@ public class WebView extends AbsoluteLayout
mUserScroll = true;
}
- if (!getSettings().getBuiltInZoomControls()) {
+ if (!getSettings().getBuiltInZoomControls() && !mInZoomOverview) {
boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
boolean showMagnify = canZoomScrollOut();
if (mZoomControls != null && (showPlusMinus || showMagnify)) {
@@ -3929,7 +3976,22 @@ public class WebView extends AbsoluteLayout
case MotionEvent.ACTION_UP: {
mLastTouchUpTime = eventTime;
switch (mTouchMode) {
+ case TOUCH_DOUBLE_TAP_MODE: // double tap
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ doDoubleTap();
+ break;
case TOUCH_INIT_MODE: // tap
+ if (ENABLE_DOUBLETAP_ZOOM) {
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ if (!mPreventDrag) {
+ mPrivateHandler.sendMessageDelayed(
+ mPrivateHandler.obtainMessage(
+ RELEASE_SINGLE_TAP),
+ ViewConfiguration.getDoubleTapTimeout());
+ }
+ break;
+ }
+ // fall through
case TOUCH_SHORTPRESS_START_MODE:
case TOUCH_SHORTPRESS_MODE:
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -4365,6 +4427,9 @@ public class WebView extends AbsoluteLayout
mInvInitialZoomScale = 1.0f / oldScale;
mInvFinalZoomScale = 1.0f / mActualScale;
mZoomScale = mActualScale;
+ if (!mInZoomOverview) {
+ mLastScale = scale;
+ }
invalidate();
return true;
} else {
@@ -4470,6 +4535,9 @@ public class WebView extends AbsoluteLayout
public boolean zoomIn() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
+ // Center zooming to the center of the screen.
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
return zoomWithPreview(mActualScale * 1.25f);
}
@@ -4480,6 +4548,9 @@ public class WebView extends AbsoluteLayout
public boolean zoomOut() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
+ // Center zooming to the center of the screen.
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
return zoomWithPreview(mActualScale * 0.8f);
}
@@ -4571,6 +4642,50 @@ public class WebView extends AbsoluteLayout
}
}
+ private void doDoubleTap() {
+ if (mWebViewCore.getSettings().getUseWideViewPort() == false) {
+ return;
+ }
+ mZoomCenterX = mLastTouchX;
+ mZoomCenterY = mLastTouchY;
+ mInZoomOverview = !mInZoomOverview;
+ if (mInZoomOverview) {
+ float newScale = (float) getViewWidth()
+ / (mZoomOverviewWidth > 0 ? mZoomOverviewWidth
+ : mContentWidth);
+ if (Math.abs(newScale - mActualScale) < 0.01) {
+ mInZoomOverview = !mInZoomOverview;
+ // as it is already full screen, do nothing.
+ return;
+ }
+ if (getSettings().getBuiltInZoomControls()) {
+ if (mZoomButtonsController.isVisible()) {
+ mZoomButtonsController.setVisible(false);
+ }
+ } else {
+ if (mZoomControlRunnable != null) {
+ mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+ }
+ if (mZoomControls != null) {
+ mZoomControls.hide();
+ }
+ }
+ zoomWithPreview(newScale);
+ } else {
+ // mLastTouchX and mLastTouchY are the point in the current viewport
+ int contentX = viewToContent((int) mLastTouchX + mScrollX);
+ int contentY = viewToContent((int) mLastTouchY + mScrollY);
+ int left = nativeGetBlockLeftEdge(contentX, contentY);
+ if (left != NO_LEFTEDGE) {
+ // add a 5pt padding to the left edge. Re-calculate the zoom
+ // center so that the new scroll x will be on the left edge.
+ mZoomCenterX = left < 5 ? 0 : (left - 5) * mLastScale
+ * mActualScale / (mLastScale - mActualScale);
+ }
+ zoomWithPreview(mLastScale);
+ }
+ }
+
// Called by JNI to handle a touch on a node representing an email address,
// address, or phone number
private void overrideLoading(String url) {
@@ -4791,6 +4906,8 @@ public class WebView extends AbsoluteLayout
if (mTouchMode == TOUCH_INIT_MODE) {
mTouchMode = TOUCH_SHORTPRESS_START_MODE;
updateSelection();
+ } else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
+ mTouchMode = TOUCH_DONE_MODE;
}
break;
}
@@ -4802,6 +4919,13 @@ public class WebView extends AbsoluteLayout
}
break;
}
+ case RELEASE_SINGLE_TAP: {
+ if (!mPreventDrag) {
+ mTouchMode = TOUCH_DONE_MODE;
+ doShortPress();
+ }
+ break;
+ }
case SWITCH_TO_CLICK:
// The user clicked with the trackball, and did not click a
// second time, so perform the action of a trackball single
@@ -4854,6 +4978,7 @@ public class WebView extends AbsoluteLayout
break;
case NEW_PICTURE_MSG_ID:
// called for new content
+ final int viewWidth = getViewWidth();
final WebViewCore.DrawData draw =
(WebViewCore.DrawData) msg.obj;
final Point viewSize = draw.mViewPoint;
@@ -4861,16 +4986,12 @@ public class WebView extends AbsoluteLayout
// use the same logic in sendViewSizeZoom() to make sure
// the mZoomScale has matched the viewSize so that we
// can clear mZoomScale
- if (Math.round(getViewWidth() / mZoomScale) == viewSize.x) {
+ if (Math.round(viewWidth / mZoomScale) == viewSize.x) {
mZoomScale = 0;
mWebViewCore.sendMessage(EventHub.SET_SNAP_ANCHOR,
0, 0);
}
}
- if (!mMinZoomScaleFixed) {
- mMinZoomScale = (float) getViewWidth()
- / Math.max(ZOOM_OUT_WIDTH, draw.mWidthHeight.x);
- }
// We update the layout (i.e. request a layout from the
// view system) if the last view size that we sent to
// WebCore matches the view size of the picture we just
@@ -4888,6 +5009,25 @@ public class WebView extends AbsoluteLayout
if (mPictureListener != null) {
mPictureListener.onNewPicture(WebView.this, capturePicture());
}
+ if (mWebViewCore.getSettings().getUseWideViewPort()) {
+ mZoomOverviewWidth = Math.max(draw.mMinPrefWidth,
+ draw.mViewPoint.x);
+ }
+ if (!mMinZoomScaleFixed) {
+ mMinZoomScale = (float) viewWidth
+ / Math.max(ZOOM_OUT_WIDTH,
+ mZoomOverviewWidth > 0 ? mZoomOverviewWidth
+ : mContentWidth);
+ }
+ if (!mDrawHistory && mInZoomOverview) {
+ // fit the content width to the current view. Ignore
+ // the rounding error case.
+ if (Math.abs((viewWidth * mInvActualScale)
+ - mZoomOverviewWidth) > 1) {
+ zoomWithPreview((float) viewWidth
+ / mZoomOverviewWidth);
+ }
+ }
break;
case WEBCORE_INITIALIZED_MSG_ID:
// nativeCreate sets mNativeClass to a non-zero value
@@ -4916,7 +5056,7 @@ public class WebView extends AbsoluteLayout
}
}
break;
- case DID_FIRST_LAYOUT_MSG_ID:
+ case DID_FIRST_LAYOUT_MSG_ID: {
if (mNativeClass == 0) {
break;
}
@@ -4943,15 +5083,17 @@ public class WebView extends AbsoluteLayout
if (width == 0) {
break;
}
+ final WebSettings settings = mWebViewCore.getSettings();
int initialScale = msg.arg1;
int viewportWidth = msg.arg2;
// start a new page with DEFAULT_SCALE zoom scale.
float scale = mDefaultScale;
+ mInZoomOverview = false;
if (mInitialScale > 0) {
scale = mInitialScale / 100.0f;
} else {
- if (initialScale < 0) break;
- if (mWebViewCore.getSettings().getUseWideViewPort()) {
+ if (initialScale == -1) break;
+ if (settings.getUseWideViewPort()) {
// force viewSizeChanged by setting mLastWidthSent
// to 0
mLastWidthSent = 0;
@@ -4961,11 +5103,21 @@ public class WebView extends AbsoluteLayout
// than the view width, zoom in to fill the view
if (viewportWidth > 0 && viewportWidth < width) {
scale = (float) width / viewportWidth;
+ } else {
+ if (settings.getUseWideViewPort()) {
+ mInZoomOverview = ENABLE_DOUBLETAP_ZOOM;
+ }
}
+ } else if (initialScale < 0) {
+ // this should only happen when
+ // ENABLE_DOUBLETAP_ZOOM is true
+ mInZoomOverview = true;
+ scale = -initialScale / 100.0f;
} else {
scale = initialScale / 100.0f;
}
}
+ mLastScale = scale;
setNewZoomScale(scale, false);
// As we are on a new page, remove the WebTextView. This
// is necessary for page loads driven by webkit, and in
@@ -4973,6 +5125,7 @@ public class WebView extends AbsoluteLayout
// the WebTextView was visible.
clearTextEntry();
break;
+ }
case MOVE_OUT_OF_PLUGIN:
if (nativePluginEatsNavKey()) {
navHandledKey(msg.arg1, 1, false, 0, true);
@@ -5542,4 +5695,7 @@ public class WebView extends AbsoluteLayout
private native void nativeUpdateCachedTextfield(String updatedText,
int generation);
private native void nativeUpdatePluginReceivesEvents();
+ // return NO_LEFTEDGE means failure.
+ private static final int NO_LEFTEDGE = -1;
+ private native int nativeGetBlockLeftEdge(int x, int y);
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 4993fcf..36c5f0c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -96,7 +96,8 @@ final class WebViewCore {
private boolean mViewportUserScalable = true;
- private int mRestoredScale = WebView.DEFAULT_SCALE_PERCENT;
+ private int mRestoredScale = 0;
+ private int mRestoredScreenWidthScale = 0;
private int mRestoredX = 0;
private int mRestoredY = 0;
@@ -1340,9 +1341,8 @@ final class WebViewCore {
Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
return;
}
- if (mSettings.getUseWideViewPort()
- && (w < mViewportWidth || mViewportWidth == -1)) {
- int width = mViewportWidth;
+ if (mSettings.getUseWideViewPort()) {
+ int width;
if (mViewportWidth == -1) {
if (mSettings.getLayoutAlgorithm() ==
WebSettings.LayoutAlgorithm.NORMAL) {
@@ -1362,9 +1362,15 @@ final class WebViewCore {
*/
width = Math.max(w, nativeGetContentMinPrefWidth());
}
+ } else {
+ width = Math.max(w, mViewportWidth);
}
- nativeSetSize(width, Math.round((float) width * h / w), w, scale,
- w, h);
+ // while in zoom overview mode, the text are wrapped to the screen
+ // width matching mWebView.mLastScale. So that we don't trigger
+ // re-flow while toggling between overview mode and normal mode.
+ nativeSetSize(width, Math.round((float) width * h / w),
+ Math.round(mWebView.mInZoomOverview ? w * scale
+ / mWebView.mLastScale : w), scale, w, h);
} else {
nativeSetSize(w, h, w, scale, w, h);
}
@@ -1409,6 +1415,7 @@ final class WebViewCore {
public Region mInvalRegion;
public Point mViewPoint;
public Point mWidthHeight;
+ public int mMinPrefWidth;
}
private void webkitDraw() {
@@ -1424,6 +1431,9 @@ final class WebViewCore {
// Send the native view size that was used during the most recent
// layout.
draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
+ if (WebView.ENABLE_DOUBLETAP_ZOOM && mSettings.getUseWideViewPort()) {
+ draw.mMinPrefWidth = nativeGetContentMinPrefWidth();
+ }
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
Message.obtain(mWebView.mPrivateHandler,
WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
@@ -1734,9 +1744,10 @@ final class WebViewCore {
if (mRestoredScale > 0) {
Message.obtain(mWebView.mPrivateHandler,
- WebView.DID_FIRST_LAYOUT_MSG_ID, mRestoredScale, 0,
+ WebView.DID_FIRST_LAYOUT_MSG_ID,
+ mRestoredScreenWidthScale > 0 ?
+ -mRestoredScreenWidthScale : mRestoredScale, 0,
scaleLimit).sendToTarget();
- mRestoredScale = 0;
} else {
// if standardLoad is true, use mViewportInitialScale, otherwise
// pass -1 to the WebView to indicate no change of the scale.
@@ -1764,8 +1775,8 @@ final class WebViewCore {
}
}
- // reset restored offset
- mRestoredX = mRestoredY = 0;
+ // reset restored offset, scale
+ mRestoredX = mRestoredY = mRestoredScale = mRestoredScreenWidthScale = 0;
}
}
@@ -1777,6 +1788,17 @@ final class WebViewCore {
}
// called by JNI
+ private void restoreScreenWidthScale(int scale) {
+ if (!WebView.ENABLE_DOUBLETAP_ZOOM || !mSettings.getUseWideViewPort()) {
+ return;
+ }
+
+ if (mBrowserFrame.firstLayoutDone() == false) {
+ mRestoredScreenWidthScale = scale;
+ }
+ }
+
+ // called by JNI
private void needTouchEvents(boolean need) {
if (mWebView != null) {
Message.obtain(mWebView.mPrivateHandler,