Bug 915985 - Refactoring to introduce a ZoomConstraints class. r=botond

This commit is contained in:
Kartikaya Gupta 2014-01-06 13:26:44 -05:00
parent ec4092c0d6
commit 9ae1485883
15 changed files with 118 additions and 103 deletions

View File

@ -24,6 +24,7 @@ using struct gfxSize from "gfxPoint.h";
using CSSRect from "Units.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
using struct mozilla::layers::ZoomConstraints from "FrameMetrics.h";
using FrameMetrics::ViewID from "FrameMetrics.h";
using mozilla::layout::ScrollingBehavior from "mozilla/layout/RenderFrameUtils.h";
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
@ -301,7 +302,7 @@ parent:
* have up-to-date zoom constraints.
*/
UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId, bool aIsRoot,
bool aAllowZoom, CSSToScreenScale aMinZoom, CSSToScreenScale aMaxZoom);
ZoomConstraints aConstraints);
__delete__();

View File

@ -521,12 +521,14 @@ TabChild::HandlePossibleViewportChange()
ViewID viewId;
if (APZCCallbackHelper::GetScrollIdentifiers(document->GetDocumentElement(),
&presShellId, &viewId)) {
ZoomConstraints constraints(
viewportInfo.IsZoomAllowed(),
viewportInfo.GetMinZoom(),
viewportInfo.GetMaxZoom());
SendUpdateZoomConstraints(presShellId,
viewId,
/* isRoot = */ true,
viewportInfo.IsZoomAllowed(),
viewportInfo.GetMinZoom(),
viewportInfo.GetMaxZoom());
constraints);
}

View File

@ -1713,12 +1713,10 @@ bool
TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const bool& aIsRoot,
const bool& aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom)
const ZoomConstraints& aConstraints)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aAllowZoom, aMinZoom, aMaxZoom);
rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aConstraints);
}
return true;
}

View File

@ -168,9 +168,7 @@ public:
virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const bool& aIsRoot,
const bool& aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom);
const ZoomConstraints& aConstraints);
virtual bool RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
const bool& aPreventDefault);
virtual PContentDialogParent* AllocPContentDialogParent(const uint32_t& aType,

View File

@ -685,6 +685,26 @@ struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
}
};
template <>
struct ParamTraits<mozilla::layers::ZoomConstraints>
{
typedef mozilla::layers::ZoomConstraints paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mAllowZoom);
WriteParam(aMsg, aParam.mMinZoom);
WriteParam(aMsg, aParam.mMaxZoom);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return (ReadParam(aMsg, aIter, &aResult->mAllowZoom) &&
ReadParam(aMsg, aIter, &aResult->mMinZoom) &&
ReadParam(aMsg, aIter, &aResult->mMaxZoom));
}
};
template <>
struct ParamTraits<mozilla::layers::EventRegions>
{

View File

@ -349,6 +349,45 @@ struct ScrollableLayerGuid {
}
};
struct ZoomConstraints {
bool mAllowZoom;
CSSToScreenScale mMinZoom;
CSSToScreenScale mMaxZoom;
ZoomConstraints()
: mAllowZoom(true)
{
MOZ_COUNT_CTOR(ZoomConstraints);
}
ZoomConstraints(bool aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom)
: mAllowZoom(aAllowZoom)
, mMinZoom(aMinZoom)
, mMaxZoom(aMaxZoom)
{
MOZ_COUNT_CTOR(ZoomConstraints);
}
~ZoomConstraints()
{
MOZ_COUNT_DTOR(ZoomConstraints);
}
bool operator==(const ZoomConstraints& other) const
{
return mAllowZoom == other.mAllowZoom
&& mMinZoom == other.mMinZoom
&& mMaxZoom == other.mMaxZoom;
}
bool operator!=(const ZoomConstraints& other) const
{
return !(*this == other);
}
};
}
}

View File

