Backed out changeset 6a452e522e07 - Boris Zbarsky – Bug 67752. Implement interruptible reflow. r=roc,dbaron - because of apparent Tp hangs.

This commit is contained in:
Joe Drew
2009-04-21 23:02:17 -04:00
parent 600528e80b
commit 659abece3b
37 changed files with 147 additions and 823 deletions

View File

@@ -48,12 +48,8 @@ enum mozFlushType {
notifications. */ notifications. */
Flush_Style = 3, /* As above, plus flush style reresolution */ Flush_Style = 3, /* As above, plus flush style reresolution */
Flush_Frames = Flush_Style, Flush_Frames = Flush_Style,
Flush_InterruptibleLayout = 4, /* As above, plus flush reflow, Flush_Layout = 4, /* As above, plus flush reflow */
but allow it to be interrupted (so Flush_Display = 5 /* As above, plus flush painting */
an incomplete layout may result) */
Flush_Layout = 5, /* As above, but layout must run to
completion */
Flush_Display = 6 /* As above, plus flush painting */
}; };
#endif /* mozFlushType_h___ */ #endif /* mozFlushType_h___ */

View File

@@ -6257,8 +6257,8 @@ nsDocument::FlushPendingNotifications(mozFlushType aType)
// correct size to determine the correct style. // correct size to determine the correct style.
if (mParentDocument && IsSafeToFlush()) { if (mParentDocument && IsSafeToFlush()) {
mozFlushType parentType = aType; mozFlushType parentType = aType;
if (aType >= Flush_Style) if (aType == Flush_Style)
parentType = PR_MAX(Flush_Layout, aType); parentType = Flush_Layout;
mParentDocument->FlushPendingNotifications(parentType); mParentDocument->FlushPendingNotifications(parentType);
} }

View File

@@ -5749,7 +5749,7 @@ nsEventStateManager::FlushPendingEvents(nsPresContext* aPresContext)
NS_PRECONDITION(nsnull != aPresContext, "nsnull ptr"); NS_PRECONDITION(nsnull != aPresContext, "nsnull ptr");
nsIPresShell *shell = aPresContext->GetPresShell(); nsIPresShell *shell = aPresContext->GetPresShell();
if (shell) { if (shell) {
shell->FlushPendingNotifications(Flush_InterruptibleLayout); shell->FlushPendingNotifications(Flush_Display);
} }
} }

View File

