зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
04db0be1a4
Коммит
bdd0e13912
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче