summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContents.java20
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java70
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java2
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java63
4 files changed, 136 insertions, 19 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 aceb024..a0e55fc 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -439,6 +439,7 @@ public class AwContents {
}
}
+ //--------------------------------------------------------------------------------------------
private class AwComponentCallbacks implements ComponentCallbacks2 {
@Override
public void onTrimMemory(int level) {
@@ -455,6 +456,16 @@ public class AwContents {
}
};
+ //--------------------------------------------------------------------------------------------
+ private class AwLayoutChangeListener implements View.OnLayoutChangeListener {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ assert v == mContainerView;
+ mLayoutSizer.onLayoutChange();
+ }
+ }
+
/**
* @param browserContext the browsing context to associate this view contents with.
* @param containerView the view-hierarchy item this object will be bound to.
@@ -509,7 +520,7 @@ public class AwContents {
mInternalAccessAdapter = internalAccessAdapter;
mContentsClient = contentsClient;
mLayoutSizer = layoutSizer;
- mDIPScale = DeviceDisplayInfo.create(containerView.getContext()).getDIPScale();
+ mDIPScale = DeviceDisplayInfo.create(mContainerView.getContext()).getDIPScale();
mLayoutSizer.setDelegate(new AwLayoutSizerDelegate());
mLayoutSizer.setDIPScale(mDIPScale);
mWebContentsDelegate = new AwWebContentsDelegateAdapter(contentsClient, mContainerView);
@@ -518,7 +529,7 @@ public class AwContents {
mIoThreadClient = new IoThreadClientImpl();
mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl();
- boolean hasInternetPermission = containerView.getContext().checkPermission(
+ boolean hasInternetPermission = mContainerView.getContext().checkPermission(
android.Manifest.permission.INTERNET,
Process.myPid(),
Process.myUid()) == PackageManager.PERMISSION_GRANTED;
@@ -541,6 +552,7 @@ public class AwContents {
setOverScrollMode(mContainerView.getOverScrollMode());
setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle());
+ mContainerView.addOnLayoutChangeListener(new AwLayoutChangeListener());
setNewAwContents(nativeInit(browserContext));
@@ -1578,9 +1590,11 @@ public class AwContents {
public void onSizeChanged(int w, int h, int ow, int oh) {
if (mNativeAwContents == 0) return;
mScrollOffsetManager.setContainerViewSize(w, h);
+ // The AwLayoutSizer needs to go first so that if we're in fixedLayoutSize mode the update
+ // to enter fixedLayoutSize mode is sent before the first resize update.
+ mLayoutSizer.onSizeChanged(w, h, ow, oh);
mContentViewCore.onPhysicalBackingSizeChanged(w, h);
mContentViewCore.onSizeChanged(w, h, ow, oh);
- mLayoutSizer.onSizeChanged(w, h, ow, oh);
nativeOnSizeChanged(mNativeAwContents, w, h, ow, oh);
}
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 b2d3fe8..c3a9ec9 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwLayoutSizer.java
@@ -27,9 +27,9 @@ 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;
+ private float mPageScaleFactor = 0.0f;
// The page scale factor that was used in the most recent onMeasure call.
- private double mLastMeasuredPageScaleFactor = 0.0;
+ private float mLastMeasuredPageScaleFactor = 0.0f;
// Whether to postpone layout requests.
private boolean mFreezeLayoutRequests;
@@ -43,6 +43,14 @@ public class AwLayoutSizer {
// If mHeightMeasurementLimited is true then this contains the height limit.
private int mHeightMeasurementLimit;
+ // The most recent width and height seen in onSizeChanged.
+ private int mLastWidth;
+ private int mLastHeight;
+
+ // Used to prevent sending multiple setFixedLayoutSize notifications with the same values.
+ private int mLastSentFixedLayoutSizeWidth = -1;
+ private int mLastSentFixedLayoutSizeHeight = -1;
+
// Callback object for interacting with the View.
private Delegate mDelegate;
@@ -102,21 +110,23 @@ public class AwLayoutSizer {
* This should be called whenever the content page scale factor changes (due to pinch zoom, for
* example).
*/
- public void onPageScaleChanged(double pageScaleFactor) {
+ public void onPageScaleChanged(float pageScaleFactor) {
doUpdate(mContentWidthCss, mContentHeightCss, pageScaleFactor);
}
- private void doUpdate(int widthCss, int heightCss, double pageScaleFactor) {
+ private void doUpdate(int widthCss, int heightCss, float 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'.
final int heightPix = (int) (heightCss * mPageScaleFactor * mDIPScale);
- boolean anyMeasurementNotFixed = !mWidthMeasurementIsFixed || !mHeightMeasurementIsFixed;
+ boolean pageScaleChanged = mPageScaleFactor != pageScaleFactor;
boolean contentHeightChangeMeaningful = !mHeightMeasurementIsFixed &&
(!mHeightMeasurementLimited || heightPix < mHeightMeasurementLimit);
+ boolean pageScaleChangeMeaningful =
+ !mWidthMeasurementIsFixed || contentHeightChangeMeaningful;
boolean layoutNeeded = (mContentWidthCss != widthCss && !mWidthMeasurementIsFixed) ||
(mContentHeightCss != heightCss && contentHeightChangeMeaningful) ||
- (mPageScaleFactor != pageScaleFactor && anyMeasurementNotFixed);
+ (pageScaleChanged && pageScaleChangeMeaningful);
mContentWidthCss = widthCss;
mContentHeightCss = heightCss;
@@ -128,6 +138,10 @@ public class AwLayoutSizer {
} else {
mDelegate.requestLayout();
}
+ } else if (pageScaleChanged && mLastWidth != 0) {
+ // Because the fixed layout size is directly impacted by the pageScaleFactor we must
+ // update it even if the physical size of the view doesn't change.
+ updateFixedLayoutSize(mLastWidth, mLastHeight, mPageScaleFactor);
}
}
@@ -175,7 +189,42 @@ public class AwLayoutSizer {
mDelegate.setMeasuredDimension(measuredWidth, measuredHeight);
}
+ /**
+ * Notify the AwLayoutSizer that the size of the view has changed.
+ * This should be called by the Android view system after onMeasure if the view's size has
+ * changed.
+ */
public void onSizeChanged(int w, int h, int ow, int oh) {
+ mLastWidth = w;
+ mLastHeight = h;
+ updateFixedLayoutSize(mLastWidth, mLastHeight, mLastMeasuredPageScaleFactor);
+ }
+
+ /**
+ * Notify the AwLayoutSizer that the layout pass requested via Delegate.requestLayout has
+ * completed.
+ * This should be called after onSizeChanged regardless of whether the size has changed or not.
+ */
+ public void onLayoutChange() {
+ updateFixedLayoutSize(mLastWidth, mLastHeight, mLastMeasuredPageScaleFactor);
+ }
+
+ private void setFixedLayoutSize(int widthDip, int heightDip) {
+ if (widthDip == mLastSentFixedLayoutSizeWidth &&
+ heightDip == mLastSentFixedLayoutSizeHeight)
+ return;
+ mLastSentFixedLayoutSizeWidth = widthDip;
+ mLastSentFixedLayoutSizeHeight = heightDip;
+
+ mDelegate.setFixedLayoutSize(widthDip, heightDip);
+ }
+
+ // This needs to be called every time either the physical size of the view is changed or the
+ // pageScale is changed. Since we need to ensure that this is called immediately after
+ // onSizeChanged we can't just wait for onLayoutChange. At the same time we can't only make this
+ // call from onSizeChanged, since onSizeChanged won't fire if the view's physical size doesn't
+ // change.
+ private void updateFixedLayoutSize(int w, int h, float pageScaleFactor) {
// 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
@@ -183,13 +232,12 @@ public class AwLayoutSizer {
// 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);
+ if ((mWidthMeasurementIsFixed && mHeightMeasurementIsFixed) || pageScaleFactor == 0) {
+ setFixedLayoutSize(0, 0);
return;
}
- final double dipAndPageScale = mLastMeasuredPageScaleFactor * mDIPScale;
+ final double dipAndPageScale = pageScaleFactor * mDIPScale;
final int contentWidthPix = (int) (mContentWidthCss * dipAndPageScale);
int widthDip = (int) Math.ceil(w / dipAndPageScale);
@@ -204,6 +252,6 @@ public class AwLayoutSizer {
// 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);
+ setFixedLayoutSize(widthDip, FIXED_LAYOUT_HEIGHT);
}
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
index 512a50a..d2ea75c 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
@@ -62,7 +62,7 @@ public class AndroidViewIntegrationTest extends AwTestBase {
}
@Override
- public void onPageScaleChanged(double pageScaleFactor) {
+ public void onPageScaleChanged(float pageScaleFactor) {
super.onPageScaleChanged(pageScaleFactor);
mOnPageScaleChangedHelper.notifyCalled();
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
index 327fcff..5d8b56b 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwLayoutSizerTest.java
@@ -49,7 +49,7 @@ public class AwLayoutSizerTest extends InstrumentationTestCase {
private static final int AT_MOST_MEASURE_SIZE = 50;
private static final int TOO_LARGE_CONTENT_SIZE = 100;
- private static final double INITIAL_PAGE_SCALE = 1.0;
+ private static final float INITIAL_PAGE_SCALE = 1.0f;
private static final double DIP_SCALE = 1.0;
@SmallTest
@@ -227,7 +227,7 @@ public class AwLayoutSizerTest extends InstrumentationTestCase {
MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int requestLayoutCallCount = delegate.requestLayoutCallCount;
- layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE + 0.5);
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE + 0.5f);
assertEquals(requestLayoutCallCount + 1, delegate.requestLayoutCallCount);
}
@@ -245,7 +245,7 @@ public class AwLayoutSizerTest extends InstrumentationTestCase {
layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(50, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int requestLayoutCallCount = delegate.requestLayoutCallCount;
- layoutSizer.onPageScaleChanged(DIP_SCALE);
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE);
assertEquals(requestLayoutCallCount, delegate.requestLayoutCallCount);
}
@@ -258,7 +258,7 @@ public class AwLayoutSizerTest extends InstrumentationTestCase {
layoutSizer.setDelegate(delegate);
layoutSizer.setDIPScale(DIP_SCALE);
- final double tooLargePageScale = 3.00;
+ final float tooLargePageScale = 3.00f;
layoutSizer.onContentSizeChanged(SMALLER_CONTENT_SIZE, SMALLER_CONTENT_SIZE);
layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE);
@@ -459,4 +459,59 @@ public class AwLayoutSizerTest extends InstrumentationTestCase {
assertTrue(delegate.fixedLayoutWidth != 0);
assertEquals(0, delegate.fixedLayoutHeight);
}
+
+ @SmallTest
+ @Feature({"AndroidWebView"})
+ public void testFixedLayoutSizeUpdatedOnPageScaleChangeItNoLayoutRequest() {
+ AwLayoutSizer layoutSizer = new AwLayoutSizer();
+ LayoutSizerDelegate delegate = new LayoutSizerDelegate();
+ layoutSizer.setDelegate(delegate);
+ layoutSizer.setDIPScale(DIP_SCALE);
+
+ layoutSizer.onContentSizeChanged(TOO_LARGE_CONTENT_SIZE, TOO_LARGE_CONTENT_SIZE);
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE);
+ layoutSizer.onMeasure(
+ MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(AT_MOST_MEASURE_SIZE, MeasureSpec.AT_MOST));
+ layoutSizer.onSizeChanged(AT_MOST_MEASURE_SIZE, AT_MOST_MEASURE_SIZE, 0, 0);
+
+ assertTrue(delegate.fixedLayoutWidth != 0);
+ final int fixedLayoutWidth = delegate.fixedLayoutWidth;
+ final int requestLayoutCallCount = delegate.requestLayoutCallCount;
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE * 2f);
+ assertEquals(requestLayoutCallCount, delegate.requestLayoutCallCount);
+ assertEquals(fixedLayoutWidth / 2, delegate.fixedLayoutWidth);
+ }
+
+ @SmallTest
+ @Feature({"AndroidWebView"})
+ public void testFixedLayoutSizeUpdatedIfNoSizeChangeAfterLayoutRequested() {
+ AwLayoutSizer layoutSizer = new AwLayoutSizer();
+ LayoutSizerDelegate delegate = new LayoutSizerDelegate();
+ layoutSizer.setDelegate(delegate);
+ layoutSizer.setDIPScale(DIP_SCALE);
+
+ layoutSizer.onContentSizeChanged(FIRST_CONTENT_WIDTH, FIRST_CONTENT_HEIGHT);
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE);
+ layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+
+ layoutSizer.onSizeChanged((int) (FIRST_CONTENT_WIDTH * DIP_SCALE),
+ (int) (FIRST_CONTENT_HEIGHT * DIP_SCALE), 0, 0);
+
+ assertTrue(delegate.fixedLayoutWidth != 0);
+ final int fixedLayoutWidth = delegate.fixedLayoutWidth;
+ final int requestLayoutCallCount = delegate.requestLayoutCallCount;
+ layoutSizer.onPageScaleChanged(INITIAL_PAGE_SCALE * 0.5f);
+ assertEquals(requestLayoutCallCount + 1, delegate.requestLayoutCallCount);
+ assertEquals(fixedLayoutWidth, delegate.fixedLayoutWidth);
+
+ // onMeasure and onLayoutChange should always be called as a result of the AwLayoutSizer
+ // calling Delegate.requestLayout.
+ layoutSizer.onMeasure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ layoutSizer.onLayoutChange();
+
+ assertEquals(fixedLayoutWidth * 2, delegate.fixedLayoutWidth);
+ }
}