Bug 1531582 - Don't drop the change hint for ContentStateChanged on the floor. r=heycam

This doesn't matter yet because all the states that return a change hint are on
stylesheets, but will matter with bug 1472637.

Differential Revision: https://phabricator.services.mozilla.com/D21616

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-03-01 02:04:12 +00:00
Родитель 60c93bddeb
Коммит 94bec57b28
2 изменённых файлов: 24 добавлений и 39 удалений

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

@ -464,46 +464,40 @@ void RestyleManager::ContentRemoved(nsIContent* aOldChild,
/**
* Calculates the change hint and the restyle hint for a given content state
* change.
*
* This is called from both Restyle managers.
*/
void RestyleManager::ContentStateChangedInternal(const Element& aElement,
EventStates aStateMask,
nsChangeHint* aOutChangeHint) {
MOZ_ASSERT(!mInStyleRefresh);
MOZ_ASSERT(aOutChangeHint);
static nsChangeHint ChangeForContentStateChange(const Element& aElement,
EventStates aStateMask) {
auto changeHint = nsChangeHint(0);
*aOutChangeHint = nsChangeHint(0);
// 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 = aElement.GetPrimaryFrame();
if (primaryFrame) {
if (nsIFrame* primaryFrame = aElement.GetPrimaryFrame()) {
// If it's generated content, ignore LOADING/etc state changes on it.
if (!primaryFrame->IsGeneratedContentFrame() &&
aStateMask.HasAtLeastOneOfStates(
NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
NS_EVENT_STATE_SUPPRESSED | NS_EVENT_STATE_LOADING)) {
*aOutChangeHint = nsChangeHint_ReconstructFrame;
} else {
auto* disp = primaryFrame->StyleDisplay();
if (disp->HasAppearance()) {
nsITheme* theme = PresContext()->GetTheme();
if (theme && theme->ThemeSupportsWidget(PresContext(), primaryFrame,
disp->mAppearance)) {
bool repaint = false;
theme->WidgetStateChanged(primaryFrame, disp->mAppearance, nullptr,
&repaint, nullptr);
if (repaint) {
*aOutChangeHint |= nsChangeHint_RepaintFrame;
}
return nsChangeHint_ReconstructFrame;
}
auto* disp = primaryFrame->StyleDisplay();
if (disp->HasAppearance()) {
nsPresContext* pc = primaryFrame->PresContext();
nsITheme* theme = pc->GetTheme();
if (theme &&
theme->ThemeSupportsWidget(pc, primaryFrame, disp->mAppearance)) {
bool repaint = false;
theme->WidgetStateChanged(primaryFrame, disp->mAppearance, nullptr,
&repaint, nullptr);
if (repaint) {
changeHint |= nsChangeHint_RepaintFrame;
}
}
}
primaryFrame->ContentStatesChanged(aStateMask);
}
@ -511,8 +505,10 @@ void RestyleManager::ContentStateChangedInternal(const Element& aElement,
// Exposing information to the page about whether the link is
// visited or not isn't really something we can worry about here.
// FIXME: We could probably do this a bit better.
*aOutChangeHint |= nsChangeHint_RepaintFrame;
changeHint |= nsChangeHint_RepaintFrame;
}
return changeHint;
}
/* static */ nsCString RestyleManager::RestyleHintToString(
@ -3220,17 +3216,15 @@ void RestyleManager::ContentStateChanged(nsIContent* aContent,
}
}
nsChangeHint changeHint;
ContentStateChangedInternal(element, aChangedBits, &changeHint);
if (auto changeHint = ChangeForContentStateChange(element, aChangedBits)) {
Servo_NoteExplicitHints(&element, nsRestyleHint(0), changeHint);
}
// Don't bother taking a snapshot if no rules depend on these state bits.
//
// We always take a snapshot for the LTR/RTL event states, since Servo doesn't
// track those bits in the same way, and we know that :dir() rules are always
// present in UA style sheets.
//
// FIXME(emilio): Doesn't this early-return drop the change hint on the floor?
// Should it?
if (!aChangedBits.HasAtLeastOneOfStates(DIRECTION_STATES) &&
!StyleSet()->HasStateDependency(element, aChangedBits)) {
return;
@ -3240,10 +3234,6 @@ void RestyleManager::ContentStateChanged(nsIContent* aContent,
EventStates previousState = element.StyleState() ^ aChangedBits;
snapshot.AddState(previousState);
if (changeHint) {
Servo_NoteExplicitHints(&element, nsRestyleHint(0), changeHint);
}
// Assuming we need to invalidate cached style in getComputedStyle for
// undisplayed elements, since we don't know if it is needed.
IncrementUndisplayedRestyleGeneration();

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

@ -456,11 +456,6 @@ class RestyleManager {
void MaybeRestyleForEdgeChildChange(Element* aContainer,
nsIContent* aChangedChild);
// TODO(emilio): there's no good reason this isn't part of ContentStateChanged
// now, or the change hint isn't returned instead of via an out-param, really.
void ContentStateChangedInternal(const Element&, EventStates aStateMask,
nsChangeHint* aOutChangeHint);
bool IsDisconnected() const { return !mPresContext; }
void IncrementRestyleGeneration() {