diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index e715605564de..ff8ad6531ce3 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -183,9 +183,17 @@ abstract public class BrowserApp extends GeckoApp @Override public boolean onInterceptTouchEvent(View view, MotionEvent event) { int action = event.getActionMasked(); - int pointerCount = event.getPointerCount(); + // Whenever there are no pointers left on the screen, tell the page + // to clamp the viewport on fixed layer margin changes. This lets the + // toolbar scrolling off the top of the page make the page scroll up + // if it'd cause the page to go into overscroll, but only when there + // are no pointers held down. + mLayerView.getLayerClient().setClampOnFixedLayerMarginsChange( + pointerCount == 0 || action == MotionEvent.ACTION_CANCEL || + action == MotionEvent.ACTION_UP); + View toolbarView = mBrowserToolbar.getLayout(); if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) { diff --git a/mobile/android/base/gfx/GeckoLayerClient.java b/mobile/android/base/gfx/GeckoLayerClient.java index ce8064de301b..7951b7671eaa 100644 --- a/mobile/android/base/gfx/GeckoLayerClient.java +++ b/mobile/android/base/gfx/GeckoLayerClient.java @@ -91,6 +91,8 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget private final PanZoomController mPanZoomController; private LayerView mView; + private boolean mClampOnMarginChange; + public GeckoLayerClient(Context context, LayerView view, EventDispatcher eventDispatcher) { // we can fill these in with dummy values because they are always written // to before being read @@ -105,6 +107,7 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget mProgressiveUpdateDisplayPort = new DisplayPortMetrics(); mLastProgressiveUpdateWasLowPrecision = false; mProgressiveUpdateWasInDanger = false; + mClampOnMarginChange = true; mForceRedraw = true; DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); @@ -354,11 +357,21 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget */ public void setFixedLayerMargins(float left, float top, float right, float bottom) { ImmutableViewportMetrics oldMetrics = getViewportMetrics(); - setViewportMetrics(oldMetrics.setFixedLayerMargins(left, top, right, bottom), false); + ImmutableViewportMetrics newMetrics = oldMetrics.setFixedLayerMargins(left, top, right, bottom); + + if (mClampOnMarginChange) { + newMetrics = newMetrics.clampWithMargins(); + } + + setViewportMetrics(newMetrics, false); mView.requestRender(); } + public void setClampOnFixedLayerMarginsChange(boolean aClamp) { + mClampOnMarginChange = aClamp; + } + // This is called on the Gecko thread to determine if we're still interested // in the update of this display-port to continue. We can return true here // to abort the current update and continue with any subsequent ones. This @@ -470,7 +483,15 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget float pageLeft, float pageTop, float pageRight, float pageBottom, float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) { synchronized (this) { - final ImmutableViewportMetrics newMetrics = getViewportMetrics() + ImmutableViewportMetrics currentMetrics = getViewportMetrics(); + + // If we're meant to be scrolled to the top, take into account any + // margin set on the pan zoom controller. + if (offsetY == 0) { + offsetY = -currentMetrics.fixedLayerMarginTop; + } + + final ImmutableViewportMetrics newMetrics = currentMetrics .setViewportOrigin(offsetX, offsetY) .setZoomFactor(zoom) .setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom), @@ -549,10 +570,20 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget mCurrentViewTransform.x = mFrameMetrics.viewportRectLeft; mCurrentViewTransform.y = mFrameMetrics.viewportRectTop; mCurrentViewTransform.scale = mFrameMetrics.zoomFactor; - mCurrentViewTransform.fixedLayerMarginLeft = mFrameMetrics.fixedLayerMarginLeft; - mCurrentViewTransform.fixedLayerMarginTop = mFrameMetrics.fixedLayerMarginTop; - mCurrentViewTransform.fixedLayerMarginRight = mFrameMetrics.fixedLayerMarginRight; - mCurrentViewTransform.fixedLayerMarginBottom = mFrameMetrics.fixedLayerMarginBottom; + + // Adjust the fixed layer margins so that overscroll subtracts from them. + mCurrentViewTransform.fixedLayerMarginLeft = + Math.max(0, mFrameMetrics.fixedLayerMarginLeft + + Math.min(0, mFrameMetrics.viewportRectLeft - mFrameMetrics.pageRectLeft)); + mCurrentViewTransform.fixedLayerMarginTop = + Math.max(0, mFrameMetrics.fixedLayerMarginTop + + Math.min(0, mFrameMetrics.viewportRectTop - mFrameMetrics.pageRectTop)); + mCurrentViewTransform.fixedLayerMarginRight = + Math.max(0, mFrameMetrics.fixedLayerMarginRight + + Math.min(0, (mFrameMetrics.pageRectRight - mFrameMetrics.viewportRectRight))); + mCurrentViewTransform.fixedLayerMarginBottom = + Math.max(0, mFrameMetrics.fixedLayerMarginBottom + + Math.min(0, (mFrameMetrics.pageRectBottom - mFrameMetrics.viewportRectBottom))); mRootLayer.setPositionAndResolution(x, y, x + width, y + height, resolution); diff --git a/mobile/android/base/gfx/ImmutableViewportMetrics.java b/mobile/android/base/gfx/ImmutableViewportMetrics.java index d6cc2f710014..5627d3f8e89f 100644 --- a/mobile/android/base/gfx/ImmutableViewportMetrics.java +++ b/mobile/android/base/gfx/ImmutableViewportMetrics.java @@ -237,19 +237,20 @@ public class ImmutableViewportMetrics { } /** Clamps the viewport to remain within the page rect. */ - public ImmutableViewportMetrics clamp() { + private ImmutableViewportMetrics clamp(float marginLeft, float marginTop, + float marginRight, float marginBottom) { RectF newViewport = getViewport(); // The viewport bounds ought to never exceed the page bounds. - if (newViewport.right > pageRectRight) - newViewport.offset(pageRectRight - newViewport.right, 0); - if (newViewport.left < pageRectLeft) - newViewport.offset(pageRectLeft - newViewport.left, 0); + if (newViewport.right > pageRectRight + marginRight) + newViewport.offset((pageRectRight + marginRight) - newViewport.right, 0); + if (newViewport.left < pageRectLeft - marginLeft) + newViewport.offset((pageRectLeft - marginLeft) - newViewport.left, 0); - if (newViewport.bottom > pageRectBottom) - newViewport.offset(0, pageRectBottom - newViewport.bottom); - if (newViewport.top < pageRectTop) - newViewport.offset(0, pageRectTop - newViewport.top); + if (newViewport.bottom > pageRectBottom + marginBottom) + newViewport.offset(0, (pageRectBottom + marginBottom) - newViewport.bottom); + if (newViewport.top < pageRectTop - marginTop) + newViewport.offset(0, (pageRectTop - marginTop) - newViewport.top); return new ImmutableViewportMetrics( pageRectLeft, pageRectTop, pageRectRight, pageRectBottom, @@ -259,6 +260,15 @@ public class ImmutableViewportMetrics { zoomFactor); } + public ImmutableViewportMetrics clamp() { + return clamp(0, 0, 0, 0); + } + + public ImmutableViewportMetrics clampWithMargins() { + return clamp(fixedLayerMarginLeft, fixedLayerMarginTop, + fixedLayerMarginRight, fixedLayerMarginBottom); + } + public boolean fuzzyEquals(ImmutableViewportMetrics other) { // Don't bother checking the pageRectXXX values because they are a product // of the cssPageRectXXX values and the zoomFactor, except with more rounding diff --git a/mobile/android/base/gfx/JavaPanZoomController.java b/mobile/android/base/gfx/JavaPanZoomController.java index 3b86a2853a30..8ad97b4d9c1d 100644 --- a/mobile/android/base/gfx/JavaPanZoomController.java +++ b/mobile/android/base/gfx/JavaPanZoomController.java @@ -937,7 +937,7 @@ class JavaPanZoomController } /* Now we pan to the right origin. */ - viewportMetrics = viewportMetrics.clamp(); + viewportMetrics = viewportMetrics.clampWithMargins(); return viewportMetrics; } @@ -949,9 +949,15 @@ class JavaPanZoomController @Override protected float getViewportLength() { return getMetrics().getWidth(); } @Override - protected float getPageStart() { return getMetrics().pageRectLeft; } + protected float getPageStart() { + ImmutableViewportMetrics metrics = getMetrics(); + return metrics.pageRectLeft - metrics.fixedLayerMarginLeft; + } @Override - protected float getPageLength() { return getMetrics().getPageWidth(); } + protected float getPageLength() { + ImmutableViewportMetrics metrics = getMetrics(); + return metrics.getPageWidth() + metrics.fixedLayerMarginLeft + metrics.fixedLayerMarginRight; + } } private class AxisY extends Axis { @@ -961,9 +967,15 @@ class JavaPanZoomController @Override protected float getViewportLength() { return getMetrics().getHeight(); } @Override - protected float getPageStart() { return getMetrics().pageRectTop; } + protected float getPageStart() { + ImmutableViewportMetrics metrics = getMetrics(); + return metrics.pageRectTop - metrics.fixedLayerMarginTop; + } @Override - protected float getPageLength() { return getMetrics().getPageHeight(); } + protected float getPageLength() { + ImmutableViewportMetrics metrics = getMetrics(); + return metrics.getPageHeight() + metrics.fixedLayerMarginTop + metrics.fixedLayerMarginBottom; + } } /*