Bug 1285474: Add mozilla::RestyleManagerBase to share logic between RestyleManager and ServoRestyleManager. r=bholley

Partially implement some restyling APIs to take rid of some gecko-only code
paths.

MozReview-Commit-ID: L5i6Kr2Qars
This commit is contained in:
Emilio Cobos Álvarez 2016-07-08 00:08:46 -07:00
Родитель acd21d26c0
Коммит 289ca90dc4
12 изменённых файлов: 334 добавлений и 195 удалений

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

@ -83,15 +83,12 @@ ElementTagToString(dom::Element* aElement)
#endif
RestyleManager::RestyleManager(nsPresContext* aPresContext)
: mPresContext(aPresContext)
: RestyleManagerBase(aPresContext)
, mDoRebuildAllStyleData(false)
, mInRebuildAllStyleData(false)
, mObservingRefreshDriver(false)
, mInStyleRefresh(false)
, mSkipAnimationRules(false)
, mHavePendingNonAnimationRestyles(false)
, mRestyleGeneration(1)
, mHoverGeneration(0)
, mRebuildAllExtraHint(nsChangeHint(0))
, mRebuildAllRestyleHint(nsRestyleHint(0))
, mAnimationGeneration(0)
@ -220,7 +217,7 @@ SyncViewsAndInvalidateDescendants(nsIFrame* aFrame,
* frame.
*/
static nsIFrame*
GetFrameForChildrenOnlyTransformHint(nsIFrame *aFrame)
GetFrameForChildrenOnlyTransformHint(nsIFrame* aFrame)
{
if (aFrame->GetType() == nsGkAtoms::viewportFrame) {
// This happens if the root-<svg> is fixed positioned, in which case we
@ -357,7 +354,7 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext,
aFrame->StyleDisplay()->HasTransformStyle(),
"Unexpected UpdateTransformLayer hint");
nsIPresShell *shell = aPresContext->PresShell();
nsIPresShell* shell = aPresContext->PresShell();
if (shell->IsPaintingSuppressed()) {
// Don't allow synchronous rendering changes when painting is turned off.
aChange &= ~nsChangeHint_RepaintFrame;
@ -374,7 +371,7 @@ ApplyRenderingChangeToTree(nsPresContext* aPresContext,
if (aChange & nsChangeHint_RepaintFrame) {
// If the frame's background is propagated to an ancestor, walk up to
// that ancestor and apply the RepaintFrame change hint to it.
nsStyleContext *bgSC;
nsStyleContext* bgSC;
nsIFrame* propagatedFrame = aFrame;
while (!nsCSSRendering::FindBackground(propagatedFrame, &bgSC)) {
propagatedFrame = propagatedFrame->GetParent();
@ -442,7 +439,7 @@ RestyleManager::RecomputePosition(nsIFrame* aFrame)
// continuation or ib-split sibling, but it can happen when styles differ
// across continuations such as ::first-line or ::first-letter, and in
// those cases we will generally (but maybe not always) do the work twice.
nsIFrame *firstContinuation =
nsIFrame* firstContinuation =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
StickyScrollContainer::ComputeStickyOffsets(firstContinuation);
@ -454,7 +451,7 @@ RestyleManager::RecomputePosition(nsIFrame* aFrame)
} else {
MOZ_ASSERT(NS_STYLE_POSITION_RELATIVE == display->mPosition,
"Unexpected type of positioning");
for (nsIFrame *cont = aFrame; cont;
for (nsIFrame* cont = aFrame; cont;
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
nsIFrame* cb = cont->GetContainingBlock();
nsMargin newOffsets;
@ -642,7 +639,7 @@ RestyleManager::StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint)
}
do {
mPresContext->PresShell()->FrameNeedsReflow(aFrame, dirtyType, dirtyBits,
PresContext()->PresShell()->FrameNeedsReflow(aFrame, dirtyType, dirtyBits,
rootHandling);
aFrame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame);
} while (aFrame);
@ -745,7 +742,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
// processing restyles
FrameConstructor()->BeginUpdate();
FramePropertyTable* propTable = mPresContext->PropertyTable();
FramePropertyTable* propTable = PresContext()->PropertyTable();
// Mark frames so that we skip frames that die along the way, bug 123049.
// A frame can be in the list multiple times with different hints. Further
@ -798,7 +795,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
// it can't easily be converted to/from being an abs-pos container correctly.
hint |= nsChangeHint_ReconstructFrame;
} else {
for (nsIFrame *cont = frame; cont;
for (nsIFrame* cont = frame; cont;
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
// Normally frame construction would set state bits as needed,
// but we're not going to reconstruct the frame so we need to set them.
@ -856,7 +853,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
}
if (hint & nsChangeHint_UpdateEffects) {
for (nsIFrame *cont = frame; cont;
for (nsIFrame* cont = frame; cont;
cont = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
nsSVGEffects::UpdateEffects(cont);
}
@ -903,7 +900,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
nsChangeHint_ChildrenOnlyTransform | nsChangeHint_SchedulePaint)) {
ApplyRenderingChangeToTree(mPresContext, frame, hint);
ApplyRenderingChangeToTree(PresContext(), frame, hint);
}
if ((hint & nsChangeHint_RecomputePosition) && !didReflowThisFrame) {
ActiveLayerTracker::NotifyOffsetRestyle(frame);
@ -921,7 +918,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
nsChangeHint_UpdateParentOverflow |
nsChangeHint_UpdateSubtreeOverflow))) {
if (hint & nsChangeHint_UpdateSubtreeOverflow) {
for (nsIFrame *cont = frame; cont; cont =
for (nsIFrame* cont = frame; cont; cont =
nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
AddSubtreeToOverflowTracker(cont);
}
@ -973,7 +970,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
} else {
changeKind = OverflowChangedTracker::TRANSFORM_CHANGED;
}
for (nsIFrame *cont = frame; cont; cont =
for (nsIFrame* cont = frame; cont; cont =
nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
mOverflowChangedTracker.AddFrame(cont, changeKind);
}
@ -985,7 +982,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
if (hint & nsChangeHint_UpdateParentOverflow) {
MOZ_ASSERT(frame->GetParent(),
"shouldn't get style hints for the root frame");
for (nsIFrame *cont = frame; cont; cont =
for (nsIFrame* cont = frame; cont; cont =
nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) {
mOverflowChangedTracker.AddFrame(cont->GetParent(),
OverflowChangedTracker::CHILDREN_CHANGED);
@ -994,7 +991,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
}
}
if ((hint & nsChangeHint_UpdateCursor) && !didUpdateCursor) {
mPresContext->PresShell()->SynthesizeMouseMove(false);
PresContext()->PresShell()->SynthesizeMouseMove(false);
didUpdateCursor = true;
}
}
@ -1053,9 +1050,9 @@ RestyleManager::RestyleElement(Element* aElement,
// If we're restyling the root element and there are 'rem' units in
// use, handle dynamic changes to the definition of a 'rem' here.
if (mPresContext->UsesRootEMUnits() && aPrimaryFrame &&
if (PresContext()->UsesRootEMUnits() && aPrimaryFrame &&
!mInRebuildAllStyleData) {
nsStyleContext *oldContext = aPrimaryFrame->StyleContext();
nsStyleContext* oldContext = aPrimaryFrame->StyleContext();
if (!oldContext->GetParent()) { // check that we're the root element
RefPtr<nsStyleContext> newContext = StyleSet()->
ResolveStyleFor(aElement, nullptr /* == oldContext->GetParent() */);
@ -1117,7 +1114,7 @@ RestyleManager::ReframingStyleContexts::~ReframingStyleContexts()
// Note that this is a little bit evil in that we're calling into code
// that calls our member functions from our destructor, but it's at
// the beginning of our destructor, so it shouldn't be too bad.
mRestyleManager->mPresContext->FrameConstructor()->CreateNeededFrames();
mRestyleManager->PresContext()->FrameConstructor()->CreateNeededFrames();
}
RestyleManager::AnimationsWithDestroyedFrame::AnimationsWithDestroyedFrame(
@ -1186,75 +1183,11 @@ RestyleManager::ContentStateChanged(nsIContent* aContent,
Element* aElement = aContent->AsElement();
nsStyleSet* styleSet = StyleSet();
NS_ASSERTION(styleSet, "couldn't get style set");
nsChangeHint changeHint;
nsRestyleHint restyleHint;
ContentStateChangedInternal(aElement, aStateMask, &changeHint, &restyleHint);
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 = aElement->GetPrimaryFrame();
CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
if (primaryFrame) {
// 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)) {
hint = nsChangeHint_ReconstructFrame;
} else {
uint8_t app = primaryFrame->StyleDisplay()->mAppearance;
if (app) {
nsITheme *theme = mPresContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(mPresContext,
primaryFrame, app)) {
bool repaint = false;
theme->WidgetStateChanged(primaryFrame, app, nullptr, &repaint, nullptr);
if (repaint) {
hint |= nsChangeHint_RepaintFrame;
}
}
}
}
pseudoType = primaryFrame->StyleContext()->GetPseudoType();
primaryFrame->ContentStatesChanged(aStateMask);
}
nsRestyleHint rshint;
if (pseudoType >= CSSPseudoElementType::Count) {
rshint = styleSet->HasStateDependentStyle(aElement, aStateMask);
} else if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(
pseudoType)) {
// If aElement is a pseudo-element, we want to check to see whether there
// are any state-dependent rules applying to that pseudo.
Element* ancestor = ElementForStyleContext(nullptr, primaryFrame,
pseudoType);
rshint = styleSet->HasStateDependentStyle(ancestor, pseudoType, aElement,
aStateMask);
} else {
rshint = nsRestyleHint(0);
}
if (aStateMask.HasState(NS_EVENT_STATE_HOVER) && rshint != 0) {
++mHoverGeneration;
}
if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
// 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.
hint |= nsChangeHint_RepaintFrame;
}
PostRestyleEvent(aElement, rshint, hint);
PostRestyleEvent(aElement, restyleHint, changeHint);
return NS_OK;
}
@ -1290,7 +1223,7 @@ RestyleManager::AttributeChanged(Element* aElement,
// Hold onto the PresShell to prevent ourselves from being destroyed.
// XXXbz how, exactly, would this attribute change cause us to be
// destroyed from inside this function?
nsCOMPtr<nsIPresShell> shell = mPresContext->GetPresShell();
nsCOMPtr<nsIPresShell> shell = PresContext()->GetPresShell();
// Get the frame associated with the content which is the highest in the frame tree
nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
@ -1312,7 +1245,7 @@ RestyleManager::AttributeChanged(Element* aElement,
// happen otherwise).
if (!primaryFrame && !reframe) {
int32_t namespaceID;
nsIAtom* tag = mPresContext->Document()->BindingManager()->
nsIAtom* tag = PresContext()->Document()->BindingManager()->
ResolveTag(aElement, &namespaceID);
if (namespaceID == kNameSpaceID_XUL &&
@ -1324,7 +1257,7 @@ RestyleManager::AttributeChanged(Element* aElement,
if (aAttribute == nsGkAtoms::tooltiptext ||
aAttribute == nsGkAtoms::tooltip)
{
nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresContext->GetPresShell());
nsIRootBox* rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
if (rootBox) {
if (aModType == nsIDOMMutationEvent::REMOVAL)
rootBox->RemoveTooltipSupport(aElement);
@ -1339,8 +1272,8 @@ RestyleManager::AttributeChanged(Element* aElement,
// See if we have appearance information for a theme.
const nsStyleDisplay* disp = primaryFrame->StyleDisplay();
if (disp->mAppearance) {
nsITheme *theme = mPresContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(mPresContext, primaryFrame, disp->mAppearance)) {
nsITheme* theme = PresContext()->GetTheme();
if (theme && theme->ThemeSupportsWidget(PresContext(), primaryFrame, disp->mAppearance)) {
bool repaint = false;
theme->WidgetStateChanged(primaryFrame, disp->mAppearance, aAttribute,
&repaint, aOldValue);
@ -1458,7 +1391,7 @@ static void
RestyleSiblingsStartingWith(RestyleManager* aRestyleManager,
nsIContent* aStartingSibling /* may be null */)
{
for (nsIContent *sibling = aStartingSibling; sibling;
for (nsIContent* sibling = aStartingSibling; sibling;
sibling = sibling->GetNextSibling()) {
if (sibling->IsElement()) {
aRestyleManager->
@ -1661,7 +1594,7 @@ RestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
// Processing the style changes could cause a flush that propagates to
// the parent frame and thus destroys the pres shell, so we must hold
// a reference.
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
nsCOMPtr<nsIPresShell> presShell = PresContext()->GetPresShell();
if (!presShell || !presShell->GetRootFrame()) {
mDoRebuildAllStyleData = false;
return;
@ -1686,7 +1619,7 @@ RestyleManager::StartRebuildAllStyleData(RestyleTracker& aRestyleTracker)
{
MOZ_ASSERT(mIsProcessingRestyles);
nsIFrame* rootFrame = mPresContext->PresShell()->GetRootFrame();
nsIFrame* rootFrame = PresContext()->PresShell()->GetRootFrame();
if (!rootFrame) {
// No need to do anything.
return;
@ -1717,7 +1650,7 @@ RestyleManager::StartRebuildAllStyleData(RestyleTracker& aRestyleTracker)
// different styles). If we use up the hint for one of the
// ancestors that we hit first, then we'll fail to do the restyling
// we need to do.
Element* root = mPresContext->Document()->GetRootElement();
Element* root = PresContext()->Document()->GetRootElement();
if (root) {
// If the root element is gone, dropping the hint on the floor
// should be fine.
@ -1757,13 +1690,13 @@ RestyleManager::FinishRebuildAllStyleData()
void
RestyleManager::ProcessPendingRestyles()
{
NS_PRECONDITION(mPresContext->Document(), "No document? Pshaw!");
NS_PRECONDITION(PresContext()->Document(), "No document? Pshaw!");
NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
"Missing a script blocker!");
// First do any queued-up frame creation. (We should really
// merge this into the rest of the process, though; see bug 827239.)
mPresContext->FrameConstructor()->CreateNeededFrames();
PresContext()->FrameConstructor()->CreateNeededFrames();
// Process non-animation restyles...
MOZ_ASSERT(!mIsProcessingRestyles,
@ -1801,13 +1734,13 @@ RestyleManager::ProcessPendingRestyles()
// that we can use UpdateOnlyAnimationStyles, with a different
// boolean argument, for this update as well, instead of having them
// post style updates in their WillRefresh methods.
mPresContext->TransitionManager()->SetInAnimationOnlyStyleUpdate(true);
PresContext()->TransitionManager()->SetInAnimationOnlyStyleUpdate(true);
}
ProcessRestyles(mPendingRestyles);
if (!haveNonAnimation) {
mPresContext->TransitionManager()->SetInAnimationOnlyStyleUpdate(false);
PresContext()->TransitionManager()->SetInAnimationOnlyStyleUpdate(false);
}
mIsProcessingRestyles = false;
@ -1835,7 +1768,7 @@ RestyleManager::BeginProcessingRestyles(RestyleTracker& aRestyleTracker)
{
// Make sure to not rebuild quote or counter lists while we're
// processing restyles
mPresContext->FrameConstructor()->BeginUpdate();
PresContext()->FrameConstructor()->BeginUpdate();
mInStyleRefresh = true;
@ -1862,19 +1795,19 @@ RestyleManager::EndProcessingRestyles()
FinishRebuildAllStyleData();
}
mPresContext->FrameConstructor()->EndUpdate();
PresContext()->FrameConstructor()->EndUpdate();
#ifdef DEBUG
mPresContext->PresShell()->VerifyStyleTree();
PresContext()->PresShell()->VerifyStyleTree();
#endif
}
void
RestyleManager::UpdateOnlyAnimationStyles()
{
bool doCSS = mPresContext->EffectCompositor()->HasPendingStyleUpdates();
bool doCSS = PresContext()->EffectCompositor()->HasPendingStyleUpdates();
nsIDocument* document = mPresContext->Document();
nsIDocument* document = PresContext()->Document();
nsSMILAnimationController* animationController =
document->HasAnimationController() ?
document->GetAnimationController() :
@ -1886,7 +1819,7 @@ RestyleManager::UpdateOnlyAnimationStyles()
return;
}
nsTransitionManager* transitionManager = mPresContext->TransitionManager();
nsTransitionManager* transitionManager = PresContext()->TransitionManager();
transitionManager->SetInAnimationOnlyStyleUpdate(true);
@ -1899,7 +1832,7 @@ RestyleManager::UpdateOnlyAnimationStyles()
// add only the elements for which animations are currently throttled
// (i.e., animating on the compositor with main-thread style updates
// suppressed).
mPresContext->EffectCompositor()->AddStyleUpdatesTo(tracker);
PresContext()->EffectCompositor()->AddStyleUpdatesTo(tracker);
}
if (doSMIL) {
@ -1917,8 +1850,8 @@ RestyleManager::PostRestyleEvent(Element* aElement,
nsChangeHint aMinChangeHint,
const RestyleHintData* aRestyleHintData)
{
if (MOZ_UNLIKELY(!mPresContext) ||
MOZ_UNLIKELY(mPresContext->PresShell()->IsDestroying())) {
if (MOZ_UNLIKELY(IsDisconnected()) ||
MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
return;
}
@ -1948,10 +1881,10 @@ RestyleManager::PostRestyleEventInternal(bool aForLazyConstruction)
// a call to ProcessPendingRestyles coming and there's no need to
// add ourselves as a refresh observer until then.
bool inRefresh = !aForLazyConstruction && mInStyleRefresh;
nsIPresShell* presShell = mPresContext->PresShell();
if (!mObservingRefreshDriver && !inRefresh) {
mObservingRefreshDriver = mPresContext->RefreshDriver()->
AddStyleFlushObserver(presShell);
nsIPresShell* presShell = PresContext()->PresShell();
if (!ObservingRefreshDriver() && !inRefresh) {
SetObservingRefreshDriver(PresContext()->RefreshDriver()->
AddStyleFlushObserver(presShell));
}
// Unconditionally flag our document as needing a flush. The other
@ -2415,9 +2348,9 @@ RestyleManager::ReparentStyleContext(nsIFrame* aFrame)
// unstyled letter/line frames distinguished by pseudo-type, and
// then need to distinguish their descendants based on having
// different parents.)
nsIFrame *nextContinuation = aFrame->GetNextContinuation();
nsIFrame* nextContinuation = aFrame->GetNextContinuation();
if (nextContinuation) {
nsStyleContext *nextContinuationContext =
nsStyleContext* nextContinuationContext =
nextContinuation->StyleContext();
NS_ASSERTION(oldContext == nextContinuationContext ||
oldContext->GetPseudo() !=
@ -2429,9 +2362,9 @@ RestyleManager::ReparentStyleContext(nsIFrame* aFrame)
}
#endif
nsIFrame *prevContinuation =
nsIFrame* prevContinuation =
GetPrevContinuationWithPossiblySameStyle(aFrame);
nsStyleContext *prevContinuationContext;
nsStyleContext* prevContinuationContext;
bool copyFromContinuation =
prevContinuation &&
(prevContinuationContext = prevContinuation->StyleContext())
@ -3973,9 +3906,9 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
// do primary context
RefPtr<nsStyleContext> newContext;
nsIFrame *prevContinuation =
nsIFrame* prevContinuation =
GetPrevContinuationWithPossiblySameStyle(aSelf);
nsStyleContext *prevContinuationContext;
nsStyleContext* prevContinuationContext;
bool copyFromContinuation =
prevContinuation &&
(prevContinuationContext = prevContinuation->StyleContext())
@ -4440,7 +4373,7 @@ ElementRestyler::RestyleChildren(nsRestyleHint aChildRestyleHint)
// kids would use mFrame->StyleContext(), which is out of date if
// mHintsHandled has a ReconstructFrame hint; doing this could trigger
// assertions about mismatched rule trees.
nsIFrame *lastContinuation;
nsIFrame* lastContinuation;
if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
InitializeAccessibilityNotifications(mFrame->StyleContext());
@ -5048,15 +4981,6 @@ RestyleManager::ComputeAndProcessStyleChange(nsStyleContext* aNewContext,
ClearCachedInheritedStyleDataOnDescendants(contextsToClear);
}
nsStyleSet*
RestyleManager::StyleSet() const
{
MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
"RestyleManager should only be used with a Gecko-flavored "
"style backend");
return mPresContext->StyleSet()->AsGecko();
}
nsStyleSet*
ElementRestyler::StyleSet() const
{

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

@ -12,6 +12,7 @@
#define mozilla_RestyleManager_h
#include "mozilla/RestyleLogging.h"
#include "mozilla/RestyleManagerBase.h"
#include "nsISupportsImpl.h"
#include "nsChangeHint.h"
#include "RestyleTracker.h"
@ -33,14 +34,11 @@ namespace dom {
class Element;
} // namespace dom
class RestyleManager final
class RestyleManager final : public RestyleManagerBase
{
public:
friend class ::nsRefreshDriver;
friend class RestyleTracker;
typedef mozilla::dom::Element Element;
explicit RestyleManager(nsPresContext* aPresContext);
private:
@ -56,15 +54,6 @@ private:
public:
NS_INLINE_DECL_REFCOUNTING(mozilla::RestyleManager)
void Disconnect() {
mPresContext = nullptr;
}
nsPresContext* PresContext() const {
MOZ_ASSERT(mPresContext);
return mPresContext;
}
// Should be called when a frame is going to be destroyed and
// WillDestroyFrameTree hasn't been called yet.
void NotifyDestroyingFrame(nsIFrame* aFrame);
@ -88,14 +77,6 @@ public:
int32_t aModType,
const nsAttrValue* aOldValue);
// Get an integer that increments every time we process pending restyles.
// The value is never 0.
uint32_t GetRestyleGeneration() const { return mRestyleGeneration; }
// Get an integer that increments every time there is a style change
// as a result of a change to the :hover content state.
uint32_t GetHoverGeneration() const { return mHoverGeneration; }
// Get a counter that increments on every style change, that we use to
// track whether off-main-thread animations are up-to-date.
uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
@ -139,15 +120,13 @@ public:
}
private:
nsCSSFrameConstructor* FrameConstructor() const
{ return PresContext()->FrameConstructor(); }
// Used when restyling an element with a frame.
void ComputeAndProcessStyleChange(nsIFrame* aFrame,
nsChangeHint aMinChange,
RestyleTracker& aRestyleTracker,
nsRestyleHint aRestyleHint,
const RestyleHintData& aRestyleHintData);
// Used when restyling a display:contents element.
void ComputeAndProcessStyleChange(nsStyleContext* aNewContext,
Element* aElement,
@ -456,7 +435,7 @@ public:
* RestyleManager should be logged.
*/
bool ShouldLogRestyle() {
return ShouldLogRestyle(mPresContext);
return ShouldLogRestyle(PresContext());
}
/**
@ -492,7 +471,12 @@ public:
#endif
private:
inline nsStyleSet* StyleSet() const;
inline nsStyleSet* StyleSet() const {
MOZ_ASSERT(PresContext()->StyleSet()->IsGecko(),
"RestyleManager should only be used with a Gecko-flavored "
"style backend");
return PresContext()->StyleSet()->AsGecko();
}
/* aMinHint is the minimal change that should be made to the element */
// XXXbz do we really need the aPrimaryFrame argument here?
@ -527,34 +511,23 @@ private:
// Fast-path the common case (esp. for the animation restyle
// tracker) of not having anything to do.
if (aRestyleTracker.Count() || ShouldStartRebuildAllFor(aRestyleTracker)) {
if (++mRestyleGeneration == 0) {
// Keep mRestyleGeneration from being 0, since that's what
// nsPresContext::GetRestyleGeneration returns when it no
// longer has a RestyleManager.
++mRestyleGeneration;
}
IncrementRestyleGeneration();
aRestyleTracker.DoProcessRestyles();
}
}
private:
nsPresContext* mPresContext; // weak, disconnected in Disconnect
// True if we need to reconstruct the rule tree the next time we
// process restyles.
bool mDoRebuildAllStyleData : 1;
// True if we're currently in the process of reconstructing the rule tree.
bool mInRebuildAllStyleData : 1;
// True if we're already waiting for a refresh notification
bool mObservingRefreshDriver : 1;
// True if we're in the middle of a nsRefreshDriver refresh
bool mInStyleRefresh : 1;
// Whether rule matching should skip styles associated with animation
bool mSkipAnimationRules : 1;
bool mHavePendingNonAnimationRestyles : 1;
uint32_t mRestyleGeneration;
uint32_t mHoverGeneration;
nsChangeHint mRebuildAllExtraHint;
nsRestyleHint mRebuildAllRestyleHint;

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

@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/RestyleManagerBase.h"
#include "mozilla/StyleSetHandle.h"
#include "nsIFrame.h"
namespace mozilla {
RestyleManagerBase::RestyleManagerBase(nsPresContext* aPresContext)
: mPresContext(aPresContext)
, mRestyleGeneration(1)
, mHoverGeneration(0)
, mObservingRefreshDriver(false)
{
MOZ_ASSERT(mPresContext);
}
/**
* Calculates the change hint and the restyle hint for a given content state
* change.
*
* This is called from both Restyle managers.
*/
void
RestyleManagerBase::ContentStateChangedInternal(Element* aElement,
EventStates aStateMask,
nsChangeHint* aOutChangeHint,
nsRestyleHint* aOutRestyleHint)
{
MOZ_ASSERT(aOutChangeHint);
MOZ_ASSERT(aOutRestyleHint);
StyleSetHandle styleSet = PresContext()->StyleSet();
NS_ASSERTION(styleSet, "couldn't get style set");
*aOutChangeHint = 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 = aElement->GetPrimaryFrame();
CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
if (primaryFrame) {
// 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 {
uint8_t app = primaryFrame->StyleDisplay()->mAppearance;
if (app) {
nsITheme *theme = PresContext()->GetTheme();
if (theme && theme->ThemeSupportsWidget(PresContext(),
primaryFrame, app)) {
bool repaint = false;
theme->WidgetStateChanged(primaryFrame, app, nullptr, &repaint, nullptr);
if (repaint) {
*aOutChangeHint |= nsChangeHint_RepaintFrame;
}
}
}
}
pseudoType = primaryFrame->StyleContext()->GetPseudoType();
primaryFrame->ContentStatesChanged(aStateMask);
}
if (pseudoType >= CSSPseudoElementType::Count) {
*aOutRestyleHint = styleSet->HasStateDependentStyle(aElement, aStateMask);
} else if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(
pseudoType)) {
// If aElement is a pseudo-element, we want to check to see whether there
// are any state-dependent rules applying to that pseudo.
Element* ancestor = ElementForStyleContext(nullptr, primaryFrame,
pseudoType);
*aOutRestyleHint = styleSet->HasStateDependentStyle(ancestor, pseudoType, aElement,
aStateMask);
} else {
*aOutRestyleHint = nsRestyleHint(0);
}
if (aStateMask.HasState(NS_EVENT_STATE_HOVER) && *aOutRestyleHint != 0) {
IncrementHoverGeneration();
}
if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
// 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;
}
}
} // namespace mozilla

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

@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_RestyleManagerBase_h
#define mozilla_RestyleManagerBase_h
#include "nsChangeHint.h"
namespace mozilla {
class ServoRestyleManager;
class RestyleManager;
/**
* Class for sharing data and logic common to both RestyleManager and
* ServoRestyleManager.
*/
class RestyleManagerBase
{
protected:
explicit RestyleManagerBase(nsPresContext* aPresContext);
public:
typedef mozilla::dom::Element Element;
// Get an integer that increments every time we process pending restyles.
// The value is never 0.
uint32_t GetRestyleGeneration() const { return mRestyleGeneration; }
// Get an integer that increments every time there is a style change
// as a result of a change to the :hover content state.
uint32_t GetHoverGeneration() const { return mHoverGeneration; }
bool ObservingRefreshDriver() const { return mObservingRefreshDriver; }
void SetObservingRefreshDriver(bool aObserving) {
mObservingRefreshDriver = aObserving;
}
void Disconnect() { mPresContext = nullptr; }
protected:
void ContentStateChangedInternal(Element* aElement,
EventStates aStateMask,
nsChangeHint* aOutChangeHint,
nsRestyleHint* aOutRestyleHint);
bool IsDisconnected() { return mPresContext == nullptr; }
void IncrementHoverGeneration() {
++mHoverGeneration;
}
void IncrementRestyleGeneration() {
if (++mRestyleGeneration == 0) {
// Keep mRestyleGeneration from being 0, since that's what
// nsPresContext::GetRestyleGeneration returns when it no
// longer has a RestyleManager.
++mRestyleGeneration;
}
}
nsPresContext* PresContext() const {
MOZ_ASSERT(mPresContext);
return mPresContext;
}
nsCSSFrameConstructor* FrameConstructor() const {
return PresContext()->FrameConstructor();
}
inline bool IsGecko() const {
return !IsServo();
}
inline bool IsServo() const {
#ifdef MOZ_STYLO
return PresContext()->StyleSet()->IsServo();
#else
return false;
#endif
}
private:
nsPresContext* mPresContext; // weak, can be null after Disconnect().
uint32_t mRestyleGeneration;
uint32_t mHoverGeneration;
// True if we're already waiting for a refresh notification.
bool mObservingRefreshDriver;
};
} // namespace mozilla
#endif

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

@ -135,6 +135,8 @@ public:
inline nsresult ReparentStyleContext(nsIFrame* aFrame);
inline bool HasPendingRestyles();
inline uint64_t GetRestyleGeneration() const;
inline uint32_t GetHoverGeneration() const;
inline void SetObservingRefreshDriver(bool aObserving);
private:
// Stores a pointer to an RestyleManager or a ServoRestyleManager. The least

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

@ -143,6 +143,19 @@ RestyleManagerHandle::Ptr::GetRestyleGeneration() const
FORWARD(GetRestyleGeneration, ());
}
uint32_t
RestyleManagerHandle::Ptr::GetHoverGeneration() const
{
FORWARD(GetHoverGeneration, ());
}
void
RestyleManagerHandle::Ptr::SetObservingRefreshDriver(bool aObserving)
{
FORWARD(SetObservingRefreshDriver, (aObserving));
}
} // namespace mozilla
#undef FORWARD

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

@ -5,13 +5,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ServoRestyleManager.h"
#include "mozilla/ServoStyleSet.h"
using namespace mozilla::dom;
namespace mozilla {
ServoRestyleManager::ServoRestyleManager()
: mRestyleGeneration(1)
ServoRestyleManager::ServoRestyleManager(nsPresContext* aPresContext)
: RestyleManagerBase(aPresContext)
{
}
@ -26,7 +27,26 @@ ServoRestyleManager::PostRestyleEvent(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
NS_ERROR("stylo: ServoRestyleManager::PostRestyleEvent not implemented");
if (MOZ_UNLIKELY(IsDisconnected()) ||
MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
return;
}
nsIPresShell* presShell = PresContext()->PresShell();
if (!ObservingRefreshDriver()) {
SetObservingRefreshDriver(PresContext()->RefreshDriver()->
AddStyleFlushObserver(presShell));
}
aElement->SetIsDirtyForServo();
nsINode* cur = aElement;
while ((cur = cur->GetParentNode())) {
if (cur->HasDirtyDescendantsForServo())
break;
cur->SetHasDirtyDescendantsForServo();
}
presShell->GetDocument()->SetNeedStyleFlush();
}
void
@ -53,7 +73,7 @@ void
ServoRestyleManager::ProcessPendingRestyles()
{
// XXXheycam Do nothing for now.
mRestyleGeneration++;
IncrementRestyleGeneration();
}
void
@ -82,7 +102,17 @@ nsresult
ServoRestyleManager::ContentStateChanged(nsIContent* aContent,
EventStates aStateMask)
{
NS_ERROR("stylo: ServoRestyleManager::ContentStateChanged not implemented");
if (!aContent->IsElement()) {
return NS_OK;
}
Element* aElement = aContent->AsElement();
nsChangeHint changeHint;
nsRestyleHint restyleHint;
ContentStateChangedInternal(aElement, aStateMask, &changeHint, &restyleHint);
// TODO(emilio): Post a restyle here, and make it effective.
// PostRestyleEvent(aElement, restyleHint, changeHint);
return NS_OK;
}
@ -119,10 +149,4 @@ ServoRestyleManager::HasPendingRestyles()
return false;
}
uint64_t
ServoRestyleManager::GetRestyleGeneration() const
{
return mRestyleGeneration;
}
} // namespace mozilla

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

@ -8,8 +8,11 @@
#define mozilla_ServoRestyleManager_h
#include "mozilla/EventStates.h"
#include "mozilla/RestyleManagerBase.h"
#include "nsChangeHint.h"
#include "nsISupportsImpl.h"
#include "nsPresContext.h"
#include "nsINode.h"
namespace mozilla {
namespace dom {
@ -26,12 +29,12 @@ namespace mozilla {
/**
* Restyle manager for a Servo-backed style system.
*/
class ServoRestyleManager
class ServoRestyleManager : public RestyleManagerBase
{
public:
NS_INLINE_DECL_REFCOUNTING(ServoRestyleManager)
ServoRestyleManager();
explicit ServoRestyleManager(nsPresContext* aPresContext);
void Disconnect();
void PostRestyleEvent(dom::Element* aElement,
@ -64,12 +67,17 @@ public:
const nsAttrValue* aOldValue);
nsresult ReparentStyleContext(nsIFrame* aFrame);
bool HasPendingRestyles();
uint64_t GetRestyleGeneration() const;
protected:
~ServoRestyleManager() {}
uint64_t mRestyleGeneration;
private:
inline ServoStyleSet* StyleSet() const {
MOZ_ASSERT(PresContext()->StyleSet()->IsServo(),
"ServoRestyleManager should only be used with a Servo-flavored "
"style backend");
return PresContext()->StyleSet()->AsServo();
}
};
} // namespace mozilla

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

@ -107,6 +107,7 @@ EXPORTS.mozilla += [
'PaintTracker.h',
'RestyleLogging.h',
'RestyleManager.h',
'RestyleManagerBase.h',
'RestyleManagerHandle.h',
'RestyleManagerHandleInlines.h',
'ServoRestyleManager.h',
@ -154,6 +155,7 @@ UNIFIED_SOURCES += [
'PaintTracker.cpp',
'PositionedEventTargeting.cpp',
'RestyleManager.cpp',
'RestyleManagerBase.cpp',
'RestyleTracker.cpp',
'ScrollbarStyles.cpp',
'ServoRestyleManager.cpp',

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

@ -21,6 +21,7 @@
#include "GeckoProfiler.h"
#include "nsExpirationTracker.h"
#include "RoundedRect.h"
#include "nsIScriptError.h"
#include "nsClassHashtable.h"
#include "nsPresContext.h"
#include "nsStyleStruct.h"

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

@ -3682,13 +3682,8 @@ PresShell::DispatchSynthMouseMove(WidgetGUIEvent* aEvent,
bool aFlushOnHoverChange)
{
RestyleManagerHandle restyleManager = mPresContext->RestyleManager();
if (restyleManager->IsServo()) {
NS_ERROR("stylo: cannot dispatch synthetic mouse moves when using a "
"ServoRestyleManager yet");
return;
}
uint32_t hoverGenerationBefore =
restyleManager->AsGecko()->GetHoverGeneration();
restyleManager->GetHoverGeneration();
nsEventStatus status;
nsView* targetView = nsView::GetViewFor(aEvent->mWidget);
if (!targetView)
@ -3698,7 +3693,7 @@ PresShell::DispatchSynthMouseMove(WidgetGUIEvent* aEvent,
return;
}
if (aFlushOnHoverChange &&
hoverGenerationBefore != restyleManager->AsGecko()->GetHoverGeneration()) {
hoverGenerationBefore != restyleManager->GetHoverGeneration()) {
// Flush so that the resulting reflow happens now so that our caller
// can suppress any synthesized mouse moves caused by that reflow.
// This code only ever runs for the root document, but :hover changes

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

@ -1746,10 +1746,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
mStyleFlushObservers.RemoveElement(shell);
RestyleManagerHandle restyleManager =
shell->GetPresContext()->RestyleManager();
// XXX stylo: ServoRestyleManager does not observer the refresh driver yet.
if (restyleManager->IsGecko()) {
restyleManager->AsGecko()->mObservingRefreshDriver = false;
}
restyleManager->SetObservingRefreshDriver(false);
shell->FlushPendingNotifications(ChangesToFlush(Flush_Style, false));
// Inform the FontFaceSet that we ticked, so that it can resolve its
// ready promise if it needs to (though it might still be waiting on