mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 702463 - Smooth scrolling should use refresh observer instead of a timer. r=roc
This commit is contained in:
parent
dffd8d682c
commit
3ecca78724
@ -1333,17 +1333,19 @@ NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
|||||||
const double kCurrentVelocityWeighting = 0.25;
|
const double kCurrentVelocityWeighting = 0.25;
|
||||||
const double kStopDecelerationWeighting = 0.4;
|
const double kStopDecelerationWeighting = 0.4;
|
||||||
|
|
||||||
class nsGfxScrollFrameInner::AsyncScroll {
|
// AsyncScroll has ref counting.
|
||||||
|
class nsGfxScrollFrameInner::AsyncScroll : public nsARefreshObserver {
|
||||||
public:
|
public:
|
||||||
typedef mozilla::TimeStamp TimeStamp;
|
typedef mozilla::TimeStamp TimeStamp;
|
||||||
typedef mozilla::TimeDuration TimeDuration;
|
typedef mozilla::TimeDuration TimeDuration;
|
||||||
|
|
||||||
AsyncScroll():
|
AsyncScroll()
|
||||||
mIsFirstIteration(true)
|
: mIsFirstIteration(true)
|
||||||
{}
|
, mCallee(nsnull)
|
||||||
|
{}
|
||||||
|
|
||||||
~AsyncScroll() {
|
~AsyncScroll() {
|
||||||
if (mScrollTimer) mScrollTimer->Cancel();
|
RemoveObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPoint PositionAt(TimeStamp aTime);
|
nsPoint PositionAt(TimeStamp aTime);
|
||||||
@ -1357,7 +1359,6 @@ public:
|
|||||||
return aTime > mStartTime + mDuration; // XXX or if we've hit the wall
|
return aTime > mStartTime + mDuration; // XXX or if we've hit the wall
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsITimer> mScrollTimer;
|
|
||||||
TimeStamp mStartTime;
|
TimeStamp mStartTime;
|
||||||
|
|
||||||
// mPrevStartTime holds previous 3 timestamps for intervals averaging (to
|
// mPrevStartTime holds previous 3 timestamps for intervals averaging (to
|
||||||
@ -1403,6 +1404,51 @@ protected:
|
|||||||
nscoord aDestination);
|
nscoord aDestination);
|
||||||
|
|
||||||
void InitDuration(nsIAtom *aOrigin);
|
void InitDuration(nsIAtom *aOrigin);
|
||||||
|
|
||||||
|
// The next section is observer/callback management
|
||||||
|
// Bodies of WillRefresh and RefreshDriver contain nsGfxScrollFrameInner specific code.
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(AsyncScroll)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a refresh observer for smooth scroll iterations (and start observing).
|
||||||
|
* Should be used at most once during the lifetime of this object.
|
||||||
|
* Return value: true on success, false otherwise.
|
||||||
|
*/
|
||||||
|
bool SetRefreshObserver(nsGfxScrollFrameInner *aCallee) {
|
||||||
|
NS_ASSERTION(aCallee && !mCallee, "AsyncScroll::SetRefreshObserver - Invalid usage.");
|
||||||
|
|
||||||
|
if (!RefreshDriver(aCallee)->AddRefreshObserver(this, Flush_Display)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCallee = aCallee;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void WillRefresh(mozilla::TimeStamp aTime) {
|
||||||
|
// The callback may release "this".
|
||||||
|
// We don't access members after returning, so no need for KungFuDeathGrip.
|
||||||
|
nsGfxScrollFrameInner::AsyncScrollCallback(mCallee, aTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsGfxScrollFrameInner *mCallee;
|
||||||
|
|
||||||
|
nsRefreshDriver* RefreshDriver(nsGfxScrollFrameInner* aCallee) {
|
||||||
|
return aCallee->mOuter->PresContext()->RefreshDriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The refresh driver doesn't hold a reference to its observers,
|
||||||
|
* so releasing this object can (and is) used to remove the observer on DTOR.
|
||||||
|
* Currently, this object is released once the scrolling ends.
|
||||||
|
*/
|
||||||
|
void RemoveObserver() {
|
||||||
|
if (mCallee) {
|
||||||
|
RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Display);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
nsPoint
|
nsPoint
|
||||||
@ -1616,7 +1662,6 @@ nsGfxScrollFrameInner::~nsGfxScrollFrameInner()
|
|||||||
delete gScrollFrameActivityTracker;
|
delete gScrollFrameActivityTracker;
|
||||||
gScrollFrameActivityTracker = nsnull;
|
gScrollFrameActivityTracker = nsnull;
|
||||||
}
|
}
|
||||||
delete mAsyncScroll;
|
|
||||||
|
|
||||||
if (mScrollActivityTimer) {
|
if (mScrollActivityTimer) {
|
||||||
mScrollActivityTimer->Cancel();
|
mScrollActivityTimer->Cancel();
|
||||||
@ -1651,28 +1696,23 @@ nsGfxScrollFrameInner::ClampScrollPosition(const nsPoint& aPt) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback function from timer used in nsGfxScrollFrameInner::ScrollTo
|
* Callback function from AsyncScroll, used in nsGfxScrollFrameInner::ScrollTo
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
nsGfxScrollFrameInner::AsyncScrollCallback(nsITimer *aTimer, void* anInstance)
|
nsGfxScrollFrameInner::AsyncScrollCallback(void* anInstance, mozilla::TimeStamp aTime)
|
||||||
{
|
{
|
||||||
nsGfxScrollFrameInner* self = static_cast<nsGfxScrollFrameInner*>(anInstance);
|
nsGfxScrollFrameInner* self = static_cast<nsGfxScrollFrameInner*>(anInstance);
|
||||||
if (!self || !self->mAsyncScroll)
|
if (!self || !self->mAsyncScroll)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (self->mAsyncScroll->mIsSmoothScroll) {
|
if (self->mAsyncScroll->mIsSmoothScroll) {
|
||||||
TimeStamp now = TimeStamp::Now();
|
nsPoint destination = self->mAsyncScroll->PositionAt(aTime);
|
||||||
nsPoint destination = self->mAsyncScroll->PositionAt(now);
|
if (self->mAsyncScroll->IsFinished(aTime)) {
|
||||||
if (self->mAsyncScroll->IsFinished(now)) {
|
|
||||||
delete self->mAsyncScroll;
|
|
||||||
self->mAsyncScroll = nsnull;
|
self->mAsyncScroll = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->ScrollToImpl(destination);
|
self->ScrollToImpl(destination);
|
||||||
} else {
|
} else {
|
||||||
delete self->mAsyncScroll;
|
|
||||||
self->mAsyncScroll = nsnull;
|
self->mAsyncScroll = nsnull;
|
||||||
|
|
||||||
self->ScrollToImpl(self->mDestination);
|
self->ScrollToImpl(self->mDestination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1695,7 +1735,6 @@ nsGfxScrollFrameInner::ScrollToWithOrigin(nsPoint aScrollPosition,
|
|||||||
if (aMode == nsIScrollableFrame::INSTANT) {
|
if (aMode == nsIScrollableFrame::INSTANT) {
|
||||||
// Asynchronous scrolling is not allowed, so we'll kill any existing
|
// Asynchronous scrolling is not allowed, so we'll kill any existing
|
||||||
// async-scrolling process and do an instant scroll
|
// async-scrolling process and do an instant scroll
|
||||||
delete mAsyncScroll;
|
|
||||||
mAsyncScroll = nsnull;
|
mAsyncScroll = nsnull;
|
||||||
ScrollToImpl(mDestination);
|
ScrollToImpl(mDestination);
|
||||||
return;
|
return;
|
||||||
@ -1714,22 +1753,12 @@ nsGfxScrollFrameInner::ScrollToWithOrigin(nsPoint aScrollPosition,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mAsyncScroll = new AsyncScroll;
|
mAsyncScroll = new AsyncScroll;
|
||||||
mAsyncScroll->mScrollTimer = do_CreateInstance("@mozilla.org/timer;1");
|
if (!mAsyncScroll->SetRefreshObserver(this)) {
|
||||||
if (!mAsyncScroll->mScrollTimer) {
|
|
||||||
delete mAsyncScroll;
|
|
||||||
mAsyncScroll = nsnull;
|
mAsyncScroll = nsnull;
|
||||||
// allocation failed. Scroll the normal way.
|
// Observer setup failed. Scroll the normal way.
|
||||||
ScrollToImpl(mDestination);
|
ScrollToImpl(mDestination);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isSmoothScroll) {
|
|
||||||
mAsyncScroll->mScrollTimer->InitWithFuncCallback(
|
|
||||||
AsyncScrollCallback, this, 1000 / 60,
|
|
||||||
nsITimer::TYPE_REPEATING_SLACK);
|
|
||||||
} else {
|
|
||||||
mAsyncScroll->mScrollTimer->InitWithFuncCallback(
|
|
||||||
AsyncScrollCallback, this, 0, nsITimer::TYPE_ONE_SHOT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mAsyncScroll->mIsSmoothScroll = isSmoothScroll;
|
mAsyncScroll->mIsSmoothScroll = isSmoothScroll;
|
||||||
|
@ -186,7 +186,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
nsPoint RestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx, bool aShouldClamp) const;
|
nsPoint RestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx, bool aShouldClamp) const;
|
||||||
nsPoint ClampScrollPosition(const nsPoint& aPt) const;
|
nsPoint ClampScrollPosition(const nsPoint& aPt) const;
|
||||||
static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance);
|
static void AsyncScrollCallback(void* anInstance, mozilla::TimeStamp aTime);
|
||||||
void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode) {
|
void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode) {
|
||||||
ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other);
|
ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other);
|
||||||
};
|
};
|
||||||
@ -295,7 +295,7 @@ public:
|
|||||||
nsIBox* mScrollCornerBox;
|
nsIBox* mScrollCornerBox;
|
||||||
nsIBox* mResizerBox;
|
nsIBox* mResizerBox;
|
||||||
nsContainerFrame* mOuter;
|
nsContainerFrame* mOuter;
|
||||||
AsyncScroll* mAsyncScroll;
|
nsRefPtr<AsyncScroll> mAsyncScroll;
|
||||||
nsTArray<nsIScrollPositionListener*> mListeners;
|
nsTArray<nsIScrollPositionListener*> mListeners;
|
||||||
nsRect mScrollPort;
|
nsRect mScrollPort;
|
||||||
// Where we're currently scrolling to, if we're scrolling asynchronously.
|
// Where we're currently scrolling to, if we're scrolling asynchronously.
|
||||||
|
Loading…
Reference in New Issue
Block a user