@@ -1308,8 +1308,9 @@ nsGenericHTMLElement::GetFormControlFrameFor(nsIContent* aContent,
PRBool aFlushContent) PRBool aFlushContent)
{ {
if (aFlushContent) { if (aFlushContent) {
// Cause a flush of the frames, so we get up-to-date frame information // Cause a flush of content, so we get up-to-date frame
aDocument->FlushPendingNotifications(Flush_Frames); // information
aDocument->FlushPendingNotifications(Flush_Layout);
} }
nsIFrame* frame = GetPrimaryFrameFor(aContent, aDocument); nsIFrame* frame = GetPrimaryFrameFor(aContent, aDocument);
if (frame) { if (frame) {
@@ -2695,10 +2696,7 @@ nsGenericHTMLFormElement::SetFocusAndScrollIntoView(nsPresContext* aPresContext)
{ {
nsIEventStateManager *esm = aPresContext->EventStateManager(); nsIEventStateManager *esm = aPresContext->EventStateManager();
if (esm->SetContentState(this, NS_EVENT_STATE_FOCUS)) { if (esm->SetContentState(this, NS_EVENT_STATE_FOCUS)) {
// XXXldb once bug 43114 is fixed, we don't need to flush here. nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
aPresContext->Document()->
FlushPendingNotifications(Flush_InterruptibleLayout);
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (formControlFrame) { if (formControlFrame) {
formControlFrame->SetFocus(PR_TRUE, PR_TRUE); formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell(); nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();

View File

@@ -3200,7 +3200,7 @@ HTMLContentSink::FlushPendingNotifications(mozFlushType aType)
else if (mCurrentContext) { else if (mCurrentContext) {
mCurrentContext->FlushText(); mCurrentContext->FlushText();
} }
if (aType >= Flush_InterruptibleLayout) { if (aType >= Flush_Layout) {
// Make sure that layout has started so that the reflow flush // Make sure that layout has started so that the reflow flush
// will actually happen. // will actually happen.
StartLayout(PR_TRUE); StartLayout(PR_TRUE);

View File

@@ -1653,7 +1653,7 @@ nsXMLContentSink::FlushPendingNotifications(mozFlushType aType)
else { else {
FlushText(PR_FALSE); FlushText(PR_FALSE);
} }
if (aType >= Flush_InterruptibleLayout) { if (aType >= Flush_Layout) {
// Make sure that layout has started so that the reflow flush // Make sure that layout has started so that the reflow flush
// will actually happen. // will actually happen.
MaybeStartLayout(PR_TRUE); MaybeStartLayout(PR_TRUE);

View File

@@ -101,10 +101,10 @@ class nsPIDOMEventTarget;
typedef short SelectionType; typedef short SelectionType;
typedef PRUint32 nsFrameState; typedef PRUint32 nsFrameState;
// 4fb87dae-8986-429f-b6ba-f040750e3ee8 // fa7f090d-b19a-4ef8-9552-82992a3b4a83
#define NS_IPRESSHELL_IID \ #define NS_IPRESSHELL_IID \
{ 0x4fb87dae, 0x8986, 0x429f, \ { 0xfa7f090d, 0xb19a, 0x4ef8, \
{ 0xb6, 0xba, 0xf0, 0x40, 0x75, 0x0e, 0x3e, 0xe8 } } { 0x95, 0x52, 0x82, 0x99, 0x2a, 0x3b, 0x4a, 0x83 } }
// Constants for ScrollContentIntoView() function // Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0 #define NS_PRESSHELL_SCROLL_TOP 0
@@ -124,8 +124,6 @@ typedef PRUint32 nsFrameState;
#define VERIFY_REFLOW_REALLY_NOISY_RC 0x20 #define VERIFY_REFLOW_REALLY_NOISY_RC 0x20
#define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x40 #define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x40
#undef NOISY_INTERRUPTIBLE_REFLOW
/** /**
* Presentation shell interface. Presentation shells are the * Presentation shell interface. Presentation shells are the
* controlling point for managing the presentation of a document. The * controlling point for managing the presentation of a document. The
@@ -369,19 +367,6 @@ public:
IntrinsicDirty aIntrinsicDirty, IntrinsicDirty aIntrinsicDirty,
nsFrameState aBitToAdd) = 0; 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; NS_IMETHOD CancelAllPendingReflows() = 0;
/** /**
@@ -476,7 +461,7 @@ public:
*/ */
NS_IMETHOD ScrollContentIntoView(nsIContent* aContent, NS_IMETHOD ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, PRIntn aVPercent,
PRIntn aHPercent) = 0; PRIntn aHPercent) const = 0;
/** /**
* Suppress notification of the frame manager that frames are * Suppress notification of the frame manager that frames are

View File

@@ -90,8 +90,6 @@
#include "nsFontFaceLoader.h" #include "nsFontFaceLoader.h"
#include "nsIEventListenerManager.h" #include "nsIEventListenerManager.h"
#include "nsStyleStructInlines.h" #include "nsStyleStructInlines.h"
#include "nsIAppShell.h"
#include "prenv.h"
#ifdef MOZ_SMIL #ifdef MOZ_SMIL
#include "nsSMILAnimationController.h" #include "nsSMILAnimationController.h"
@@ -2029,125 +2027,3 @@ nsPresContext::HasCachedStyleData()
{ {
return mShell && mShell->StyleSet()->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;
}

View File

@@ -806,58 +806,6 @@ public:
mCrossDocDirtyRegion.SetEmpty(); 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: protected:
friend class nsRunnableMethod<nsPresContext>; friend class nsRunnableMethod<nsPresContext>;
NS_HIDDEN_(void) ThemeChangedInternal(); NS_HIDDEN_(void) ThemeChangedInternal();
@@ -886,8 +834,6 @@ protected:
FlushUserFontSet(); FlushUserFontSet();
} }
PRBool HavePendingInputEvent();
// Can't be inline because we can't include nsStyleSet.h. // Can't be inline because we can't include nsStyleSet.h.
PRBool HasCachedStyleData(); PRBool HasCachedStyleData();
@@ -975,10 +921,6 @@ protected:
nscoord mBorderWidthTable[3]; nscoord mBorderWidthTable[3];
PRUint32 mInterruptChecksToSkip;
unsigned mHasPendingInterrupt : 1;
unsigned mInterruptsEnabled : 1;
unsigned mUseDocumentFonts : 1; unsigned mUseDocumentFonts : 1;
unsigned mUseDocumentColors : 1; unsigned mUseDocumentColors : 1;
unsigned mUnderlineLinks : 1; unsigned mUnderlineLinks : 1;

View File

@@ -934,7 +934,6 @@ public:
nsIFrame** aPlaceholderFrame) const; nsIFrame** aPlaceholderFrame) const;
NS_IMETHOD FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, NS_IMETHOD FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
nsFrameState aBitToAdd); nsFrameState aBitToAdd);
NS_IMETHOD_(void) FrameNeedsToContinueReflow(nsIFrame *aFrame);
NS_IMETHOD CancelAllPendingReflows(); NS_IMETHOD CancelAllPendingReflows();
NS_IMETHOD IsSafeToFlush(PRBool& aIsSafeToFlush); NS_IMETHOD IsSafeToFlush(PRBool& aIsSafeToFlush);
NS_IMETHOD FlushPendingNotifications(mozFlushType aType); NS_IMETHOD FlushPendingNotifications(mozFlushType aType);
@@ -958,7 +957,7 @@ public:
NS_IMETHOD ScrollContentIntoView(nsIContent* aContent, NS_IMETHOD ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, PRIntn aVPercent,
PRIntn aHPercent); PRIntn aHPercent) const;
NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore); NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore);
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame); NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame);
@@ -1134,31 +1133,23 @@ public:
protected: protected:
virtual ~PresShell(); virtual ~PresShell();
void HandlePostedReflowCallbacks(PRBool aInterruptible); void HandlePostedReflowCallbacks();
void CancelPostedReflowCallbacks(); void CancelPostedReflowCallbacks();
void UnsuppressAndInvalidate(); void UnsuppressAndInvalidate();
void WillDoReflow(); void WillDoReflow();
void DidDoReflow(PRBool aInterruptible); void DidDoReflow();
// ProcessReflowCommands returns whether we processed all our dirty roots nsresult ProcessReflowCommands(PRBool aInterruptible);
// without interruptions.
PRBool ProcessReflowCommands(PRBool aInterruptible);
void ClearReflowEventStatus(); void ClearReflowEventStatus();
void PostReflowEvent(); void PostReflowEvent();
// DoReflow returns whether the reflow finished without interruption void DoReflow(nsIFrame* aFrame);
PRBool DoReflow(nsIFrame* aFrame, PRBool aInterruptible);
#ifdef DEBUG #ifdef DEBUG
void DoVerifyReflow(); void DoVerifyReflow();
void VerifyHasDirtyRootAncestor(nsIFrame* aFrame); void VerifyHasDirtyRootAncestor(nsIFrame* aFrame);
#endif #endif
// Helper for ScrollContentIntoView
nsresult DoScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent);
friend class nsPresShellEventCB; friend class nsPresShellEventCB;
class ReflowEvent; class ReflowEvent;
@@ -1242,6 +1233,11 @@ protected:
// Utility method to restore the root scrollframe state // Utility method to restore the root scrollframe state
void RestoreRootScrollPosition(); 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<nsICSSStyleSheet> mPrefStyleSheet; // mStyleSet owns it but we nsCOMPtr<nsICSSStyleSheet> mPrefStyleSheet; // mStyleSet owns it but we
// maintain a ref, may be null // maintain a ref, may be null
#ifdef DEBUG #ifdef DEBUG
@@ -1272,25 +1268,6 @@ protected:
nsRevocableEventPtr<ReflowEvent> mReflowEvent; nsRevocableEventPtr<ReflowEvent> 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<nsIFrame> > 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<nsIContent> mContentToScrollTo;
PRIntn mContentScrollVPosition;
PRIntn mContentScrollHPosition;
struct nsBlurOrFocusTarget struct nsBlurOrFocusTarget
{ {
nsBlurOrFocusTarget(nsPIDOMEventTarget* aTarget, PRUint32 aEventType) nsBlurOrFocusTarget(nsPIDOMEventTarget* aTarget, PRUint32 aEventType)
@@ -1307,8 +1284,6 @@ protected:
nsCallbackEventRequest* mFirstCallbackEventRequest; nsCallbackEventRequest* mFirstCallbackEventRequest;
nsCallbackEventRequest* mLastCallbackEventRequest; nsCallbackEventRequest* mLastCallbackEventRequest;
PRPackedBool mSuppressInterruptibleReflows;
PRPackedBool mIsThemeSupportDisabled; // Whether or not form controls should use nsITheme in this shell. PRPackedBool mIsThemeSupportDisabled; // Whether or not form controls should use nsITheme in this shell.
PRPackedBool mIsDocumentGone; // We've been disconnected from the document. PRPackedBool mIsDocumentGone; // We've been disconnected from the document.
@@ -1643,10 +1618,6 @@ PresShell::Init(nsIDocument* aDocument,
result = mStackArena.Init(); result = mStackArena.Init();
NS_ENSURE_SUCCESS(result, result); NS_ENSURE_SUCCESS(result, result);
if (!mFramesToDirty.Init()) {
return NS_ERROR_OUT_OF_MEMORY;
}
mDocument = aDocument; mDocument = aDocument;
NS_ADDREF(mDocument); NS_ADDREF(mDocument);
mViewManager = aViewManager; mViewManager = aViewManager;
@@ -1778,8 +1749,6 @@ PresShell::Destroy()
if (mHaveShutDown) if (mHaveShutDown)
return NS_OK; return NS_OK;
mContentToScrollTo = nsnull;
if (mPresContext) { if (mPresContext) {
// We need to notify the destroying the nsPresContext to ESM for // We need to notify the destroying the nsPresContext to ESM for
// suppressing to use from ESM. // suppressing to use from ESM.
@@ -2725,12 +2694,14 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
// Kick off a top-down reflow // Kick off a top-down reflow
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow); AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
mIsReflowing = PR_TRUE;
mDirtyRoots.RemoveElement(rootFrame); mDirtyRoots.RemoveElement(rootFrame);
DoReflow(rootFrame, PR_TRUE); DoReflow(rootFrame);
mIsReflowing = PR_FALSE;
} }
DidDoReflow(PR_TRUE); DidDoReflow();
} }
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
@@ -3440,20 +3411,6 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
return NS_OK; 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* nsIScrollableView*
PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection) PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection)
{ {
@@ -3587,8 +3544,6 @@ PresShell::ClearFrameRefs(nsIFrame* aFrame)
} }
} }
mFramesToDirty.RemoveEntry(aFrame);
nsWeakFrame* weakFrame = mWeakFrames; nsWeakFrame* weakFrame = mWeakFrames;
while (weakFrame) { while (weakFrame) {
nsWeakFrame* prev = weakFrame->GetPreviousWeakFrame(); nsWeakFrame* prev = weakFrame->GetPreviousWeakFrame();
@@ -4127,21 +4082,17 @@ static void ScrollViewToShowRect(nsIScrollableView* aScrollingView,
NS_IMETHODIMP NS_IMETHODIMP
PresShell::ScrollContentIntoView(nsIContent* aContent, PresShell::ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent, PRIntn aVPercent,
PRIntn aHPercent) PRIntn aHPercent) const
{ {
mContentToScrollTo = aContent;
mContentScrollVPosition = aVPercent;
mContentScrollHPosition = aHPercent;
nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing. nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDocument> currentDoc = content->GetCurrentDoc(); nsCOMPtr<nsIDocument> currentDoc = content->GetCurrentDoc();
NS_ENSURE_STATE(currentDoc); NS_ENSURE_STATE(currentDoc);
currentDoc->FlushPendingNotifications(Flush_InterruptibleLayout); currentDoc->FlushPendingNotifications(Flush_Layout);
nsIFrame* frame = GetPrimaryFrameFor(content);
// If mContentToScrollTo is non-null, that means we interrupted the reflow if (!frame) {
// and won't necessarily get the position correct, but do a best-effort return NS_ERROR_NULL_POINTER;
// scroll. }
// Before we scroll the frame into view, ask the command dispatcher // Before we scroll the frame into view, ask the command dispatcher
// if we're resetting focus because a window just got an activate // if we're resetting focus because a window just got an activate
@@ -4158,26 +4109,11 @@ PresShell::ScrollContentIntoView(nsIContent* aContent,
PRBool dontScroll = PR_FALSE; PRBool dontScroll = PR_FALSE;
focusController->GetSuppressFocusScroll(&dontScroll); focusController->GetSuppressFocusScroll(&dontScroll);
if (dontScroll) { if (dontScroll) {
mContentToScrollTo = nsnull;
return NS_OK; 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. // This is a two-step process.
// Step 1: Find the bounds of the rect we want to scroll into view. For // 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 // example, for an inline frame we may want to scroll in the whole
@@ -4640,7 +4576,7 @@ PresShell::CancelPostedReflowCallbacks()
} }
void void
PresShell::HandlePostedReflowCallbacks(PRBool aInterruptible) PresShell::HandlePostedReflowCallbacks()
{ {
PRBool shouldFlush = PR_FALSE; PRBool shouldFlush = PR_FALSE;
@@ -4659,10 +4595,8 @@ PresShell::HandlePostedReflowCallbacks(PRBool aInterruptible)
} }
} }
mozFlushType flushType =
aInterruptible ? Flush_InterruptibleLayout : Flush_Layout;
if (shouldFlush) if (shouldFlush)
FlushPendingNotifications(flushType); FlushPendingNotifications(Flush_Layout);
} }
NS_IMETHODIMP NS_IMETHODIMP
@@ -4689,6 +4623,13 @@ PresShell::IsSafeToFlush(PRBool& aIsSafeToFlush)
NS_IMETHODIMP NS_IMETHODIMP
PresShell::FlushPendingNotifications(mozFlushType aType) 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?"); NS_ASSERTION(aType >= Flush_Frames, "Why did we get called?");
@@ -4758,16 +4699,10 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
// worry about them. They can't be triggered during reflow, so we should // worry about them. They can't be triggered during reflow, so we should
// be good. // be good.
if (aType >= (mSuppressInterruptibleReflows ? Flush_Layout : Flush_InterruptibleLayout) && if (aType >= Flush_Layout && !mIsDestroying) {
!mIsDestroying) {
mFrameConstructor->RecalcQuotesAndCounters(); mFrameConstructor->RecalcQuotesAndCounters();
mViewManager->FlushDelayedResize(); mViewManager->FlushDelayedResize();
if (ProcessReflowCommands(aType < Flush_Layout) && mContentToScrollTo) { ProcessReflowCommands(aInterruptibleReflow);
// We didn't get interrupted. Go ahead and scroll to our content
DoScrollContentIntoView(mContentToScrollTo, mContentScrollVPosition,
mContentScrollHPosition);
mContentToScrollTo = nsnull;
}
} }
PRUint32 updateFlags = NS_VMREFRESH_NO_SYNC; PRUint32 updateFlags = NS_VMREFRESH_NO_SYNC;
@@ -4776,7 +4711,7 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
// immediately // immediately
updateFlags = NS_VMREFRESH_IMMEDIATE; 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 // Not flushing reflows, so do deferred invalidates. This will keep us
// from possibly flushing out reflows due to invalidates being processed // from possibly flushing out reflows due to invalidates being processed
// at the end of this view batch. // at the end of this view batch.
@@ -6610,7 +6545,7 @@ PresShell::WillPaint()
// reflow being interspersed. Note that we _do_ allow this to be // 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 // interruptible; if we can't do all the reflows it's better to flicker a bit
// than to freeze up. // than to freeze up.
FlushPendingNotifications(Flush_InterruptibleLayout); DoFlushPendingNotifications(Flush_Layout, PR_TRUE);
} }
nsresult nsresult
@@ -6820,17 +6755,7 @@ PresShell::ReflowEvent::Run() {
// before processing that pres shell's reflow commands. Fixes bug 54868. // before processing that pres shell's reflow commands. Fixes bug 54868.
nsCOMPtr<nsIViewManager> viewManager = ps->GetViewManager(); nsCOMPtr<nsIViewManager> viewManager = ps->GetViewManager();
ps->mSuppressInterruptibleReflows = PR_FALSE; ps->DoFlushPendingNotifications(Flush_Layout, PR_TRUE);
#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 */
// Now, explicitly release the pres shell before the view manager // Now, explicitly release the pres shell before the view manager
ps = nsnull; ps = nsnull;
@@ -6877,11 +6802,11 @@ PresShell::WillDoReflow()
} }
void void
PresShell::DidDoReflow(PRBool aInterruptible) PresShell::DidDoReflow()
{ {
mFrameConstructor->EndUpdate(); mFrameConstructor->EndUpdate();
HandlePostedReflowCallbacks(aInterruptible); HandlePostedReflowCallbacks();
// Null-check mViewManager in case this happens during Destroy. See // Null-check mViewManager in case this happens during Destroy. See
// bugs 244435 and 238546. // bugs 244435 and 238546.
if (!mPaintingSuppressed && mViewManager) if (!mPaintingSuppressed && mViewManager)
@@ -6894,24 +6819,8 @@ PresShell::DidDoReflow(PRBool aInterruptible)
} }
} }
static PLDHashOperator void
MarkFramesDirtyToRoot(nsPtrHashKey<nsIFrame>* p, void* closure) PresShell::DoReflow(nsIFrame* target)
{
nsIFrame* target = static_cast<nsIFrame*>(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)
{ {
nsIFrame* rootFrame = FrameManager()->GetRootFrame(); nsIFrame* rootFrame = FrameManager()->GetRootFrame();
@@ -6921,13 +6830,9 @@ PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible)
nsresult rv = CreateRenderingContext(rootFrame, getter_AddRefs(rcx)); nsresult rv = CreateRenderingContext(rootFrame, getter_AddRefs(rcx));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_NOTREACHED("CreateRenderingContext failure"); NS_NOTREACHED("CreateRenderingContext failure");
return PR_FALSE; return;
} }
#ifdef DEBUG
mCurrentReflowRoot = target;
#endif
target->WillReflow(mPresContext); target->WillReflow(mPresContext);
// If the target frame is the root of the frame hierarchy, then // If the target frame is the root of the frame hierarchy, then
@@ -6961,9 +6866,6 @@ PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible)
reflowState.mComputedBorderPadding.LeftRight(), reflowState.mComputedBorderPadding.LeftRight(),
"reflow state computed incorrect width"); "reflow state computed incorrect width");
mPresContext->ReflowStarted(aInterruptible);
mIsReflowing = PR_TRUE;
nsReflowStatus status; nsReflowStatus status;
nsHTMLReflowMetrics desiredSize; nsHTMLReflowMetrics desiredSize;
target->Reflow(mPresContext, desiredSize, reflowState, status); target->Reflow(mPresContext, desiredSize, reflowState, status);
@@ -6995,38 +6897,6 @@ PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible)
mPresContext->SetVisibleArea(nsRect(0, 0, desiredSize.width, mPresContext->SetVisibleArea(nsRect(0, 0, desiredSize.width,
desiredSize.height)); 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 #ifdef DEBUG
@@ -7063,13 +6933,12 @@ PresShell::DoVerifyReflow()
} }
#endif #endif
PRBool nsresult
PresShell::ProcessReflowCommands(PRBool aInterruptible) PresShell::ProcessReflowCommands(PRBool aInterruptible)
{ {
MOZ_TIMER_DEBUGLOG(("Start: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Start: Reflow: PresShell::ProcessReflowCommands(), this=%p\n", this));
MOZ_TIMER_START(mReflowWatch); MOZ_TIMER_START(mReflowWatch);
PRBool interrupted = PR_FALSE;
if (0 != mDirtyRoots.Length()) { if (0 != mDirtyRoots.Length()) {
#ifdef DEBUG #ifdef DEBUG
@@ -7089,6 +6958,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
{ {
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow); AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
mIsReflowing = PR_TRUE;
do { do {
// Send an incremental reflow notification to the target frame. // Send an incremental reflow notification to the target frame.
@@ -7103,19 +6973,22 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
continue; continue;
} }
interrupted = !DoReflow(target, aInterruptible); DoReflow(target);
// Keep going until we're out of reflow commands, or we've run // Keep going until we're out of reflow commands, or we've run
// past our deadline, or we're interrupted. // past our deadline.
} while (!interrupted && mDirtyRoots.Length() && } while (mDirtyRoots.Length() &&
(!aInterruptible || PR_IntervalNow() < deadline)); (!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 // Exiting the scriptblocker might have killed us
if (!mIsDestroying) { if (!mIsDestroying) {
DidDoReflow(aInterruptible); DidDoReflow();
} }
// DidDoReflow might have killed us // DidDoReflow might have killed us
@@ -7151,7 +7024,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
UnsuppressAndInvalidate(); UnsuppressAndInvalidate();
} }
return !interrupted; return NS_OK;
} }
void void

View File

@@ -147,9 +147,9 @@ nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame,
nsIFrame* kidFrame; nsIFrame* kidFrame;
nsOverflowContinuationTracker tracker(aPresContext, aDelegatingFrame, PR_TRUE); nsOverflowContinuationTracker tracker(aPresContext, aDelegatingFrame, PR_TRUE);
for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) { for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
PRBool kidNeedsReflow = reflowAll || NS_SUBTREE_DIRTY(kidFrame) || if (reflowAll ||
FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged); NS_SUBTREE_DIRTY(kidFrame) ||
if (kidNeedsReflow && !aPresContext->HasPendingInterrupt()) { FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged)) {
// Reflow the frame // Reflow the frame
nsReflowStatus kidStatus = NS_FRAME_COMPLETE; nsReflowStatus kidStatus = NS_FRAME_COMPLETE;
ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState,
@@ -188,16 +188,7 @@ nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame,
kidFrame->GetPosition()); 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, // Abspos frames can't cause their parent to be incomplete,
// only overflow incomplete. // only overflow incomplete.
if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus))
@@ -343,25 +334,11 @@ nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame)
void void
nsAbsoluteContainingBlock::MarkSizeDependentFramesDirty() nsAbsoluteContainingBlock::MarkSizeDependentFramesDirty()
{
DoMarkFramesDirty(PR_FALSE);
}
void
nsAbsoluteContainingBlock::MarkAllFramesDirty()
{
DoMarkFramesDirty(PR_TRUE);
}
void
nsAbsoluteContainingBlock::DoMarkFramesDirty(PRBool aMarkAllDirty)
{ {
for (nsIFrame* kidFrame = mAbsoluteFrames.FirstChild(); for (nsIFrame* kidFrame = mAbsoluteFrames.FirstChild();
kidFrame; kidFrame;
kidFrame = kidFrame->GetNextSibling()) { kidFrame = kidFrame->GetNextSibling()) {
if (aMarkAllDirty) { if (FrameDependsOnContainer(kidFrame, PR_TRUE, PR_TRUE)) {
kidFrame->AddStateBits(NS_FRAME_IS_DIRTY);
} else if (FrameDependsOnContainer(kidFrame, PR_TRUE, PR_TRUE)) {
// Add the weakest flags that will make sure we reflow this frame later // Add the weakest flags that will make sure we reflow this frame later
kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
} }

View File

@@ -127,13 +127,8 @@ public:
PRBool HasAbsoluteFrames() {return mAbsoluteFrames.NotEmpty();} 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(); void MarkSizeDependentFramesDirty();
// Mark all our absolute frames with NS_FRAME_IS_DIRTY
void MarkAllFramesDirty();
protected: protected:
// Returns PR_TRUE if the position of f depends on the position of // 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 // its placeholder or if the position or size of f depends on a
@@ -151,11 +146,6 @@ protected:
nsReflowStatus& aStatus, nsReflowStatus& aStatus,
nsRect* aChildBounds); 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: protected:
nsFrameList mAbsoluteFrames; // additional named child list nsFrameList mAbsoluteFrames; // additional named child list

View File

@@ -1122,20 +1122,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// in that situation --- what we think is our "new size" // in that situation --- what we think is our "new size"
// will not be our real new size. This also happens to be more efficient. // will not be our real new size. This also happens to be more efficient.
if (mAbsoluteContainer.HasAbsoluteFrames()) { if (mAbsoluteContainer.HasAbsoluteFrames()) {
PRBool haveInterrupt = aPresContext->HasPendingInterrupt(); if (aReflowState.WillReflowAgainForClearance()) {
if (aReflowState.WillReflowAgainForClearance() ||
haveInterrupt) {
// Make sure that when we reflow again we'll actually reflow all the abs // 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, // pos frames that might conceivably depend on our size. Sadly, we can't
// if we're dirty right now and interrupted; in that case we also need // do much better than that, because we don't really know what our size
// to mark them all with NS_FRAME_IS_DIRTY). Sadly, we can't do much // will be, and it might in fact not change on the followup reflow!
// 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(); mAbsoluteContainer.MarkSizeDependentFramesDirty();
}
} else { } else {
nsRect childBounds; nsRect childBounds;
nsSize containingBlockSize = nsSize containingBlockSize =
@@ -2024,18 +2016,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
} }
DumpLine(aState, line, deltaY, -1); 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 // Handle BR-clearance from the last line of the block
@@ -2057,9 +2037,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (repositionViews) if (repositionViews)
::PlaceFrameView(this); ::PlaceFrameView(this);
// We can skip trying to pull up the next line if our height is constrained // We can skip trying to pull up the next line if there is no next
// (so we can report being incomplete) and there is no next in flow or we // in flow or we were told not to or we know it will be futile, i.e.,
// were told not to or we know it will be futile, i.e.,
// -- the next in flow is not changing // -- the next in flow is not changing
// -- and we cannot have added more space for its first line to be // -- and we cannot have added more space for its first line to be
// pulled up into, // pulled up into,
@@ -2068,10 +2047,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// didn't change) // didn't change)
// -- my chain of next-in-flows either has no first line, or its first // -- my chain of next-in-flows either has no first line, or its first
// line isn't dirty. // line isn't dirty.
PRBool heightConstrained = PRBool skipPull = willReflowAgain;
aState.mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE; if (aState.mNextInFlow &&
PRBool skipPull = willReflowAgain && heightConstrained;
if (!skipPull && heightConstrained && aState.mNextInFlow &&
(aState.mReflowState.mFlags.mNextInFlowUntouched && (aState.mReflowState.mFlags.mNextInFlowUntouched &&
!lastLineMovedUp && !lastLineMovedUp &&
!(GetStateBits() & NS_FRAME_IS_DIRTY) && !(GetStateBits() & NS_FRAME_IS_DIRTY) &&
@@ -2090,17 +2067,13 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// (First, see if there is such a line, and second, see if it's clean) // (First, see if there is such a line, and second, see if it's clean)
if (!bifLineIter.Next() || if (!bifLineIter.Next() ||
!bifLineIter.GetLine()->IsDirty()) { !bifLineIter.GetLine()->IsDirty()) {
skipPull=PR_TRUE;
}
}
}
if (skipPull && aState.mNextInFlow) {
NS_ASSERTION(heightConstrained, "Height should be constrained here\n");
if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow)) if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow))
NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus); NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
else else
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus); NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
skipPull=PR_TRUE;
}
}
} }
if (!skipPull && aState.mNextInFlow) { if (!skipPull && aState.mNextInFlow) {
@@ -2184,9 +2157,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
AutoNoisyIndenter indent2(gNoisyReflow); AutoNoisyIndenter indent2(gNoisyReflow);
#endif #endif
if (aState.mPresContext->HasPendingInterrupt()) {
MarkLineDirtyForInterrupt(line);
} else {
// Now reflow it and any lines that it makes during it's reflow // 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 // (we have to loop here because reflowing the line may case a new
// line to be created; see SplitLine's callers for examples of // line to be created; see SplitLine's callers for examples of
@@ -2206,18 +2176,11 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
foundAnyClears = PR_TRUE; 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 // If this is an inline frame then its time to stop
++line; ++line;
aState.AdvanceToNextLine(); aState.AdvanceToNextLine();
} }
} }
}
if (NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) { if (NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW; aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
@@ -2253,54 +2216,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
return rv; 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 void
nsBlockFrame::DeleteLine(nsBlockReflowState& aState, nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
nsLineList::iterator aLine, nsLineList::iterator aLine,
@@ -5043,6 +4958,23 @@ nsBlockFrame::RemoveFloat(nsIFrame* aFloat) {
return line_end; 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) static void MarkSameFloatManagerLinesDirty(nsBlockFrame* aBlock)
{ {
nsBlockFrame* blockWithFloatMgr = aBlock; nsBlockFrame* blockWithFloatMgr = aBlock;

View File

@@ -464,9 +464,6 @@ protected:
/** reflow all lines that have been marked dirty */ /** reflow all lines that have been marked dirty */
nsresult ReflowDirtyLines(nsBlockReflowState& aState); 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 // Methods for line reflow
/** /**

View File

@@ -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 // Advance to the next column
child = child->GetNextSibling(); child = child->GetNextSibling();
@@ -781,14 +771,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
} }
} }
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 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) { if (RTL && childOrigin.x != targetX) {
overflowRect = nsRect(0, 0, 0, 0); overflowRect = nsRect(0, 0, 0, 0);
@@ -915,7 +897,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
PRBool feasible = ReflowChildren(aDesiredSize, aReflowState, PRBool feasible = ReflowChildren(aDesiredSize, aReflowState,
aStatus, config, unboundedLastColumn, &carriedOutBottomMargin, colData); aStatus, config, unboundedLastColumn, &carriedOutBottomMargin, colData);
if (isBalancing && !aPresContext->HasPendingInterrupt()) { if (isBalancing) {
nscoord availableContentHeight = GetAvailableContentHeight(aReflowState); nscoord availableContentHeight = GetAvailableContentHeight(aReflowState);
// Termination of the algorithm below is guaranteed because // Termination of the algorithm below is guaranteed because
@@ -928,7 +910,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
// search) // search)
PRBool maybeContinuousBreakingDetected = PR_FALSE; PRBool maybeContinuousBreakingDetected = PR_FALSE;
while (!aPresContext->HasPendingInterrupt()) { while (1) {
nscoord lastKnownFeasibleHeight = knownFeasibleHeight; nscoord lastKnownFeasibleHeight = knownFeasibleHeight;
// Record what we learned from the last reflow // Record what we learned from the last reflow
@@ -1020,7 +1002,7 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
&carriedOutBottomMargin, colData); &carriedOutBottomMargin, colData);
} }
if (!feasible && !aPresContext->HasPendingInterrupt()) { if (!feasible) {
// We may need to reflow one more time at the feasible height to // We may need to reflow one more time at the feasible height to
// get a valid layout. // get a valid layout.
PRBool skip = PR_FALSE; PRBool skip = PR_FALSE;
@@ -1040,13 +1022,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); CheckInvalidateSizeChange(aDesiredSize);
FinishAndStoreOverflow(&aDesiredSize); FinishAndStoreOverflow(&aDesiredSize);

View File

@@ -1926,7 +1926,7 @@ nsGfxScrollFrameInner::AsyncScrollPortEvent::Run()
{ {
if (mInner) { if (mInner) {
mInner->mOuter->PresContext()->GetPresShell()-> mInner->mOuter->PresContext()->GetPresShell()->
FlushPendingNotifications(Flush_InterruptibleLayout); FlushPendingNotifications(Flush_Layout);
} }
return mInner ? mInner->FireScrollPortEvent() : NS_OK; return mInner ? mInner->FireScrollPortEvent() : NS_OK;
} }

View File

@@ -2055,9 +2055,6 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
#ifdef NOISY_VERTICAL_ALIGN #ifdef NOISY_VERTICAL_ALIGN
printf(" new values: %d,%d\n", minY, maxY); 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 #endif
} }
else { else {

View File

@@ -1,15 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<style>
span { display: inline-block; width: 1em; height: 10px; background: green; }
</style>
</head>
<body style="position: relative; font-size: 20px">
Test
<div style="position: absolute; left: 0; width: 25px; height: 0; top: 0;">
<span></span>
<span></span>
</div>
</body>
</html>

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
function f() {
document.body.style.fontSize = "20px";
// End the test asynchronously so we get a chance to do a reflow before
// that happens.
setTimeout("document.documentElement.className = ''", 0);
}
</script>
<style>
span { display: inline-block; width: 1em; height: 10px; background: green; }
</style>
</head>
<body onload="f()" style="position: relative; font-size: 10px">
Test
<div style="position: absolute; left: 0; width: 25px; height: 0; top: 0;">
<span></span>
<span></span>
</div>
</body>
</html>

View File

@@ -1,15 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<style>
span { display: inline-block; width: 1em; height: 10px; background: green; }
</style>
</head>
<body style="font-size: 20px">
Test
<div style="position: absolute; left: 0; width: 25px; height: 0; top: 0;">
<span></span>
<span></span>
</div>
</body>
</html>

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
function f() {
document.body.style.fontSize = "20px";
// End the test asynchronously so we get a chance to do a reflow before
// that happens.
setTimeout("document.documentElement.className = ''", 0);
}
</script>
<style>
span { display: inline-block; width: 1em; height: 10px; background: green; }
</style>
</head>
<body onload="f()" style="font-size: 10px">
Test
<div style="position: absolute; left: 0; width: 25px; height: 0; top: 0;">
<span></span>
<span></span>
</div>
</body>
</html>

View File

@@ -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-ref.html
== 50630-4.html 50630-4-ref2.html == 50630-4.html 50630-4-ref2.html
== 50630-5.html 50630-5-ref.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-1.xml 68061-1-ref.xml
== 68061-2.xml 68061-2-ref.xml == 68061-2.xml 68061-2-ref.xml
== 76331-1.html 76331-1-ref.html == 76331-1.html 76331-1-ref.html

View File

@@ -379,9 +379,6 @@ nsSVGForeignObjectFrame::InitialUpdate()
"before our nsSVGOuterSVGFrame's initial Reflow()!!!"); "before our nsSVGOuterSVGFrame's initial Reflow()!!!");
UpdateCoveredRegion(); UpdateCoveredRegion();
// Make sure to not allow interrupts if we're not being reflown as a root
nsPresContext::InterruptPreventer noInterrupts(PresContext());
DoReflow(); DoReflow();
NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW), NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
@@ -604,9 +601,6 @@ nsSVGForeignObjectFrame::MaybeReflowFromOuterSVGFrame()
if (kid->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN) { if (kid->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN) {
return; return;
} }
// Make sure to not allow interrupts if we're not being reflown as a root
nsPresContext::InterruptPreventer noInterrupts(PresContext());
DoReflow(); DoReflow();
} }

View File

@@ -100,10 +100,10 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
#endif #endif
// 3d277f04-93f4-4384-9fdc-e1e2d1fc4e33 // af70b716-2e34-463f-8f1c-273dbddd845b
#define NS_IWIDGET_IID \ #define NS_IWIDGET_IID \
{ 0x3d277f04, 0x93f4, 0x4384, \ { 0xaf70b716, 0x2e34, 0x463f, \
{ 0x9f, 0xdc, 0xe1, 0xe2, 0xd1, 0xfc, 0x4e, 0x33 } } { 0x8f, 0x1c, 0x27, 0x3d, 0xbd, 0xdd, 0x84, 0x5b } }
/* /*
* Window shadow styles * Window shadow styles
@@ -816,12 +816,6 @@ class nsIWidget : public nsISupports {
*/ */
NS_IMETHOD GetLastInputEventTime(PRUint32& aTime) = 0; 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 * Called when when we need to begin secure keyboard input, such as when a password field
* gets focus. * gets focus.

View File

@@ -668,10 +668,6 @@ nsAppShell::ProcessNextNativeEvent(PRBool aMayWait)
NS_OBJC_END_TRY_ABORT_BLOCK; NS_OBJC_END_TRY_ABORT_BLOCK;
if (!moreEvents) {
nsChildView::UpdateCurrentInputEventCount();
}
return moreEvents; return moreEvents;
} }

View File

@@ -369,8 +369,6 @@ public:
NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetAttention(PRInt32 aCycleCount);
virtual PRBool HasPendingInputEvent();
NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString); NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString);
NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString); NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString);
@@ -411,9 +409,6 @@ public:
void HidePlugin(); void HidePlugin();
static PRBool DoHasPendingInputEvent();
static PRUint32 GetCurrentInputEventCount();
static void UpdateCurrentInputEventCount();
protected: protected:
PRBool ReportDestroyEvent(); PRBool ReportDestroyEvent();
@@ -459,8 +454,6 @@ protected:
nsPluginPort mPluginPort; nsPluginPort mPluginPort;
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK] nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
static PRUint32 sLastInputEventCount;
}; };
void NS_InstallPluginKeyEventsHandler(); void NS_InstallPluginKeyEventsHandler();

