Bug 1209970 - Fire scroll events early in the refresh tick. r=mats

With APZ we want to be firing scroll events to content more consistently, so
we tie them to the refresh driver tick rather than firing them on paint or
haphazardly on the next spin of the event loop.

Patch by Markus Stange, test fixes by Kartikaya Gupta

--HG--
extra : commitid : DpIZ6B0IF0c
This commit is contained in:
Markus Stange 2015-12-17 17:19:30 -05:00
Родитель 9354363010
Коммит 8449f0d092
5 изменённых файлов: 32 добавлений и 17 удалений

Просмотреть файл

@ -16,6 +16,8 @@ const SCROLL2_X = Math.round(300 * (1 + Math.random()));
const SCROLL2_Y = Math.round(400 * (1 + Math.random()));
const SCROLL2_STR = SCROLL2_X + "," + SCROLL2_Y;
requestLongerTimeout(2);
/**
* This test ensures that we properly serialize and restore scroll positions
* for an average page without any frames.

Просмотреть файл

@ -4227,18 +4227,28 @@ void ScrollFrameHelper::CurPosAttributeChanged(nsIContent* aContent)
/* ============= Scroll events ========== */
NS_IMETHODIMP
ScrollFrameHelper::ScrollEvent::Run()
ScrollFrameHelper::ScrollEvent::ScrollEvent(ScrollFrameHelper* aHelper)
: mHelper(aHelper)
{
if (mHelper)
mHelper->FireScrollEvent();
return NS_OK;
mHelper->mOuter->PresContext()->RefreshDriver()->AddRefreshObserver(this, Flush_Style);
}
ScrollFrameHelper::ScrollEvent::~ScrollEvent()
{
mHelper->mOuter->PresContext()->RefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
}
void
ScrollFrameHelper::ScrollEvent::WillRefresh(mozilla::TimeStamp aTime)
{
mHelper->FireScrollEvent();
}
void
ScrollFrameHelper::FireScrollEvent()
{
mScrollEvent.Forget();
MOZ_ASSERT(mScrollEvent);
mScrollEvent = nullptr;
ActiveLayerTracker::SetCurrentScrollHandlerFrame(mOuter);
WidgetGUIEvent event(true, eScroll, nullptr);
@ -4265,14 +4275,11 @@ ScrollFrameHelper::FireScrollEvent()
void
ScrollFrameHelper::PostScrollEvent()
{
if (mScrollEvent.IsPending())
if (mScrollEvent)
return;
nsRootPresContext* rpc = mOuter->PresContext()->GetRootPresContext();
if (!rpc)
return;
// The ScrollEvent constructor registers itself with the refresh driver.
mScrollEvent = new ScrollEvent(this);
rpc->AddWillPaintObserver(mScrollEvent.get());
}
NS_IMETHODIMP

Просмотреть файл

@ -19,6 +19,7 @@
#include "nsIReflowCallback.h"
#include "nsBoxLayoutState.h"
#include "nsQueryFrame.h"
#include "nsRefreshDriver.h"
#include "nsExpirationTracker.h"
#include "TextOverflow.h"
#include "ScrollVelocityQueue.h"
@ -100,11 +101,13 @@ public:
bool IsSmoothScrollingEnabled();
class ScrollEvent : public nsRunnable {
class ScrollEvent : public nsARefreshObserver {
public:
NS_DECL_NSIRUNNABLE
explicit ScrollEvent(ScrollFrameHelper *helper) : mHelper(helper) {}
void Revoke() { mHelper = nullptr; }
NS_INLINE_DECL_REFCOUNTING(ScrollEvent, override)
explicit ScrollEvent(ScrollFrameHelper *helper);
void WillRefresh(mozilla::TimeStamp aTime) override;
protected:
virtual ~ScrollEvent();
private:
ScrollFrameHelper *mHelper;
};
@ -416,7 +419,7 @@ public:
nsCOMPtr<nsIContent> mScrollCornerContent;
nsCOMPtr<nsIContent> mResizerContent;
nsRevocableEventPtr<ScrollEvent> mScrollEvent;
RefPtr<ScrollEvent> mScrollEvent;
nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
nsIFrame* mHScrollbarBox;

Просмотреть файл

@ -526,8 +526,10 @@ function sendWheelAndPaint(aTarget, aOffsetX, aOffsetY, aEvent, aCallback, aWind
setTimeout(function() {
utils.advanceTimeAndRefresh(1000);
if (!aCallback)
if (!aCallback) {
utils.advanceTimeAndRefresh(0);
return;
}
var waitForPaints = function () {
SpecialPowers.Services.obs.removeObserver(waitForPaints, "apz-repaints-flushed", false);

Просмотреть файл

@ -1034,6 +1034,7 @@ function initElements()
resetScrollPosition(gSubView1);
resetScrollPosition(gSubView2);
resetScrollPosition(gSubView3);
_getDOMWindowUtils(window).advanceTimeAndRefresh(0);
runNextTestStep();
}