Bug 473805 - Prevent resize event loops, r=dbaron

--HG--
extra : rebase_source : e0476c7c1b390ebe194e508c3c728d517483989b
This commit is contained in:
Olli Pettay 2009-08-15 11:49:20 +03:00
Родитель 90dc08a58b
Коммит 72a18ed5c6
1 изменённых файлов: 39 добавлений и 6 удалений

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

@ -1394,7 +1394,11 @@ private:
nsIntPoint& aTargetPt); nsIntPoint& aTargetPt);
void FireResizeEvent(); void FireResizeEvent();
static void AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell);
nsRevocableEventPtr<nsRunnableMethod<PresShell> > mResizeEvent; nsRevocableEventPtr<nsRunnableMethod<PresShell> > mResizeEvent;
nsCOMPtr<nsITimer> mAsyncResizeEventTimer;
PRPackedBool mAsyncResizeTimerIsActive;
PRPackedBool mInResize;
typedef void (*nsPluginEnumCallback)(PresShell*, nsIContent*); typedef void (*nsPluginEnumCallback)(PresShell*, nsIContent*);
void EnumeratePlugins(nsIDOMDocument *aDocument, void EnumeratePlugins(nsIDOMDocument *aDocument,
@ -2029,6 +2033,10 @@ PresShell::Destroy()
// plug-ins are involved(!). // plug-ins are involved(!).
mReflowEvent.Revoke(); mReflowEvent.Revoke();
mResizeEvent.Revoke(); mResizeEvent.Revoke();
if (mAsyncResizeTimerIsActive) {
mAsyncResizeEventTimer->Cancel();
mAsyncResizeTimerIsActive = PR_FALSE;
}
CancelAllPendingReflows(); CancelAllPendingReflows();
CancelPostedReflowCallbacks(); CancelPostedReflowCallbacks();
@ -2798,6 +2806,12 @@ PresShell::sPaintSuppressionCallback(nsITimer *aTimer, void* aPresShell)
self->UnsuppressPainting(); self->UnsuppressPainting();
} }
void
PresShell::AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell)
{
static_cast<PresShell*>(aPresShell)->FireResizeEvent();
}
NS_IMETHODIMP NS_IMETHODIMP
PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
{ {
@ -2862,11 +2876,24 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
nsRect(0, 0, aWidth, rootFrame->GetRect().height)); nsRect(0, 0, aWidth, rootFrame->GetRect().height));
} }
if (!mIsDestroying && !mResizeEvent.IsPending()) { if (!mIsDestroying && !mResizeEvent.IsPending() &&
nsRefPtr<nsRunnableMethod<PresShell> > resizeEvent = !mAsyncResizeTimerIsActive) {
NS_NEW_RUNNABLE_METHOD(PresShell, this, FireResizeEvent); if (mInResize) {
if (NS_SUCCEEDED(NS_DispatchToCurrentThread(resizeEvent))) { if (!mAsyncResizeEventTimer) {
mResizeEvent = resizeEvent; mAsyncResizeEventTimer = do_CreateInstance("@mozilla.org/timer;1");
}
if (mAsyncResizeEventTimer) {
mAsyncResizeTimerIsActive = PR_TRUE;
mAsyncResizeEventTimer->InitWithFuncCallback(AsyncResizeEventCallback,
this, 15,
nsITimer::TYPE_ONE_SHOT);
}
} else {
nsRefPtr<nsRunnableMethod<PresShell> > resizeEvent =
NS_NEW_RUNNABLE_METHOD(PresShell, this, FireResizeEvent);
if (NS_SUCCEEDED(NS_DispatchToCurrentThread(resizeEvent))) {
mResizeEvent = resizeEvent;
}
} }
} }
@ -2876,6 +2903,10 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
void void
PresShell::FireResizeEvent() PresShell::FireResizeEvent()
{ {
if (mAsyncResizeTimerIsActive) {
mAsyncResizeTimerIsActive = PR_FALSE;
mAsyncResizeEventTimer->Cancel();
}
mResizeEvent.Revoke(); mResizeEvent.Revoke();
if (mIsDocumentGone) if (mIsDocumentGone)
@ -2887,8 +2918,10 @@ PresShell::FireResizeEvent()
nsPIDOMWindow *window = mDocument->GetWindow(); nsPIDOMWindow *window = mDocument->GetWindow();
if (window) { if (window) {
nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
mInResize = PR_TRUE;
nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status); nsEventDispatcher::Dispatch(window, mPresContext, &event, nsnull, &status);
// |this| may now be destroyed mInResize = PR_FALSE;
} }
} }