Make style changes know whether they are for transitions or not. (Bug 435441) r=bzbarsky

This commit is contained in:
L. David Baron 2009-09-11 06:46:36 -04:00
parent a242d6fd9e
commit 0b77a89d40
5 changed files with 102 additions and 20 deletions

View File

@ -1544,7 +1544,7 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument,
, mRebuildAllExtraHint(nsChangeHint(0))
{
// XXXbz this should be in Init() or something!
if (!mPendingRestyles.Init()) {
if (!mPendingRestyles.Init() || !mPendingAnimationRestyles.Init()) {
// now what?
}
@ -11598,13 +11598,10 @@ nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
}
void
nsCSSFrameConstructor::ProcessPendingRestyles()
nsCSSFrameConstructor::ProcessPendingRestyleTable(
nsDataHashtable<nsISupportsHashKey, RestyleData>& aRestyles)
{
NS_PRECONDITION(mDocument, "No document? Pshaw!\n");
NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
"Missing a script blocker!");
PRUint32 count = mPendingRestyles.Count();
PRUint32 count = aRestyles.Count();
// Make sure to not rebuild quote or counter lists while we're
// processing restyles
@ -11621,14 +11618,14 @@ nsCSSFrameConstructor::ProcessPendingRestyles()
}
RestyleEnumerateData* lastRestyle = restylesToProcess;
mPendingRestyles.Enumerate(CollectRestyles, &lastRestyle);
aRestyles.Enumerate(CollectRestyles, &lastRestyle);
NS_ASSERTION(lastRestyle - restylesToProcess == PRInt32(count),
"Enumeration screwed up somehow");
// Clear the hashtable so we don't end up trying to process a restyle we're
// already processing, sending us into an infinite loop.
mPendingRestyles.Clear();
aRestyles.Clear();
for (RestyleEnumerateData* currentRestyle = restylesToProcess;
currentRestyle != lastRestyle;
@ -11646,6 +11643,30 @@ nsCSSFrameConstructor::ProcessPendingRestyles()
#ifdef DEBUG
mPresShell->VerifyStyleTree();
#endif
}
void
nsCSSFrameConstructor::ProcessPendingRestyles()
{
NS_PRECONDITION(mDocument, "No document? Pshaw!\n");
NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
"Missing a script blocker!");
// Process non-animation restyles...
ProcessPendingRestyleTable(mPendingRestyles);
// ...and then process animation restyles. This needs to happen
// second because we need to start animations that resulted from the
// first set of restyles (e.g., CSS transitions with negative
// transition-delay), and because we need to immediately
// restyle-with-animation any just-restyled elements that are
// mid-transition (since processing the non-animation restyle ignores
// the running transition so it can check for a new change on the same
// property, and then posts an immediate animation style change).
nsPresContext *presContext = mPresShell->GetPresContext();
presContext->SetProcessingAnimationStyleChange(PR_TRUE);
ProcessPendingRestyleTable(mPendingAnimationRestyles);
presContext->SetProcessingAnimationStyleChange(PR_FALSE);
if (mRebuildAllStyleData) {
// We probably wasted a lot of work up above, but this seems safest
@ -11655,9 +11676,10 @@ nsCSSFrameConstructor::ProcessPendingRestyles()
}
void
nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent,
nsReStyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
nsCSSFrameConstructor::PostRestyleEventCommon(nsIContent* aContent,
nsReStyleHint aRestyleHint,
nsChangeHint aMinChangeHint,
PRBool aForAnimation)
{
if (NS_UNLIKELY(mPresShell->IsDestroying())) {
return;
@ -11675,12 +11697,15 @@ nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent,
existingData.mRestyleHint = nsReStyleHint(0);
existingData.mChangeHint = NS_STYLE_HINT_NONE;
mPendingRestyles.Get(aContent, &existingData);
nsDataHashtable<nsISupportsHashKey, RestyleData> &restyles =
aForAnimation ? mPendingAnimationRestyles : mPendingRestyles;
restyles.Get(aContent, &existingData);
existingData.mRestyleHint =
nsReStyleHint(existingData.mRestyleHint | aRestyleHint);
NS_UpdateHint(existingData.mChangeHint, aMinChangeHint);
mPendingRestyles.Put(aContent, existingData);
restyles.Put(aContent, existingData);
PostRestyleEventInternal();
}

View File

@ -181,6 +181,9 @@ public:
NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
}
struct RestyleData;
friend struct RestyleData;
// Maintain global objects - gXBLService
static nsIXBLService * GetXBLService();
static void ReleaseGlobals() { NS_IF_RELEASE(gXBLService); }
@ -274,6 +277,9 @@ private:
void ProcessOneRestyle(nsIContent* aContent, nsReStyleHint aRestyleHint,
nsChangeHint aChangeHint);
void ProcessPendingRestyleTable(
nsDataHashtable<nsISupportsHashKey, RestyleData>& aRestyles);
public:
// Restyling for a ContentInserted (notification after insertion) or
// for a CharacterDataChanged. |aContainer| must be non-null; when
@ -303,9 +309,43 @@ public:
// must not contain nsChangeHint_ReconstructFrame) to the root frame.
void RebuildAllStyleData(nsChangeHint aExtraHint);
// See PostRestyleEventCommon below.
void PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint,
nsChangeHint aMinChangeHint);
nsChangeHint aMinChangeHint)
{
nsPresContext *presContext = mPresShell->GetPresContext();
if (presContext) {
PostRestyleEventCommon(aContent, aRestyleHint, aMinChangeHint,
presContext->IsProcessingAnimationStyleChange());
}
}
// See PostRestyleEventCommon below.
void PostAnimationRestyleEvent(nsIContent* aContent,
nsReStyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
PostRestyleEventCommon(aContent, aRestyleHint, aMinChangeHint, PR_TRUE);
}
private:
/**
* Notify the frame constructor that a content node needs to have its
* style recomputed.
* @param aContent: The content node to be restyled.
* @param aRestyleHint: Which nodes need to have selector matching run
* on them.
* @param aMinChangeHint: A minimum change hint for aContent and its
* descendants.
* @param aForAnimation: Whether the style should be computed with or
* without animation data. Animation code
* sometimes needs to pass true; other code
* should generally pass the the pres context's
* IsProcessingAnimationStyleChange() value
* (which is the default value).
*/
void PostRestyleEventCommon(nsIContent* aContent, nsReStyleHint aRestyleHint,
nsChangeHint aMinChangeHint,
PRBool aForAnimation);
void PostRestyleEventInternal();
public:
@ -1707,8 +1747,6 @@ private:
}
public:
struct RestyleData;
friend struct RestyleData;
struct RestyleData {
nsReStyleHint mRestyleHint; // What we want to restyle
@ -1794,6 +1832,7 @@ private:
nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
nsDataHashtable<nsISupportsHashKey, RestyleData> mPendingRestyles;
nsDataHashtable<nsISupportsHashKey, RestyleData> mPendingAnimationRestyles;
static nsIXBLService * gXBLService;
};

