Bug 935219 - Fix composition bounds calculation and APZC hit testing (again). r=kats,tn

--HG--
extra : amend_source : 06c6bb658dfead6907250831bbe73fae6c20b45c
This commit is contained in:
Botond Ballo 2014-03-10 17:56:59 -04:00
parent 4b19f5e6c6
commit 70dfe7ab91
21 changed files with 307 additions and 168 deletions

View File

@ -72,6 +72,7 @@
#include "nsILoadContext.h"
#include "ipc/nsGUIEventIPC.h"
#include "mozilla/gfx/Matrix.h"
#include "UnitTransforms.h"
#include "nsColorPickerProxy.h"
@ -316,7 +317,9 @@ TabChild::InitializeRootMetrics()
// be keeping, as well as putting the scroll offset back to
// the top-left of the page.
mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
mLastRootMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
mLastRootMetrics.mCompositionBounds = ParentLayerIntRect(
ParentLayerIntPoint(),
ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot));
mLastRootMetrics.mZoom = mLastRootMetrics.CalculateIntrinsicScale();
mLastRootMetrics.mDevPixelsPerCSSPixel = mWidget->GetDefaultScale();
// We use ScreenToLayerScale(1) below in order to turn the
@ -588,7 +591,9 @@ TabChild::HandlePossibleViewportChange()
FrameMetrics metrics(mLastRootMetrics);
metrics.mViewport = CSSRect(CSSPoint(), viewport);
metrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
metrics.mCompositionBounds = ParentLayerIntRect(
ParentLayerIntPoint(),
ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot));
// This change to the zoom accounts for all types of changes I can conceive:
// 1. screen size changes, CSS viewport does not (pages with no meta viewport
@ -631,7 +636,7 @@ TabChild::HandlePossibleViewportChange()
metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale);
CSSSize scrollPort = metrics.CalculateCompositedRectInCssPixels().Size();
CSSSize scrollPort = CSSSize(metrics.CalculateCompositedRectInCssPixels().Size());
utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
// The call to GetPageSize forces a resize event to content, so we need to
@ -1511,7 +1516,7 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
FrameMetrics newMetrics = aFrameMetrics;
APZCCallbackHelper::UpdateRootFrame(utils, newMetrics);
CSSRect cssCompositedRect = newMetrics.CalculateCompositedRectInCssPixels();
CSSRect cssCompositedRect = CSSRect(newMetrics.CalculateCompositedRectInCssPixels());
// The BrowserElementScrolling helper must know about these updated metrics
// for other functions it performs, such as double tap handling.
// Note, %f must not be used because it is locale specific!
@ -1524,22 +1529,6 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
data.AppendLiteral(", \"height\" : ");
data.AppendFloat(newMetrics.mViewport.height);
data.AppendLiteral(" }");
data.AppendLiteral(", \"displayPort\" : ");
data.AppendLiteral("{ \"x\" : ");
data.AppendFloat(newMetrics.mDisplayPort.x);
data.AppendLiteral(", \"y\" : ");
data.AppendFloat(newMetrics.mDisplayPort.y);
data.AppendLiteral(", \"width\" : ");
data.AppendFloat(newMetrics.mDisplayPort.width);
data.AppendLiteral(", \"height\" : ");
data.AppendFloat(newMetrics.mDisplayPort.height);
data.AppendLiteral(" }");
data.AppendLiteral(", \"compositionBounds\" : ");
data.AppendPrintf("{ \"x\" : %d", newMetrics.mCompositionBounds.x);
data.AppendPrintf(", \"y\" : %d", newMetrics.mCompositionBounds.y);
data.AppendPrintf(", \"width\" : %d", newMetrics.mCompositionBounds.width);
data.AppendPrintf(", \"height\" : %d", newMetrics.mCompositionBounds.height);
data.AppendLiteral(" }");
data.AppendLiteral(", \"cssPageRect\" : ");
data.AppendLiteral("{ \"x\" : ");
data.AppendFloat(newMetrics.mScrollableRect.x);

View File

@ -622,6 +622,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mUpdateScrollOffset);
WriteParam(aMsg, aParam.mScrollGeneration);
WriteParam(aMsg, aParam.mContentDescription);
WriteParam(aMsg, aParam.mTransformScale);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
@ -643,7 +644,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) &&
ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mScrollGeneration) &&
ReadParam(aMsg, aIter, &aResult->mContentDescription));
ReadParam(aMsg, aIter, &aResult->mContentDescription) &&
ReadParam(aMsg, aIter, &aResult->mTransformScale));
}
};

View File

