Make sure to flush out the content model before processing restyles; otherwise

we can end up with odd content duplication.  Bug 309986, r+sr=dbaron
This commit is contained in:
bzbarsky%mit.edu 2005-09-26 01:27:42 +00:00
Родитель 04db0be1a4
Коммит bdd0e13912
2 изменённых файлов: 42 добавлений и 15 удалений

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

@ -3977,10 +3977,20 @@ HTMLContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
// notification to occur. Since this could result in frame // notification to occur. Since this could result in frame
// creation, make sure we've flushed everything before we // creation, make sure we've flushed everything before we
// continue. // continue.
// Also increment mInNotification to make sure we don't flush again
// until the end of this update, even if nested updates or // Note that UPDATE_CONTENT_STATE notifications never cause
// synchronous frame construction, so we never have to worry about
// them here. The code that handles the async event these
// notifications post will flush us out if it needs to.
// Also, if this is not an UPDATE_CONTENT_STATE notification,
// increment mInNotification to make sure we don't flush again until
// the end of this update, even if nested updates or
// FlushPendingNotifications calls happen during it. // FlushPendingNotifications calls happen during it.
if (!mInNotification++ && mCurrentContext) { NS_ASSERTION(aUpdateType && (aUpdateType & UPDATE_ALL) == aUpdateType,
"Weird update type bitmask");
if (aUpdateType != UPDATE_CONTENT_STATE && !mInNotification++ &&
mCurrentContext) {
mCurrentContext->FlushTags(PR_TRUE); mCurrentContext->FlushTags(PR_TRUE);
} }
} }
@ -3992,8 +4002,13 @@ HTMLContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
// something else in the script processing caused the // something else in the script processing caused the
// notification to occur. Update our notion of how much // notification to occur. Update our notion of how much
// has been flushed to include any new content if ending // has been flushed to include any new content if ending
// this update leaves us not inside a notification. // this update leaves us not inside a notification. Note that we
if (!--mInNotification) { // exclude UPDATE_CONTENT_STATE notifications here, since those
// never affect the frame model directly while inside the
// notification.
NS_ASSERTION(aUpdateType && (aUpdateType & UPDATE_ALL) == aUpdateType,
"Weird update type bitmask");
if (aUpdateType != UPDATE_CONTENT_STATE && !--mInNotification) {
UpdateAllContexts(); UpdateAllContexts();
} }
} }

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

@ -10425,16 +10425,19 @@ nsCSSFrameConstructor::DoContentStateChanged(nsIContent* aContent,
NS_ASSERTION(styleSet, "couldn't get style set"); NS_ASSERTION(styleSet, "couldn't get style set");
if (aContent) { if (aContent) {
nsChangeHint hint; nsChangeHint hint = NS_STYLE_HINT_NONE;
if (aStateMask & (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED | // Any change to a content state that affects which frames we construct
NS_EVENT_STATE_SUPPRESSED)) { // must lead to a frame reconstruct here if we already have a frame.
// Any change to a content state that affects which frames we // Note that we never decide through non-CSS means to not create frames
// construct must lead to a frame reconstruct here // based on content states, so if we already don't have a frame we don't
hint = nsChangeHint_ReconstructFrame; // need to force a reframe -- if it's needed, the HasStateDependentStyle
} else { // call will handle things.
hint = NS_STYLE_HINT_NONE; nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent);
nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent); if (primaryFrame) {
if (primaryFrame) { if (aStateMask & (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED)) {
hint = nsChangeHint_ReconstructFrame;
} else {
PRUint8 app = primaryFrame->GetStyleDisplay()->mAppearance; PRUint8 app = primaryFrame->GetStyleDisplay()->mAppearance;
if (app) { if (app) {
nsITheme *theme = presContext->GetTheme(); nsITheme *theme = presContext->GetTheme();
@ -13253,7 +13256,16 @@ void nsCSSFrameConstructor::RestyleEvent::HandleEvent() {
NS_ASSERTION(viewManager, "Must have view manager for update"); NS_ASSERTION(viewManager, "Must have view manager for update");
viewManager->BeginUpdateViewBatch(); viewManager->BeginUpdateViewBatch();
// Force flushing of any pending content notifications that might have queued
// up while our event was pending. That will ensure that we don't construct
// frames for content right now that's still waiting to be notified on,
constructor->mPresShell->GetDocument()->
FlushPendingNotifications(Flush_ContentAndNotify);
// Make sure that any restyles that happen from now on will go into
// a new event.
constructor->mRestyleEventQueue = nsnull; constructor->mRestyleEventQueue = nsnull;
constructor->ProcessPendingRestyles(); constructor->ProcessPendingRestyles();
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC); viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
} }