diff options
author | mkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-16 19:56:45 +0000 |
---|---|---|
committer | mkosiba@chromium.org <mkosiba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-16 19:56:45 +0000 |
commit | afb59f5fd23a2392761e8be2e4a23bcc63b4a1fd (patch) | |
tree | 86be51026d615480678bb75b9f1e894e7b845d63 /android_webview/java | |
parent | 4b6bff3ea78537b5e8cd3811bf6c131a506fc7ea (diff) | |
download | chromium_src-afb59f5fd23a2392761e8be2e4a23bcc63b4a1fd.zip chromium_src-afb59f5fd23a2392761e8be2e4a23bcc63b4a1fd.tar.gz chromium_src-afb59f5fd23a2392761e8be2e4a23bcc63b4a1fd.tar.bz2 |
[android_webview] Fixes for wrap_content layouts.
This changes AwContents to work correctly when in a WRAP_CONTENT
layout mode.
TBR=danakj@chromium.org
BUG=246621
Review URL: https://chromiumcodereview.appspot.com/23478022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223386 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview/java')
-rw-r--r-- | android_webview/java/src/org/chromium/android_webview/AwContents.java | 7 | ||||
-rw-r--r-- | android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java | 76 |
2 files changed, 68 insertions, 15 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 2d7c101..700b9c1 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -344,6 +344,11 @@ public class AwContents { public void setMeasuredDimension(int measuredWidth, int measuredHeight) { mInternalAccessAdapter.setMeasuredDimension(measuredWidth, measuredHeight); } + + @Override + public void setFixedLayoutSize(int widthDip, int heightDip) { + nativeSetFixedLayoutSize(mNativeAwContents, widthDip, heightDip); + } } //-------------------------------------------------------------------------------------------- @@ -1514,6 +1519,7 @@ public class AwContents { mScrollOffsetManager.setContainerViewSize(w, h); mContentViewCore.onPhysicalBackingSizeChanged(w, h); mContentViewCore.onSizeChanged(w, h, ow, oh); + mLayoutSizer.onSizeChanged(w, h, ow, oh); nativeOnSizeChanged(mNativeAwContents, w, h, ow, oh); } @@ -1907,6 +1913,7 @@ public class AwContents { private native void nativeSetDipScale(int nativeAwContents, float dipScale); private native void nativeSetDisplayedPageScaleFactor(int nativeAwContents, float pageScaleFactor); + private native void nativeSetFixedLayoutSize(int nativeAwContents, int widthDip, int heightDip); // Returns null if save state fails. private native byte[] nativeGetOpaqueState(int nativeAwContents); diff --git a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java index e09259b..bee46a1 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java +++ b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java @@ -14,6 +14,8 @@ import org.chromium.content.browser.ContentViewCore; * Helper methods used to manage the layout of the View that contains AwContents. */ public class AwLayoutSizer { + public static final int FIXED_LAYOUT_HEIGHT = 0; + // These are used to prevent a re-layout if the content size changes within a dimension that is // fixed by the view system. private boolean mWidthMeasurementIsFixed; @@ -26,6 +28,8 @@ public class AwLayoutSizer { // Page scale factor. This is set to zero initially so that we don't attempt to do a layout if // we get the content size change notification first and a page scale change second. private double mPageScaleFactor = 0.0; + // The page scale factor that was used in the most recent onMeasure call. + private double mLastMeasuredPageScaleFactor = 0.0; // Whether to postpone layout requests. private boolean mFreezeLayoutRequests; @@ -34,12 +38,18 @@ public class AwLayoutSizer { private double mDIPScale; + // Was our heightSpec set to AT_MOST the last time onMeasure was called? + private boolean mHeightMeasurementLimited; + // If mHeightMeasurementLimited is true then this contains the height limit. + private int mHeightMeasurementLimit; + // Callback object for interacting with the View. private Delegate mDelegate; public interface Delegate { void requestLayout(); void setMeasuredDimension(int measuredWidth, int measuredHeight); + void setFixedLayoutSize(int widthDip, int heightDip); } /** @@ -116,9 +126,12 @@ public class AwLayoutSizer { // We want to request layout only if the size or scale change, however if any of the // measurements are 'fixed', then changing the underlying size won't have any effect, so we // ignore changes to dimensions that are 'fixed'. + final int heightPix = (int) (heightCss * mPageScaleFactor * mDIPScale); boolean anyMeasurementNotFixed = !mWidthMeasurementIsFixed || !mHeightMeasurementIsFixed; + boolean contentHeightChangeMeaningful = !mHeightMeasurementIsFixed && + (!mHeightMeasurementLimited || heightPix < mHeightMeasurementLimit); boolean layoutNeeded = (mContentWidthCss != widthCss && !mWidthMeasurementIsFixed) || - (mContentHeightCss != heightCss && !mHeightMeasurementIsFixed) || + (mContentHeightCss != heightCss && contentHeightChangeMeaningful) || (mPageScaleFactor != pageScaleFactor && anyMeasurementNotFixed); mContentWidthCss = widthCss; @@ -144,27 +157,28 @@ public class AwLayoutSizer { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int measuredHeight = heightSize; - int measuredWidth = widthSize; - int contentHeightPix = (int) (mContentHeightCss * mPageScaleFactor * mDIPScale); int contentWidthPix = (int) (mContentWidthCss * mPageScaleFactor * mDIPScale); + int measuredHeight = contentHeightPix; + int measuredWidth = contentWidthPix; + + mLastMeasuredPageScaleFactor = mPageScaleFactor; + // Always use the given size unless unspecified. This matches WebViewClassic behavior. mWidthMeasurementIsFixed = (widthMode != MeasureSpec.UNSPECIFIED); - // Freeze the height if an exact size is given by the parent or if the content size has - // exceeded the maximum size specified by the parent. - // TODO(mkosiba): Actually we'd like the reduction in content size to cause the WebView to - // shrink back again but only as a result of a page load. - mHeightMeasurementIsFixed = (heightMode == MeasureSpec.EXACTLY) || - (heightMode == MeasureSpec.AT_MOST && contentHeightPix > heightSize); - - if (!mHeightMeasurementIsFixed) { - measuredHeight = contentHeightPix; + mHeightMeasurementIsFixed = (heightMode == MeasureSpec.EXACTLY); + mHeightMeasurementLimited = (heightMode == MeasureSpec.AT_MOST); + mHeightMeasurementLimit = heightSize; + + final boolean measuredHeightClipped = + mHeightMeasurementLimited && (contentHeightPix > heightSize); + if (mHeightMeasurementIsFixed || measuredHeightClipped) { + measuredHeight = heightSize; } - if (!mWidthMeasurementIsFixed) { - measuredWidth = contentWidthPix; + if (mWidthMeasurementIsFixed) { + measuredWidth = widthSize; } if (measuredHeight < contentHeightPix) { @@ -177,4 +191,36 @@ public class AwLayoutSizer { mDelegate.setMeasuredDimension(measuredWidth, measuredHeight); } + + public void onSizeChanged(int w, int h, int ow, int oh) { + // If the WebView's measuredDimension depends on the size of its contents (which is the + // case if any of the measurement modes are AT_MOST or UNSPECIFIED) the viewport size + // cannot be directly calculated from the size as that can result in the layout being + // unstable or unpredictable. + // If both the width and height are fixed (specified by the parent) then content size + // changes will not cause subsequent layout passes and so we don't need to do anything + // special. + if ((mWidthMeasurementIsFixed && mHeightMeasurementIsFixed) || + mLastMeasuredPageScaleFactor == 0) { + mDelegate.setFixedLayoutSize(0, 0); + return; + } + + final double dipAndPageScale = mLastMeasuredPageScaleFactor * mDIPScale; + final int contentWidthPix = (int) (mContentWidthCss * dipAndPageScale); + + int widthDip = (int) Math.ceil(w / dipAndPageScale); + + // Make sure that we don't introduce rounding errors if the viewport is to be exactly as + // wide as the contents. + if (w == contentWidthPix) { + widthDip = mContentWidthCss; + } + + // This is workaround due to the fact that in wrap content mode we need to use a fixed + // layout size independent of view height, otherwise things like <div style="height:120%"> + // cause the webview to grow indefinitely. We need to use a height independent of the + // webview's height. 0 is the value used in WebViewClassic. + mDelegate.setFixedLayoutSize(widthDip, FIXED_LAYOUT_HEIGHT); + } } |