@ -19,18 +19,38 @@ template <typename T> struct ParamTraits;
} // namespace IPC
namespace mozilla {
namespace layers {
// The layer coordinates of the parent layer. Like the layer coordinates
// of the current layer (LayerPixel) but doesn't include the current layer's
// resolution.
// The layer coordinates of the parent layer.
// This can be arrived at in two ways:
// - Start with the CSS coordinates of the parent layer (note: NOT the
// CSS coordinates of the current layer, that will give you the wrong
// answer), multiply by the device scale and the resolutions of all
// layers from the root down to and including the parent.
// - Start with global screen coordinates and unapply all CSS and async
// transforms from the root down to and including the parent.
// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems
// to get a picture of how the various coordinate systems relate to each other.
struct ParentLayerPixel {};
typedef gfx::ScaleFactor<LayoutDevicePixel, ParentLayerPixel> LayoutDeviceToParentLayerScale;
typedef gfx::ScaleFactor<ParentLayerPixel, LayerPixel> ParentLayerToLayerScale;
typedef gfx::PointTyped<ParentLayerPixel> ParentLayerPoint;
typedef gfx::RectTyped<ParentLayerPixel> ParentLayerRect;
typedef gfx::SizeTyped<ParentLayerPixel> ParentLayerSize;
typedef gfx::IntMarginTyped<ParentLayerPixel> ParentLayerIntMargin;
typedef gfx::IntPointTyped<ParentLayerPixel> ParentLayerIntPoint;
typedef gfx::IntRectTyped<ParentLayerPixel> ParentLayerIntRect;
typedef gfx::IntSizeTyped<ParentLayerPixel> ParentLayerIntSize;
typedef gfx::ScaleFactor<CSSPixel, ParentLayerPixel> CSSToParentLayerScale;
typedef gfx::ScaleFactor<LayoutDevicePixel, ParentLayerPixel> LayoutDeviceToParentLayerScale;
typedef gfx::ScaleFactor<ScreenPixel, ParentLayerPixel> ScreenToParentLayerScale;
typedef gfx::ScaleFactor<ParentLayerPixel, LayerPixel> ParentLayerToLayerScale;
typedef gfx::ScaleFactor<ParentLayerPixel, ScreenPixel> ParentLayerToScreenScale;
namespace layers {
/**
* The viewport and displayport metrics for the painted frame at the
* time of a layer-tree transaction. These metrics are especially
@ -57,6 +77,7 @@ public:
, mResolution(1)
, mCumulativeResolution(1)
, mZoom(1)
, mTransformScale(1)
, mDevPixelsPerCSSPixel(1)
, mPresShellId(-1)
, mMayHaveTouchListeners(false)
@ -135,7 +156,7 @@ public:
CSSRect GetExpandedScrollableRect() const
{
CSSRect scrollableRect = mScrollableRect;
CSSRect compBounds = CalculateCompositedRectInCssPixels();
CSSRect compBounds = CSSRect(CalculateCompositedRectInCssPixels());
if (scrollableRect.width < compBounds.width) {
scrollableRect.x = std::max(0.f,
scrollableRect.x - (compBounds.width - scrollableRect.width));
@ -151,18 +172,26 @@ public:
return scrollableRect;
}
/**
* Return the scale factor needed to fit the viewport
* into its composition bounds.
*/
// Return the scale factor needed to fit the viewport
// into its composition bounds.
CSSToScreenScale CalculateIntrinsicScale() const
{
return CSSToScreenScale(float(mCompositionBounds.width) / float(mViewport.width));
}
CSSRect CalculateCompositedRectInCssPixels() const
// Return the scale factor for converting from CSS pixels (for this layer)
// to layer pixels of our parent layer. Much as mZoom is used to interface
// between inputs we get in screen pixels and quantities in CSS pixels,
// this is used to interface between mCompositionBounds and quantities
// in CSS pixels.
CSSToParentLayerScale GetZoomToParent() const
{
return CSSRect(gfx::RoundedIn(mCompositionBounds / mZoom));
return mZoom * mTransformScale;
}
CSSIntRect CalculateCompositedRectInCssPixels() const
{
return gfx::RoundedIn(mCompositionBounds / GetZoomToParent());
}
// ---------------------------------------------------------------------------
@ -184,7 +213,7 @@ public:
// This value is valid for nested scrollable layers as well, and is still
// relative to the layer tree origin. This value is provided by Gecko at
// layout/paint time.
ScreenIntRect mCompositionBounds;
ParentLayerIntRect mCompositionBounds;
// ---------------------------------------------------------------------------
// The following metrics are all in CSS pixels. They are not in any uniform
@ -282,6 +311,17 @@ public:
// diverge. This information is initialized in Gecko but updated in the APZC.
CSSToScreenScale mZoom;
// The conversion factor between local screen pixels (the coordinate
// system in which APZCs receive input events) and our parent layer's
// layer pixels (the coordinate system of mCompositionBounds).
// This consists of the scale of the local CSS transform and the
// nontransient async transform.
// TODO: APZ does not currently work well if there is a CSS transform
// on the layer being scrolled that's not just a scale that's
// the same in both directions. When we fix this, mTransformScale
// will probably need to turn into a matrix.
ScreenToParentLayerScale mTransformScale;
// The conversion factor between CSS pixels and device pixels for this frame.
// This can vary based on a variety of things, such as reflowing-zoom. The
// conversion factor for device pixels to layers pixels is just the

View File

@ -517,8 +517,8 @@ ClientLayerManager::GetBackendName(nsAString& aName)
bool
ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
ScreenRect& aCompositionBounds,
CSSToScreenScale& aZoom,
ParentLayerRect& aCompositionBounds,
CSSToParentLayerScale& aZoom,
bool aDrawingCritical)
{
aZoom.scale = 1.0;

View File

@ -147,8 +147,8 @@ public:
* true.
*/
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
ScreenRect& aCompositionBounds,
CSSToScreenScale& aZoom,
ParentLayerRect& aCompositionBounds,
CSSToParentLayerScale& aZoom,
bool aDrawingCritical);
bool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }

View File

@ -5,6 +5,7 @@
#include "ClientTiledThebesLayer.h"
#include "FrameMetrics.h" // for FrameMetrics
#include "Units.h" // for ScreenIntRect, CSSPoint, etc
#include "UnitTransforms.h" // for TransformTo
#include "ClientLayerManager.h" // for ClientLayerManager, etc
#include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxPlatform.h" // for gfxPlatform
@ -52,11 +53,9 @@ ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
}
static LayoutDeviceRect
ApplyScreenToLayoutTransform(const gfx3DMatrix& aTransform, const ScreenRect& aScreenRect)
ApplyParentLayerToLayoutTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
{
gfxRect input(aScreenRect.x, aScreenRect.y, aScreenRect.width, aScreenRect.height);
gfxRect output = aTransform.TransformBounds(input);
return LayoutDeviceRect(output.x, output.y, output.width, output.height);
return TransformTo<LayoutDevicePixel>(aTransform, aParentLayerRect);
}
void
@ -89,30 +88,32 @@ ClientTiledThebesLayer::BeginPaint()
const FrameMetrics& metrics = scrollParent->GetFrameMetrics();
// Calculate the transform required to convert screen space into transformed
// layout device space.
// Calculate the transform required to convert parent layer space into
// transformed layout device space.
gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform();
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
if (parent->UseIntermediateSurface()) {
effectiveTransform = effectiveTransform * parent->GetEffectiveTransform();
}
}
gfx3DMatrix layoutToScreen;
gfx::To3DMatrix(effectiveTransform, layoutToScreen);
layoutToScreen.ScalePost(metrics.mCumulativeResolution.scale,
metrics.mCumulativeResolution.scale,
1.f);
gfx3DMatrix layoutToParentLayer;
gfx::To3DMatrix(effectiveTransform, layoutToParentLayer);
layoutToParentLayer.ScalePost(metrics.GetParentResolution().scale,
metrics.GetParentResolution().scale,
1.f);
mPaintData.mTransformScreenToLayout = layoutToScreen.Inverse();
mPaintData.mTransformParentLayerToLayout = layoutToParentLayer.Inverse();
// Compute the critical display port in layer space.
mPaintData.mLayoutCriticalDisplayPort.SetEmpty();
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
// Convert the display port to screen space first so that we can transform
// it into layout device space.
const ScreenRect& criticalDisplayPort = metrics.mCriticalDisplayPort * metrics.mZoom;
const ParentLayerRect& criticalDisplayPort = metrics.mCriticalDisplayPort
* metrics.mDevPixelsPerCSSPixel
* metrics.GetParentResolution();
LayoutDeviceRect transformedCriticalDisplayPort =
ApplyScreenToLayoutTransform(mPaintData.mTransformScreenToLayout, criticalDisplayPort);
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout, criticalDisplayPort);
mPaintData.mLayoutCriticalDisplayPort =
LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort));
}
@ -130,8 +131,8 @@ ClientTiledThebesLayer::BeginPaint()
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
mPaintData.mScrollOffset = metrics.mScrollOffset * metrics.mZoom;
mPaintData.mCompositionBounds =
ApplyScreenToLayoutTransform(mPaintData.mTransformScreenToLayout,
ScreenRect(metrics.mCompositionBounds));
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout,
ParentLayerRect(metrics.mCompositionBounds));
}
}