View File

@@ -82,8 +82,6 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <ApplicationServices/ApplicationServices.h>
#undef DEBUG_IME #undef DEBUG_IME
#undef DEBUG_UPDATE #undef DEBUG_UPDATE
#undef INVALIDATE_DEBUGGING // flash areas as they are invalidated #undef INVALIDATE_DEBUGGING // flash areas as they are invalidated
@@ -151,8 +149,6 @@ PRUint32 gLastModifierState = 0;
PRBool gUserCancelledDrag = PR_FALSE; PRBool gUserCancelledDrag = PR_FALSE;
PRUint32 nsChildView::sLastInputEventCount = 0;
@interface ChildView(Private) @interface ChildView(Private)
// sets up our view, attaching it to its owning gecko view // 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; 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 - #pragma mark -

View File

@@ -247,7 +247,6 @@ public:
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ; NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ;
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent); NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetAttention(PRInt32 aCycleCount);
virtual PRBool HasPendingInputEvent();
virtual nsTransparencyMode GetTransparencyMode(); virtual nsTransparencyMode GetTransparencyMode();
virtual void SetTransparencyMode(nsTransparencyMode aMode); virtual void SetTransparencyMode(nsTransparencyMode aMode);
NS_IMETHOD SetWindowShadowStyle(PRInt32 aStyle); NS_IMETHOD SetWindowShadowStyle(PRInt32 aStyle);

