Bug 696248. Flush pending onscroll events before painting. r=mats

This commit is contained in:
Robert O'Callahan 2011-10-26 17:14:31 +13:00
Родитель 2e602e5305
Коммит 91cce0a191
4 изменённых файлов: 75 добавлений и 15 удалений

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

@ -2700,3 +2700,27 @@ nsRootPresContext::EnsureEventualDidPaintEvent()
mNotifyDidPaintTimer->InitWithFuncCallback(NotifyDidPaintForSubtreeCallback,
(void*)this, 100, nsITimer::TYPE_ONE_SHOT);
}
void
nsRootPresContext::AddWillPaintObserver(nsIRunnable* aRunnable)
{
if (!mWillPaintFallbackEvent.IsPending()) {
mWillPaintFallbackEvent = new RunWillPaintObservers(this);
NS_DispatchToMainThread(mWillPaintFallbackEvent.get());
}
mWillPaintObservers.AppendElement(aRunnable);
}
/**
* Run all runnables that need to get called before the next paint.
*/
void
nsRootPresContext::FlushWillPaintObservers()
{
mWillPaintFallbackEvent = nsnull;
nsTArray<nsCOMPtr<nsIRunnable> > observers;
observers.SwapElements(mWillPaintObservers);
for (PRUint32 i = 0; i < observers.Length(); ++i) {
observers[i]->Run();
}
}

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

@ -1304,12 +1304,40 @@ public:
*/
PRUint32 GetDOMGeneration() { return mDOMGeneration; }
private:
/**
* Add a runnable that will get called before the next paint. They will get
* run eventually even if painting doesn't happen. They might run well before
* painting happens.
*/
void AddWillPaintObserver(nsIRunnable* aRunnable);
/**
* Run all runnables that need to get called before the next paint.
*/
void FlushWillPaintObservers();
protected:
class RunWillPaintObservers : public nsRunnable {
public:
RunWillPaintObservers(nsRootPresContext* aPresContext) : mPresContext(aPresContext) {}
void Revoke() { mPresContext = nsnull; }
NS_IMETHOD Run()
{
if (mPresContext) {
mPresContext->FlushWillPaintObservers();
}
return NS_OK;
}
nsRootPresContext* mPresContext;
};
nsCOMPtr<nsITimer> mNotifyDidPaintTimer;
nsTHashtable<nsPtrHashKey<nsObjectFrame> > mRegisteredPlugins;
// if mNeedsToUpdatePluginGeometry is set, then this is the frame to
// use as the root of the subtree to search for plugin updates, or
// null to use the root frame of this prescontext
nsTArray<nsCOMPtr<nsIRunnable> > mWillPaintObservers;
nsRevocableEventPtr<RunWillPaintObservers> mWillPaintFallbackEvent;
nsIFrame* mUpdatePluginGeometryForFrame;
PRUint32 mDOMGeneration;
bool mNeedsToUpdatePluginGeometry;

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

@ -4460,6 +4460,13 @@ PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
NS_ENSURE_TRUE(!(aFlags & RENDER_IS_UNTRUSTED), NS_ERROR_NOT_IMPLEMENTED);
nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
if (rootPresContext) {
rootPresContext->FlushWillPaintObservers();
if (mIsDestroying)
return NS_OK;
}
nsAutoScriptBlocker blockScripts;
// Set up the rectangle as the path in aThebesContext
@ -6861,16 +6868,18 @@ PresShell::WillPaint(bool aWillSendDidPaint)
return;
}
if (!aWillSendDidPaint) {
nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
if (!rootPresContext) {
return;
}
if (rootPresContext == mPresContext) {
rootPresContext->UpdatePluginGeometry();
}
nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
if (!rootPresContext) {
return;
}
if (!aWillSendDidPaint && rootPresContext == mPresContext) {
rootPresContext->UpdatePluginGeometry();
}
rootPresContext->FlushWillPaintObservers();
if (mIsDestroying)
return;
// Process reflows, if we have them, to reduce flicker due to invalidates and
// reflow being interspersed. Note that we _do_ allow this to be
// interruptible; if we can't do all the reflows it's better to flicker a bit

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

@ -2643,12 +2643,11 @@ nsGfxScrollFrameInner::PostScrollEvent()
if (mScrollEvent.IsPending())
return;
nsRefPtr<ScrollEvent> ev = new ScrollEvent(this);
if (NS_FAILED(NS_DispatchToCurrentThread(ev))) {
NS_WARNING("failed to dispatch ScrollEvent");
} else {
mScrollEvent = ev;
}
nsRootPresContext* rpc = mOuter->PresContext()->GetRootPresContext();
if (!rpc)
return;
mScrollEvent = new ScrollEvent(this);
rpc->AddWillPaintObserver(mScrollEvent.get());
}
NS_IMETHODIMP