View File

@ -141,8 +141,8 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
ContainerLayer* aLayer,
bool aHasPendingNewThebesContent,
bool aLowPrecision,
ScreenRect& aCompositionBounds,
CSSToScreenScale& aZoom)
ParentLayerRect& aCompositionBounds,
CSSToParentLayerScale& aZoom)
{
MOZ_ASSERT(aLayer);
@ -162,8 +162,8 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
return false;
}
aCompositionBounds = ScreenRect(compositorMetrics.mCompositionBounds);
aZoom = compositorMetrics.mZoom;
aCompositionBounds = ParentLayerRect(compositorMetrics.mCompositionBounds);
aZoom = compositorMetrics.GetZoomToParent();
// Reset the checkerboard risk flag when switching to low precision
// rendering.
@ -215,8 +215,8 @@ SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
void
SharedFrameMetricsHelper::FindFallbackContentFrameMetrics(ContainerLayer* aLayer,
ScreenRect& aCompositionBounds,
CSSToScreenScale& aZoom) {
ParentLayerRect& aCompositionBounds,
CSSToParentLayerScale& aZoom) {
if (!aLayer) {
return;
}
@ -232,16 +232,16 @@ SharedFrameMetricsHelper::FindFallbackContentFrameMetrics(ContainerLayer* aLayer
MOZ_ASSERT(!contentMetrics->mCompositionBounds.IsEmpty());
aCompositionBounds = ScreenRect(contentMetrics->mCompositionBounds);
aZoom = contentMetrics->mZoom;
aCompositionBounds = ParentLayerRect(contentMetrics->mCompositionBounds);
aZoom = contentMetrics->GetZoomToParent(); // TODO(botond): double-check this
return;
}
bool
SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetrics,
const FrameMetrics& aCompositorMetrics)
const FrameMetrics& aCompositorMetrics)
{
return !aContentMetrics.mDisplayPort.Contains(aCompositorMetrics.CalculateCompositedRectInCssPixels() - aCompositorMetrics.mScrollOffset);
return !aContentMetrics.mDisplayPort.Contains(CSSRect(aCompositorMetrics.CalculateCompositedRectInCssPixels()) - aCompositorMetrics.mScrollOffset);
}
ClientTiledLayerBuffer::ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
@ -843,8 +843,8 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
}
static LayoutDeviceRect
TransformCompositionBounds(const ScreenRect& aCompositionBounds,
const CSSToScreenScale& aZoom,
TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
const CSSToParentLayerScale& aZoom,
const ScreenPoint& aScrollOffset,
const CSSToScreenScale& aResolution,
const gfx3DMatrix& aTransformScreenToLayout)
@ -895,8 +895,8 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
// Find out the current view transform to determine which tiles to draw
// first, and see if we should just abort this paint. Aborting is usually
// caused by there being an incoming, more relevant paint.
ScreenRect compositionBounds;
CSSToScreenScale zoom;
ParentLayerRect compositionBounds;
CSSToParentLayerScale zoom;
#if defined(MOZ_WIDGET_ANDROID)
bool abortPaint = mManager->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
compositionBounds, zoom,
@ -929,7 +929,7 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
// Transform the screen coordinates into transformed layout device coordinates.
LayoutDeviceRect transformedCompositionBounds =
TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
aPaintData->mResolution, aPaintData->mTransformScreenToLayout);
aPaintData->mResolution, aPaintData->mTransformParentLayerToLayout);
// Paint tiles that have stale content or that intersected with the screen
// at the time of issuing the draw command in a single transaction first.

View File

