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
// creation, make sure we've flushed everything before we
// 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.
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);
}
}
@ -3992,8 +4002,13 @@ HTMLContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
// something else in the script processing caused the
// notification to occur. Update our notion of how much
// has been flushed to include any new content if ending
// this update leaves us not inside a notification.
if (!--mInNotification) {
// this update leaves us not inside a notification. Note that we
// 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();
}
}

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

@ -10425,16 +10425,19 @@ nsCSSFrameConstructor::DoContentStateChanged(nsIContent* aContent,
NS_ASSERTION(styleSet, "couldn't get style set");
if (aContent) {
nsChangeHint hint;
if (aStateMask & (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED)) {
// Any change to a content state that affects which frames we
// construct must lead to a frame reconstruct here
hint = nsChangeHint_ReconstructFrame;
} else {
hint = NS_STYLE_HINT_NONE;
nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent);
if (primaryFrame) {
nsChangeHint hint = NS_STYLE_HINT_NONE;
// Any change to a content state that affects which frames we construct
// must lead to a frame reconstruct here if we already have a frame.
// Note that we never decide through non-CSS means to not create frames
// based on content states, so if we already don't have a frame we don't
// need to force a reframe -- if it's needed, the HasStateDependentStyle
// call will handle things.
nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent);
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;
if (app) {
nsITheme *theme = presContext->GetTheme();
@ -13253,7 +13256,16 @@ void nsCSSFrameConstructor::RestyleEvent::HandleEvent() {
NS_ASSERTION(viewManager, "Must have view manager for update");
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->ProcessPendingRestyles();
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}