mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-06 06:16:27 +00:00
Bug 949132 - Add a flag to FrameMetrics indicating a non-APZ scroll (original patch by mstange). r=tn
This commit is contained in:
parent
b85de8fde7
commit
4ad1847fb9
@ -87,6 +87,7 @@ GK_ATOM(applet, "applet")
|
||||
GK_ATOM(applyImports, "apply-imports")
|
||||
GK_ATOM(applyTemplates, "apply-templates")
|
||||
GK_ATOM(mozapptype, "mozapptype")
|
||||
GK_ATOM(apz, "apz")
|
||||
GK_ATOM(archive, "archive")
|
||||
GK_ATOM(area, "area")
|
||||
GK_ATOM(arrow, "arrow")
|
||||
|
@ -1636,23 +1636,6 @@ nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aSc
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::ScrollToCSSPixelsApproximate(float aX, float aY, bool* aRetVal)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
|
||||
nsIScrollableFrame* sf = static_cast<nsGlobalWindow*>(window.get())->GetScrollFrame();
|
||||
if (sf) {
|
||||
sf->ScrollToCSSPixelsApproximate(CSSPoint(aX, aY));
|
||||
}
|
||||
if (aRetVal) {
|
||||
*aRetVal = (sf != nullptr);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetScrollXYFloat(bool aFlushLayout, float* aScrollX, float* aScrollY)
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ interface nsIDOMEventTarget;
|
||||
interface nsIRunnable;
|
||||
interface nsICompositionStringSynthesizer;
|
||||
|
||||
[scriptable, uuid(38740b7e-095e-4198-a012-cf5f9e102a6a)]
|
||||
[scriptable, uuid(c6efd629-7282-4f0d-9db8-0fa59c191dd5)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -750,13 +750,6 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
*/
|
||||
void getScrollXYFloat(in boolean aFlushLayout, out float aScrollX, out float aScrollY);
|
||||
|
||||
/**
|
||||
* Sets the scroll position of the root scroll frame of the window.
|
||||
* Returns true on success, false on error (if the window didn't have a root
|
||||
* scroll frame).
|
||||
*/
|
||||
boolean scrollToCSSPixelsApproximate(in float aX, in float aY);
|
||||
|
||||
/**
|
||||
* Returns the scrollbar width of the window's scroll frame.
|
||||
*
|
||||
|
@ -585,6 +585,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
WriteParam(aMsg, aParam.mPresShellId);
|
||||
WriteParam(aMsg, aParam.mIsRoot);
|
||||
WriteParam(aMsg, aParam.mHasScrollgrab);
|
||||
WriteParam(aMsg, aParam.mUpdateScrollOffset);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
@ -603,7 +604,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRoot) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasScrollgrab));
|
||||
ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
, mPresShellId(-1)
|
||||
, mIsRoot(false)
|
||||
, mHasScrollgrab(false)
|
||||
, mUpdateScrollOffset(false)
|
||||
{}
|
||||
|
||||
// Default copy ctor and operator= are fine
|
||||
@ -73,7 +74,8 @@ public:
|
||||
mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel &&
|
||||
mMayHaveTouchListeners == aOther.mMayHaveTouchListeners &&
|
||||
mPresShellId == aOther.mPresShellId &&
|
||||
mIsRoot == aOther.mIsRoot;
|
||||
mIsRoot == aOther.mIsRoot &&
|
||||
mUpdateScrollOffset == aOther.mUpdateScrollOffset;
|
||||
}
|
||||
bool operator!=(const FrameMetrics& aOther) const
|
||||
{
|
||||
@ -284,6 +286,10 @@ public:
|
||||
|
||||
// Whether or not this frame is for an element marked 'scrollgrab'.
|
||||
bool mHasScrollgrab;
|
||||
|
||||
// Whether mScrollOffset was updated by something other than the APZ code, and
|
||||
// if the APZC receiving this metrics should update its local copy.
|
||||
bool mUpdateScrollOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -630,6 +630,13 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
||||
metrics.mScrollableRect = CSSRect::FromAppUnits(contentBounds);
|
||||
nsPoint scrollPosition = scrollableFrame->GetScrollPosition();
|
||||
metrics.mScrollOffset = CSSPoint::FromAppUnits(scrollPosition);
|
||||
|
||||
// If the frame was scrolled since the last layers update, and by
|
||||
// something other than the APZ code, we want to tell the APZ to update
|
||||
// its scroll offset.
|
||||
nsIAtom* originOfLastScroll = scrollableFrame->OriginOfLastScroll();
|
||||
metrics.mUpdateScrollOffset = (originOfLastScroll && originOfLastScroll != nsGkAtoms::apz);
|
||||
scrollableFrame->ResetOriginOfLastScroll();
|
||||
}
|
||||
else {
|
||||
nsRect contentBounds = aForFrame->GetRect();
|
||||
|
@ -1537,6 +1537,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter,
|
||||
, mResizerBox(nullptr)
|
||||
, mOuter(aOuter)
|
||||
, mAsyncScroll(nullptr)
|
||||
, mOriginOfLastScroll(nullptr)
|
||||
, mDestination(0, 0)
|
||||
, mScrollPosAtLastPaint(0, 0)
|
||||
, mRestorePos(-1, -1)
|
||||
@ -1652,12 +1653,13 @@ ScrollFrameHelper::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition)
|
||||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::ScrollToCSSPixelsApproximate(const CSSPoint& aScrollPosition)
|
||||
ScrollFrameHelper::ScrollToCSSPixelsApproximate(const CSSPoint& aScrollPosition,
|
||||
nsIAtom *aOrigin)
|
||||
{
|
||||
nsPoint pt = CSSPoint::ToAppUnits(aScrollPosition);
|
||||
nscoord halfRange = nsPresContext::CSSPixelsToAppUnits(1000);
|
||||
nsRect range(pt.x - halfRange, pt.y - halfRange, 2*halfRange - 1, 2*halfRange - 1);
|
||||
ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
|
||||
ScrollToWithOrigin(pt, nsIScrollableFrame::INSTANT, aOrigin, &range);
|
||||
// 'this' might be destroyed here
|
||||
}
|
||||
|
||||
@ -1687,7 +1689,7 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition,
|
||||
// async-scrolling process and do an instant scroll.
|
||||
mAsyncScroll = nullptr;
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
ScrollToImpl(mDestination, range);
|
||||
ScrollToImpl(mDestination, range, aOrigin);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
@ -1707,7 +1709,7 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition,
|
||||
mAsyncScroll = nullptr;
|
||||
// Observer setup failed. Scroll the normal way.
|
||||
nsWeakFrame weakFrame(mOuter);
|
||||
ScrollToImpl(mDestination, range);
|
||||
ScrollToImpl(mDestination, range, aOrigin);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return;
|
||||
}
|
||||
@ -1982,8 +1984,15 @@ ScrollFrameHelper::ScheduleSyntheticMouseMove()
|
||||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange)
|
||||
ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOrigin)
|
||||
{
|
||||
if (aOrigin == nullptr) {
|
||||
// If no origin was specified, we still want to set it to something that's
|
||||
// non-null, so that we can use nullness to distinguish if the frame was scrolled
|
||||
// at all. Default it to some generic placeholder.
|
||||
aOrigin = nsGkAtoms::other;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = mOuter->PresContext();
|
||||
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
// 'scale' is our estimate of the scale factor that will be applied
|
||||
@ -2038,6 +2047,7 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange)
|
||||
nsPoint oldScrollFramePos = mScrolledFrame->GetPosition();
|
||||
// Update frame position for scrolling
|
||||
mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt);
|
||||
mOriginOfLastScroll = aOrigin;
|
||||
|
||||
// We pass in the amount to move visually
|
||||
ScrollVisual(oldScrollFramePos);
|
||||
|
@ -191,13 +191,14 @@ public:
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition);
|
||||
void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
|
||||
nsIAtom* aOrigin = nullptr);
|
||||
|
||||
CSSIntPoint GetScrollPositionCSSPixels();
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange);
|
||||
void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange, nsIAtom* aOrigin = nullptr);
|
||||
void ScrollVisual(nsPoint aOldScrolledFramePosition);
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
@ -305,6 +306,9 @@ public:
|
||||
|
||||
void HandleScrollbarStyleSwitching();
|
||||
|
||||
nsIAtom* OriginOfLastScroll() const { return mOriginOfLastScroll; }
|
||||
void ResetOriginOfLastScroll() { mOriginOfLastScroll = nullptr; }
|
||||
|
||||
// owning references to the nsIAnonymousContentCreator-built content
|
||||
nsCOMPtr<nsIContent> mHScrollbarContent;
|
||||
nsCOMPtr<nsIContent> mVScrollbarContent;
|
||||
@ -323,6 +327,7 @@ public:
|
||||
nsRefPtr<AsyncScroll> mAsyncScroll;
|
||||
nsRefPtr<ScrollbarActivity> mScrollbarActivity;
|
||||
nsTArray<nsIScrollPositionListener*> mListeners;
|
||||
nsIAtom* mOriginOfLastScroll;
|
||||
nsRect mScrollPort;
|
||||
// Where we're currently scrolling to, if we're scrolling asynchronously.
|
||||
// If we're not in the middle of an asynchronous scroll then this is
|
||||
@ -589,8 +594,9 @@ public:
|
||||
virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mHelper.ScrollToCSSPixels(aScrollPosition);
|
||||
}
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mHelper.ScrollToCSSPixelsApproximate(aScrollPosition);
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
|
||||
nsIAtom* aOrigin = nullptr) MOZ_OVERRIDE {
|
||||
mHelper.ScrollToCSSPixelsApproximate(aScrollPosition, aOrigin);
|
||||
}
|
||||
/**
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
@ -642,6 +648,12 @@ public:
|
||||
virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
|
||||
return mHelper.IsRectNearlyVisible(aRect);
|
||||
}
|
||||
virtual nsIAtom* OriginOfLastScroll() MOZ_OVERRIDE {
|
||||
return mHelper.OriginOfLastScroll();
|
||||
}
|
||||
virtual void ResetOriginOfLastScroll() MOZ_OVERRIDE {
|
||||
mHelper.ResetOriginOfLastScroll();
|
||||
}
|
||||
|
||||
// nsIStatefulFrame
|
||||
NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE {
|
||||
@ -883,8 +895,9 @@ public:
|
||||
virtual void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mHelper.ScrollToCSSPixels(aScrollPosition);
|
||||
}
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition) MOZ_OVERRIDE {
|
||||
mHelper.ScrollToCSSPixelsApproximate(aScrollPosition);
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
|
||||
nsIAtom* aOrigin = nullptr) MOZ_OVERRIDE {
|
||||
mHelper.ScrollToCSSPixelsApproximate(aScrollPosition, aOrigin);
|
||||
}
|
||||
virtual CSSIntPoint GetScrollPositionCSSPixels() MOZ_OVERRIDE {
|
||||
return mHelper.GetScrollPositionCSSPixels();
|
||||
@ -893,7 +906,7 @@ public:
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
|
||||
nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr) MOZ_OVERRIDE {
|
||||
nsIntPoint* aOverflow, nsIAtom* aOrigin = nullptr) MOZ_OVERRIDE {
|
||||
mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin);
|
||||
}
|
||||
/**
|
||||
@ -933,6 +946,12 @@ public:
|
||||
virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
|
||||
return mHelper.IsRectNearlyVisible(aRect);
|
||||
}
|
||||
virtual nsIAtom* OriginOfLastScroll() MOZ_OVERRIDE {
|
||||
return mHelper.OriginOfLastScroll();
|
||||
}
|
||||
virtual void ResetOriginOfLastScroll() MOZ_OVERRIDE {
|
||||
mHelper.ResetOriginOfLastScroll();
|
||||
}
|
||||
|
||||
// nsIStatefulFrame
|
||||
NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE {
|
||||
|
@ -25,6 +25,7 @@ class nsIFrame;
|
||||
class nsPresContext;
|
||||
class nsIContent;
|
||||
class nsRenderingContext;
|
||||
class nsIAtom;
|
||||
|
||||
/**
|
||||
* Interface for frames that are scrollable. This interface exposes
|
||||
@ -186,7 +187,8 @@ public:
|
||||
* number of layer pixels (so the operation is fast and looks clean).
|
||||
* The scroll mode is INSTANT.
|
||||
*/
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition) = 0;
|
||||
virtual void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
|
||||
nsIAtom *aOrigin = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* Returns the scroll position in integer CSS pixels, rounded to the nearest
|
||||
@ -268,6 +270,15 @@ public:
|
||||
* visibility heuristics for how close it is to the visible scrollport.
|
||||
*/
|
||||
virtual bool IsRectNearlyVisible(const nsRect& aRect) = 0;
|
||||
/**
|
||||
* Returns the origin passed in to the last ScrollToImpl call that took
|
||||
* effect.
|
||||
*/
|
||||
virtual nsIAtom* OriginOfLastScroll() = 0;
|
||||
/**
|
||||
* Clears the "origin of last scroll" property stored in this frame.
|
||||
*/
|
||||
virtual void ResetOriginOfLastScroll() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -84,6 +84,25 @@ MaybeAlignAndClampDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics,
|
||||
- aActualScrollOffset;
|
||||
}
|
||||
|
||||
static CSSPoint
|
||||
ScrollFrameTo(nsIScrollableFrame* aFrame, const CSSPoint& aPoint)
|
||||
{
|
||||
if (!aFrame) {
|
||||
return CSSPoint();
|
||||
}
|
||||
|
||||
// If the scrollable frame got a scroll request from something other than us
|
||||
// since the last layers update, then we don't want to push our scroll request
|
||||
// because we'll clobber that one, which is bad.
|
||||
if (!aFrame->OriginOfLastScroll() || aFrame->OriginOfLastScroll() == nsGkAtoms::apz) {
|
||||
aFrame->ScrollToCSSPixelsApproximate(aPoint, nsGkAtoms::apz);
|
||||
}
|
||||
// Return the final scroll position after setting it so that anything that relies
|
||||
// on it can have an accurate value. Note that even if we set it above re-querying it
|
||||
// is a good idea because it may have gotten clamped or rounded.
|
||||
return CSSPoint::FromAppUnits(aFrame->GetScrollPosition());
|
||||
}
|
||||
|
||||
void
|
||||
APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
|
||||
FrameMetrics& aMetrics)
|
||||
@ -105,12 +124,8 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
|
||||
aUtils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
|
||||
|
||||
// Scroll the window to the desired spot
|
||||
aUtils->ScrollToCSSPixelsApproximate(aMetrics.mScrollOffset.x, aMetrics.mScrollOffset.y, nullptr);
|
||||
|
||||
// Re-query the scroll position after setting it so that anything that relies on it
|
||||
// can have an accurate value.
|
||||
CSSPoint actualScrollOffset;
|
||||
aUtils->GetScrollXYFloat(false, &actualScrollOffset.x, &actualScrollOffset.y);
|
||||
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.mScrollId);
|
||||
CSSPoint actualScrollOffset = ScrollFrameTo(sf, aMetrics.mScrollOffset);
|
||||
|
||||
// Correct the display port due to the difference between mScrollOffset and the
|
||||
// actual scroll offset, possibly align it to tile boundaries (if tiled layers are
|
||||
@ -167,12 +182,8 @@ APZCCallbackHelper::UpdateSubFrame(nsIContent* aContent,
|
||||
// We currently do not support zooming arbitrary subframes. They can only
|
||||
// be scrolled, so here we only have to set the scroll position and displayport.
|
||||
|
||||
CSSPoint actualScrollOffset;
|
||||
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.mScrollId);
|
||||
if (sf) {
|
||||
sf->ScrollToCSSPixelsApproximate(aMetrics.mScrollOffset);
|
||||
actualScrollOffset = CSSPoint::FromAppUnits(sf->GetScrollPosition());
|
||||
}
|
||||
CSSPoint actualScrollOffset = ScrollFrameTo(sf, aMetrics.mScrollOffset);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
|
||||
if (element) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user