@ -243,10 +243,10 @@ struct BasicTiledLayerPaintData {
ScreenPoint mLastScrollOffset;
/*
* The transform matrix to go from Screen units to transformed LayoutDevice
* units.
* The transform matrix to go from ParentLayer units to transformed
* LayoutDevice units.
*/
gfx3DMatrix mTransformScreenToLayout;
gfx3DMatrix mTransformParentLayerToLayout;
/*
* The critical displayport of the content from the nearest ancestor layer
@ -307,8 +307,8 @@ public:
bool UpdateFromCompositorFrameMetrics(ContainerLayer* aLayer,
bool aHasPendingNewThebesContent,
bool aLowPrecision,
ScreenRect& aCompositionBounds,
CSSToScreenScale& aZoom);
ParentLayerRect& aCompositionBounds,
CSSToParentLayerScale& aZoom);
/**
* When a shared FrameMetrics can not be found for a given layer,
@ -316,8 +316,8 @@ public:
* by traversing up the layer tree.
*/
void FindFallbackContentFrameMetrics(ContainerLayer* aLayer,
ScreenRect& aCompositionBounds,
CSSToScreenScale& aZoom);
ParentLayerRect& aCompositionBounds,
CSSToParentLayerScale& aZoom);
/**
* Determines if the compositor's upcoming composition bounds has fallen
* outside of the contents display port. If it has then the compositor

View File

@ -20,6 +20,8 @@
#include "nsDebug.h" // for NS_WARNING
#include "nsPoint.h" // for nsIntPoint
#include "nsThreadUtils.h" // for NS_IsMainThread
#include "mozilla/gfx/Logging.h" // for gfx::TreeLog
#include "UnitTransforms.h" // for ViewAs
#include <algorithm> // for std::stable_sort
@ -155,7 +157,8 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
AsyncPanZoomController* apzc = nullptr;
mApzcTreeLog << aLayer->Name() << '\t';
if (container) {
if (container->GetFrameMetrics().IsScrollable()) {
const FrameMetrics& metrics = container->GetFrameMetrics();
if (metrics.IsScrollable()) {
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
if (state && state->mController.get()) {
// If we get here, aLayer is a scrollable container layer and somebody
@ -168,7 +171,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
// be possible because of DLBI heuristics) then we don't want to keep using
// the same old APZC for the new content. Null it out so we run through the
// code to find another one or create one.
ScrollableLayerGuid guid(aLayersId, container->GetFrameMetrics());
ScrollableLayerGuid guid(aLayersId, metrics);
if (apzc && !apzc->Matches(guid)) {
apzc = nullptr;
}
@ -210,19 +213,22 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
}
APZC_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, aLayersId, container->GetFrameMetrics().mScrollId);
apzc->NotifyLayersUpdated(container->GetFrameMetrics(),
apzc->NotifyLayersUpdated(metrics,
aIsFirstPaint && (aLayersId == aFirstPaintLayersId));
// Use the composition bounds as the hit test region.
// Optionally, the GeckoContentController can provide a touch-sensitive
// region that constrains all frames associated with the controller.
// In this case we intersect the composition bounds with that region.
ScreenRect visible(container->GetFrameMetrics().mCompositionBounds);
ParentLayerRect visible(metrics.mCompositionBounds);
CSSRect touchSensitiveRegion;
if (state->mController->GetTouchSensitiveRegion(&touchSensitiveRegion)) {
// Note: we assume here that touchSensitiveRegion is in the CSS pixels
// of our parent layer, which makes this coordinate conversion
// correct.
visible = visible.Intersect(touchSensitiveRegion
* container->GetFrameMetrics().LayersPixelsPerCSSPixel()
* LayerToScreenScale(1.0));
* metrics.mDevPixelsPerCSSPixel
* metrics.GetParentResolution());
}
gfx3DMatrix transform;
gfx::To3DMatrix(aLayer->GetTransform(), transform);
@ -869,25 +875,21 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& a
// use standard matrix notation where the leftmost matrix in a multiplication is applied first.
// ancestorUntransform takes points from aApzc's parent APZC's layer coordinates
// to aApzc's screen coordinates.
// to aApzc's parent layer's layer coordinates.
// It is OC.Inverse() * NC.Inverse() * MC.Inverse() at recursion level for L,
// and RC.Inverse() * QC.Inverse() at recursion level for P.
gfx3DMatrix ancestorUntransform = aApzc->GetAncestorTransform().Inverse();
// hitTestTransform takes points from aApzc's parent APZC's layer coordinates to
// the hit test space (which is aApzc's transient coordinates).
// It is OC.Inverse() * NC.Inverse() * MC.Inverse() * LC.Inverse() * LN.Inverse() at L,
// and RC.Inverse() * QC.Inverse() * PC.Inverse() * PN.Inverse() at P.
gfx3DMatrix hitTestTransform = ancestorUntransform
* aApzc->GetCSSTransform().Inverse()
* aApzc->GetNontransientAsyncTransform().Inverse();
gfxPoint hitTestPointForThisLayer = hitTestTransform.ProjectPoint(aHitTestPoint);
// Hit testing for this layer takes place in our parent layer coordinates,
// since the composition bounds (used to initialize the visible rect against
// which we hit test are in those coordinates).
gfxPoint hitTestPointForThisLayer = ancestorUntransform.ProjectPoint(aHitTestPoint);
APZC_LOG("Untransformed %f %f to transient coordinates %f %f for hit-testing APZC %p\n",
aHitTestPoint.x, aHitTestPoint.y,
hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc);
// childUntransform takes points from aApzc's parent APZC's layer coordinates
// to aApzc's layer coordinates (which are aApzc's children's screen coordinates).
// to aApzc's layer coordinates (which are aApzc's children's ParentLayer coordinates).
// It is OC.Inverse() * NC.Inverse() * MC.Inverse() * LC.Inverse() * LA.Inverse() at L
// and RC.Inverse() * QC.Inverse() * PC.Inverse() * PA.Inverse() at P.
gfx3DMatrix childUntransform = ancestorUntransform
@ -906,7 +908,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& a
return match;
}
}
if (aApzc->VisibleRegionContains(ScreenPoint(hitTestPointForThisLayer.x, hitTestPointForThisLayer.y))) {
if (aApzc->VisibleRegionContains(ViewAs<ParentLayerPixel>(hitTestPointForThisLayer))) {
APZC_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n",
hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc);
return aApzc;

View File

@ -390,7 +390,7 @@ ContainerRender(ContainerT* aContainer,
if (aContainer->GetFrameMetrics().IsScrollable()) {
const FrameMetrics& frame = aContainer->GetFrameMetrics();
LayerRect layerBounds = ScreenRect(frame.mCompositionBounds) * ScreenToLayerScale(1.0);
LayerRect layerBounds = ParentLayerRect(frame.mCompositionBounds) * ParentLayerToLayerScale(1.0);
gfx::Rect rect(layerBounds.x, layerBounds.y, layerBounds.width, layerBounds.height);
gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
aManager->GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTAINER,

View File

@ -16,6 +16,7 @@
#include "InputData.h" // for MultiTouchInput, etc
#include "LayerTransactionParent.h" // for LayerTransactionParent
#include "Units.h" // for CSSRect, CSSPoint, etc
#include "UnitTransforms.h" // for TransformTo
#include "base/message_loop.h" // for MessageLoop
#include "base/task.h" // for NewRunnableMethod, etc
#include "base/tracked.h" // for FROM_HERE
@ -44,6 +45,7 @@
#include "mozilla/layers/TaskThrottler.h" // for TaskThrottler
#include "mozilla/mozalloc.h" // for operator new, etc
#include "mozilla/unused.h" // for unused
#include "mozilla/FloatingPoint.h" // for FuzzyEqualsMultiplicative
#include "nsAlgorithm.h" // for clamped
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsCOMPtr.h" // for already_AddRefed
@ -797,7 +799,7 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve
}
SetState(PINCHING);
mLastZoomFocus = aEvent.mFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft();
mLastZoomFocus = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft();
return nsEventStatus_eConsumeNoDefault;
}
@ -819,8 +821,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
{
ReentrantMonitorAutoEnter lock(mMonitor);
CSSToScreenScale userZoom = mFrameMetrics.mZoom;
ScreenPoint focusPoint = aEvent.mFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft();
CSSToParentLayerScale userZoom = mFrameMetrics.GetZoomToParent();
ParentLayerPoint focusPoint = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft();
CSSPoint cssFocusPoint = focusPoint / userZoom;
CSSPoint focusChange = (mLastZoomFocus - focusPoint) / userZoom;
@ -839,8 +841,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
// either axis such that we don't overscroll the boundaries when zooming.
CSSPoint neededDisplacement;
CSSToScreenScale realMinZoom = mZoomConstraints.mMinZoom;
CSSToScreenScale realMaxZoom = mZoomConstraints.mMaxZoom;
CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale;
CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale;
realMinZoom.scale = std::max(realMinZoom.scale,
mFrameMetrics.mCompositionBounds.width / mFrameMetrics.mScrollableRect.width);
realMinZoom.scale = std::max(realMinZoom.scale,
@ -1345,7 +1347,7 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort(
const ScreenPoint& aVelocity,
double aEstimatedPaintDuration)
{
CSSRect compositionBounds = aFrameMetrics.CalculateCompositedRectInCssPixels();
CSSRect compositionBounds(aFrameMetrics.CalculateCompositedRectInCssPixels());
CSSPoint velocity = aVelocity / aFrameMetrics.mZoom;
CSSPoint scrollOffset = aFrameMetrics.mScrollOffset;
CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect();
@ -1528,7 +1530,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
LogRendertraceRect(GetGuid(), "viewport", "red",
CSSRect(mFrameMetrics.mScrollOffset,
ScreenSize(mFrameMetrics.mCompositionBounds.Size()) / mFrameMetrics.mZoom));
ParentLayerSize(mFrameMetrics.mCompositionBounds.Size()) / mFrameMetrics.GetZoomToParent()));
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
}
@ -1578,7 +1580,7 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() {
// within rendered content.
if (!gAllowCheckerboarding &&
!mLastContentPaintMetrics.mDisplayPort.IsEmpty()) {
CSSRect compositedRect = mLastContentPaintMetrics.CalculateCompositedRectInCssPixels();
CSSRect compositedRect(mLastContentPaintMetrics.CalculateCompositedRectInCssPixels());
CSSPoint maxScrollOffset = lastPaintScrollOffset +
CSSPoint(mLastContentPaintMetrics.mDisplayPort.XMost() - compositedRect.width,
mLastContentPaintMetrics.mDisplayPort.YMost() - compositedRect.height);
@ -1620,6 +1622,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
ReentrantMonitorAutoEnter lock(mMonitor);
mLastContentPaintMetrics = aLayerMetrics;
UpdateTransformScale();
bool isDefault = mFrameMetrics.IsDefault();
mFrameMetrics.mMayHaveTouchListeners = aLayerMetrics.mMayHaveTouchListeners;
@ -1729,27 +1732,27 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
{
ReentrantMonitorAutoEnter lock(mMonitor);
ScreenIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
ParentLayerIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
CSSRect cssPageRect = mFrameMetrics.mScrollableRect;
CSSPoint scrollOffset = mFrameMetrics.mScrollOffset;
CSSToScreenScale currentZoom = mFrameMetrics.mZoom;
CSSToScreenScale targetZoom;
CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoomToParent();
CSSToParentLayerScale targetZoom;
// The minimum zoom to prevent over-zoom-out.
// If the zoom factor is lower than this (i.e. we are zoomed more into the page),
// then the CSS content rect, in layers pixels, will be smaller than the
// composition bounds. If this happens, we can't fill the target composited
// area with this frame.
CSSToScreenScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale,
std::max(compositionBounds.width / cssPageRect.width,
compositionBounds.height / cssPageRect.height)));
CSSToScreenScale localMaxZoom = mZoomConstraints.mMaxZoom;
CSSToParentLayerScale localMinZoom(std::max((mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale).scale,
std::max(compositionBounds.width / cssPageRect.width,
compositionBounds.height / cssPageRect.height)));
CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale;
if (!aRect.IsEmpty()) {
// Intersect the zoom-to-rect to the CSS rect to make sure it fits.
aRect = aRect.Intersect(cssPageRect);
targetZoom = CSSToScreenScale(std::min(compositionBounds.width / aRect.width,
compositionBounds.height / aRect.height));
targetZoom = CSSToParentLayerScale(std::min(compositionBounds.width / aRect.width,
compositionBounds.height / aRect.height));
}
// 1. If the rect is empty, request received from browserElementScrolling.js
// 2. currentZoom is equal to mZoomConstraints.mMaxZoom and user still double-tapping it
@ -1758,27 +1761,27 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
if (aRect.IsEmpty() ||
(currentZoom == localMaxZoom && targetZoom >= localMaxZoom) ||
(currentZoom == localMinZoom && targetZoom <= localMinZoom)) {
CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
CSSRect compositedRect = CSSRect(mFrameMetrics.CalculateCompositedRectInCssPixels());
float y = scrollOffset.y;
float newHeight =
cssPageRect.width * (compositedRect.height / compositedRect.width);
float dh = compositedRect.height - newHeight;
aRect = CSSRect(0.0f,
y + dh/2,
cssPageRect.width,
newHeight);
y + dh/2,
cssPageRect.width,
newHeight);
aRect = aRect.Intersect(cssPageRect);
targetZoom = CSSToScreenScale(std::min(compositionBounds.width / aRect.width,
compositionBounds.height / aRect.height));
targetZoom = CSSToParentLayerScale(std::min(compositionBounds.width / aRect.width,
compositionBounds.height / aRect.height));
}
targetZoom.scale = clamped(targetZoom.scale, localMinZoom.scale, localMaxZoom.scale);
FrameMetrics endZoomToMetrics = mFrameMetrics;
endZoomToMetrics.mZoom = targetZoom;
endZoomToMetrics.mZoom = targetZoom / mFrameMetrics.mTransformScale;
// Adjust the zoomToRect to a sensible position to prevent overscrolling.
CSSRect rectAfterZoom = endZoomToMetrics.CalculateCompositedRectInCssPixels();
CSSRect rectAfterZoom = CSSRect(endZoomToMetrics.CalculateCompositedRectInCssPixels());
// If either of these conditions are met, the page will be
// overscrolled after zoomed
@ -1988,7 +1991,7 @@ void AsyncPanZoomController::SendAsyncScrollEvent() {
isRoot = mFrameMetrics.mIsRoot;
scrollableSize = mFrameMetrics.mScrollableRect.Size();
contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
contentRect = CSSRect(mFrameMetrics.CalculateCompositedRectInCssPixels());
contentRect.MoveTo(mCurrentAsyncScrollOffset);
}
@ -2071,5 +2074,19 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() {
}
}
ParentLayerPoint AsyncPanZoomController::ToParentLayerCoords(const ScreenPoint& aPoint)
{
return TransformTo<ParentLayerPixel>(GetNontransientAsyncTransform() * GetCSSTransform(), aPoint);
}
void AsyncPanZoomController::UpdateTransformScale()
{
gfx3DMatrix nontransientTransforms = GetNontransientAsyncTransform() * GetCSSTransform();
if (!FuzzyEqualsMultiplicative(nontransientTransforms.GetXScale(), nontransientTransforms.GetYScale())) {
NS_WARNING("The x- and y-scales of the nontransient transforms should be equal");
}
mFrameMetrics.mTransformScale.scale = nontransientTransforms.GetXScale();
}
}
}

View File

@ -615,6 +615,16 @@ private:
static AxisLockMode GetAxisLockMode();
// Convert a point from local screen coordinates to parent layer coordinates.
// This is a common operation as inputs from the tree manager are in screen
// coordinates but the composition bounds is in parent layer coordinates.
ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint);
// Update mFrameMetrics.mTransformScale. This should be called whenever
// our CSS transform or the non-transient part of our async transform
// changes, as it corresponds to the scale portion of those transforms.
void UpdateTransformScale();
uint64_t mLayersId;
nsRefPtr<CompositorParent> mCompositorParent;
PCompositorParent* mCrossProcessCompositorParent;
@ -690,7 +700,7 @@ private:
// Stores the previous focus point if there is a pinch gesture happening. Used
// to allow panning by moving multiple fingers (thus moving the focus point).
ScreenPoint mLastZoomFocus;
ParentLayerPoint mLastZoomFocus;
// Stores the state of panning and zooming this frame. This is protected by
// |mMonitor|; that is, it should be held whenever this is updated.
@ -790,11 +800,12 @@ private:
* hit-testing to see which APZC instance should handle touch events.
*/
public:
void SetLayerHitTestData(const ScreenRect& aRect, const gfx3DMatrix& aTransformToLayer,
void SetLayerHitTestData(const ParentLayerRect& aRect, const gfx3DMatrix& aTransformToLayer,
const gfx3DMatrix& aTransformForLayer) {
mVisibleRect = aRect;
mAncestorTransform = aTransformToLayer;
mCSSTransform = aTransformForLayer;
UpdateTransformScale();
}
gfx3DMatrix GetAncestorTransform() const {
@ -805,7 +816,7 @@ public:
return mCSSTransform;
}
bool VisibleRegionContains(const ScreenPoint& aPoint) const {
bool VisibleRegionContains(const ParentLayerPoint& aPoint) const {
return mVisibleRect.Contains(aPoint);
}
@ -816,7 +827,7 @@ private:
/* This is the visible region of the layer that this APZC corresponds to, in
* that layer's screen pixels (the same coordinate system in which this APZC
* receives events in ReceiveInputEvent()). */
ScreenRect mVisibleRect;
ParentLayerRect mVisibleRect;
/* This is the cumulative CSS transform for all the layers between the parent
* APZC and this one (not inclusive) */
gfx3DMatrix mAncestorTransform;

View File

@ -269,7 +269,7 @@ float Axis::GetOrigin() {
float Axis::GetCompositionLength() {
const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
CSSRect cssCompositedRect = metrics.CalculateCompositedRectInCssPixels();
CSSRect cssCompositedRect = CSSRect(metrics.CalculateCompositedRectInCssPixels());
return GetRectLength(cssCompositedRect);
}
@ -286,7 +286,7 @@ float Axis::GetPageLength() {
bool Axis::ScaleWillOverscrollBothSides(float aScale) {
const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
CSSToScreenScale scale(metrics.mZoom.scale * aScale);
CSSToParentLayerScale scale(metrics.GetZoomToParent().scale * aScale);
CSSRect cssCompositionBounds = metrics.mCompositionBounds / scale;
return GetRectLength(metrics.mScrollableRect) < GetRectLength(cssCompositionBounds);

View File

@ -156,7 +156,7 @@ FrameMetrics TestFrameMetrics() {
FrameMetrics fm;
fm.mDisplayPort = CSSRect(0, 0, 10, 10);
fm.mCompositionBounds = ScreenIntRect(0, 0, 10, 10);
fm.mCompositionBounds = ParentLayerIntRect(0, 0, 10, 10);
fm.mCriticalDisplayPort = CSSRect(0, 0, 10, 10);
fm.mScrollableRect = CSSRect(0, 0, 100, 100);
fm.mViewport = CSSRect(0, 0, 10, 10);
@ -347,7 +347,7 @@ TEST(AsyncPanZoomController, Pinch) {
FrameMetrics fm;
fm.mViewport = CSSRect(0, 0, 980, 480);
fm.mCompositionBounds = ScreenIntRect(200, 200, 100, 200);
fm.mCompositionBounds = ParentLayerIntRect(200, 200, 100, 200);
fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
fm.mScrollOffset = CSSPoint(300, 300);
fm.mZoom = CSSToScreenScale(2.0);
@ -390,7 +390,7 @@ TEST(AsyncPanZoomController, PinchWithTouchActionNone) {
FrameMetrics fm;
fm.mViewport = CSSRect(0, 0, 980, 480);
fm.mCompositionBounds = ScreenIntRect(200, 200, 100, 200);
fm.mCompositionBounds = ParentLayerIntRect(200, 200, 100, 200);
fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
fm.mScrollOffset = CSSPoint(300, 300);
fm.mZoom = CSSToScreenScale(2.0);
@ -424,7 +424,7 @@ TEST(AsyncPanZoomController, Overzoom) {
FrameMetrics fm;
fm.mViewport = CSSRect(0, 0, 100, 100);
fm.mCompositionBounds = ScreenIntRect(0, 0, 100, 100);
fm.mCompositionBounds = ParentLayerIntRect(0, 0, 100, 100);
fm.mScrollableRect = CSSRect(0, 0, 125, 150);
fm.mScrollOffset = CSSPoint(10, 0);
fm.mZoom = CSSToScreenScale(1.0);
@ -502,7 +502,7 @@ TEST(AsyncPanZoomController, ComplexTransform) {
nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
FrameMetrics metrics;
metrics.mCompositionBounds = ScreenIntRect(0, 0, 24, 24);
metrics.mCompositionBounds = ParentLayerIntRect(0, 0, 24, 24);
metrics.mDisplayPort = CSSRect(-1, -1, 6, 6);
metrics.mViewport = CSSRect(0, 0, 4, 4);
metrics.mScrollOffset = CSSPoint(10, 10);
@ -929,8 +929,8 @@ SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId,
FrameMetrics metrics;
metrics.mScrollId = aScrollId;
nsIntRect layerBound = aLayer->GetVisibleRegion().GetBounds();
metrics.mCompositionBounds = ScreenIntRect(layerBound.x, layerBound.y,
layerBound.width, layerBound.height);
metrics.mCompositionBounds = ParentLayerIntRect(layerBound.x, layerBound.y,
layerBound.width, layerBound.height);
metrics.mScrollableRect = aScrollableRect;
metrics.mScrollOffset = CSSPoint(0, 0);
container->SetFrameMetrics(metrics);

View File

@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZ_UNIT_TRANSFORMS_H_
#define MOZ_UNIT_TRANSFORMS_H_
#include "Units.h"
namespace mozilla {
// Convenience functions for converting an entity from one strongly-typed
// coordinate system to another without changing the values it stores (this
// can be thought of as a cast).
// To use these functions, you must provide a justification for each use!
// Feel free to add more justifications to PixelCastJustification, along with
// a comment that explains under what circumstances it is appropriate to use.
MOZ_BEGIN_ENUM_CLASS(PixelCastJustification, uint8_t)
// For the root layer, Screen Pixel = Parent Layer Pixel.
ScreenToParentLayerForRoot
MOZ_END_ENUM_CLASS(PixelCastJustification)
template <class TargetUnits, class SourceUnits>
gfx::SizeTyped<TargetUnits> ViewAs(const gfx::SizeTyped<SourceUnits>& aSize, PixelCastJustification) {
return gfx::SizeTyped<TargetUnits>(aSize.width, aSize.height);
}
template <class TargetUnits, class SourceUnits>
gfx::IntSizeTyped<TargetUnits> ViewAs(const gfx::IntSizeTyped<SourceUnits>& aSize, PixelCastJustification) {
return gfx::IntSizeTyped<TargetUnits>(aSize.width, aSize.height);
}
// Convenience functions for casting untyped entities to typed entities.
// Using these functions does not require a justification, but once we convert
// all code to use strongly typed units they should not be needed any longer.
template <class TargetUnits>
gfx::PointTyped<TargetUnits> ViewAs(const gfxPoint& aPoint) {
return gfx::PointTyped<TargetUnits>(aPoint.x, aPoint.y);
}
template <class TargetUnits>
gfx::RectTyped<TargetUnits> ViewAs(const gfxRect& aRect) {
return gfx::RectTyped<TargetUnits>(aRect.x, aRect.y, aRect.width, aRect.height);
}
// Convenience functions for casting typed entities to untyped entities.
// Using these functions does not require a justification, but once we convert
// all code to use strongly typed units they should not be needed any longer.
template <class SourceUnits>
gfxPoint ViewAsUntyped(const gfx::PointTyped<SourceUnits>& aPoint) {
return gfxPoint(aPoint.x, aPoint.y);
}
template <class SourceUnits>
gfxRect ViewAsUntyped(const gfx::RectTyped<SourceUnits>& aRect) {
return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
}
// Convenience functions for transforming an entity from one strongly-typed
// coordinate system to another using the provided transformation matrix.
template <typename TargetUnits, typename SourceUnits>
static gfx::PointTyped<TargetUnits> TransformTo(const gfx3DMatrix& aTransform,
const gfx::PointTyped<SourceUnits>& aPoint)
{
return ViewAs<TargetUnits>(aTransform.Transform(ViewAsUntyped(aPoint)));
}
template <typename TargetUnits, typename SourceUnits>
static gfx::RectTyped<TargetUnits> TransformTo(const gfx3DMatrix& aTransform,
const gfx::RectTyped<SourceUnits>& aRect)
{
return ViewAs<TargetUnits>(aTransform.TransformBounds(ViewAsUntyped(aRect)));
}
}
#endif

View File

@ -277,6 +277,6 @@ gfx::MarginTyped<dst> operator/(const gfx::MarginTyped<src>& aMargin, const gfx:
aMargin.left / aScale.scale);
}
};
}
#endif

View File

@ -56,6 +56,7 @@ EXPORTS += [
'ScrollbarStyles.h',
'StackArena.h',
'Units.h',
'UnitTransforms.h',
]
EXPORTS.mozilla += [

View File

@ -625,15 +625,6 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
}
}
static void AdjustForScrollBars(ScreenIntRect& aToAdjust, nsIScrollableFrame* aScrollableFrame) {
if (aScrollableFrame && !LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars)) {
nsMargin sizes = aScrollableFrame->GetActualScrollbarSizes();
// Scrollbars are not subject to scaling, so CSS pixels = screen pixels for them.
ScreenIntMargin boundMargins = RoundedToInt(CSSMargin::FromAppUnits(sizes) * CSSToScreenScale(1.0f));
aToAdjust.Deflate(boundMargins);
}
}
static bool gPrintApzcTree = false;
static bool GetApzcTreePrintPref() {
@ -759,33 +750,41 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
nsRect compositionBounds(frameForCompositionBoundsCalculation->GetOffsetToCrossDoc(aReferenceFrame),
frameForCompositionBoundsCalculation->GetSize());
metrics.mCompositionBounds = RoundedToInt(LayoutDeviceRect::FromAppUnits(compositionBounds, auPerDevPixel)
* metrics.mCumulativeResolution
* layerToScreenScale);
* metrics.GetParentResolution());
// For the root scroll frame of the root content document, clamp the
// composition bounds to the widget bounds. This is necessary because, if
// the page is zoomed in, the frame's size might be larger than the widget
// bounds, but we don't want the composition bounds to be.
bool useWidgetBounds = false;
// For the root scroll frame of the root content document, the above calculation
// will yield the size of the viewport frame as the composition bounds, which
// doesn't actually correspond to what is visible when
// nsIDOMWindowUtils::setCSSViewport has been called to modify the visible area of
// the prescontext that the viewport frame is reflowed into. In that case if our
// document has a widget then the widget's bounds will correspond to what is
// visible. If we don't have a widget the root view's bounds correspond to what
// would be visible because they don't get modified by setCSSViewport.
bool isRootContentDocRootScrollFrame = presContext->IsRootContentDocument()
&& aScrollFrame == presShell->GetRootScrollFrame();
if (isRootContentDocRootScrollFrame) {
if (nsIWidget* widget = aForFrame->GetNearestWidget()) {
nsIntRect bounds;
widget->GetBounds(bounds);
ScreenIntRect screenBounds = ScreenIntRect::FromUnknownRect(mozilla::gfx::IntRect(
bounds.x, bounds.y, bounds.width, bounds.height));
AdjustForScrollBars(screenBounds, scrollableFrame);
metrics.mCompositionBounds = metrics.mCompositionBounds.ForceInside(screenBounds);
useWidgetBounds = true;
if (nsIFrame* rootFrame = presShell->GetRootFrame()) {
if (nsView* view = rootFrame->GetView()) {
nsIWidget* widget = view->GetWidget();
if (widget) {
nsIntRect bounds;
widget->GetBounds(bounds);
metrics.mCompositionBounds = ParentLayerIntRect::FromUnknownRect(mozilla::gfx::IntRect(
bounds.x, bounds.y, bounds.width, bounds.height));
} else {
metrics.mCompositionBounds = RoundedToInt(LayoutDeviceRect::FromAppUnits(view->GetBounds(), auPerDevPixel)
* metrics.GetParentResolution());
}
}
}
}
// Adjust composition bounds for the size of scroll bars.
// If the widget bounds were used to clamp the composition bounds,
// this adjustment was already made to the widget bounds.
if (!useWidgetBounds) {
AdjustForScrollBars(metrics.mCompositionBounds, scrollableFrame);
if (scrollableFrame && !LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars)) {
nsMargin sizes = scrollableFrame->GetActualScrollbarSizes();
// Scrollbars are not subject to scaling, so CSS pixels = layer pixels for them.
ParentLayerIntMargin boundMargins = RoundedToInt(CSSMargin::FromAppUnits(sizes) * CSSToParentLayerScale(1.0f));
metrics.mCompositionBounds.Deflate(boundMargins);
}
if (GetApzcTreePrintPref()) {

View File

@ -1835,7 +1835,7 @@ AndroidBridge::IsContentDocumentDisplayed()
}
bool
AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, ScreenRect& aCompositionBounds, CSSToScreenScale& aZoom)
AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, ParentLayerRect& aCompositionBounds, CSSToParentLayerScale& aZoom)
{
GeckoLayerClient *client = mLayerClient;
if (!client) {

View File

@ -202,7 +202,7 @@ public:
void ContentDocumentChanged();
bool IsContentDocumentDisplayed();
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, ScreenRect& aCompositionBounds, CSSToScreenScale& aZoom);
bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, ParentLayerRect& aCompositionBounds, CSSToParentLayerScale& aZoom);
void SetLayerClient(JNIEnv* env, jobject jobj);
GeckoLayerClient* GetLayerClient() { return mLayerClient; }

View File

@ -91,7 +91,7 @@ MaybeAlignAndClampDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics,
static void
RecenterDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics)
{
CSSRect compositionBounds = aFrameMetrics.CalculateCompositedRectInCssPixels();
CSSRect compositionBounds(aFrameMetrics.CalculateCompositedRectInCssPixels());
aFrameMetrics.mDisplayPort.x = (compositionBounds.width - aFrameMetrics.mDisplayPort.width) / 2;
aFrameMetrics.mDisplayPort.y = (compositionBounds.height - aFrameMetrics.mDisplayPort.height) / 2;
}
@ -156,7 +156,7 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
// be 1000 pixels long but the frame would still be 100 pixels, and so the maximum
// scroll range would be 900. Therefore this calculation depends on the zoom applied
// to the content relative to the container.
CSSSize scrollPort = aMetrics.CalculateCompositedRectInCssPixels().Size();
CSSSize scrollPort = CSSSize(aMetrics.CalculateCompositedRectInCssPixels().Size());
aUtils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
// Scroll the window to the desired spot
@ -189,7 +189,7 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
// Finally, we multiply by a ScreenToLayerScale of 1.0f because the goal here is to
// take the async zoom calculated by the APZC and tell gecko about it (turning it into
// a "sync" zoom) which will update the resolution at which the layer is painted.
mozilla::layers::ParentLayerToLayerScale presShellResolution =
ParentLayerToLayerScale presShellResolution =
aMetrics.mZoom
/ aMetrics.mDevPixelsPerCSSPixel
/ aMetrics.GetParentResolution()