First draft of multitouch in the WebView.
Currently we just handle a simple pinch action. We will wait for framework support for more complicated gesture. When pinch in the webview, zoom level will be changed on the fly. But we won't re-wrap the text until user action like double tap, rotate screen. Double tap will re-layout the page and wrap the text to the screen width. We try to keep the spot you tapped at the same place on the screen after relayout. If the block after relayout fully fit on the current screen, we will center it for easy reading. Fix http://b/issue?id=2360032
This commit is contained in:
@@ -21,6 +21,7 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.DialogInterface.OnCancelListener;
|
import android.content.DialogInterface.OnCancelListener;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.database.DataSetObserver;
|
import android.database.DataSetObserver;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@@ -349,6 +350,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
private static final int TOUCH_DOUBLE_TAP_MODE = 6;
|
private static final int TOUCH_DOUBLE_TAP_MODE = 6;
|
||||||
private static final int TOUCH_DONE_MODE = 7;
|
private static final int TOUCH_DONE_MODE = 7;
|
||||||
private static final int TOUCH_SELECT_MODE = 8;
|
private static final int TOUCH_SELECT_MODE = 8;
|
||||||
|
private static final int TOUCH_PINCH_DRAG = 9;
|
||||||
|
|
||||||
// Whether to forward the touch events to WebCore
|
// Whether to forward the touch events to WebCore
|
||||||
private boolean mForwardTouchEvents = false;
|
private boolean mForwardTouchEvents = false;
|
||||||
@@ -460,6 +462,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
// obj=Rect in doc coordinates
|
// obj=Rect in doc coordinates
|
||||||
static final int INVAL_RECT_MSG_ID = 26;
|
static final int INVAL_RECT_MSG_ID = 26;
|
||||||
static final int REQUEST_KEYBOARD = 27;
|
static final int REQUEST_KEYBOARD = 27;
|
||||||
|
static final int SHOW_RECT_MSG_ID = 28;
|
||||||
|
|
||||||
static final String[] HandlerDebugString = {
|
static final String[] HandlerDebugString = {
|
||||||
"REMEMBER_PASSWORD", // = 1;
|
"REMEMBER_PASSWORD", // = 1;
|
||||||
@@ -488,7 +491,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
"PREVENT_TOUCH_ID", // = 24;
|
"PREVENT_TOUCH_ID", // = 24;
|
||||||
"WEBCORE_NEED_TOUCH_EVENTS", // = 25;
|
"WEBCORE_NEED_TOUCH_EVENTS", // = 25;
|
||||||
"INVAL_RECT_MSG_ID", // = 26;
|
"INVAL_RECT_MSG_ID", // = 26;
|
||||||
"REQUEST_KEYBOARD" // = 27;
|
"REQUEST_KEYBOARD", // = 27;
|
||||||
|
"SHOW_RECT_MSG_ID" // = 28;
|
||||||
};
|
};
|
||||||
|
|
||||||
// default scale limit. Depending on the display density
|
// default scale limit. Depending on the display density
|
||||||
@@ -511,7 +515,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
// ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
|
// ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
|
||||||
// engadget always have wider mContentWidth no matter what viewport size is.
|
// engadget always have wider mContentWidth no matter what viewport size is.
|
||||||
int mZoomOverviewWidth = WebViewCore.DEFAULT_VIEWPORT_WIDTH;
|
int mZoomOverviewWidth = WebViewCore.DEFAULT_VIEWPORT_WIDTH;
|
||||||
float mLastScale;
|
float mTextWrapScale;
|
||||||
|
|
||||||
// default scale. Depending on the display density.
|
// default scale. Depending on the display density.
|
||||||
static int DEFAULT_SCALE_PERCENT;
|
static int DEFAULT_SCALE_PERCENT;
|
||||||
@@ -743,6 +747,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
params;
|
params;
|
||||||
frameParams.gravity = Gravity.RIGHT;
|
frameParams.gravity = Gravity.RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSupportMultiTouch = context.getPackageManager().hasSystemFeature(
|
||||||
|
PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateZoomButtonsEnabled() {
|
private void updateZoomButtonsEnabled() {
|
||||||
@@ -785,6 +792,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
mDefaultScale = density;
|
mDefaultScale = density;
|
||||||
mActualScale = density;
|
mActualScale = density;
|
||||||
mInvActualScale = 1 / density;
|
mInvActualScale = 1 / density;
|
||||||
|
mTextWrapScale = density;
|
||||||
DEFAULT_MAX_ZOOM_SCALE = 4.0f * density;
|
DEFAULT_MAX_ZOOM_SCALE = 4.0f * density;
|
||||||
DEFAULT_MIN_ZOOM_SCALE = 0.25f * density;
|
DEFAULT_MIN_ZOOM_SCALE = 0.25f * density;
|
||||||
mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
|
mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
|
||||||
@@ -805,7 +813,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
mDefaultScale = density;
|
mDefaultScale = density;
|
||||||
mMaxZoomScale *= scaleFactor;
|
mMaxZoomScale *= scaleFactor;
|
||||||
mMinZoomScale *= scaleFactor;
|
mMinZoomScale *= scaleFactor;
|
||||||
setNewZoomScale(mActualScale * scaleFactor, false);
|
setNewZoomScale(mActualScale * scaleFactor, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1162,9 +1170,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
b.putInt("scrollX", mScrollX);
|
b.putInt("scrollX", mScrollX);
|
||||||
b.putInt("scrollY", mScrollY);
|
b.putInt("scrollY", mScrollY);
|
||||||
b.putFloat("scale", mActualScale);
|
b.putFloat("scale", mActualScale);
|
||||||
if (mInZoomOverview) {
|
b.putFloat("textwrapScale", mTextWrapScale);
|
||||||
b.putFloat("lastScale", mLastScale);
|
b.putBoolean("overview", mInZoomOverview);
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1209,13 +1216,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
// onSizeChanged() is called, the rest will be set
|
// onSizeChanged() is called, the rest will be set
|
||||||
// correctly
|
// correctly
|
||||||
mActualScale = scale;
|
mActualScale = scale;
|
||||||
float lastScale = b.getFloat("lastScale", -1.0f);
|
mTextWrapScale = b.getFloat("textwrapScale", scale);
|
||||||
if (lastScale > 0) {
|
mInZoomOverview = b.getBoolean("overview");
|
||||||
mInZoomOverview = true;
|
|
||||||
mLastScale = lastScale;
|
|
||||||
} else {
|
|
||||||
mInZoomOverview = false;
|
|
||||||
}
|
|
||||||
invalidate();
|
invalidate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1938,12 +1940,18 @@ public class WebView extends AbsoluteLayout
|
|||||||
contentSizeChanged(updateLayout);
|
contentSizeChanged(updateLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setNewZoomScale(float scale, boolean force) {
|
private void setNewZoomScale(float scale, boolean updateTextWrapScale,
|
||||||
|
boolean force) {
|
||||||
if (scale < mMinZoomScale) {
|
if (scale < mMinZoomScale) {
|
||||||
scale = mMinZoomScale;
|
scale = mMinZoomScale;
|
||||||
} else if (scale > mMaxZoomScale) {
|
} else if (scale > mMaxZoomScale) {
|
||||||
scale = mMaxZoomScale;
|
scale = mMaxZoomScale;
|
||||||
}
|
}
|
||||||
|
if (updateTextWrapScale) {
|
||||||
|
mTextWrapScale = scale;
|
||||||
|
// reset mLastHeightSent to force VIEW_SIZE_CHANGED sent to WebKit
|
||||||
|
mLastHeightSent = 0;
|
||||||
|
}
|
||||||
if (scale != mActualScale || force) {
|
if (scale != mActualScale || force) {
|
||||||
if (mDrawHistory) {
|
if (mDrawHistory) {
|
||||||
// If history Picture is drawn, don't update scroll. They will
|
// If history Picture is drawn, don't update scroll. They will
|
||||||
@@ -1953,9 +1961,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
mActualScale = scale;
|
mActualScale = scale;
|
||||||
mInvActualScale = 1 / scale;
|
mInvActualScale = 1 / scale;
|
||||||
if (!mPreviewZoomOnly) {
|
|
||||||
sendViewSizeZoom();
|
sendViewSizeZoom();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// update our scroll so we don't appear to jump
|
// update our scroll so we don't appear to jump
|
||||||
// i.e. keep the center of the doc in the center of the view
|
// i.e. keep the center of the doc in the center of the view
|
||||||
@@ -1983,19 +1989,20 @@ public class WebView extends AbsoluteLayout
|
|||||||
mScrollX = pinLocX(Math.round(sx));
|
mScrollX = pinLocX(Math.round(sx));
|
||||||
mScrollY = pinLocY(Math.round(sy));
|
mScrollY = pinLocY(Math.round(sy));
|
||||||
|
|
||||||
if (!mPreviewZoomOnly) {
|
// update webkit
|
||||||
sendViewSizeZoom();
|
sendViewSizeZoom();
|
||||||
sendOurVisibleRect();
|
sendOurVisibleRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Used to avoid sending many visible rect messages.
|
// Used to avoid sending many visible rect messages.
|
||||||
private Rect mLastVisibleRectSent;
|
private Rect mLastVisibleRectSent;
|
||||||
private Rect mLastGlobalRect;
|
private Rect mLastGlobalRect;
|
||||||
|
|
||||||
private Rect sendOurVisibleRect() {
|
private Rect sendOurVisibleRect() {
|
||||||
|
if (mPreviewZoomOnly) return mLastVisibleRectSent;
|
||||||
|
|
||||||
Rect rect = new Rect();
|
Rect rect = new Rect();
|
||||||
calcOurContentVisibleRect(rect);
|
calcOurContentVisibleRect(rect);
|
||||||
// Rect.equals() checks for null input.
|
// Rect.equals() checks for null input.
|
||||||
@@ -2049,6 +2056,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
int mWidth;
|
int mWidth;
|
||||||
int mHeight;
|
int mHeight;
|
||||||
int mTextWrapWidth;
|
int mTextWrapWidth;
|
||||||
|
int mAnchorX;
|
||||||
|
int mAnchorY;
|
||||||
float mScale;
|
float mScale;
|
||||||
boolean mIgnoreHeight;
|
boolean mIgnoreHeight;
|
||||||
}
|
}
|
||||||
@@ -2060,6 +2069,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
* @return true if new values were sent
|
* @return true if new values were sent
|
||||||
*/
|
*/
|
||||||
private boolean sendViewSizeZoom() {
|
private boolean sendViewSizeZoom() {
|
||||||
|
if (mPreviewZoomOnly) return false;
|
||||||
|
|
||||||
int viewWidth = getViewWidth();
|
int viewWidth = getViewWidth();
|
||||||
int newWidth = Math.round(viewWidth * mInvActualScale);
|
int newWidth = Math.round(viewWidth * mInvActualScale);
|
||||||
int newHeight = Math.round(getViewHeight() * mInvActualScale);
|
int newHeight = Math.round(getViewHeight() * mInvActualScale);
|
||||||
@@ -2079,13 +2090,11 @@ public class WebView extends AbsoluteLayout
|
|||||||
ViewSizeData data = new ViewSizeData();
|
ViewSizeData data = new ViewSizeData();
|
||||||
data.mWidth = newWidth;
|
data.mWidth = newWidth;
|
||||||
data.mHeight = newHeight;
|
data.mHeight = newHeight;
|
||||||
// while in zoom overview mode, the text are wrapped to the screen
|
data.mTextWrapWidth = Math.round(viewWidth / mTextWrapScale);;
|
||||||
// width matching mLastScale. So that we don't trigger re-flow while
|
|
||||||
// toggling between overview mode and normal mode.
|
|
||||||
data.mTextWrapWidth = mInZoomOverview ? Math.round(viewWidth
|
|
||||||
/ mLastScale) : newWidth;
|
|
||||||
data.mScale = mActualScale;
|
data.mScale = mActualScale;
|
||||||
data.mIgnoreHeight = mZoomScale != 0 && !mHeightCanMeasure;
|
data.mIgnoreHeight = mZoomScale != 0 && !mHeightCanMeasure;
|
||||||
|
data.mAnchorX = mAnchorX;
|
||||||
|
data.mAnchorY = mAnchorY;
|
||||||
mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
|
mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
|
||||||
mLastWidthSent = newWidth;
|
mLastWidthSent = newWidth;
|
||||||
mLastHeightSent = newHeight;
|
mLastHeightSent = newHeight;
|
||||||
@@ -2838,6 +2847,38 @@ public class WebView extends AbsoluteLayout
|
|||||||
*/
|
*/
|
||||||
private boolean mNeedToAdjustWebTextView;
|
private boolean mNeedToAdjustWebTextView;
|
||||||
|
|
||||||
|
// if checkVisibility is false, the WebTextView may trigger a move of
|
||||||
|
// WebView to bring itself into the view.
|
||||||
|
private void adjustTextView(boolean checkVisibility) {
|
||||||
|
Rect contentBounds = nativeFocusCandidateNodeBounds();
|
||||||
|
Rect vBox = contentToViewRect(contentBounds);
|
||||||
|
Rect visibleRect = new Rect();
|
||||||
|
calcOurVisibleRect(visibleRect);
|
||||||
|
if (!checkVisibility || visibleRect.contains(vBox)) {
|
||||||
|
// As a result of the zoom, the textfield is now on
|
||||||
|
// screen. Place the WebTextView in its new place,
|
||||||
|
// accounting for our new scroll/zoom values.
|
||||||
|
mWebTextView
|
||||||
|
.setTextSize(
|
||||||
|
TypedValue.COMPLEX_UNIT_PX,
|
||||||
|
contentToViewDimension(nativeFocusCandidateTextSize()));
|
||||||
|
mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
|
||||||
|
vBox.height());
|
||||||
|
// If it is a password field, start drawing the
|
||||||
|
// WebTextView once again.
|
||||||
|
if (nativeFocusCandidateIsPassword()) {
|
||||||
|
mWebTextView.setInPassword(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The textfield is now off screen. The user probably
|
||||||
|
// was not zooming to see the textfield better. Remove
|
||||||
|
// the WebTextView. If the user types a key, and the
|
||||||
|
// textfield is still in focus, we will reconstruct
|
||||||
|
// the WebTextView and scroll it back on screen.
|
||||||
|
mWebTextView.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void drawCoreAndCursorRing(Canvas canvas, int color,
|
private void drawCoreAndCursorRing(Canvas canvas, int color,
|
||||||
boolean drawCursorRing) {
|
boolean drawCursorRing) {
|
||||||
if (mDrawHistory) {
|
if (mDrawHistory) {
|
||||||
@@ -2865,32 +2906,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
invalidate();
|
invalidate();
|
||||||
if (mNeedToAdjustWebTextView) {
|
if (mNeedToAdjustWebTextView) {
|
||||||
mNeedToAdjustWebTextView = false;
|
mNeedToAdjustWebTextView = false;
|
||||||
Rect contentBounds = nativeFocusCandidateNodeBounds();
|
adjustTextView(true);
|
||||||
Rect vBox = contentToViewRect(contentBounds);
|
|
||||||
Rect visibleRect = new Rect();
|
|
||||||
calcOurVisibleRect(visibleRect);
|
|
||||||
if (visibleRect.contains(vBox)) {
|
|
||||||
// As a result of the zoom, the textfield is now on
|
|
||||||
// screen. Place the WebTextView in its new place,
|
|
||||||
// accounting for our new scroll/zoom values.
|
|
||||||
mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
|
|
||||||
contentToViewDimension(
|
|
||||||
nativeFocusCandidateTextSize()));
|
|
||||||
mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
|
|
||||||
vBox.height());
|
|
||||||
// If it is a password field, start drawing the
|
|
||||||
// WebTextView once again.
|
|
||||||
if (nativeFocusCandidateIsPassword()) {
|
|
||||||
mWebTextView.setInPassword(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The textfield is now off screen. The user probably
|
|
||||||
// was not zooming to see the textfield better. Remove
|
|
||||||
// the WebTextView. If the user types a key, and the
|
|
||||||
// textfield is still in focus, we will reconstruct
|
|
||||||
// the WebTextView and scroll it back on screen.
|
|
||||||
mWebTextView.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// calculate the intermediate scroll position. As we need to use
|
// calculate the intermediate scroll position. As we need to use
|
||||||
@@ -2924,11 +2940,11 @@ public class WebView extends AbsoluteLayout
|
|||||||
canvas.scale(mActualScale, mActualScale);
|
canvas.scale(mActualScale, mActualScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
mWebViewCore.drawContentPicture(canvas, color, animateZoom,
|
mWebViewCore.drawContentPicture(canvas, color,
|
||||||
animateScroll);
|
(animateZoom || mPreviewZoomOnly), animateScroll);
|
||||||
|
|
||||||
if (mNativeClass == 0) return;
|
if (mNativeClass == 0) return;
|
||||||
if (mShiftIsPressed && !animateZoom) {
|
if (mShiftIsPressed && !(animateZoom || mPreviewZoomOnly)) {
|
||||||
if (mTouchSelection) {
|
if (mTouchSelection) {
|
||||||
nativeDrawSelectionRegion(canvas);
|
nativeDrawSelectionRegion(canvas);
|
||||||
} else {
|
} else {
|
||||||
@@ -3029,10 +3045,15 @@ public class WebView extends AbsoluteLayout
|
|||||||
if (mWebTextView == null) return;
|
if (mWebTextView == null) return;
|
||||||
|
|
||||||
imm.showSoftInput(mWebTextView, 0);
|
imm.showSoftInput(mWebTextView, 0);
|
||||||
if (mInZoomOverview) {
|
if (mActualScale < mDefaultScale) {
|
||||||
// if in zoom overview mode, call doDoubleTap() to bring it back
|
// bring it back to the default scale so that user can enter
|
||||||
// to normal mode so that user can enter text.
|
// text.
|
||||||
doDoubleTap();
|
mInZoomOverview = false;
|
||||||
|
mZoomCenterX = mLastTouchX;
|
||||||
|
mZoomCenterY = mLastTouchY;
|
||||||
|
// do not change text wrap scale so that there is no reflow
|
||||||
|
setNewZoomScale(mDefaultScale, false, false);
|
||||||
|
adjustTextView(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // used by plugins
|
else { // used by plugins
|
||||||
@@ -3604,6 +3625,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
if (mZoomScale == 0) { // unless we're already zooming
|
if (mZoomScale == 0) { // unless we're already zooming
|
||||||
mZoomCenterX = getViewWidth() * .5f;
|
mZoomCenterX = getViewWidth() * .5f;
|
||||||
mZoomCenterY = getViewHeight() * .5f;
|
mZoomCenterY = getViewHeight() * .5f;
|
||||||
|
mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
|
||||||
|
mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update mMinZoomScale if the minimum zoom scale is not fixed
|
// update mMinZoomScale if the minimum zoom scale is not fixed
|
||||||
@@ -3626,7 +3649,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
|
|
||||||
// we always force, in case our height changed, in which case we still
|
// we always force, in case our height changed, in which case we still
|
||||||
// want to send the notification over to webkit
|
// want to send the notification over to webkit
|
||||||
setNewZoomScale(mActualScale, true);
|
// only update the text wrap scale if width changed.
|
||||||
|
setNewZoomScale(mActualScale, w != ow, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -3674,6 +3698,97 @@ public class WebView extends AbsoluteLayout
|
|||||||
private static final float MAX_SLOPE_FOR_DIAG = 1.5f;
|
private static final float MAX_SLOPE_FOR_DIAG = 1.5f;
|
||||||
private static final int MIN_BREAK_SNAP_CROSS_DISTANCE = 80;
|
private static final int MIN_BREAK_SNAP_CROSS_DISTANCE = 80;
|
||||||
|
|
||||||
|
// MultiTouch handling
|
||||||
|
private static boolean mSupportMultiTouch;
|
||||||
|
|
||||||
|
private double mPinchDistance;
|
||||||
|
private int mAnchorX;
|
||||||
|
private int mAnchorY;
|
||||||
|
|
||||||
|
private boolean doMultiTouch(MotionEvent ev) {
|
||||||
|
int action = ev.getAction();
|
||||||
|
|
||||||
|
if ((action & 0xff) == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
|
// cancel the single touch handling
|
||||||
|
cancelTouch();
|
||||||
|
// reset the zoom overview mode so that the page won't auto grow
|
||||||
|
mInZoomOverview = false;
|
||||||
|
// If it is in password mode, turn it off so it does not draw
|
||||||
|
// misplaced.
|
||||||
|
if (inEditingMode() && nativeFocusCandidateIsPassword()) {
|
||||||
|
mWebTextView.setInPassword(false);
|
||||||
|
}
|
||||||
|
// start multi (2-pointer) touch
|
||||||
|
mPreviewZoomOnly = true;
|
||||||
|
float x0 = ev.getX(0);
|
||||||
|
float y0 = ev.getY(0);
|
||||||
|
float x1 = ev.getX(1);
|
||||||
|
float y1 = ev.getY(1);
|
||||||
|
mLastTouchTime = ev.getEventTime();
|
||||||
|
mPinchDistance = Math.sqrt((x0 - x1) * (x0 - x1) + (y0 - y1)
|
||||||
|
* (y0 - y1));
|
||||||
|
mZoomCenterX = mZoomCenterY = 0;
|
||||||
|
} else if ((action & 0xff) == MotionEvent.ACTION_POINTER_UP) {
|
||||||
|
mPreviewZoomOnly = false;
|
||||||
|
// for testing only, default don't reflow now
|
||||||
|
boolean reflowNow = !getSettings().getPluginsEnabled();
|
||||||
|
// force zoom after mPreviewZoomOnly is set to false so that the new
|
||||||
|
// view size will be passed to the WebKit
|
||||||
|
if (reflowNow && (mZoomCenterX != 0) && (mZoomCenterY != 0)) {
|
||||||
|
mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
|
||||||
|
mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
|
||||||
|
}
|
||||||
|
setNewZoomScale(mActualScale, reflowNow, true);
|
||||||
|
// call invalidate() to draw without zoom filter
|
||||||
|
invalidate();
|
||||||
|
// adjust the edit text view if needed
|
||||||
|
if (inEditingMode()) {
|
||||||
|
adjustTextView(true);
|
||||||
|
}
|
||||||
|
// start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as it
|
||||||
|
// may trigger the unwanted click, can't use TOUCH_DRAG_MODE as it
|
||||||
|
// may trigger the unwanted fling.
|
||||||
|
mTouchMode = TOUCH_PINCH_DRAG;
|
||||||
|
// action indicates which pointer is UP. Use the other one as drag's
|
||||||
|
// starting position.
|
||||||
|
int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
|
||||||
|
>> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
|
||||||
|
startTouch(ev.getX(id), ev.getY(id), ev.getEventTime());
|
||||||
|
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||||
|
float x0 = ev.getX(0);
|
||||||
|
float y0 = ev.getY(0);
|
||||||
|
float x1 = ev.getX(1);
|
||||||
|
float y1 = ev.getY(1);
|
||||||
|
double distance = Math.sqrt((x0 - x1) * (x0 - x1) + (y0 - y1)
|
||||||
|
* (y0 - y1));
|
||||||
|
float scale = (float) (Math.round(distance / mPinchDistance
|
||||||
|
* mActualScale * 100) / 100.0);
|
||||||
|
long time = ev.getEventTime();
|
||||||
|
// add distance/time checking to avoid the minor shift right before
|
||||||
|
// lifting the fingers after a pause
|
||||||
|
if (Math.abs(scale - mActualScale) >= 0.01f
|
||||||
|
&& ((time - mLastTouchTime) < 300 || Math.abs(distance
|
||||||
|
- mPinchDistance) > (10 * mDefaultScale))) {
|
||||||
|
// limit the scale change per step
|
||||||
|
if (scale > mActualScale) {
|
||||||
|
scale = Math.min(scale, mActualScale * 1.25f);
|
||||||
|
} else {
|
||||||
|
scale = Math.max(scale, mActualScale * 0.8f);
|
||||||
|
}
|
||||||
|
mZoomCenterX = (x0 + x1) / 2;
|
||||||
|
mZoomCenterY = (y0 + y1) / 2;
|
||||||
|
setNewZoomScale(scale, false, false);
|
||||||
|
invalidate();
|
||||||
|
mPinchDistance = distance;
|
||||||
|
mLastTouchTime = time;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(LOGTAG, action + " should not happen during doMultiTouch");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent ev) {
|
public boolean onTouchEvent(MotionEvent ev) {
|
||||||
if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
|
if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
|
||||||
@@ -3685,6 +3800,11 @@ public class WebView extends AbsoluteLayout
|
|||||||
+ mTouchMode);
|
+ mTouchMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSupportMultiTouch && getSettings().supportZoom()
|
||||||
|
&& ev.getPointerCount() > 1) {
|
||||||
|
return doMultiTouch(ev);
|
||||||
|
}
|
||||||
|
|
||||||
int action = ev.getAction();
|
int action = ev.getAction();
|
||||||
float x = ev.getX();
|
float x = ev.getX();
|
||||||
float y = ev.getY();
|
float y = ev.getY();
|
||||||
@@ -3745,6 +3865,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
// continue, mTouchMode should be still TOUCH_INIT_MODE
|
// continue, mTouchMode should be still TOUCH_INIT_MODE
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
mPreviewZoomOnly = false;
|
||||||
mTouchMode = TOUCH_INIT_MODE;
|
mTouchMode = TOUCH_INIT_MODE;
|
||||||
mPreventDrag = mForwardTouchEvents ? PREVENT_DRAG_MAYBE_YES
|
mPreventDrag = mForwardTouchEvents ? PREVENT_DRAG_MAYBE_YES
|
||||||
: PREVENT_DRAG_NO;
|
: PREVENT_DRAG_NO;
|
||||||
@@ -3762,11 +3883,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
.obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
|
.obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
|
||||||
}
|
}
|
||||||
// Remember where the motion event started
|
// Remember where the motion event started
|
||||||
mLastTouchX = x;
|
startTouch(x, y, eventTime);
|
||||||
mLastTouchY = y;
|
|
||||||
mLastTouchTime = eventTime;
|
|
||||||
mVelocityTracker = VelocityTracker.obtain();
|
|
||||||
mSnapScrollMode = SNAP_NONE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MotionEvent.ACTION_MOVE: {
|
case MotionEvent.ACTION_MOVE: {
|
||||||
@@ -3821,6 +3938,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
if (!mDragFromTextInput) {
|
if (!mDragFromTextInput) {
|
||||||
nativeHideCursor();
|
nativeHideCursor();
|
||||||
}
|
}
|
||||||
|
if (!mSupportMultiTouch) {
|
||||||
WebSettings settings = getSettings();
|
WebSettings settings = getSettings();
|
||||||
if (settings.supportZoom()
|
if (settings.supportZoom()
|
||||||
&& settings.getBuiltInZoomControls()
|
&& settings.getBuiltInZoomControls()
|
||||||
@@ -3836,6 +3954,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// do pan
|
// do pan
|
||||||
int newScrollX = pinLocX(mScrollX + deltaX);
|
int newScrollX = pinLocX(mScrollX + deltaX);
|
||||||
@@ -3911,7 +4030,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
mUserScroll = true;
|
mUserScroll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getSettings().getBuiltInZoomControls()) {
|
if (!mSupportMultiTouch
|
||||||
|
&& !getSettings().getBuiltInZoomControls()) {
|
||||||
boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
|
boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
|
||||||
if (mZoomControls != null && showPlusMinus) {
|
if (mZoomControls != null && showPlusMinus) {
|
||||||
if (mZoomControls.getVisibility() == View.VISIBLE) {
|
if (mZoomControls.getVisibility() == View.VISIBLE) {
|
||||||
@@ -4010,9 +4130,25 @@ public class WebView extends AbsoluteLayout
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MotionEvent.ACTION_CANCEL: {
|
case MotionEvent.ACTION_CANCEL: {
|
||||||
// we also use mVelocityTracker == null to tell us that we are
|
cancelTouch();
|
||||||
// not "moving around", so we can take the slower/prettier
|
break;
|
||||||
// mode in the drawing code
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTouch(float x, float y, long eventTime) {
|
||||||
|
mLastTouchX = x;
|
||||||
|
mLastTouchY = y;
|
||||||
|
mLastTouchTime = eventTime;
|
||||||
|
mVelocityTracker = VelocityTracker.obtain();
|
||||||
|
mSnapScrollMode = SNAP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelTouch() {
|
||||||
|
// we also use mVelocityTracker == null to tell us that we are not
|
||||||
|
// "moving around", so we can take the slower/prettier mode in the
|
||||||
|
// drawing code
|
||||||
if (mVelocityTracker != null) {
|
if (mVelocityTracker != null) {
|
||||||
mVelocityTracker.recycle();
|
mVelocityTracker.recycle();
|
||||||
mVelocityTracker = null;
|
mVelocityTracker = null;
|
||||||
@@ -4024,10 +4160,6 @@ public class WebView extends AbsoluteLayout
|
|||||||
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
||||||
mTouchMode = TOUCH_DONE_MODE;
|
mTouchMode = TOUCH_DONE_MODE;
|
||||||
nativeHideCursor();
|
nativeHideCursor();
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private long mTrackballFirstTime = 0;
|
private long mTrackballFirstTime = 0;
|
||||||
@@ -4389,7 +4521,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
scale = mDefaultScale;
|
scale = mDefaultScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
setNewZoomScale(scale, false);
|
setNewZoomScale(scale, true, false);
|
||||||
|
|
||||||
if (oldScale != mActualScale) {
|
if (oldScale != mActualScale) {
|
||||||
// use mZoomPickerScale to see zoom preview first
|
// use mZoomPickerScale to see zoom preview first
|
||||||
@@ -4397,9 +4529,6 @@ public class WebView extends AbsoluteLayout
|
|||||||
mInvInitialZoomScale = 1.0f / oldScale;
|
mInvInitialZoomScale = 1.0f / oldScale;
|
||||||
mInvFinalZoomScale = 1.0f / mActualScale;
|
mInvFinalZoomScale = 1.0f / mActualScale;
|
||||||
mZoomScale = mActualScale;
|
mZoomScale = mActualScale;
|
||||||
if (!mInZoomOverview) {
|
|
||||||
mLastScale = scale;
|
|
||||||
}
|
|
||||||
invalidate();
|
invalidate();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -4497,19 +4626,14 @@ public class WebView extends AbsoluteLayout
|
|||||||
public boolean zoomIn() {
|
public boolean zoomIn() {
|
||||||
// TODO: alternatively we can disallow this during draw history mode
|
// TODO: alternatively we can disallow this during draw history mode
|
||||||
switchOutDrawHistory();
|
switchOutDrawHistory();
|
||||||
|
mInZoomOverview = false;
|
||||||
// Center zooming to the center of the screen.
|
// Center zooming to the center of the screen.
|
||||||
if (mInZoomOverview) {
|
|
||||||
// if in overview mode, bring it back to normal mode
|
|
||||||
mLastTouchX = getViewWidth() * .5f;
|
|
||||||
mLastTouchY = getViewHeight() * .5f;
|
|
||||||
doDoubleTap();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
mZoomCenterX = getViewWidth() * .5f;
|
mZoomCenterX = getViewWidth() * .5f;
|
||||||
mZoomCenterY = getViewHeight() * .5f;
|
mZoomCenterY = getViewHeight() * .5f;
|
||||||
|
mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
|
||||||
|
mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
|
||||||
return zoomWithPreview(mActualScale * 1.25f);
|
return zoomWithPreview(mActualScale * 1.25f);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform zoom out in the webview
|
* Perform zoom out in the webview
|
||||||
@@ -4518,18 +4642,12 @@ public class WebView extends AbsoluteLayout
|
|||||||
public boolean zoomOut() {
|
public boolean zoomOut() {
|
||||||
// TODO: alternatively we can disallow this during draw history mode
|
// TODO: alternatively we can disallow this during draw history mode
|
||||||
switchOutDrawHistory();
|
switchOutDrawHistory();
|
||||||
float scale = mActualScale * 0.8f;
|
|
||||||
if (scale < (mMinZoomScale + 0.1f)
|
|
||||||
&& mWebViewCore.getSettings().getUseWideViewPort()) {
|
|
||||||
// when zoom out to min scale, switch to overview mode
|
|
||||||
doDoubleTap();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Center zooming to the center of the screen.
|
// Center zooming to the center of the screen.
|
||||||
mZoomCenterX = getViewWidth() * .5f;
|
mZoomCenterX = getViewWidth() * .5f;
|
||||||
mZoomCenterY = getViewHeight() * .5f;
|
mZoomCenterY = getViewHeight() * .5f;
|
||||||
return zoomWithPreview(scale);
|
mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
|
||||||
}
|
mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
|
||||||
|
return zoomWithPreview(mActualScale * 0.8f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSelection() {
|
private void updateSelection() {
|
||||||
@@ -4645,15 +4763,22 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rule for double tap:
|
||||||
|
// 1. if the current scale is not same as the text wrap scale and layout
|
||||||
|
// algorithm is NARROW_COLUMNS, fit to column;
|
||||||
|
// 2. if the current state is not overview mode, change to overview mode;
|
||||||
|
// 3. if the current state is overview mode, change to default scale.
|
||||||
private void doDoubleTap() {
|
private void doDoubleTap() {
|
||||||
if (mWebViewCore.getSettings().getUseWideViewPort() == false) {
|
if (mWebViewCore.getSettings().getUseWideViewPort() == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mZoomCenterX = mLastTouchX;
|
mZoomCenterX = mLastTouchX;
|
||||||
mZoomCenterY = mLastTouchY;
|
mZoomCenterY = mLastTouchY;
|
||||||
mInZoomOverview = !mInZoomOverview;
|
mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
|
||||||
// remove the zoom control after double tap
|
mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
|
||||||
WebSettings settings = getSettings();
|
WebSettings settings = getSettings();
|
||||||
|
if (!mSupportMultiTouch) {
|
||||||
|
// remove the zoom control after double tap
|
||||||
if (settings.getBuiltInZoomControls()) {
|
if (settings.getBuiltInZoomControls()) {
|
||||||
if (mZoomButtonsController.isVisible()) {
|
if (mZoomButtonsController.isVisible()) {
|
||||||
mZoomButtonsController.setVisible(false);
|
mZoomButtonsController.setVisible(false);
|
||||||
@@ -4667,22 +4792,42 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings.setDoubleTapToastCount(0);
|
settings.setDoubleTapToastCount(0);
|
||||||
if (mInZoomOverview) {
|
}
|
||||||
|
if ((settings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NARROW_COLUMNS)
|
||||||
|
&& (Math.abs(mActualScale - mTextWrapScale) >= 0.01f)) {
|
||||||
|
setNewZoomScale(mActualScale, true, true);
|
||||||
|
float overviewScale = (float) getViewWidth() / mZoomOverviewWidth;
|
||||||
|
if (Math.abs(mActualScale - overviewScale) < 0.01f) {
|
||||||
|
mInZoomOverview = true;
|
||||||
|
}
|
||||||
|
} else if (!mInZoomOverview) {
|
||||||
|
float newScale = (float) getViewWidth() / mZoomOverviewWidth;
|
||||||
|
if (Math.abs(mActualScale - newScale) >= 0.01f) {
|
||||||
|
mInZoomOverview = true;
|
||||||
// Force the titlebar fully reveal in overview mode
|
// Force the titlebar fully reveal in overview mode
|
||||||
if (mScrollY < getTitleHeight()) mScrollY = 0;
|
if (mScrollY < getTitleHeight()) mScrollY = 0;
|
||||||
zoomWithPreview((float) getViewWidth() / mZoomOverviewWidth);
|
zoomWithPreview(newScale);
|
||||||
} else {
|
} else if (Math.abs(mActualScale - mDefaultScale) >= 0.01f) {
|
||||||
// mLastTouchX and mLastTouchY are the point in the current viewport
|
mInZoomOverview = true;
|
||||||
int contentX = viewToContentX((int) mLastTouchX + mScrollX);
|
|
||||||
int contentY = viewToContentY((int) mLastTouchY + mScrollY);
|
|
||||||
int left = nativeGetBlockLeftEdge(contentX, contentY, mActualScale);
|
|
||||||
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);
|
} else {
|
||||||
|
mInZoomOverview = false;
|
||||||
|
int left = nativeGetBlockLeftEdge(mAnchorX, mAnchorY, mActualScale);
|
||||||
|
if (left != NO_LEFTEDGE) {
|
||||||
|
// add a 5pt padding to the left edge.
|
||||||
|
int viewLeft = contentToViewX(left < 5 ? 0 : (left - 5))
|
||||||
|
- mScrollX;
|
||||||
|
// Re-calculate the zoom center so that the new scroll x will be
|
||||||
|
// on the left edge.
|
||||||
|
if (viewLeft > 0) {
|
||||||
|
mZoomCenterX = viewLeft * mDefaultScale
|
||||||
|
/ (mDefaultScale - mActualScale);
|
||||||
|
} else {
|
||||||
|
scrollBy(viewLeft, 0);
|
||||||
|
mZoomCenterX = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zoomWithPreview(mDefaultScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4888,9 +5033,10 @@ public class WebView extends AbsoluteLayout
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
if (DebugFlags.WEB_VIEW) {
|
if (DebugFlags.WEB_VIEW) {
|
||||||
Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
|
Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD
|
||||||
> INVAL_RECT_MSG_ID ? Integer.toString(msg.what)
|
|| msg.what > SHOW_RECT_MSG_ID ? Integer
|
||||||
: HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
|
.toString(msg.what) : HandlerDebugString[msg.what
|
||||||
|
- REMEMBER_PASSWORD]);
|
||||||
}
|
}
|
||||||
if (mWebViewCore == null) {
|
if (mWebViewCore == null) {
|
||||||
// after WebView's destroy() is called, skip handling messages.
|
// after WebView's destroy() is called, skip handling messages.
|
||||||
@@ -4975,9 +5121,6 @@ public class WebView extends AbsoluteLayout
|
|||||||
WebViewCore.RestoreState restoreState = draw.mRestoreState;
|
WebViewCore.RestoreState restoreState = draw.mRestoreState;
|
||||||
if (restoreState != null) {
|
if (restoreState != null) {
|
||||||
mInZoomOverview = false;
|
mInZoomOverview = false;
|
||||||
mLastScale = mInitialScaleInPercent > 0
|
|
||||||
? mInitialScaleInPercent / 100.0f
|
|
||||||
: restoreState.mTextWrapScale;
|
|
||||||
if (restoreState.mMinScale == 0) {
|
if (restoreState.mMinScale == 0) {
|
||||||
if (restoreState.mMobileSite) {
|
if (restoreState.mMobileSite) {
|
||||||
if (draw.mMinPrefWidth >
|
if (draw.mMinPrefWidth >
|
||||||
@@ -4985,6 +5128,8 @@ public class WebView extends AbsoluteLayout
|
|||||||
mMinZoomScale = (float) viewWidth
|
mMinZoomScale = (float) viewWidth
|
||||||
/ draw.mMinPrefWidth;
|
/ draw.mMinPrefWidth;
|
||||||
mMinZoomScaleFixed = false;
|
mMinZoomScaleFixed = false;
|
||||||
|
mInZoomOverview = useWideViewport &&
|
||||||
|
settings.getLoadWithOverviewMode();
|
||||||
} else {
|
} else {
|
||||||
mMinZoomScale = restoreState.mDefaultScale;
|
mMinZoomScale = restoreState.mDefaultScale;
|
||||||
mMinZoomScaleFixed = true;
|
mMinZoomScaleFixed = true;
|
||||||
@@ -5002,17 +5147,27 @@ public class WebView extends AbsoluteLayout
|
|||||||
} else {
|
} else {
|
||||||
mMaxZoomScale = restoreState.mMaxScale;
|
mMaxZoomScale = restoreState.mMaxScale;
|
||||||
}
|
}
|
||||||
setNewZoomScale(mLastScale, false);
|
if (mInitialScaleInPercent > 0) {
|
||||||
|
setNewZoomScale(mInitialScaleInPercent / 100.0f,
|
||||||
|
true, false);
|
||||||
|
} else if (restoreState.mViewScale > 0) {
|
||||||
|
mTextWrapScale = restoreState.mTextWrapScale;
|
||||||
|
setNewZoomScale(restoreState.mViewScale, false,
|
||||||
|
false);
|
||||||
|
} else {
|
||||||
|
mInZoomOverview = useWideViewport
|
||||||
|
&& settings.getLoadWithOverviewMode();
|
||||||
|
if (mInZoomOverview) {
|
||||||
|
setNewZoomScale((float) viewWidth
|
||||||
|
/ WebViewCore.DEFAULT_VIEWPORT_WIDTH,
|
||||||
|
true, false);
|
||||||
|
} else {
|
||||||
|
setNewZoomScale(restoreState.mTextWrapScale,
|
||||||
|
true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
setContentScrollTo(restoreState.mScrollX,
|
setContentScrollTo(restoreState.mScrollX,
|
||||||
restoreState.mScrollY);
|
restoreState.mScrollY);
|
||||||
if (useWideViewport
|
|
||||||
&& settings.getLoadWithOverviewMode()) {
|
|
||||||
if (restoreState.mViewScale == 0
|
|
||||||
|| (restoreState.mMobileSite
|
|
||||||
&& mMinZoomScale < restoreState.mDefaultScale)) {
|
|
||||||
mInZoomOverview = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// As we are on a new page, remove the WebTextView. This
|
// As we are on a new page, remove the WebTextView. This
|
||||||
// is necessary for page loads driven by webkit, and in
|
// is necessary for page loads driven by webkit, and in
|
||||||
// particular when the user was on a password field, so
|
// particular when the user was on a password field, so
|
||||||
@@ -5050,7 +5205,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
if (Math.abs((viewWidth * mInvActualScale)
|
if (Math.abs((viewWidth * mInvActualScale)
|
||||||
- mZoomOverviewWidth) > 1) {
|
- mZoomOverviewWidth) > 1) {
|
||||||
setNewZoomScale((float) viewWidth
|
setNewZoomScale((float) viewWidth
|
||||||
/ mZoomOverviewWidth, false);
|
/ mZoomOverviewWidth, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -5182,6 +5337,43 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SHOW_RECT_MSG_ID:
|
||||||
|
WebViewCore.ShowRectData data = (WebViewCore.ShowRectData) msg.obj;
|
||||||
|
int x = mScrollX;
|
||||||
|
int left = contentToViewDimension(data.mLeft);
|
||||||
|
int width = contentToViewDimension(data.mWidth);
|
||||||
|
int maxWidth = contentToViewDimension(data.mContentWidth);
|
||||||
|
int viewWidth = getViewWidth();
|
||||||
|
if (width < viewWidth) {
|
||||||
|
// center align
|
||||||
|
x += left + width / 2 - mScrollX - viewWidth / 2;
|
||||||
|
} else {
|
||||||
|
x += (int) (left + data.mXPercentInDoc * width
|
||||||
|
- mScrollX - data.mXPercentInView * viewWidth);
|
||||||
|
}
|
||||||
|
// use the passing content width to cap x as the current
|
||||||
|
// mContentWidth may not be updated yet
|
||||||
|
x = Math.max(0,
|
||||||
|
(Math.min(maxWidth, x + viewWidth)) - viewWidth);
|
||||||
|
int y = mScrollY;
|
||||||
|
int top = contentToViewDimension(data.mTop);
|
||||||
|
int height = contentToViewDimension(data.mHeight);
|
||||||
|
int maxHeight = contentToViewDimension(data.mContentHeight);
|
||||||
|
int viewHeight = getViewHeight();
|
||||||
|
if (height < viewHeight) {
|
||||||
|
// middle align
|
||||||
|
y += top + height / 2 - mScrollY - viewHeight / 2;
|
||||||
|
} else {
|
||||||
|
y += (int) (top + data.mYPercentInDoc * height
|
||||||
|
- mScrollY - data.mYPercentInView * viewHeight);
|
||||||
|
}
|
||||||
|
// use the passing content height to cap y as the current
|
||||||
|
// mContentHeight may not be updated yet
|
||||||
|
y = Math.max(0,
|
||||||
|
(Math.min(maxHeight, y + viewHeight) - viewHeight));
|
||||||
|
scrollTo(x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
super.handleMessage(msg);
|
super.handleMessage(msg);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -447,8 +447,8 @@ final class WebViewCore {
|
|||||||
should this be called nativeSetViewPortSize?
|
should this be called nativeSetViewPortSize?
|
||||||
*/
|
*/
|
||||||
private native void nativeSetSize(int width, int height, int screenWidth,
|
private native void nativeSetSize(int width, int height, int screenWidth,
|
||||||
float scale, int realScreenWidth, int screenHeight,
|
float scale, int realScreenWidth, int screenHeight, int anchorX,
|
||||||
boolean ignoreHeight);
|
int anchorY, boolean ignoreHeight);
|
||||||
|
|
||||||
private native int nativeGetContentMinPrefWidth();
|
private native int nativeGetContentMinPrefWidth();
|
||||||
|
|
||||||
@@ -961,6 +961,7 @@ final class WebViewCore {
|
|||||||
(WebView.ViewSizeData) msg.obj;
|
(WebView.ViewSizeData) msg.obj;
|
||||||
viewSizeChanged(data.mWidth, data.mHeight,
|
viewSizeChanged(data.mWidth, data.mHeight,
|
||||||
data.mTextWrapWidth, data.mScale,
|
data.mTextWrapWidth, data.mScale,
|
||||||
|
data.mAnchorX, data.mAnchorY,
|
||||||
data.mIgnoreHeight);
|
data.mIgnoreHeight);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1483,7 +1484,7 @@ final class WebViewCore {
|
|||||||
|
|
||||||
// notify webkit that our virtual view size changed size (after inv-zoom)
|
// notify webkit that our virtual view size changed size (after inv-zoom)
|
||||||
private void viewSizeChanged(int w, int h, int textwrapWidth, float scale,
|
private void viewSizeChanged(int w, int h, int textwrapWidth, float scale,
|
||||||
boolean ignoreHeight) {
|
int anchorX, int anchorY, boolean ignoreHeight) {
|
||||||
if (DebugFlags.WEB_VIEW_CORE) {
|
if (DebugFlags.WEB_VIEW_CORE) {
|
||||||
Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h
|
Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h
|
||||||
+ "; textwrapWidth=" + textwrapWidth + "; scale=" + scale);
|
+ "; textwrapWidth=" + textwrapWidth + "; scale=" + scale);
|
||||||
@@ -1514,12 +1515,14 @@ final class WebViewCore {
|
|||||||
width = Math.max(w, Math.max(DEFAULT_VIEWPORT_WIDTH,
|
width = Math.max(w, Math.max(DEFAULT_VIEWPORT_WIDTH,
|
||||||
nativeGetContentMinPrefWidth()));
|
nativeGetContentMinPrefWidth()));
|
||||||
}
|
}
|
||||||
} else {
|
} else if (mViewportWidth > 0) {
|
||||||
width = Math.max(w, mViewportWidth);
|
width = Math.max(w, mViewportWidth);
|
||||||
|
} else {
|
||||||
|
width = Math.max(w, nativeGetContentMinPrefWidth());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
|
nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
|
||||||
textwrapWidth, scale, w, h, ignoreHeight);
|
textwrapWidth, scale, w, h, anchorX, anchorY, ignoreHeight);
|
||||||
// Remember the current width and height
|
// Remember the current width and height
|
||||||
boolean needInvalidate = (mCurrentViewWidth == 0);
|
boolean needInvalidate = (mCurrentViewWidth == 0);
|
||||||
mCurrentViewWidth = w;
|
mCurrentViewWidth = w;
|
||||||
@@ -1953,14 +1956,12 @@ final class WebViewCore {
|
|||||||
mRestoreState.mScrollY = mRestoredY;
|
mRestoreState.mScrollY = mRestoredY;
|
||||||
mRestoreState.mMobileSite = (0 == mViewportWidth);
|
mRestoreState.mMobileSite = (0 == mViewportWidth);
|
||||||
if (mRestoredScale > 0) {
|
if (mRestoredScale > 0) {
|
||||||
|
mRestoreState.mViewScale = mRestoredScale / 100.0f;
|
||||||
if (mRestoredScreenWidthScale > 0) {
|
if (mRestoredScreenWidthScale > 0) {
|
||||||
mRestoreState.mTextWrapScale =
|
mRestoreState.mTextWrapScale =
|
||||||
mRestoredScreenWidthScale / 100.0f;
|
mRestoredScreenWidthScale / 100.0f;
|
||||||
// 0 will trigger WebView to turn on zoom overview mode
|
|
||||||
mRestoreState.mViewScale = 0;
|
|
||||||
} else {
|
} else {
|
||||||
mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
|
mRestoreState.mTextWrapScale = mRestoreState.mViewScale;
|
||||||
mRestoredScale / 100.0f;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mViewportInitialScale > 0) {
|
if (mViewportInitialScale > 0) {
|
||||||
@@ -1993,6 +1994,7 @@ final class WebViewCore {
|
|||||||
data.mTextWrapWidth = data.mWidth;
|
data.mTextWrapWidth = data.mWidth;
|
||||||
data.mScale = -1.0f;
|
data.mScale = -1.0f;
|
||||||
data.mIgnoreHeight = false;
|
data.mIgnoreHeight = false;
|
||||||
|
data.mAnchorX = data.mAnchorY = 0;
|
||||||
// send VIEW_SIZE_CHANGED to the front of the queue so that we can
|
// send VIEW_SIZE_CHANGED to the front of the queue so that we can
|
||||||
// avoid pushing the wrong picture to the WebView side. If there is
|
// avoid pushing the wrong picture to the WebView side. If there is
|
||||||
// a VIEW_SIZE_CHANGED in the queue, probably from WebView side,
|
// a VIEW_SIZE_CHANGED in the queue, probably from WebView side,
|
||||||
@@ -2021,6 +2023,7 @@ final class WebViewCore {
|
|||||||
data.mTextWrapWidth = Math.round(webViewWidth
|
data.mTextWrapWidth = Math.round(webViewWidth
|
||||||
/ mRestoreState.mTextWrapScale);
|
/ mRestoreState.mTextWrapScale);
|
||||||
data.mIgnoreHeight = false;
|
data.mIgnoreHeight = false;
|
||||||
|
data.mAnchorX = data.mAnchorY = 0;
|
||||||
// send VIEW_SIZE_CHANGED to the front of the queue so that we
|
// send VIEW_SIZE_CHANGED to the front of the queue so that we
|
||||||
// can avoid pushing the wrong picture to the WebView side.
|
// can avoid pushing the wrong picture to the WebView side.
|
||||||
mEventHub.removeMessages(EventHub.VIEW_SIZE_CHANGED);
|
mEventHub.removeMessages(EventHub.VIEW_SIZE_CHANGED);
|
||||||
@@ -2177,6 +2180,40 @@ final class WebViewCore {
|
|||||||
childView.removeView();
|
childView.removeView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called by JNI
|
||||||
|
static class ShowRectData {
|
||||||
|
int mLeft;
|
||||||
|
int mTop;
|
||||||
|
int mWidth;
|
||||||
|
int mHeight;
|
||||||
|
int mContentWidth;
|
||||||
|
int mContentHeight;
|
||||||
|
float mXPercentInDoc;
|
||||||
|
float mXPercentInView;
|
||||||
|
float mYPercentInDoc;
|
||||||
|
float mYPercentInView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showRect(int left, int top, int width, int height,
|
||||||
|
int contentWidth, int contentHeight, float xPercentInDoc,
|
||||||
|
float xPercentInView, float yPercentInDoc, float yPercentInView) {
|
||||||
|
if (mWebView != null) {
|
||||||
|
ShowRectData data = new ShowRectData();
|
||||||
|
data.mLeft = left;
|
||||||
|
data.mTop = top;
|
||||||
|
data.mWidth = width;
|
||||||
|
data.mHeight = height;
|
||||||
|
data.mContentWidth = contentWidth;
|
||||||
|
data.mContentHeight = contentHeight;
|
||||||
|
data.mXPercentInDoc = xPercentInDoc;
|
||||||
|
data.mXPercentInView = xPercentInView;
|
||||||
|
data.mYPercentInDoc = yPercentInDoc;
|
||||||
|
data.mYPercentInView = yPercentInView;
|
||||||
|
Message.obtain(mWebView.mPrivateHandler, WebView.SHOW_RECT_MSG_ID,
|
||||||
|
data).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private native void nativePause();
|
private native void nativePause();
|
||||||
private native void nativeResume();
|
private native void nativeResume();
|
||||||
private native void nativeFreeMemory();
|
private native void nativeFreeMemory();
|
||||||
|
|||||||
Reference in New Issue
Block a user