View File

@ -401,6 +401,7 @@ public:
NS_IMETHOD RecreateFramesFor(nsIContent* aContent) = 0;
void PostRecreateFramesFor(nsIContent* aContent);
void RestyleForAnimation(nsIContent* aContent);
/**
* Determine if it is safe to flush all pending notifications

View File

@ -818,6 +818,16 @@ public:
mCrossDocDirtyRegion.SetEmpty();
}
PRBool IsProcessingAnimationStyleChange() const {
return mProcessingAnimationStyleChange;
}
void SetProcessingAnimationStyleChange(PRBool aProcessing) {
NS_ASSERTION(aProcessing != mProcessingAnimationStyleChange,
"should never nest");
mProcessingAnimationStyleChange = aProcessing;
}
/**
* Notify the prescontext that the presshell is about to reflow a reflow root.
* The single argument indicates whether this reflow should be interruptible.
@ -1031,10 +1041,10 @@ protected:
// the document rather than to change the document's dimensions
unsigned mSupressResizeReflow : 1;
#ifdef IBMBIDI
unsigned mIsVisual : 1;
#endif
unsigned mProcessingAnimationStyleChange : 1;
#ifdef DEBUG
PRBool mInitialized;
#endif

View File

@ -3568,7 +3568,14 @@ void
nsIPresShell::PostRecreateFramesFor(nsIContent* aContent)
{
FrameConstructor()->PostRestyleEvent(aContent, eReStyle_Self,
nsChangeHint_ReconstructFrame);
nsChangeHint_ReconstructFrame);
}
void
nsIPresShell::RestyleForAnimation(nsIContent* aContent)
{
FrameConstructor()->PostAnimationRestyleEvent(aContent, eReStyle_Self,
NS_STYLE_HINT_NONE);
}
NS_IMETHODIMP