diff --git a/content/base/public/mozFlushType.h b/content/base/public/mozFlushType.h index 5b203d14377f..bb2c590f4e23 100644 --- a/content/base/public/mozFlushType.h +++ b/content/base/public/mozFlushType.h @@ -48,12 +48,8 @@ enum mozFlushType { notifications. */ Flush_Style = 3, /* As above, plus flush style reresolution */ Flush_Frames = Flush_Style, - Flush_InterruptibleLayout = 4, /* As above, plus flush reflow, - but allow it to be interrupted (so - an incomplete layout may result) */ - Flush_Layout = 5, /* As above, but layout must run to - completion */ - Flush_Display = 6 /* As above, plus flush painting */ + Flush_Layout = 4, /* As above, plus flush reflow */ + Flush_Display = 5 /* As above, plus flush painting */ }; #endif /* mozFlushType_h___ */ diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 5a5f155d0aaa..c7949b91da44 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -6257,8 +6257,8 @@ nsDocument::FlushPendingNotifications(mozFlushType aType) // correct size to determine the correct style. if (mParentDocument && IsSafeToFlush()) { mozFlushType parentType = aType; - if (aType >= Flush_Style) - parentType = PR_MAX(Flush_Layout, aType); + if (aType == Flush_Style) + parentType = Flush_Layout; mParentDocument->FlushPendingNotifications(parentType); } diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 84db4356eb15..547cc8a6277c 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -5749,7 +5749,7 @@ nsEventStateManager::FlushPendingEvents(nsPresContext* aPresContext) NS_PRECONDITION(nsnull != aPresContext, "nsnull ptr"); nsIPresShell *shell = aPresContext->GetPresShell(); if (shell) { - shell->FlushPendingNotifications(Flush_InterruptibleLayout); + shell->FlushPendingNotifications(Flush_Display); } } diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 5d44e5eb8e30..d52d3fe0c7a5 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1308,8 +1308,9 @@ nsGenericHTMLElement::GetFormControlFrameFor(nsIContent* aContent, PRBool aFlushContent) { if (aFlushContent) { - // Cause a flush of the frames, so we get up-to-date frame information - aDocument->FlushPendingNotifications(Flush_Frames); + // Cause a flush of content, so we get up-to-date frame + // information + aDocument->FlushPendingNotifications(Flush_Layout); } nsIFrame* frame = GetPrimaryFrameFor(aContent, aDocument); if (frame) { @@ -2695,10 +2696,7 @@ nsGenericHTMLFormElement::SetFocusAndScrollIntoView(nsPresContext* aPresContext) { nsIEventStateManager *esm = aPresContext->EventStateManager(); if (esm->SetContentState(this, NS_EVENT_STATE_FOCUS)) { - // XXXldb once bug 43114 is fixed, we don't need to flush here. - aPresContext->Document()-> - FlushPendingNotifications(Flush_InterruptibleLayout); - nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); + nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE); if (formControlFrame) { formControlFrame->SetFocus(PR_TRUE, PR_TRUE); nsCOMPtr presShell = aPresContext->GetPresShell(); diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index fc0b1ddcc3db..c883bf4cb032 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -3200,7 +3200,7 @@ HTMLContentSink::FlushPendingNotifications(mozFlushType aType) else if (mCurrentContext) { mCurrentContext->FlushText(); } - if (aType >= Flush_InterruptibleLayout) { + if (aType >= Flush_Layout) { // Make sure that layout has started so that the reflow flush // will actually happen. StartLayout(PR_TRUE); diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 027ef1b71799..7b56be91c2a4 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -1653,7 +1653,7 @@ nsXMLContentSink::FlushPendingNotifications(mozFlushType aType) else { FlushText(PR_FALSE); } - if (aType >= Flush_InterruptibleLayout) { + if (aType >= Flush_Layout) { // Make sure that layout has started so that the reflow flush // will actually happen. MaybeStartLayout(PR_TRUE); diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 7e245be36b53..f730eb88473a 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -101,10 +101,10 @@ class nsPIDOMEventTarget; typedef short SelectionType; typedef PRUint32 nsFrameState; -// 4fb87dae-8986-429f-b6ba-f040750e3ee8 +// fa7f090d-b19a-4ef8-9552-82992a3b4a83 #define NS_IPRESSHELL_IID \ - { 0x4fb87dae, 0x8986, 0x429f, \ - { 0xb6, 0xba, 0xf0, 0x40, 0x75, 0x0e, 0x3e, 0xe8 } } +{ 0xfa7f090d, 0xb19a, 0x4ef8, \ + { 0x95, 0x52, 0x82, 0x99, 0x2a, 0x3b, 0x4a, 0x83 } } // Constants for ScrollContentIntoView() function #define NS_PRESSHELL_SCROLL_TOP 0 @@ -124,8 +124,6 @@ typedef PRUint32 nsFrameState; #define VERIFY_REFLOW_REALLY_NOISY_RC 0x20 #define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x40 -#undef NOISY_INTERRUPTIBLE_REFLOW - /** * Presentation shell interface. Presentation shells are the * controlling point for managing the presentation of a document. The @@ -369,19 +367,6 @@ public: IntrinsicDirty aIntrinsicDirty, nsFrameState aBitToAdd) = 0; - /** - * Tell the presshell that the given frame's reflow was interrupted. This - * will mark as having dirty children a path from the given frame (inclusive) - * to the nearest ancestor with a dirty subtree, or to the reflow root - * currently being reflowed if no such ancestor exists (inclusive). This is - * to be done immediately after reflow of the current reflow root completes. - * This method must only be called during reflow, and the frame it's being - * called on must be in the process of being reflowed when it's called. This - * method doesn't mark any intrinsic widths dirty and doesn't add any bits - * other than NS_FRAME_HAS_DIRTY_CHILDREN. - */ - NS_IMETHOD_(void) FrameNeedsToContinueReflow(nsIFrame *aFrame) = 0; - NS_IMETHOD CancelAllPendingReflows() = 0; /** @@ -476,7 +461,7 @@ public: */ NS_IMETHOD ScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent) = 0; + PRIntn aHPercent) const = 0; /** * Suppress notification of the frame manager that frames are diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 6ce18f09ef4c..674cbdd481df 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -90,8 +90,6 @@ #include "nsFontFaceLoader.h" #include "nsIEventListenerManager.h" #include "nsStyleStructInlines.h" -#include "nsIAppShell.h" -#include "prenv.h" #ifdef MOZ_SMIL #include "nsSMILAnimationController.h" @@ -2029,125 +2027,3 @@ nsPresContext::HasCachedStyleData() { return mShell && mShell->StyleSet()->HasCachedStyleData(); } - -static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); -static PRBool sGotInterruptEnv = PR_FALSE; -static PRUint32 sInterruptSeed = 1; -static PRUint32 sInterruptChecksToSkip = 200; -enum InterruptMode { - ModeRandom, - ModeCounter, - ModeEvent -}; -static InterruptMode sInterruptMode = ModeEvent; -static PRUint32 sInterruptCounter; -static PRUint32 sInterruptMaxCounter = 10; - -static void GetInterruptEnv() -{ - char *ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_MODE"); - if (ev) { -#ifndef XP_WIN - if (PL_strcasecmp(ev, "random") == 0) { - ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_SEED"); - if (ev) { - sInterruptSeed = atoi(ev); - } - srandom(sInterruptSeed); - sInterruptMode = ModeRandom; - } else -#endif - if (PL_strcasecmp(ev, "counter") == 0) { - ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_FREQUENCY"); - if (ev) { - sInterruptMaxCounter = atoi(ev); - } - sInterruptCounter = 0; - sInterruptMode = ModeCounter; - } - } - ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP"); - if (ev) { - sInterruptChecksToSkip = atoi(ev); - } -} - -PRBool -nsPresContext::HavePendingInputEvent() -{ - switch (sInterruptMode) { -#ifndef XP_WIN - case ModeRandom: - return (random() & 1); -#endif - case ModeCounter: - if (sInterruptCounter < sInterruptMaxCounter) { - ++sInterruptCounter; - return PR_FALSE; - } - sInterruptCounter = 0; - return PR_TRUE; - default: - case ModeEvent: { - nsIFrame* f = PresShell()->GetRootFrame(); - if (f) { - nsIWidget* w = f->GetWindow(); - if (w) { - return w->HasPendingInputEvent(); - } - } - return PR_FALSE; - } - } -} - -void -nsPresContext::ReflowStarted(PRBool aInterruptible) -{ - // We don't support interrupting in paginated contexts, since page - // sequences only handle initial reflow - mInterruptsEnabled = aInterruptible && !IsPaginated(); - - // Don't set mHasPendingInterrupt based on HavePendingInputEvent() here. If - // we ever change that, then we need to update the code in - // PresShell::DoReflow to only add the just-reflown root to dirty roots if - // it's actually dirty. Otherwise we can end up adding a root that has no - // interruptible descendants, just because we detected an interrupt at reflow - // start. - mHasPendingInterrupt = PR_FALSE; - - mInterruptChecksToSkip = sInterruptChecksToSkip; -} - -PRBool -nsPresContext::CheckForInterrupt(nsIFrame* aFrame) -{ - if (mHasPendingInterrupt) { - mShell->FrameNeedsToContinueReflow(aFrame); - return PR_TRUE; - } - - if (!sGotInterruptEnv) { - sGotInterruptEnv = PR_TRUE; - GetInterruptEnv(); - } - - if (!mInterruptsEnabled) { - return PR_FALSE; - } - - if (mInterruptChecksToSkip > 0) { - --mInterruptChecksToSkip; - return PR_FALSE; - } - mInterruptChecksToSkip = sInterruptChecksToSkip; - - mHasPendingInterrupt = HavePendingInputEvent(); - if (mHasPendingInterrupt) { -#ifdef NOISY_INTERRUPTIBLE_REFLOW - printf("*** DETECTED pending interrupt (time=%lld)\n", PR_Now()); -#endif /* NOISY_INTERRUPTIBLE_REFLOW */ - mShell->FrameNeedsToContinueReflow(aFrame); - } - return mHasPendingInterrupt; -} diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 5e4cbe8382bb..0294fd17755e 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -806,58 +806,6 @@ public: mCrossDocDirtyRegion.SetEmpty(); } - /** - * Notify the prescontext that the presshell is about to reflow a reflow root. - * The single argument indicates whether this reflow should be interruptible. - * If aInterruptible is false then CheckForInterrupt and HasPendingInterrupt - * will always return false. If aInterruptible is true then CheckForInterrupt - * will return true when a pending event is detected. This is for use by the - * presshell only. Reflow code wanting to prevent interrupts should use - * InterruptPreventer. - */ - void ReflowStarted(PRBool aInterruptible); - - /** - * A class that can be used to temporarily disable reflow interruption. - */ - class InterruptPreventer; - friend class InterruptPreventer; - class NS_STACK_CLASS InterruptPreventer { - public: - InterruptPreventer(nsPresContext* aCtx) : - mCtx(aCtx), - mInterruptsEnabled(aCtx->mInterruptsEnabled), - mHasPendingInterrupt(aCtx->mHasPendingInterrupt) - { - mCtx->mInterruptsEnabled = PR_FALSE; - mCtx->mHasPendingInterrupt = PR_FALSE; - } - ~InterruptPreventer() { - mCtx->mInterruptsEnabled = mInterruptsEnabled; - mCtx->mHasPendingInterrupt = mHasPendingInterrupt; - } - - private: - nsPresContext* mCtx; - PRBool mInterruptsEnabled; - PRBool mHasPendingInterrupt; - }; - - /** - * Check for interrupts. This may return true if a pending event is - * detected. Once it has returned true, it will keep returning true until - * SetInterruptState is called again. In all cases where returns true, the - * passed-in frame (which should be the frame whose reflow will be - * interrupted if true is returend) will be passed to - * nsIPresShell::FrameNeedsToContinueReflow. - */ - PRBool CheckForInterrupt(nsIFrame* aFrame); - /** - * Returns true if CheckForInterrupt has returned true since the last - * SetInterruptState. Cannot itself trigger an interrupt check. - */ - PRBool HasPendingInterrupt() { return mHasPendingInterrupt; } - protected: friend class nsRunnableMethod; NS_HIDDEN_(void) ThemeChangedInternal(); @@ -886,8 +834,6 @@ protected: FlushUserFontSet(); } - PRBool HavePendingInputEvent(); - // Can't be inline because we can't include nsStyleSet.h. PRBool HasCachedStyleData(); @@ -975,10 +921,6 @@ protected: nscoord mBorderWidthTable[3]; - PRUint32 mInterruptChecksToSkip; - - unsigned mHasPendingInterrupt : 1; - unsigned mInterruptsEnabled : 1; unsigned mUseDocumentFonts : 1; unsigned mUseDocumentColors : 1; unsigned mUnderlineLinks : 1; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index aafceaf01bbf..55efe99ee05f 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -934,7 +934,6 @@ public: nsIFrame** aPlaceholderFrame) const; NS_IMETHOD FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, nsFrameState aBitToAdd); - NS_IMETHOD_(void) FrameNeedsToContinueReflow(nsIFrame *aFrame); NS_IMETHOD CancelAllPendingReflows(); NS_IMETHOD IsSafeToFlush(PRBool& aIsSafeToFlush); NS_IMETHOD FlushPendingNotifications(mozFlushType aType); @@ -958,7 +957,7 @@ public: NS_IMETHOD ScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent); + PRIntn aHPercent) const; NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore); NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame); @@ -1134,31 +1133,23 @@ public: protected: virtual ~PresShell(); - void HandlePostedReflowCallbacks(PRBool aInterruptible); + void HandlePostedReflowCallbacks(); void CancelPostedReflowCallbacks(); void UnsuppressAndInvalidate(); void WillDoReflow(); - void DidDoReflow(PRBool aInterruptible); - // ProcessReflowCommands returns whether we processed all our dirty roots - // without interruptions. - PRBool ProcessReflowCommands(PRBool aInterruptible); + void DidDoReflow(); + nsresult ProcessReflowCommands(PRBool aInterruptible); void ClearReflowEventStatus(); void PostReflowEvent(); - - // DoReflow returns whether the reflow finished without interruption - PRBool DoReflow(nsIFrame* aFrame, PRBool aInterruptible); + + void DoReflow(nsIFrame* aFrame); #ifdef DEBUG void DoVerifyReflow(); void VerifyHasDirtyRootAncestor(nsIFrame* aFrame); #endif - // Helper for ScrollContentIntoView - nsresult DoScrollContentIntoView(nsIContent* aContent, - PRIntn aVPercent, - PRIntn aHPercent); - friend class nsPresShellEventCB; class ReflowEvent; @@ -1242,6 +1233,11 @@ protected: // Utility method to restore the root scrollframe state void RestoreRootScrollPosition(); + // Method to handle actually flushing. This allows the caller to control + // whether the reflow flush (if any) should be interruptible. + nsresult DoFlushPendingNotifications(mozFlushType aType, + PRBool aInterruptibleReflow); + nsCOMPtr mPrefStyleSheet; // mStyleSet owns it but we // maintain a ref, may be null #ifdef DEBUG @@ -1272,25 +1268,6 @@ protected: nsRevocableEventPtr mReflowEvent; -#ifdef DEBUG - // The reflow root under which we're currently reflowing. Null when - // not in reflow. - nsIFrame* mCurrentReflowRoot; -#endif - - // Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after - // we finish reflowing mCurrentReflowRoot. - nsTHashtable< nsPtrHashKey > mFramesToDirty; - - // Information needed to properly handle scrolling content into view if the - // pre-scroll reflow flush can be interrupted. mContentToScrollTo is - // non-null between the initial scroll attempt and the first time we finish - // processing all our dirty roots. mContentScrollVPosition and - // mContentScrollHPosition are only used when it's non-null. - nsCOMPtr mContentToScrollTo; - PRIntn mContentScrollVPosition; - PRIntn mContentScrollHPosition; - struct nsBlurOrFocusTarget { nsBlurOrFocusTarget(nsPIDOMEventTarget* aTarget, PRUint32 aEventType) @@ -1307,8 +1284,6 @@ protected: nsCallbackEventRequest* mFirstCallbackEventRequest; nsCallbackEventRequest* mLastCallbackEventRequest; - PRPackedBool mSuppressInterruptibleReflows; - PRPackedBool mIsThemeSupportDisabled; // Whether or not form controls should use nsITheme in this shell. PRPackedBool mIsDocumentGone; // We've been disconnected from the document. @@ -1643,10 +1618,6 @@ PresShell::Init(nsIDocument* aDocument, result = mStackArena.Init(); NS_ENSURE_SUCCESS(result, result); - if (!mFramesToDirty.Init()) { - return NS_ERROR_OUT_OF_MEMORY; - } - mDocument = aDocument; NS_ADDREF(mDocument); mViewManager = aViewManager; @@ -1778,8 +1749,6 @@ PresShell::Destroy() if (mHaveShutDown) return NS_OK; - mContentToScrollTo = nsnull; - if (mPresContext) { // We need to notify the destroying the nsPresContext to ESM for // suppressing to use from ESM. @@ -2725,12 +2694,14 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) // Kick off a top-down reflow AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow); + mIsReflowing = PR_TRUE; mDirtyRoots.RemoveElement(rootFrame); - DoReflow(rootFrame, PR_TRUE); + DoReflow(rootFrame); + mIsReflowing = PR_FALSE; } - DidDoReflow(PR_TRUE); + DidDoReflow(); } batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); @@ -3440,20 +3411,6 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, return NS_OK; } -NS_IMETHODIMP_(void) -PresShell::FrameNeedsToContinueReflow(nsIFrame *aFrame) -{ - NS_ASSERTION(mIsReflowing, "Must be in reflow when marking path dirty."); - NS_PRECONDITION(mCurrentReflowRoot, "Must have a current reflow root here"); - NS_ASSERTION(aFrame == mCurrentReflowRoot || - nsLayoutUtils::IsProperAncestorFrame(mCurrentReflowRoot, aFrame), - "Frame passed in is not the descendant of mCurrentReflowRoot"); - NS_ASSERTION(aFrame->GetStateBits() & NS_FRAME_IN_REFLOW, - "Frame passed in not in reflow?"); - - mFramesToDirty.PutEntry(aFrame); -} - nsIScrollableView* PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection) { @@ -3587,8 +3544,6 @@ PresShell::ClearFrameRefs(nsIFrame* aFrame) } } - mFramesToDirty.RemoveEntry(aFrame); - nsWeakFrame* weakFrame = mWeakFrames; while (weakFrame) { nsWeakFrame* prev = weakFrame->GetPreviousWeakFrame(); @@ -4127,21 +4082,17 @@ static void ScrollViewToShowRect(nsIScrollableView* aScrollingView, NS_IMETHODIMP PresShell::ScrollContentIntoView(nsIContent* aContent, PRIntn aVPercent, - PRIntn aHPercent) + PRIntn aHPercent) const { - mContentToScrollTo = aContent; - mContentScrollVPosition = aVPercent; - mContentScrollHPosition = aHPercent; - nsCOMPtr content = aContent; // Keep content alive while flushing. NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER); nsCOMPtr currentDoc = content->GetCurrentDoc(); NS_ENSURE_STATE(currentDoc); - currentDoc->FlushPendingNotifications(Flush_InterruptibleLayout); - - // If mContentToScrollTo is non-null, that means we interrupted the reflow - // and won't necessarily get the position correct, but do a best-effort - // scroll. + currentDoc->FlushPendingNotifications(Flush_Layout); + nsIFrame* frame = GetPrimaryFrameFor(content); + if (!frame) { + return NS_ERROR_NULL_POINTER; + } // Before we scroll the frame into view, ask the command dispatcher // if we're resetting focus because a window just got an activate @@ -4158,26 +4109,11 @@ PresShell::ScrollContentIntoView(nsIContent* aContent, PRBool dontScroll = PR_FALSE; focusController->GetSuppressFocusScroll(&dontScroll); if (dontScroll) { - mContentToScrollTo = nsnull; return NS_OK; } } } - return DoScrollContentIntoView(content, aVPercent, aHPercent); -} - -nsresult -PresShell::DoScrollContentIntoView(nsIContent* aContent, - PRIntn aVPercent, - PRIntn aHPercent) -{ - nsIFrame* frame = GetPrimaryFrameFor(aContent); - if (!frame) { - mContentToScrollTo = nsnull; - return NS_ERROR_NULL_POINTER; - } - // This is a two-step process. // Step 1: Find the bounds of the rect we want to scroll into view. For // example, for an inline frame we may want to scroll in the whole @@ -4640,7 +4576,7 @@ PresShell::CancelPostedReflowCallbacks() } void -PresShell::HandlePostedReflowCallbacks(PRBool aInterruptible) +PresShell::HandlePostedReflowCallbacks() { PRBool shouldFlush = PR_FALSE; @@ -4659,10 +4595,8 @@ PresShell::HandlePostedReflowCallbacks(PRBool aInterruptible) } } - mozFlushType flushType = - aInterruptible ? Flush_InterruptibleLayout : Flush_Layout; if (shouldFlush) - FlushPendingNotifications(flushType); + FlushPendingNotifications(Flush_Layout); } NS_IMETHODIMP @@ -4687,8 +4621,15 @@ PresShell::IsSafeToFlush(PRBool& aIsSafeToFlush) } -NS_IMETHODIMP +NS_IMETHODIMP PresShell::FlushPendingNotifications(mozFlushType aType) +{ + return DoFlushPendingNotifications(aType, PR_FALSE); +} + +nsresult +PresShell::DoFlushPendingNotifications(mozFlushType aType, + PRBool aInterruptibleReflow) { NS_ASSERTION(aType >= Flush_Frames, "Why did we get called?"); @@ -4757,17 +4698,11 @@ PresShell::FlushPendingNotifications(mozFlushType aType) // There might be more pending constructors now, but we're not going to // worry about them. They can't be triggered during reflow, so we should // be good. - - if (aType >= (mSuppressInterruptibleReflows ? Flush_Layout : Flush_InterruptibleLayout) && - !mIsDestroying) { + + if (aType >= Flush_Layout && !mIsDestroying) { mFrameConstructor->RecalcQuotesAndCounters(); mViewManager->FlushDelayedResize(); - if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) { - // We didn't get interrupted. Go ahead and scroll to our content - DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition, - mContentScrollHPosition); - mContentToScrollTo = nsnull; - } + ProcessReflowCommands(aInterruptibleReflow); } PRUint32 updateFlags = NS_VMREFRESH_NO_SYNC; @@ -4776,7 +4711,7 @@ PresShell::FlushPendingNotifications(mozFlushType aType) // immediately updateFlags = NS_VMREFRESH_IMMEDIATE; } - else if (aType < Flush_InterruptibleLayout) { + else if (aType < Flush_Layout) { // Not flushing reflows, so do deferred invalidates. This will keep us // from possibly flushing out reflows due to invalidates being processed // at the end of this view batch. @@ -6610,7 +6545,7 @@ PresShell::WillPaint() // 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 // than to freeze up. - FlushPendingNotifications(Flush_InterruptibleLayout); + DoFlushPendingNotifications(Flush_Layout, PR_TRUE); } nsresult @@ -6820,17 +6755,7 @@ PresShell::ReflowEvent::Run() { // before processing that pres shell's reflow commands. Fixes bug 54868. nsCOMPtr viewManager = ps->GetViewManager(); - ps->mSuppressInterruptibleReflows = PR_FALSE; - -#ifdef NOISY_INTERRUPTIBLE_REFLOW - printf("*** Entering reflow event (time=%lld)\n", PR_Now()); -#endif /* NOISY_INTERRUPTIBLE_REFLOW */ - - ps->FlushPendingNotifications(Flush_InterruptibleLayout); - -#ifdef NOISY_INTERRUPTIBLE_REFLOW - printf("*** Returning from reflow event (time=%lld)\n", PR_Now()); -#endif /* NOISY_INTERRUPTIBLE_REFLOW */ + ps->DoFlushPendingNotifications(Flush_Layout, PR_TRUE); // Now, explicitly release the pres shell before the view manager ps = nsnull; @@ -6877,11 +6802,11 @@ PresShell::WillDoReflow() } void -PresShell::DidDoReflow(PRBool aInterruptible) +PresShell::DidDoReflow() { mFrameConstructor->EndUpdate(); - HandlePostedReflowCallbacks(aInterruptible); + HandlePostedReflowCallbacks(); // Null-check mViewManager in case this happens during Destroy. See // bugs 244435 and 238546. if (!mPaintingSuppressed && mViewManager) @@ -6894,24 +6819,8 @@ PresShell::DidDoReflow(PRBool aInterruptible) } } -static PLDHashOperator -MarkFramesDirtyToRoot(nsPtrHashKey* p, void* closure) -{ - nsIFrame* target = static_cast(closure); - for (nsIFrame* f = p->GetKey(); f && !NS_SUBTREE_DIRTY(f); - f = f->GetParent()) { - f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); - - if (f == target) { - break; - } - } - - return PL_DHASH_NEXT; -} - -PRBool -PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible) +void +PresShell::DoReflow(nsIFrame* target) { nsIFrame* rootFrame = FrameManager()->GetRootFrame(); @@ -6920,13 +6829,9 @@ PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible) // reflow; otherwise, it crashes on the mac (I'm not quite sure why) nsresult rv = CreateRenderingContext(rootFrame, getter_AddRefs(rcx)); if (NS_FAILED(rv)) { - NS_NOTREACHED("CreateRenderingContext failure"); - return PR_FALSE; - } - -#ifdef DEBUG - mCurrentReflowRoot = target; -#endif + NS_NOTREACHED("CreateRenderingContext failure"); + return; + } target->WillReflow(mPresContext); @@ -6961,9 +6866,6 @@ PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible) reflowState.mComputedBorderPadding.LeftRight(), "reflow state computed incorrect width"); - mPresContext->ReflowStarted(aInterruptible); - mIsReflowing = PR_TRUE; - nsReflowStatus status; nsHTMLReflowMetrics desiredSize; target->Reflow(mPresContext, desiredSize, reflowState, status); @@ -6995,38 +6897,6 @@ PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible) mPresContext->SetVisibleArea(nsRect(0, 0, desiredSize.width, desiredSize.height)); } - -#ifdef DEBUG - mCurrentReflowRoot = nsnull; -#endif - - NS_ASSERTION(mPresContext->HasPendingInterrupt() || - mFramesToDirty.Count() == 0, - "Why do we need to dirty anything if not interrupted?"); - - mIsReflowing = PR_FALSE; - PRBool interrupted = mPresContext->HasPendingInterrupt(); - if (interrupted) { - // Make sure target gets reflowed again. - mFramesToDirty.EnumerateEntries(&MarkFramesDirtyToRoot, target); - NS_ASSERTION(NS_SUBTREE_DIRTY(target), "Why is the target not dirty?"); - mDirtyRoots.AppendElement(target); - - // Clear mFramesToDirty after we've done the NS_SUBTREE_DIRTY(target) - // assertion so that if it fails it's easier to see what's going on. -#ifdef NOISY_INTERRUPTIBLE_REFLOW - printf("mFramesToDirty.Count() == %u\n", mFramesToDirty.Count()); -#endif /* NOISY_INTERRUPTIBLE_REFLOW */ - mFramesToDirty.Clear(); - - // Any FlushPendingNotifications with interruptible reflows - // should be suppressed now. We don't want to do extra reflow work - // before our reflow event happens. - mSuppressInterruptibleReflows = PR_TRUE; - PostReflowEvent(); - } - - return !interrupted; } #ifdef DEBUG @@ -7063,13 +6933,12 @@ PresShell::DoVerifyReflow() } #endif -PRBool +nsresult PresShell::ProcessReflowCommands(PRBool aInterruptible) { MOZ_TIMER_DEBUGLOG(("Start: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this)); MOZ_TIMER_START(mReflowWatch); - PRBool interrupted = PR_FALSE; if (0 != mDirtyRoots.Length()) { #ifdef DEBUG @@ -7089,6 +6958,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) { nsAutoScriptBlocker scriptBlocker; AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow); + mIsReflowing = PR_TRUE; do { // Send an incremental reflow notification to the target frame. @@ -7103,19 +6973,22 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) continue; } - interrupted = !DoReflow(target, aInterruptible); + DoReflow(target); // Keep going until we're out of reflow commands, or we've run - // past our deadline, or we're interrupted. - } while (!interrupted && mDirtyRoots.Length() && + // past our deadline. + } while (mDirtyRoots.Length() && (!aInterruptible || PR_IntervalNow() < deadline)); - interrupted = mDirtyRoots.Length() != 0; + // XXXwaterson for interruptible reflow, examine the tree and + // re-enqueue any unflowed reflow targets. + + mIsReflowing = PR_FALSE; } // Exiting the scriptblocker might have killed us if (!mIsDestroying) { - DidDoReflow(aInterruptible); + DidDoReflow(); } // DidDoReflow might have killed us @@ -7151,7 +7024,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible) UnsuppressAndInvalidate(); } - return !interrupted; + return NS_OK; } void diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index a5455a727e02..ff2ded318b2e 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -147,9 +147,9 @@ nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, nsIFrame* kidFrame; nsOverflowContinuationTracker tracker(aPresContext, aDelegatingFrame, PR_TRUE); for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) { - PRBool kidNeedsReflow = reflowAll || NS_SUBTREE_DIRTY(kidFrame) || - FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged); - if (kidNeedsReflow && !aPresContext->HasPendingInterrupt()) { + if (reflowAll || + NS_SUBTREE_DIRTY(kidFrame) || + FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged)) { // Reflow the frame nsReflowStatus kidStatus = NS_FRAME_COMPLETE; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, @@ -188,16 +188,7 @@ nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, kidFrame->GetPosition()); } } - - if (kidNeedsReflow && aPresContext->HasPendingInterrupt()) { - if (aDelegatingFrame->GetStateBits() & NS_FRAME_IS_DIRTY) { - kidFrame->AddStateBits(NS_FRAME_IS_DIRTY); - } else { - kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); - } - } } - // Abspos frames can't cause their parent to be incomplete, // only overflow incomplete. if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) @@ -343,25 +334,11 @@ nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame) void nsAbsoluteContainingBlock::MarkSizeDependentFramesDirty() -{ - DoMarkFramesDirty(PR_FALSE); -} - -void -nsAbsoluteContainingBlock::MarkAllFramesDirty() -{ - DoMarkFramesDirty(PR_TRUE); -} - -void -nsAbsoluteContainingBlock::DoMarkFramesDirty(PRBool aMarkAllDirty) { for (nsIFrame* kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) { - if (aMarkAllDirty) { - kidFrame->AddStateBits(NS_FRAME_IS_DIRTY); - } else if (FrameDependsOnContainer(kidFrame, PR_TRUE, PR_TRUE)) { + if (FrameDependsOnContainer(kidFrame, PR_TRUE, PR_TRUE)) { // Add the weakest flags that will make sure we reflow this frame later kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); } diff --git a/layout/generic/nsAbsoluteContainingBlock.h b/layout/generic/nsAbsoluteContainingBlock.h index d200295b07ac..6832f95116b5 100644 --- a/layout/generic/nsAbsoluteContainingBlock.h +++ b/layout/generic/nsAbsoluteContainingBlock.h @@ -127,13 +127,8 @@ public: PRBool HasAbsoluteFrames() {return mAbsoluteFrames.NotEmpty();} - // Mark our size-dependent absolute frames with NS_FRAME_HAS_DIRTY_CHILDREN - // so that we'll make sure to reflow them. void MarkSizeDependentFramesDirty(); - // Mark all our absolute frames with NS_FRAME_IS_DIRTY - void MarkAllFramesDirty(); - protected: // Returns PR_TRUE if the position of f depends on the position of // its placeholder or if the position or size of f depends on a @@ -151,11 +146,6 @@ protected: nsReflowStatus& aStatus, nsRect* aChildBounds); - // Mark our absolute frames dirty. If aMarkAllDirty is true, all will be - // marked with NS_FRAME_IS_DIRTY. Otherwise, the size-dependant ones will be - // marked with NS_FRAME_HAS_DIRTY_CHILDREN. - void DoMarkFramesDirty(PRBool aMarkAllDirty); - protected: nsFrameList mAbsoluteFrames; // additional named child list diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 8ea973459c9b..86c97e862204 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1122,20 +1122,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext, // in that situation --- what we think is our "new size" // will not be our real new size. This also happens to be more efficient. if (mAbsoluteContainer.HasAbsoluteFrames()) { - PRBool haveInterrupt = aPresContext->HasPendingInterrupt(); - if (aReflowState.WillReflowAgainForClearance() || - haveInterrupt) { + if (aReflowState.WillReflowAgainForClearance()) { // Make sure that when we reflow again we'll actually reflow all the abs - // pos frames that might conceivably depend on our size (or all of them, - // if we're dirty right now and interrupted; in that case we also need - // to mark them all with NS_FRAME_IS_DIRTY). Sadly, we can't do much - // better than that, because we don't really know what our size will be, - // and it might in fact not change on the followup reflow! - if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) { - mAbsoluteContainer.MarkAllFramesDirty(); - } else { - mAbsoluteContainer.MarkSizeDependentFramesDirty(); - } + // pos frames that might conceivably depend on our size. Sadly, we can't + // do much better than that, because we don't really know what our size + // will be, and it might in fact not change on the followup reflow! + mAbsoluteContainer.MarkSizeDependentFramesDirty(); } else { nsRect childBounds; nsSize containingBlockSize = @@ -2024,18 +2016,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) } DumpLine(aState, line, deltaY, -1); - - if (aState.mPresContext->CheckForInterrupt(this)) { - willReflowAgain = PR_TRUE; - // Another option here might be to leave |line| clean if - // !HasPendingInterrupt() before the CheckForInterrupt() call, since in - // that case the line really did reflow as it should have. Not sure - // whether that would be safe, so doing this for now instead. Also not - // sure whether we really want to mark all lines dirty after an - // interrupt, but until we get better at propagating float damage we - // really do need to do it this way; see comments inside MarkLineDirty. - MarkLineDirtyForInterrupt(line); - } } // Handle BR-clearance from the last line of the block @@ -2057,9 +2037,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) if (repositionViews) ::PlaceFrameView(this); - // We can skip trying to pull up the next line if our height is constrained - // (so we can report being incomplete) and there is no next in flow or we - // were told not to or we know it will be futile, i.e., + // We can skip trying to pull up the next line if there is no next + // in flow or we were told not to or we know it will be futile, i.e., // -- the next in flow is not changing // -- and we cannot have added more space for its first line to be // pulled up into, @@ -2068,10 +2047,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) // didn't change) // -- my chain of next-in-flows either has no first line, or its first // line isn't dirty. - PRBool heightConstrained = - aState.mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE; - PRBool skipPull = willReflowAgain && heightConstrained; - if (!skipPull && heightConstrained && aState.mNextInFlow && + PRBool skipPull = willReflowAgain; + if (aState.mNextInFlow && (aState.mReflowState.mFlags.mNextInFlowUntouched && !lastLineMovedUp && !(GetStateBits() & NS_FRAME_IS_DIRTY) && @@ -2090,18 +2067,14 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) // (First, see if there is such a line, and second, see if it's clean) if (!bifLineIter.Next() || !bifLineIter.GetLine()->IsDirty()) { + if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow)) + NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus); + else + NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus); skipPull=PR_TRUE; } } } - - if (skipPull && aState.mNextInFlow) { - NS_ASSERTION(heightConstrained, "Height should be constrained here\n"); - if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow)) - NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus); - else - NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus); - } if (!skipPull && aState.mNextInFlow) { // Pull data from a next-in-flow if there's still room for more @@ -2184,38 +2157,28 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) AutoNoisyIndenter indent2(gNoisyReflow); #endif - if (aState.mPresContext->HasPendingInterrupt()) { - MarkLineDirtyForInterrupt(line); - } else { - // Now reflow it and any lines that it makes during it's reflow - // (we have to loop here because reflowing the line may case a new - // line to be created; see SplitLine's callers for examples of - // when this happens). - while (line != end_lines()) { - rv = ReflowLine(aState, line, &keepGoing); - NS_ENSURE_SUCCESS(rv, rv); - DumpLine(aState, line, deltaY, -1); - if (!keepGoing) { - if (0 == line->GetChildCount()) { - DeleteLine(aState, line, line_end); - } - break; + // Now reflow it and any lines that it makes during it's reflow + // (we have to loop here because reflowing the line may case a new + // line to be created; see SplitLine's callers for examples of + // when this happens). + while (line != end_lines()) { + rv = ReflowLine(aState, line, &keepGoing); + NS_ENSURE_SUCCESS(rv, rv); + DumpLine(aState, line, deltaY, -1); + if (!keepGoing) { + if (0 == line->GetChildCount()) { + DeleteLine(aState, line, line_end); } - - if (LineHasClear(line.get())) { - foundAnyClears = PR_TRUE; - } - - if (aState.mPresContext->CheckForInterrupt(this)) { - willReflowAgain = PR_TRUE; - MarkLineDirtyForInterrupt(line); - break; - } - - // If this is an inline frame then its time to stop - ++line; - aState.AdvanceToNextLine(); + break; } + + if (LineHasClear(line.get())) { + foundAnyClears = PR_TRUE; + } + + // If this is an inline frame then its time to stop + ++line; + aState.AdvanceToNextLine(); } } @@ -2253,54 +2216,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) return rv; } -static void MarkAllDescendantLinesDirty(nsBlockFrame* aBlock) -{ - nsLineList::iterator line = aBlock->begin_lines(); - nsLineList::iterator endLine = aBlock->end_lines(); - while (line != endLine) { - if (line->IsBlock()) { - nsIFrame* f = line->mFirstChild; - nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(f); - if (bf) { - MarkAllDescendantLinesDirty(bf); - } - } - line->MarkDirty(); - ++line; - } -} - -void -nsBlockFrame::MarkLineDirtyForInterrupt(nsLineBox* aLine) -{ - aLine->MarkDirty(); - - // Just checking NS_FRAME_IS_DIRTY is ok, because we've already - // marked the lines that need to be marked dirty based on our - // vertical resize stuff. So we'll definitely reflow all those kids; - // the only question is how they should behave. - if (GetStateBits() & NS_FRAME_IS_DIRTY) { - // Mark all our child frames dirty so we make sure to reflow them - // later. - PRInt32 n = aLine->GetChildCount(); - for (nsIFrame* f = aLine->mFirstChild; n > 0; - f = f->GetNextSibling(), --n) { - f->AddStateBits(NS_FRAME_IS_DIRTY); - } - } else { - // Dirty all the descendant lines of block kids to handle float damage, - // since our nsFloatManager will go away by the next time we're reflowing. - // XXXbz Can we do something more like what PropagateFloatDamage does? - // Would need to sort out the exact business with mBlockDelta for that.... - // This marks way too much dirty. If we ever make this better, revisit - // which lines we mark dirty in the interrupt case in ReflowDirtyLines. - nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(aLine->mFirstChild); - if (bf) { - MarkAllDescendantLinesDirty(bf); - } - } -} - void nsBlockFrame::DeleteLine(nsBlockReflowState& aState, nsLineList::iterator aLine, @@ -5043,6 +4958,23 @@ nsBlockFrame::RemoveFloat(nsIFrame* aFloat) { return line_end; } +static void MarkAllDescendantLinesDirty(nsBlockFrame* aBlock) +{ + nsLineList::iterator line = aBlock->begin_lines(); + nsLineList::iterator endLine = aBlock->end_lines(); + while (line != endLine) { + if (line->IsBlock()) { + nsIFrame* f = line->mFirstChild; + nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(f); + if (bf) { + MarkAllDescendantLinesDirty(bf); + } + } + line->MarkDirty(); + ++line; + } +} + static void MarkSameFloatManagerLinesDirty(nsBlockFrame* aBlock) { nsBlockFrame* blockWithFloatMgr = aBlock; diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 0541dea69309..123b2bb78e22 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -464,9 +464,6 @@ protected: /** reflow all lines that have been marked dirty */ nsresult ReflowDirtyLines(nsBlockReflowState& aState); - /** Mark a given line dirty due to reflow being interrupted on or before it */ - void MarkLineDirtyForInterrupt(nsLineBox* aLine); - //---------------------------------------- // Methods for line reflow /** diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index df9d9a983723..b93db8790f41 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -755,16 +755,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize, } } - if (PresContext()->HasPendingInterrupt()) { - // Stop the loop now while |child| still points to the frame that bailed - // out. We could keep going here and condition a bunch of the code in - // this loop on whether there's an interrupt, or even just keep going and - // trying to reflow the blocks (even though we know they'll interrupt - // right after their first line), but stopping now is conceptually the - // simplest (and probably fastest) thing. - break; - } - // Advance to the next column child = child->GetNextSibling(); @@ -780,14 +770,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize, #endif } } - - if (PresContext()->HasPendingInterrupt() && - (GetStateBits() & NS_FRAME_IS_DIRTY)) { - // Mark all our kids starting with |child| dirty - for (; child; child = child->GetNextSibling()) { - child->AddStateBits(NS_FRAME_IS_DIRTY); - } - } // If we're doing RTL, we need to make sure our last column is at the left-hand side of the frame. if (RTL && childOrigin.x != targetX) { @@ -915,7 +897,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext, PRBool feasible = ReflowChildren(aDesiredSize, aReflowState, aStatus, config, unboundedLastColumn, &carriedOutBottomMargin, colData); - if (isBalancing && !aPresContext->HasPendingInterrupt()) { + if (isBalancing) { nscoord availableContentHeight = GetAvailableContentHeight(aReflowState); // Termination of the algorithm below is guaranteed because @@ -928,7 +910,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext, // search) PRBool maybeContinuousBreakingDetected = PR_FALSE; - while (!aPresContext->HasPendingInterrupt()) { + while (1) { nscoord lastKnownFeasibleHeight = knownFeasibleHeight; // Record what we learned from the last reflow @@ -1020,7 +1002,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext, &carriedOutBottomMargin, colData); } - if (!feasible && !aPresContext->HasPendingInterrupt()) { + if (!feasible) { // We may need to reflow one more time at the feasible height to // get a valid layout. PRBool skip = PR_FALSE; @@ -1039,13 +1021,6 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext, } } } - - if (aPresContext->HasPendingInterrupt() && - aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) { - // In this situation, we might be lying about our reflow status, because - // our last kid (the one that got interrupted) was incomplete. Fix that. - aStatus = NS_FRAME_COMPLETE; - } CheckInvalidateSizeChange(aDesiredSize); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 2619ed6a0fca..017fc27566b8 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1926,7 +1926,7 @@ nsGfxScrollFrameInner::AsyncScrollPortEvent::Run() { if (mInner) { mInner->mOuter->PresContext()->GetPresShell()-> - FlushPendingNotifications(Flush_InterruptibleLayout); + FlushPendingNotifications(Flush_Layout); } return mInner ? mInner->FireScrollPortEvent() : NS_OK; } diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index a574880f7199..247ec0fe5f4f 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -2055,9 +2055,6 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) #ifdef NOISY_VERTICAL_ALIGN printf(" new values: %d,%d\n", minY, maxY); -#endif -#ifdef NOISY_VERTICAL_ALIGN - printf(" Used mMinLineHeight: %d, fontHeight: %d, fontAscent: %d\n", mMinLineHeight, fontHeight, fontAscent); #endif } else { diff --git a/layout/reftests/bugs/67752-1-ref.html b/layout/reftests/bugs/67752-1-ref.html deleted file mode 100644 index f21044d0e360..000000000000 --- a/layout/reftests/bugs/67752-1-ref.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - Test -
- - -
- - diff --git a/layout/reftests/bugs/67752-1.html b/layout/reftests/bugs/67752-1.html deleted file mode 100644 index 16487b7ff9c5..000000000000 --- a/layout/reftests/bugs/67752-1.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - Test -
- - -
- - diff --git a/layout/reftests/bugs/67752-2-ref.html b/layout/reftests/bugs/67752-2-ref.html deleted file mode 100644 index 328e1a15b6dd..000000000000 --- a/layout/reftests/bugs/67752-2-ref.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - Test -
- - -
- - diff --git a/layout/reftests/bugs/67752-2.html b/layout/reftests/bugs/67752-2.html deleted file mode 100644 index 52f63cccc4a7..000000000000 --- a/layout/reftests/bugs/67752-2.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - Test -
- - -
- - diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 0a046319470b..9ef7ed7b5986 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -66,8 +66,6 @@ fails == 25888-3r.html 25888-3r-ref.html # bug 25888 == 50630-4.html 50630-4-ref.html == 50630-4.html 50630-4-ref2.html == 50630-5.html 50630-5-ref.html -== 67752-1.html 67752-1-ref.html -== 67752-2.html 67752-2-ref.html == 68061-1.xml 68061-1-ref.xml == 68061-2.xml 68061-2-ref.xml == 76331-1.html 76331-1-ref.html diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index b643761e9bb0..18bca3b3de35 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -379,9 +379,6 @@ nsSVGForeignObjectFrame::InitialUpdate() "before our nsSVGOuterSVGFrame's initial Reflow()!!!"); UpdateCoveredRegion(); - - // Make sure to not allow interrupts if we're not being reflown as a root - nsPresContext::InterruptPreventer noInterrupts(PresContext()); DoReflow(); NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), @@ -604,9 +601,6 @@ nsSVGForeignObjectFrame::MaybeReflowFromOuterSVGFrame() if (kid->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN) { return; } - - // Make sure to not allow interrupts if we're not being reflown as a root - nsPresContext::InterruptPreventer noInterrupts(PresContext()); DoReflow(); } diff --git a/widget/public/nsIWidget.h b/widget/public/nsIWidget.h index f10a8e1d1f4b..c59579dc740b 100644 --- a/widget/public/nsIWidget.h +++ b/widget/public/nsIWidget.h @@ -100,10 +100,10 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event); #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102 #endif -// 3d277f04-93f4-4384-9fdc-e1e2d1fc4e33 +// af70b716-2e34-463f-8f1c-273dbddd845b #define NS_IWIDGET_IID \ -{ 0x3d277f04, 0x93f4, 0x4384, \ - { 0x9f, 0xdc, 0xe1, 0xe2, 0xd1, 0xfc, 0x4e, 0x33 } } +{ 0xaf70b716, 0x2e34, 0x463f, \ + { 0x8f, 0x1c, 0x27, 0x3d, 0xbd, 0xdd, 0x84, 0x5b } } /* * Window shadow styles @@ -816,12 +816,6 @@ class nsIWidget : public nsISupports { */ NS_IMETHOD GetLastInputEventTime(PRUint32& aTime) = 0; - /** - * Ask whether there user input events pending. All input events are - * included, including those not targeted at this nsIwidget instance. - */ - virtual PRBool HasPendingInputEvent() = 0; - /** * Called when when we need to begin secure keyboard input, such as when a password field * gets focus. diff --git a/widget/src/cocoa/nsAppShell.mm b/widget/src/cocoa/nsAppShell.mm index f0fb6970033e..33116b2db47f 100644 --- a/widget/src/cocoa/nsAppShell.mm +++ b/widget/src/cocoa/nsAppShell.mm @@ -668,10 +668,6 @@ nsAppShell::ProcessNextNativeEvent(PRBool aMayWait) NS_OBJC_END_TRY_ABORT_BLOCK; - if (!moreEvents) { - nsChildView::UpdateCurrentInputEventCount(); - } - return moreEvents; } diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index 95283a5a95b8..76f227fb9abc 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -369,8 +369,6 @@ public: NS_IMETHOD GetAttention(PRInt32 aCycleCount); - virtual PRBool HasPendingInputEvent(); - NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString); NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString); @@ -411,9 +409,6 @@ public: void HidePlugin(); - static PRBool DoHasPendingInputEvent(); - static PRUint32 GetCurrentInputEventCount(); - static void UpdateCurrentInputEventCount(); protected: PRBool ReportDestroyEvent(); @@ -459,8 +454,6 @@ protected: nsPluginPort mPluginPort; nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK] - - static PRUint32 sLastInputEventCount; }; void NS_InstallPluginKeyEventsHandler(); diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 7e50f67f2696..cd6ec4cc34d9 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -82,8 +82,6 @@ #include -#include - #undef DEBUG_IME #undef DEBUG_UPDATE #undef INVALIDATE_DEBUGGING // flash areas as they are invalidated @@ -151,8 +149,6 @@ PRUint32 gLastModifierState = 0; PRBool gUserCancelledDrag = PR_FALSE; -PRUint32 nsChildView::sLastInputEventCount = 0; - @interface ChildView(Private) // sets up our view, attaching it to its owning gecko view @@ -2052,54 +2048,6 @@ NS_IMETHODIMP nsChildView::GetAttention(PRInt32 aCycleCount) NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } -/* static */ -PRBool nsChildView::DoHasPendingInputEvent() -{ - return sLastInputEventCount != GetCurrentInputEventCount(); -} - -/* static */ -PRUint32 nsChildView::GetCurrentInputEventCount() -{ - // Can't use kCGAnyInputEventType because that updates too rarely for us (and - // always in increments of 30+!) and because apparently it's sort of broken - // on Tiger. So just go ahead and query the counters we care about. - static const CGEventType eventTypes[] = { - kCGEventLeftMouseDown, - kCGEventLeftMouseUp, - kCGEventRightMouseDown, - kCGEventRightMouseUp, - kCGEventMouseMoved, - kCGEventLeftMouseDragged, - kCGEventRightMouseDragged, - kCGEventKeyDown, - kCGEventKeyUp, - kCGEventScrollWheel, - kCGEventTabletPointer, - kCGEventOtherMouseDown, - kCGEventOtherMouseUp, - kCGEventOtherMouseDragged - }; - - PRUint32 eventCount = 0; - for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(eventTypes); ++i) { - eventCount += - CGEventSourceCounterForEventType(kCGEventSourceStateCombinedSessionState, - eventTypes[i]); - } - return eventCount; -} - -/* static */ -void nsChildView::UpdateCurrentInputEventCount() -{ - sLastInputEventCount = GetCurrentInputEventCount(); -} - -PRBool nsChildView::HasPendingInputEvent() -{ - return DoHasPendingInputEvent(); -} #pragma mark - diff --git a/widget/src/cocoa/nsCocoaWindow.h b/widget/src/cocoa/nsCocoaWindow.h index 524403afdb84..ede96a792ea0 100644 --- a/widget/src/cocoa/nsCocoaWindow.h +++ b/widget/src/cocoa/nsCocoaWindow.h @@ -247,7 +247,6 @@ public: NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ; NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent); NS_IMETHOD GetAttention(PRInt32 aCycleCount); - virtual PRBool HasPendingInputEvent(); virtual nsTransparencyMode GetTransparencyMode(); virtual void SetTransparencyMode(nsTransparencyMode aMode); NS_IMETHOD SetWindowShadowStyle(PRInt32 aStyle); diff --git a/widget/src/cocoa/nsCocoaWindow.mm b/widget/src/cocoa/nsCocoaWindow.mm index 2caba499ecf6..a787f0a3483b 100644 --- a/widget/src/cocoa/nsCocoaWindow.mm +++ b/widget/src/cocoa/nsCocoaWindow.mm @@ -62,7 +62,6 @@ #include "nsMenuUtilsX.h" #include "nsStyleConsts.h" #include "nsNativeThemeColors.h" -#include "nsChildView.h" #include "gfxPlatform.h" #include "qcms.h" @@ -1313,11 +1312,6 @@ NS_IMETHODIMP nsCocoaWindow::GetAttention(PRInt32 aCycleCount) NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } -PRBool -nsCocoaWindow::HasPendingInputEvent() -{ - return nsChildView::DoHasPendingInputEvent(); -} NS_IMETHODIMP nsCocoaWindow::SetWindowShadowStyle(PRInt32 aStyle) { diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 304cd0102fda..3c308e5e0e6f 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -1911,39 +1911,6 @@ nsWindow::GetAttention(PRInt32 aCycleCount) return NS_OK; } -PRBool -nsWindow::HasPendingInputEvent() -{ - // This sucks, but gtk/gdk has no way to answer the question we want while - // excluding paint events, and there's no X API that will let us peek - // without blocking or removing. To prevent event reordering, peek - // anything except expose events. Reordering expose and others should be - // ok, hopefully. - PRBool haveEvent; -#ifdef MOZ_X11 - XEvent ev; - haveEvent = - XCheckMaskEvent(GDK_DISPLAY(), - KeyPressMask | KeyReleaseMask | ButtonPressMask | - ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | - PointerMotionMask | PointerMotionHintMask | - Button1MotionMask | Button2MotionMask | - Button3MotionMask | Button4MotionMask | - Button5MotionMask | ButtonMotionMask | KeymapStateMask | - VisibilityChangeMask | StructureNotifyMask | - ResizeRedirectMask | SubstructureNotifyMask | - SubstructureRedirectMask | FocusChangeMask | - PropertyChangeMask | ColormapChangeMask | - OwnerGrabButtonMask, &ev); - if (haveEvent) { - XPutBackEvent(GDK_DISPLAY(), &ev); - } -#else - haveEvent = PR_FALSE; -#endif - return haveEvent; -} - void nsWindow::LoseFocus(void) { diff --git a/widget/src/gtk2/nsWindow.h b/widget/src/gtk2/nsWindow.h index 492a8e3d9608..dbcf1688cdfa 100644 --- a/widget/src/gtk2/nsWindow.h +++ b/widget/src/gtk2/nsWindow.h @@ -204,9 +204,6 @@ public: PRBool aDoCapture, PRBool aConsumeRollupEvent); NS_IMETHOD GetAttention(PRInt32 aCycleCount); - - virtual PRBool HasPendingInputEvent(); - NS_IMETHOD MakeFullScreen(PRBool aFullScreen); NS_IMETHOD HideWindowChrome(PRBool aShouldHide); diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index cc9787e3e515..676e68c40cec 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -3393,20 +3393,16 @@ NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec) NS_IMETHODIMP nsWindow::GetLastInputEventTime(PRUint32& aTime) { - // If there is pending input then return the current time. - if (HasPendingInputEvent()) { - gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); - } + ULONG ulStatus = WinQueryQueueStatus(HWND_DESKTOP); - aTime = gLastInputEventTime; + // If there is pending input then return the current time. + if (ulStatus & (QS_KEY | QS_MOUSE)) { + gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); + } - return NS_OK; -} + aTime = gLastInputEventTime; -PRBool -nsWindow::HasPendingInputEvent() -{ - return (WinQueryQueueStatus(HWND_DESKTOP) & (QS_KEY | QS_MOUSE)) != 0; + return NS_OK; } // -------------------------------------------------------------------------- diff --git a/widget/src/os2/nsWindow.h b/widget/src/os2/nsWindow.h index 9c653b91a21f..63504a126c6a 100644 --- a/widget/src/os2/nsWindow.h +++ b/widget/src/os2/nsWindow.h @@ -161,7 +161,6 @@ class nsWindow : public nsBaseWidget, NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent); NS_IMETHOD GetLastInputEventTime(PRUint32& aTime); - virtual PRBool HasPendingInputEvent(); // Widget appearance NS_IMETHOD SetCursor( nsCursor aCursor); diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 56629d67bd62..d1db99340e26 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -7967,7 +7967,15 @@ void nsWindow::StopFlashing() NS_IMETHODIMP nsWindow::GetLastInputEventTime(PRUint32& aTime) { - if (HasPendingInputEvent()) { + WORD qstatus = HIWORD(GetQueueStatus(QS_INPUT)); + + // If there is pending input or the user is currently + // moving the window then return the current time. + // Note: When the user is moving the window WIN32 spins + // a separate event loop and input events are not + // reported to the application. + nsToolkit* toolkit = (nsToolkit *)mToolkit; + if (qstatus || (toolkit && toolkit->UserIsMovingWindow())) { gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); } @@ -7976,19 +7984,6 @@ nsWindow::GetLastInputEventTime(PRUint32& aTime) return NS_OK; } -PRBool -nsWindow::HasPendingInputEvent() -{ - // If there is pending input or the user is currently - // moving the window then return true. - // Note: When the user is moving the window WIN32 spins - // a separate event loop and input events are not - // reported to the application. - WORD qstatus = HIWORD(GetQueueStatus(QS_INPUT)); - nsToolkit* toolkit = (nsToolkit *)mToolkit; - return qstatus || (toolkit && toolkit->UserIsMovingWindow()); -} - //------------------------------------------------------------------------- //------------------------------------------------------------------------- //-- NOTE!!! These hook functions can be removed when we migrate to diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index 1b4951da66f0..5be3ad444855 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -199,7 +199,6 @@ public: NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetLastInputEventTime(PRUint32& aTime); - virtual PRBool HasPendingInputEvent(); // Note that the result of GetTopLevelWindow method can be different from the // result of GetTopLevelHWND method. The result can be non-floating window. diff --git a/widget/src/xpwidgets/nsBaseWidget.cpp b/widget/src/xpwidgets/nsBaseWidget.cpp index a9f0b1adcc99..2bc1cae2c7c6 100644 --- a/widget/src/xpwidgets/nsBaseWidget.cpp +++ b/widget/src/xpwidgets/nsBaseWidget.cpp @@ -798,12 +798,6 @@ nsBaseWidget::GetLastInputEventTime(PRUint32& aTime) { return NS_ERROR_NOT_IMPLEMENTED; } -PRBool -nsBaseWidget::HasPendingInputEvent() -{ - return PR_FALSE; -} - NS_IMETHODIMP nsBaseWidget::SetIcon(const nsAString&) { diff --git a/widget/src/xpwidgets/nsBaseWidget.h b/widget/src/xpwidgets/nsBaseWidget.h index 42d28caa923f..42a040bb5008 100644 --- a/widget/src/xpwidgets/nsBaseWidget.h +++ b/widget/src/xpwidgets/nsBaseWidget.h @@ -122,7 +122,6 @@ public: NS_IMETHOD EnableDragDrop(PRBool aEnable); NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetLastInputEventTime(PRUint32& aTime); - virtual PRBool HasPendingInputEvent(); NS_IMETHOD SetIcon(const nsAString &anIconSpec); NS_IMETHOD BeginSecureKeyboardInput(); NS_IMETHOD EndSecureKeyboardInput();