@ -191,22 +191,20 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
aParent = apzc;
if (newApzc) {
bool allowZoom;
CSSToScreenScale minZoom, maxZoom;
if (apzc->IsRootForLayersId()) {
// If we just created a new apzc that is the root for its layers ID, then
// we need to update its zoom constraints which might have arrived before this
// was created
if (state->mController->GetRootZoomConstraints(&allowZoom, &minZoom, &maxZoom)) {
apzc->UpdateZoomConstraints(allowZoom, minZoom, maxZoom);
ZoomConstraints constraints;
if (state->mController->GetRootZoomConstraints(&constraints)) {
apzc->UpdateZoomConstraints(constraints);
}
} else {
// For an apzc that is not the root for its layers ID, we give it the
// same zoom constraints as its parent. This ensures that if e.g.
// user-scalable=no was specified, none of the APZCs allow double-tap
// to zoom.
apzc->GetParent()->GetZoomConstraints(&allowZoom, &minZoom, &maxZoom);
apzc->UpdateZoomConstraints(allowZoom, minZoom, maxZoom);
apzc->UpdateZoomConstraints(apzc->GetParent()->GetZoomConstraints());
}
}
}
@ -576,32 +574,28 @@ APZCTreeManager::ContentReceivedTouch(const ScrollableLayerGuid& aGuid,
void
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
bool aAllowZoom,
const CSSToScreenScale& aMinScale,
const CSSToScreenScale& aMaxScale)
const ZoomConstraints& aConstraints)
{
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
// For a given layers id, non-root APZCs inherit the zoom constraints
// of their root.
if (apzc && apzc->IsRootForLayersId()) {
MonitorAutoLock lock(mTreeLock);
UpdateZoomConstraintsRecursively(apzc.get(), aAllowZoom, aMinScale, aMaxScale);
UpdateZoomConstraintsRecursively(apzc.get(), aConstraints);
}
}
void
APZCTreeManager::UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
bool aAllowZoom,
const CSSToScreenScale& aMinScale,
const CSSToScreenScale& aMaxScale)
const ZoomConstraints& aConstraints)
{
mTreeLock.AssertCurrentThreadOwns();
aApzc->UpdateZoomConstraints(aAllowZoom, aMinScale, aMaxScale);
aApzc->UpdateZoomConstraints(aConstraints);
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
// We can have subtrees with their own layers id - leave those alone.
if (!child->IsRootForLayersId()) {
UpdateZoomConstraintsRecursively(child, aAllowZoom, aMinScale, aMaxScale);
UpdateZoomConstraintsRecursively(child, aConstraints);
}
}
}

View File

