Bug 716403 - Make the top of the page accessible with the toolbar visible. r=kats

This makes it possible to scroll to the top of the page with the toolbar visible
in Firefox for Android. It also causes JavaScript scrolling to position 0 to
expose the toolbar.
This commit is contained in:
Chris Lord 2013-03-06 16:55:59 +00:00
parent 3bee7155b6
commit e7a2989cdd
4 changed files with 82 additions and 21 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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;
}
}
/*