View File

@@ -62,7 +62,6 @@
#include "nsMenuUtilsX.h" #include "nsMenuUtilsX.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsNativeThemeColors.h" #include "nsNativeThemeColors.h"
#include "nsChildView.h"
#include "gfxPlatform.h" #include "gfxPlatform.h"
#include "qcms.h" #include "qcms.h"
@@ -1313,11 +1312,6 @@ NS_IMETHODIMP nsCocoaWindow::GetAttention(PRInt32 aCycleCount)
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
} }
PRBool
nsCocoaWindow::HasPendingInputEvent()
{
return nsChildView::DoHasPendingInputEvent();
}
NS_IMETHODIMP nsCocoaWindow::SetWindowShadowStyle(PRInt32 aStyle) NS_IMETHODIMP nsCocoaWindow::SetWindowShadowStyle(PRInt32 aStyle)
{ {

View File

@@ -1911,39 +1911,6 @@ nsWindow::GetAttention(PRInt32 aCycleCount)
return NS_OK; 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 void
nsWindow::LoseFocus(void) nsWindow::LoseFocus(void)
{ {

View File

@@ -204,9 +204,6 @@ public:
PRBool aDoCapture, PRBool aDoCapture,
PRBool aConsumeRollupEvent); PRBool aConsumeRollupEvent);
NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetAttention(PRInt32 aCycleCount);
virtual PRBool HasPendingInputEvent();
NS_IMETHOD MakeFullScreen(PRBool aFullScreen); NS_IMETHOD MakeFullScreen(PRBool aFullScreen);
NS_IMETHOD HideWindowChrome(PRBool aShouldHide); NS_IMETHOD HideWindowChrome(PRBool aShouldHide);

View File

@@ -3393,8 +3393,10 @@ NS_METHOD nsWindow::SetIcon(const nsAString& aIconSpec)
NS_IMETHODIMP NS_IMETHODIMP
nsWindow::GetLastInputEventTime(PRUint32& aTime) nsWindow::GetLastInputEventTime(PRUint32& aTime)
{ {
ULONG ulStatus = WinQueryQueueStatus(HWND_DESKTOP);
// If there is pending input then return the current time. // If there is pending input then return the current time.
if (HasPendingInputEvent()) { if (ulStatus & (QS_KEY | QS_MOUSE)) {
gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
} }
@@ -3403,12 +3405,6 @@ nsWindow::GetLastInputEventTime(PRUint32& aTime)
return NS_OK; return NS_OK;
} }
PRBool
nsWindow::HasPendingInputEvent()
{
return (WinQueryQueueStatus(HWND_DESKTOP) & (QS_KEY | QS_MOUSE)) != 0;
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// OS2-specific routines to emulate Windows behaviors // OS2-specific routines to emulate Windows behaviors
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------

View File

@@ -161,7 +161,6 @@ class nsWindow : public nsBaseWidget,
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent); NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD GetLastInputEventTime(PRUint32& aTime); NS_IMETHOD GetLastInputEventTime(PRUint32& aTime);
virtual PRBool HasPendingInputEvent();
// Widget appearance // Widget appearance
NS_IMETHOD SetCursor( nsCursor aCursor); NS_IMETHOD SetCursor( nsCursor aCursor);

View File

@@ -7967,7 +7967,15 @@ void nsWindow::StopFlashing()
NS_IMETHODIMP NS_IMETHODIMP
nsWindow::GetLastInputEventTime(PRUint32& aTime) 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()); gLastInputEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
} }
@@ -7976,19 +7984,6 @@ nsWindow::GetLastInputEventTime(PRUint32& aTime)
return NS_OK; 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 //-- NOTE!!! These hook functions can be removed when we migrate to