@ -153,13 +153,9 @@ public:
/**
* Updates any zoom constraints contained in the <meta name="viewport"> tag.
* We try to obey everything it asks us elsewhere, but here we only handle
* minimum-scale, maximum-scale, and user-scalable.
*/
void UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
bool aAllowZoom,
const CSSToScreenScale& aMinScale,
const CSSToScreenScale& aMaxScale);
const ZoomConstraints& aConstraints);
/**
* Cancels any currently running animation. Note that all this does is set the
@ -265,9 +261,7 @@ private:
nsEventStatus ProcessMouseEvent(const WidgetMouseEvent& mouseEvent, ScrollableLayerGuid* aOutTargetGuid, WidgetMouseEvent* aOutEvent);
nsEventStatus ProcessEvent(const WidgetInputEvent& inputEvent, ScrollableLayerGuid* aOutTargetGuid, WidgetInputEvent* aOutEvent);
void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
bool aAllowZoom,
const CSSToScreenScale& aMinScale,
const CSSToScreenScale& aMaxScale);
const ZoomConstraints& aConstraints);
/**
* Recursive helper function to build the APZC tree. The tree of APZC instances has

View File

@ -395,9 +395,7 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
mTouchListenerTimeoutTask(nullptr),
mX(MOZ_THIS_IN_INITIALIZER_LIST()),
mY(MOZ_THIS_IN_INITIALIZER_LIST()),
mAllowZoom(true),
mMinZoom(MIN_ZOOM),
mMaxZoom(MAX_ZOOM),
mZoomConstraints(true, MIN_ZOOM, MAX_ZOOM),
mLastSampleTime(GetFrameTime()),
mState(NOTHING),
mLastAsyncScrollTime(GetFrameTime()),
@ -416,7 +414,7 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
mGestureEventListener = new GestureEventListener(this);
}
if (gAsyncZoomDisabled) {
mAllowZoom = false;
mZoomConstraints.mAllowZoom = false;
}
}
@ -713,7 +711,7 @@ nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEven
nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) {
APZC_LOG("%p got a scale-begin in state %d\n", this, mState);
if (!mAllowZoom) {
if (!mZoomConstraints.mAllowZoom) {
return nsEventStatus_eConsumeNoDefault;
}
@ -760,8 +758,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
// either axis such that we don't overscroll the boundaries when zooming.
CSSPoint neededDisplacement;
CSSToScreenScale realMinZoom = mMinZoom;
CSSToScreenScale realMaxZoom = mMaxZoom;
CSSToScreenScale realMinZoom = mZoomConstraints.mMinZoom;
CSSToScreenScale realMaxZoom = mZoomConstraints.mMaxZoom;
realMinZoom.scale = std::max(realMinZoom.scale,
mFrameMetrics.mCompositionBounds.width / mFrameMetrics.mScrollableRect.width);
realMinZoom.scale = std::max(realMinZoom.scale,
@ -878,9 +876,9 @@ nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEven
nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
// If mAllowZoom is true we wait for a call to OnSingleTapConfirmed before
// If mZoomConstraints.mAllowZoom is true we wait for a call to OnSingleTapConfirmed before
// sending event to content
if (controller && !mAllowZoom) {
if (controller && !mZoomConstraints.mAllowZoom) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
@ -909,7 +907,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent)
APZC_LOG("%p got a double-tap in state %d\n", this, mState);
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
if (mAllowZoom) {
if (mZoomConstraints.mAllowZoom) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
@ -1546,10 +1544,10 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
// 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(mMinZoom.scale,
CSSToScreenScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale,
std::max(compositionBounds.width / cssPageRect.width,
compositionBounds.height / cssPageRect.height)));
CSSToScreenScale localMaxZoom = mMaxZoom;
CSSToScreenScale localMaxZoom = mZoomConstraints.mMaxZoom;
if (!aRect.IsEmpty()) {
// Intersect the zoom-to-rect to the CSS rect to make sure it fits.
@ -1558,7 +1556,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
compositionBounds.height / aRect.height));
}
// 1. If the rect is empty, request received from browserElementScrolling.js
// 2. currentZoom is equal to mMaxZoom and user still double-tapping it
// 2. currentZoom is equal to mZoomConstraints.mMaxZoom and user still double-tapping it
// 3. currentZoom is equal to localMinZoom and user still double-tapping it
// Treat these three cases as a request to zoom out as much as possible.
if (aRect.IsEmpty() ||
@ -1687,25 +1685,19 @@ void AsyncPanZoomController::TimeoutTouchListeners() {
ContentReceivedTouch(false);
}
void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom) {
void AsyncPanZoomController::UpdateZoomConstraints(const ZoomConstraints& aConstraints) {
if (gAsyncZoomDisabled) {
return;
}
mAllowZoom = aAllowZoom;
mMinZoom = (MIN_ZOOM > aMinZoom ? MIN_ZOOM : aMinZoom);
mMaxZoom = (MAX_ZOOM > aMaxZoom ? aMaxZoom : MAX_ZOOM);
mZoomConstraints.mAllowZoom = aConstraints.mAllowZoom;
mZoomConstraints.mMinZoom = (MIN_ZOOM > aConstraints.mMinZoom ? MIN_ZOOM : aConstraints.mMinZoom);
mZoomConstraints.mMaxZoom = (MAX_ZOOM > aConstraints.mMaxZoom ? aConstraints.mMaxZoom : MAX_ZOOM);
}
void
AsyncPanZoomController::GetZoomConstraints(bool* aAllowZoom,
CSSToScreenScale* aMinZoom,
CSSToScreenScale* aMaxZoom)
ZoomConstraints
AsyncPanZoomController::GetZoomConstraints() const
{
*aAllowZoom = mAllowZoom;
*aMinZoom = mMinZoom;
*aMaxZoom = mMaxZoom;
return mZoomConstraints;
}

View File

@ -130,20 +130,14 @@ public:
/**
* Updates any zoom constraints contained in the <meta name="viewport"> tag.
* We try to obey everything it asks us elsewhere, but here we only handle
* minimum-scale, maximum-scale, and user-scalable.
*/
void UpdateZoomConstraints(bool aAllowZoom,
const CSSToScreenScale& aMinScale,
const CSSToScreenScale& aMaxScale);
void UpdateZoomConstraints(const ZoomConstraints& aConstraints);
/**
* Return the zoom constraints last set for this APZC (in the constructor
* or in UpdateZoomConstraints()).
*/
void GetZoomConstraints(bool* aAllowZoom,
CSSToScreenScale* aMinScale,
CSSToScreenScale* aMaxScale);
ZoomConstraints GetZoomConstraints() const;
/**
* Schedules a runnable to run on the controller/UI thread at some time
@ -609,9 +603,7 @@ private:
// Most up-to-date constraints on zooming. These should always be reasonable
// values; for example, allowing a min zoom of 0.0 can cause very bad things
// to happen.
bool mAllowZoom;
CSSToScreenScale mMinZoom;
CSSToScreenScale mMaxZoom;
ZoomConstraints mZoomConstraints;
// The last time the compositor has sampled the content transform for this
// frame.

View File

@ -76,9 +76,7 @@ public:
* for this layers tree. This function should return false if there are no
* last known zoom constraints.
*/
virtual bool GetRootZoomConstraints(bool* aOutAllowZoom,
CSSToScreenScale* aOutMinZoom,
CSSToScreenScale* aOutMaxZoom)
virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
{
return false;
}

