| Index: android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
|
| 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 d5ff1085f25c6f11de2018988a91f85e905880f7..7a48bfe2b1ef51cb8277800564a227c94b5a65fd 100644
|
| --- a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
|
| +++ b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
|
| @@ -19,37 +19,116 @@ public class AwLayoutSizer {
|
| private boolean mWidthMeasurementIsFixed;
|
| private boolean mHeightMeasurementIsFixed;
|
|
|
| - // Size of the rendered content, as reported by native, in physical pixels.
|
| - private int mContentHeight;
|
| - private int mContentWidth;
|
| + // Size of the rendered content, as reported by native.
|
| + private int mContentHeightCss;
|
| + private int mContentWidthCss;
|
| +
|
| + // 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;
|
| +
|
| + // Whether to postpone layout requests.
|
| + private boolean mFreezeLayoutRequests;
|
| + // Did we try to request a layout since the last time mPostponeLayoutRequests was set to true.
|
| + private boolean mFrozenLayoutRequestPending;
|
| +
|
| + private double mDIPScale;
|
|
|
| // Callback object for interacting with the View.
|
| - Delegate mDelegate;
|
| + private Delegate mDelegate;
|
|
|
| public interface Delegate {
|
| void requestLayout();
|
| void setMeasuredDimension(int measuredWidth, int measuredHeight);
|
| }
|
|
|
| - public AwLayoutSizer(Delegate delegate) {
|
| + /**
|
| + * Default constructor. Note: both setDelegate and setDIPScale must be called before the class
|
| + * is ready for use.
|
| + */
|
| + public AwLayoutSizer() {
|
| + }
|
| +
|
| + public void setDelegate(Delegate delegate) {
|
| mDelegate = delegate;
|
| }
|
|
|
| + public void setDIPScale(double dipScale) {
|
| + mDIPScale = dipScale;
|
| + }
|
| +
|
| + /**
|
| + * This is used to register the AwLayoutSizer to preferred content size change notifications in
|
| + * the AwWebContentsDelegate.
|
| + */
|
| + public AwWebContentsDelegateAdapter.PreferredSizeChangedListener
|
| + getPreferredSizeChangedListener() {
|
| + return new AwWebContentsDelegateAdapter.PreferredSizeChangedListener() {
|
| + @Override
|
| + public void updatePreferredSize(int widthCss, int heightCss) {
|
| + onContentSizeChanged(widthCss, heightCss);
|
| + }
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Postpone requesting layouts till unfreezeLayoutRequests is called.
|
| + */
|
| + public void freezeLayoutRequests() {
|
| + mFreezeLayoutRequests = true;
|
| + mFrozenLayoutRequestPending = false;
|
| + }
|
| +
|
| + /**
|
| + * Stop postponing layout requests and request layout if such a request would have been made
|
| + * had the freezeLayoutRequests method not been called before.
|
| + */
|
| + public void unfreezeLayoutRequests() {
|
| + mFreezeLayoutRequests = false;
|
| + if (mFrozenLayoutRequestPending) {
|
| + mFrozenLayoutRequestPending = false;
|
| + mDelegate.requestLayout();
|
| + }
|
| + }
|
| +
|
| /**
|
| * Update the contents size.
|
| * This should be called whenever the content size changes (due to DOM manipulation or page
|
| * load, for example).
|
| - * The width and height should be in physical pixels.
|
| + * The width and height should be in CSS pixels.
|
| */
|
| - public void onContentSizeChanged(int width, int height) {
|
| - boolean layoutNeeded = (mContentWidth != width && !mWidthMeasurementIsFixed) ||
|
| - (mContentHeight != height && !mHeightMeasurementIsFixed);
|
| + public void onContentSizeChanged(int widthCss, int heightCss) {
|
| + doUpdate(widthCss, heightCss, mPageScaleFactor);
|
| + }
|
|
|
| - mContentWidth = width;
|
| - mContentHeight = height;
|
| + /**
|
| + * Update the contents page scale.
|
| + * This should be called whenever the content page scale factor changes (due to pinch zoom, for
|
| + * example).
|
| + */
|
| + public void onPageScaleChanged(double pageScaleFactor) {
|
| + doUpdate(mContentWidthCss, mContentHeightCss, pageScaleFactor);
|
| + }
|
| +
|
| + private void doUpdate(int widthCss, int heightCss, double pageScaleFactor) {
|
| + // 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'.
|
| + boolean anyMeasurementNotFixed = !mWidthMeasurementIsFixed || !mHeightMeasurementIsFixed;
|
| + boolean layoutNeeded = (mContentWidthCss != widthCss && !mWidthMeasurementIsFixed) ||
|
| + (mContentHeightCss != heightCss && !mHeightMeasurementIsFixed) ||
|
| + (mPageScaleFactor != pageScaleFactor && anyMeasurementNotFixed);
|
| +
|
| + mContentWidthCss = widthCss;
|
| + mContentHeightCss = heightCss;
|
| + mPageScaleFactor = pageScaleFactor;
|
|
|
| if (layoutNeeded) {
|
| - mDelegate.requestLayout();
|
| + if (mFreezeLayoutRequests) {
|
| + mFrozenLayoutRequestPending = true;
|
| + } else {
|
| + mDelegate.requestLayout();
|
| + }
|
| }
|
| }
|
|
|
| @@ -66,6 +145,9 @@ public class AwLayoutSizer {
|
| int measuredHeight = heightSize;
|
| int measuredWidth = widthSize;
|
|
|
| + int contentHeightPix = (int) (mContentHeightCss * mPageScaleFactor * mDIPScale);
|
| + int contentWidthPix = (int) (mContentWidthCss * mPageScaleFactor * mDIPScale);
|
| +
|
| // 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
|
| @@ -73,21 +155,21 @@ public class AwLayoutSizer {
|
| // 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 && mContentHeight > heightSize);
|
| + (heightMode == MeasureSpec.AT_MOST && contentHeightPix > heightSize);
|
|
|
| if (!mHeightMeasurementIsFixed) {
|
| - measuredHeight = mContentHeight;
|
| + measuredHeight = contentHeightPix;
|
| }
|
|
|
| if (!mWidthMeasurementIsFixed) {
|
| - measuredWidth = mContentWidth;
|
| + measuredWidth = contentWidthPix;
|
| }
|
|
|
| - if (measuredHeight < mContentHeight) {
|
| + if (measuredHeight < contentHeightPix) {
|
| measuredHeight |= View.MEASURED_STATE_TOO_SMALL;
|
| }
|
|
|
| - if (measuredWidth < mContentWidth) {
|
| + if (measuredWidth < contentWidthPix) {
|
| measuredWidth |= View.MEASURED_STATE_TOO_SMALL;
|
| }
|
|
|
|
|