View File

@@ -199,7 +199,6 @@ public:
NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetAttention(PRInt32 aCycleCount);
NS_IMETHOD GetLastInputEventTime(PRUint32& aTime); NS_IMETHOD GetLastInputEventTime(PRUint32& aTime);
virtual PRBool HasPendingInputEvent();
// Note that the result of GetTopLevelWindow method can be different from the // Note that the result of GetTopLevelWindow method can be different from the
// result of GetTopLevelHWND method. The result can be non-floating window. // result of GetTopLevelHWND method. The result can be non-floating window.

View File

@@ -798,12 +798,6 @@ nsBaseWidget::GetLastInputEventTime(PRUint32& aTime) {
return NS_ERROR_NOT_IMPLEMENTED; return NS_ERROR_NOT_IMPLEMENTED;
} }
PRBool
nsBaseWidget::HasPendingInputEvent()
{
return PR_FALSE;
}
NS_IMETHODIMP NS_IMETHODIMP
nsBaseWidget::SetIcon(const nsAString&) nsBaseWidget::SetIcon(const nsAString&)
{ {

View File

@@ -122,7 +122,6 @@ public:
NS_IMETHOD EnableDragDrop(PRBool aEnable); NS_IMETHOD EnableDragDrop(PRBool aEnable);
NS_IMETHOD GetAttention(PRInt32 aCycleCount); NS_IMETHOD GetAttention(PRInt32 aCycleCount);
NS_IMETHOD GetLastInputEventTime(PRUint32& aTime); NS_IMETHOD GetLastInputEventTime(PRUint32& aTime);
virtual PRBool HasPendingInputEvent();
NS_IMETHOD SetIcon(const nsAString &anIconSpec); NS_IMETHOD SetIcon(const nsAString &anIconSpec);
NS_IMETHOD BeginSecureKeyboardInput(); NS_IMETHOD BeginSecureKeyboardInput();
NS_IMETHOD EndSecureKeyboardInput(); NS_IMETHOD EndSecureKeyboardInput();