diff options
author | Grace Kloba <klobag@google.com> | 2009-07-30 11:20:32 -0700 |
---|---|---|
committer | Grace Kloba <klobag@google.com> | 2009-07-30 11:20:32 -0700 |
commit | ef347ef9107a8ca6ab85029528e2c1518440b2c3 (patch) | |
tree | fd7c7cf5de4ec24e72ef6049dd0cc4ea6b7f8a43 /core | |
parent | 6502a380adea84e4998281d9255c3450fb9c10d6 (diff) | |
download | frameworks_base-ef347ef9107a8ca6ab85029528e2c1518440b2c3.zip frameworks_base-ef347ef9107a8ca6ab85029528e2c1518440b2c3.tar.gz frameworks_base-ef347ef9107a8ca6ab85029528e2c1518440b2c3.tar.bz2 |
Fix 2016808. We used to send the new scale/scroll info to the UI thread after
WebCore finish the first layout. As the picture in the UI thread is still
the previous one, if there is a UI update happened before we generate the new
picture, the new scale/scroll will be applied to the old picture.
On the other hand, we do want to trigger the resize for the new page after
the first layout. e.g. The page was at nytimes.com. Now user types google.com.
google.com is first layout in the wide viewport where nytimes.com is. We dont
want to show that picture. We would like to show the fit to screen version of
google.com as the first picture.
Remove the SnapToAnchor code which is left over from previous zoom attempt.
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/webkit/WebView.java | 143 | ||||
-rw-r--r-- | core/java/android/webkit/WebViewCore.java | 193 |
2 files changed, 160 insertions, 176 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 358fc9e..05a7806 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -206,11 +206,6 @@ public class WebView extends AbsoluteLayout static final String LOGTAG = "webview"; - static class ScaleLimitData { - int mMinScale; - int mMaxScale; - } - private static class ExtendedZoomControls extends FrameLayout { public ExtendedZoomControls(Context context, AttributeSet attrs) { super(context, attrs); @@ -472,7 +467,6 @@ public class WebView extends AbsoluteLayout static final int UPDATE_TEXT_ENTRY_MSG_ID = 15; static final int WEBCORE_INITIALIZED_MSG_ID = 16; static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17; - static final int DID_FIRST_LAYOUT_MSG_ID = 18; static final int MOVE_OUT_OF_PLUGIN = 19; static final int CLEAR_TEXT_ENTRY = 20; @@ -502,7 +496,7 @@ public class WebView extends AbsoluteLayout "UPDATE_TEXT_ENTRY_MSG_ID", // = 15; "WEBCORE_INITIALIZED_MSG_ID", // = 16; "UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17; - "DID_FIRST_LAYOUT_MSG_ID", // = 18; + "18", // = 18; "MOVE_OUT_OF_PLUGIN", // = 19; "CLEAR_TEXT_ENTRY", // = 20; "21", // = 21; @@ -1892,6 +1886,13 @@ public class WebView extends AbsoluteLayout r.bottom = viewToContent(r.bottom); } + static class ViewSizeData { + int mWidth; + int mHeight; + int mTextWrapWidth; + float mScale; + } + /** * Compute unzoomed width and height, and if they differ from the last * values we sent, send them to webkit (to be used has new viewport) @@ -1899,7 +1900,8 @@ public class WebView extends AbsoluteLayout * @return true if new values were sent */ private boolean sendViewSizeZoom() { - int newWidth = Math.round(getViewWidth() * mInvActualScale); + int viewWidth = getViewWidth(); + int newWidth = Math.round(viewWidth * mInvActualScale); int newHeight = Math.round(getViewHeight() * mInvActualScale); /* * Because the native side may have already done a layout before the @@ -1914,8 +1916,16 @@ public class WebView extends AbsoluteLayout } // Avoid sending another message if the dimensions have not changed. if (newWidth != mLastWidthSent || newHeight != mLastHeightSent) { - mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, - newWidth, newHeight, new Float(mActualScale)); + ViewSizeData data = new ViewSizeData(); + data.mWidth = newWidth; + data.mHeight = newHeight; + // while in zoom overview mode, the text are wrapped to the screen + // 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; + mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data); mLastWidthSent = newWidth; mLastHeightSent = newHeight; return true; @@ -3877,11 +3887,6 @@ public class WebView extends AbsoluteLayout if (!mDragFromTextInput) { nativeHideCursor(); } - // remove the zoom anchor if there is any - if (mZoomScale != 0) { - mWebViewCore - .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0); - } WebSettings settings = getSettings(); if (settings.supportZoom() && !mInZoomOverview && settings.getBuiltInZoomControls() @@ -4982,15 +4987,35 @@ public class WebView extends AbsoluteLayout final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj; final Point viewSize = draw.mViewPoint; - if (mZoomScale > 0) { - // use the same logic in sendViewSizeZoom() to make sure - // the mZoomScale has matched the viewSize so that we - // can clear mZoomScale - if (Math.round(viewWidth / mZoomScale) == viewSize.x) { - mZoomScale = 0; - mWebViewCore.sendMessage(EventHub.SET_SNAP_ANCHOR, - 0, 0); + boolean useWideViewport = + mWebViewCore.getSettings().getUseWideViewPort(); + WebViewCore.RestoreState restoreState = draw.mRestoreState; + if (restoreState != null) { + mInZoomOverview = false; + mLastScale = restoreState.mTextWrapScale; + if (restoreState.mMinScale == 0) { + mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE; + mMinZoomScaleFixed = false; + } else { + mMinZoomScale = restoreState.mMinScale; + mMinZoomScaleFixed = true; + } + if (restoreState.mMaxScale == 0) { + mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE; + } else { + mMaxZoomScale = restoreState.mMaxScale; + } + if (useWideViewport && restoreState.mViewScale == 0) { + mInZoomOverview = ENABLE_DOUBLETAP_ZOOM; } + setNewZoomScale(mLastScale, false); + setContentScrollTo(restoreState.mScrollX, + restoreState.mScrollY); + // As we are on a new page, remove the WebTextView. This + // is necessary for page loads driven by webkit, and in + // particular when the user was on a password field, so + // the WebTextView was visible. + clearTextEntry(); } // We update the layout (i.e. request a layout from the // view system) if the last view size that we sent to @@ -5009,7 +5034,7 @@ public class WebView extends AbsoluteLayout if (mPictureListener != null) { mPictureListener.onNewPicture(WebView.this, capturePicture()); } - if (mWebViewCore.getSettings().getUseWideViewPort()) { + if (useWideViewport) { mZoomOverviewWidth = Math.max(draw.mMinPrefWidth, draw.mViewPoint.x); } @@ -5056,76 +5081,6 @@ public class WebView extends AbsoluteLayout } } break; - case DID_FIRST_LAYOUT_MSG_ID: { - if (mNativeClass == 0) { - break; - } - ScaleLimitData scaleLimit = (ScaleLimitData) msg.obj; - int minScale = scaleLimit.mMinScale; - if (minScale == 0) { - mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE; - mMinZoomScaleFixed = false; - } else { - mMinZoomScale = (float) (minScale / 100.0); - mMinZoomScaleFixed = true; - } - int maxScale = scaleLimit.mMaxScale; - if (maxScale == 0) { - mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE; - } else { - mMaxZoomScale = (float) (maxScale / 100.0); - } - // If history Picture is drawn, don't update zoomWidth - if (mDrawHistory) { - break; - } - int width = getViewWidth(); - 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 == -1) break; - if (settings.getUseWideViewPort()) { - // force viewSizeChanged by setting mLastWidthSent - // to 0 - mLastWidthSent = 0; - } - if (initialScale == 0) { - // if viewportWidth is defined and it is smaller - // 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 - // particular when the user was on a password field, so - // the WebTextView was visible. - clearTextEntry(); - break; - } case MOVE_OUT_OF_PLUGIN: if (nativePluginEatsNavKey()) { navHandledKey(msg.arg1, 1, false, 0, true); diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 4afc4cd..8ec8174 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -443,10 +443,6 @@ final class WebViewCore { 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); @@ -674,7 +670,7 @@ final class WebViewCore { "CLICK", // = 118; "SET_NETWORK_STATE", // = 119; "DOC_HAS_IMAGES", // = 120; - "SET_SNAP_ANCHOR", // = 121; + "121", // = 121; "DELETE_SELECTION", // = 122; "LISTBOX_CHOICES", // = 123; "SINGLE_LISTBOX_CHOICE", // = 124; @@ -725,7 +721,6 @@ final class WebViewCore { static final int CLICK = 118; static final int SET_NETWORK_STATE = 119; static final int DOC_HAS_IMAGES = 120; - static final int SET_SNAP_ANCHOR = 121; static final int DELETE_SELECTION = 122; static final int LISTBOX_CHOICES = 123; static final int SINGLE_LISTBOX_CHOICE = 124; @@ -904,11 +899,13 @@ final class WebViewCore { nativeClick(msg.arg1, msg.arg2); break; - case VIEW_SIZE_CHANGED: - viewSizeChanged(msg.arg1, msg.arg2, - ((Float) msg.obj).floatValue()); + case VIEW_SIZE_CHANGED: { + WebView.ViewSizeData data = + (WebView.ViewSizeData) msg.obj; + viewSizeChanged(data.mWidth, data.mHeight, + data.mTextWrapWidth, data.mScale); break; - + } case SET_SCROLL_OFFSET: // note: these are in document coordinates // (inv-zoom) @@ -1107,10 +1104,6 @@ final class WebViewCore { imageResult.sendToTarget(); break; - case SET_SNAP_ANCHOR: - nativeSetSnapAnchor(msg.arg1, msg.arg2); - break; - case DELETE_SELECTION: DeleteSelectionData deleteSelectionData = (DeleteSelectionData) msg.obj; @@ -1401,16 +1394,20 @@ final class WebViewCore { // These values are used to avoid requesting a layout based on old values private int mCurrentViewWidth = 0; private int mCurrentViewHeight = 0; + private float mCurrentViewScale = 1.0f; // notify webkit that our virtual view size changed size (after inv-zoom) - private void viewSizeChanged(int w, int h, float scale) { - if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "CORE onSizeChanged"); + private void viewSizeChanged(int w, int h, int textwrapWidth, float scale) { + if (DebugFlags.WEB_VIEW_CORE) { + Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h + + "; textwrapWidth=" + textwrapWidth + "; scale=" + scale); + } if (w == 0) { Log.w(LOGTAG, "skip viewSizeChanged as w is 0"); return; } + int width = w; if (mSettings.getUseWideViewPort()) { - int width; if (mViewportWidth == -1) { if (mSettings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NORMAL) { @@ -1433,19 +1430,14 @@ final class WebViewCore { } else { width = Math.max(w, mViewportWidth); } - // 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); } + nativeSetSize(width, width == w ? h : Math.round((float) width * h / w), + textwrapWidth, scale, w, h); // Remember the current width and height boolean needInvalidate = (mCurrentViewWidth == 0); mCurrentViewWidth = w; mCurrentViewHeight = h; + mCurrentViewScale = scale; if (needInvalidate) { // ensure {@link #webkitDraw} is called as we were blocking in // {@link #contentDraw} when mCurrentViewWidth is 0 @@ -1490,15 +1482,30 @@ final class WebViewCore { // Used to end scale+scroll mode, accessed by both threads boolean mEndScaleZoom = false; - public class DrawData { - public DrawData() { + // mRestoreState is set in didFirstLayout(), and reset in the next + // webkitDraw after passing it to the UI thread. + private RestoreState mRestoreState = null; + + static class RestoreState { + float mMinScale; + float mMaxScale; + float mViewScale; + float mTextWrapScale; + int mScrollX; + int mScrollY; + } + + static class DrawData { + DrawData() { mInvalRegion = new Region(); mWidthHeight = new Point(); } - public Region mInvalRegion; - public Point mViewPoint; - public Point mWidthHeight; - public int mMinPrefWidth; + Region mInvalRegion; + Point mViewPoint; + Point mWidthHeight; + int mMinPrefWidth; + RestoreState mRestoreState; // only non-null if it is for the first + // picture set after the first layout } private void webkitDraw() { @@ -1517,6 +1524,10 @@ final class WebViewCore { if (WebView.ENABLE_DOUBLETAP_ZOOM && mSettings.getUseWideViewPort()) { draw.mMinPrefWidth = nativeGetContentMinPrefWidth(); } + if (mRestoreState != null) { + draw.mRestoreState = mRestoreState; + mRestoreState = null; + } if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID"); Message.obtain(mWebView.mPrivateHandler, WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget(); @@ -1527,9 +1538,6 @@ final class WebViewCore { mWebkitScrollY).sendToTarget(); mWebkitScrollX = mWebkitScrollY = 0; } - // nativeSnapToAnchor() needs to be called after NEW_PICTURE_MSG_ID - // is sent, so that scroll will be based on the new content size. - nativeSnapToAnchor(); } } @@ -1751,17 +1759,8 @@ final class WebViewCore { // 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 - // white space in the GMail which uses WebView for message view. - if (mWebView != null && mWebView.mHeightCanMeasure) { - mWebView.mLastHeightSent = 0; - // Send a negative scale to indicate that WebCore should reuse the - // current scale - mEventHub.sendMessage(Message.obtain(null, - EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent, - mWebView.mLastHeightSent, -1.0f)); + if (DebugFlags.WEB_VIEW_CORE) { + Log.v(LOGTAG, "didFirstLayout standardLoad =" + standardLoad); } mBrowserFrame.didFirstLayout(); @@ -1769,6 +1768,9 @@ final class WebViewCore { // reset the scroll position as it is a new page now mWebkitScrollX = mWebkitScrollY = 0; + // for non-standard load, we only adjust scale if mRestoredScale > 0 + if (mWebView == null || (mRestoredScale == 0 && !standardLoad)) return; + // set the viewport settings from WebKit setViewportSettingsFromNative(); @@ -1820,47 +1822,74 @@ final class WebViewCore { } // now notify webview - if (mWebView != null) { - WebView.ScaleLimitData scaleLimit = new WebView.ScaleLimitData(); - scaleLimit.mMinScale = mViewportMinimumScale; - scaleLimit.mMaxScale = mViewportMaximumScale; - - if (mRestoredScale > 0) { - Message.obtain(mWebView.mPrivateHandler, - WebView.DID_FIRST_LAYOUT_MSG_ID, - mRestoredScreenWidthScale > 0 ? - -mRestoredScreenWidthScale : mRestoredScale, 0, - scaleLimit).sendToTarget(); + int webViewWidth = Math.round(mCurrentViewWidth * mCurrentViewScale); + mRestoreState = new RestoreState(); + mRestoreState.mMinScale = mViewportMinimumScale / 100.0f; + mRestoreState.mMaxScale = mViewportMaximumScale / 100.0f; + mRestoreState.mScrollX = mRestoredX; + mRestoreState.mScrollY = mRestoredY; + if (mRestoredScale > 0) { + if (mRestoredScreenWidthScale > 0) { + mRestoreState.mTextWrapScale = + mRestoredScreenWidthScale / 100.0f; + // 0 will trigger WebView to turn on zoom overview mode + mRestoreState.mViewScale = 0; } else { - // if standardLoad is true, use mViewportInitialScale, otherwise - // pass -1 to the WebView to indicate no change of the scale. - Message.obtain(mWebView.mPrivateHandler, - WebView.DID_FIRST_LAYOUT_MSG_ID, - standardLoad ? mViewportInitialScale : -1, - mViewportWidth, scaleLimit).sendToTarget(); + mRestoreState.mViewScale = mRestoreState.mTextWrapScale = + mRestoredScale / 100.0f; } - - // force an early draw for quick feedback after the first layout - if (mCurrentViewWidth != 0) { - synchronized (this) { - if (mDrawIsScheduled) { - mEventHub.removeMessages(EventHub.WEBKIT_DRAW); - } - mDrawIsScheduled = true; - // if no restored offset, move the new page to (0, 0) - mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null, - EventHub.MESSAGE_RELAY, Message.obtain( - mWebView.mPrivateHandler, - WebView.SCROLL_TO_MSG_ID, mRestoredX, - mRestoredY))); - mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null, - EventHub.WEBKIT_DRAW)); - } + } else { + if (mViewportInitialScale > 0) { + mRestoreState.mViewScale = mRestoreState.mTextWrapScale = + mViewportInitialScale / 100.0f; + } else if (mViewportWidth > 0 && mViewportWidth < webViewWidth) { + mRestoreState.mViewScale = mRestoreState.mTextWrapScale = + (float) webViewWidth / mViewportWidth; + } else { + mRestoreState.mTextWrapScale = + WebView.DEFAULT_SCALE_PERCENT / 100.0f; + // 0 will trigger WebView to turn on zoom overview mode + mRestoreState.mViewScale = 0; } - - // reset restored offset, scale - mRestoredX = mRestoredY = mRestoredScale = mRestoredScreenWidthScale = 0; } + + if (mWebView.mHeightCanMeasure) { + // 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 white space in the GMail which uses WebView for + // message view. + mWebView.mLastHeightSent = 0; + // Send a negative scale to indicate that WebCore should reuse + // the current scale + WebView.ViewSizeData data = new WebView.ViewSizeData(); + data.mWidth = mWebView.mLastWidthSent; + data.mHeight = 0; + // if mHeightCanMeasure is true, getUseWideViewPort() can't be + // true. It is safe to use mWidth for mTextWrapWidth. + data.mTextWrapWidth = data.mWidth; + data.mScale = -1.0f; + mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null, + EventHub.VIEW_SIZE_CHANGED, data)); + } else if (mSettings.getUseWideViewPort() && mCurrentViewWidth > 0) { + WebView.ViewSizeData data = new WebView.ViewSizeData(); + // mViewScale as 0 means it is in zoom overview mode. So we don't + // know the exact scale. If mRestoredScale is non-zero, use it; + // otherwise just use mTextWrapScale as the initial scale. + data.mScale = mRestoreState.mViewScale == 0 + ? (mRestoredScale > 0 ? mRestoredScale + : mRestoreState.mTextWrapScale) + : mRestoreState.mViewScale; + data.mWidth = Math.round(webViewWidth / data.mScale); + data.mHeight = mCurrentViewHeight * data.mWidth + / mCurrentViewWidth; + data.mTextWrapWidth = Math.round(webViewWidth + / mRestoreState.mTextWrapScale); + mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null, + EventHub.VIEW_SIZE_CHANGED, data)); + } + // reset restored offset, scale + mRestoredX = mRestoredY = mRestoredScale = mRestoredScreenWidthScale = 0; } // called by JNI |