View File

@ -484,7 +484,7 @@ TEST(AsyncPanZoomController, ShortPress) {
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0));
apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0)).Times(1);
@ -503,7 +503,7 @@ TEST(AsyncPanZoomController, MediumPress) {
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0));
apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0)).Times(1);
@ -522,7 +522,7 @@ TEST(AsyncPanZoomController, LongPress) {
apzc->SetFrameMetrics(TestFrameMetrics());
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
apzc->UpdateZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0));
apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
int time = 0;

View File

@ -500,7 +500,6 @@ public:
: mUILoop(MessageLoop::current())
, mRenderFrame(aRenderFrame)
, mHaveZoomConstraints(false)
, mAllowZoom(true)
{ }
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE
@ -611,24 +610,16 @@ public:
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
}
void SaveZoomConstraints(bool aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom)
void SaveZoomConstraints(const ZoomConstraints& aConstraints)
{
mHaveZoomConstraints = true;
mAllowZoom = aAllowZoom;
mMinZoom = aMinZoom;
mMaxZoom = aMaxZoom;
mZoomConstraints = aConstraints;
}
virtual bool GetRootZoomConstraints(bool* aOutAllowZoom,
CSSToScreenScale* aOutMinZoom,
CSSToScreenScale* aOutMaxZoom)
virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
{
if (mHaveZoomConstraints) {
*aOutAllowZoom = mAllowZoom;
*aOutMinZoom = mMinZoom;
*aOutMaxZoom = mMaxZoom;
if (mHaveZoomConstraints && aOutConstraints) {
*aOutConstraints = mZoomConstraints;
}
return mHaveZoomConstraints;
}
@ -676,9 +667,7 @@ private:
RenderFrameParent* mRenderFrame;
bool mHaveZoomConstraints;
bool mAllowZoom;
CSSToScreenScale mMinZoom;
CSSToScreenScale mMaxZoom;
ZoomConstraints mZoomConstraints;
};
RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
@ -1093,16 +1082,14 @@ void
RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
ViewID aViewId,
bool aIsRoot,
bool aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom)
const ZoomConstraints& aConstraints)
{
if (mContentController && aIsRoot) {
mContentController->SaveZoomConstraints(aAllowZoom, aMinZoom, aMaxZoom);
mContentController->SaveZoomConstraints(aConstraints);
}
if (GetApzcTreeManager()) {
GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aAllowZoom, aMinZoom, aMaxZoom);
aConstraints);
}
}

View File

@ -49,6 +49,7 @@ class RenderFrameParent : public PRenderFrameParent,
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
typedef mozilla::layers::TextureFactoryIdentifier TextureFactoryIdentifier;
typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
typedef mozilla::layers::ZoomConstraints ZoomConstraints;
typedef FrameMetrics::ViewID ViewID;
public:
@ -118,9 +119,7 @@ public:
void UpdateZoomConstraints(uint32_t aPresShellId,
ViewID aViewId,
bool aIsRoot,
bool aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom);
const ZoomConstraints& aConstraints);
bool HitTest(const nsRect& aRect);

View File

@ -1615,7 +1615,8 @@ MetroWidget::Observe(nsISupports *subject, const char *topic, const char16_t *da
}
ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId);
APZController::sAPZC->UpdateZoomConstraints(guid, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f));
APZController::sAPZC->UpdateZoomConstraints(guid,
ZoomConstraints(false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f)));
}
return NS_OK;
}