2013-07-20 23:14:24 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* 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/. */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Code responsible for managing style changes: tracking what style
|
|
|
|
* changes need to happen, scheduling them, and doing them.
|
|
|
|
*/
|
|
|
|
|
2017-02-13 06:21:32 +03:00
|
|
|
#ifndef mozilla_GeckoRestyleManager_h
|
|
|
|
#define mozilla_GeckoRestyleManager_h
|
2013-07-20 23:14:24 +04:00
|
|
|
|
2014-09-25 09:45:36 +04:00
|
|
|
#include "mozilla/RestyleLogging.h"
|
2017-02-13 06:21:31 +03:00
|
|
|
#include "mozilla/RestyleManager.h"
|
2013-07-20 23:14:24 +04:00
|
|
|
#include "nsISupportsImpl.h"
|
2013-07-20 23:14:25 +04:00
|
|
|
#include "nsChangeHint.h"
|
|
|
|
#include "RestyleTracker.h"
|
|
|
|
#include "nsPresContext.h"
|
2014-07-25 08:35:34 +04:00
|
|
|
#include "nsRefreshDriver.h"
|
2014-08-14 02:39:01 +04:00
|
|
|
#include "nsRefPtrHashtable.h"
|
2015-02-17 01:15:04 +03:00
|
|
|
#include "nsTransitionManager.h"
|
2013-07-20 23:14:24 +04:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
class nsIFrame;
|
2014-06-12 21:09:31 +04:00
|
|
|
class nsStyleChangeList;
|
2013-07-20 23:14:25 +04:00
|
|
|
struct TreeMatchContext;
|
2013-07-20 23:14:24 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
2016-02-17 23:37:00 +03:00
|
|
|
enum class CSSPseudoElementType : uint8_t;
|
2014-04-03 08:18:36 +04:00
|
|
|
class EventStates;
|
2014-11-20 21:24:10 +03:00
|
|
|
struct UndisplayedNode;
|
2013-07-20 23:14:24 +04:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
namespace dom {
|
|
|
|
class Element;
|
|
|
|
} // namespace dom
|
|
|
|
|
2017-02-13 06:21:32 +03:00
|
|
|
class GeckoRestyleManager final : public RestyleManager
|
2014-11-20 21:24:09 +03:00
|
|
|
{
|
2013-07-20 23:14:24 +04:00
|
|
|
public:
|
2017-02-13 06:21:32 +03:00
|
|
|
typedef RestyleManager base_type;
|
2016-08-01 23:31:57 +03:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
friend class RestyleTracker;
|
2016-08-01 23:31:57 +03:00
|
|
|
friend class ElementRestyler;
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2017-02-13 06:21:32 +03:00
|
|
|
explicit GeckoRestyleManager(nsPresContext* aPresContext);
|
2013-07-20 23:14:24 +04:00
|
|
|
|
2017-02-13 06:21:33 +03:00
|
|
|
protected:
|
|
|
|
~GeckoRestyleManager() override
|
2014-03-21 05:16:20 +04:00
|
|
|
{
|
2014-08-14 02:39:01 +04:00
|
|
|
MOZ_ASSERT(!mReframingStyleContexts,
|
|
|
|
"temporary member should be nulled out before destruction");
|
2014-03-21 05:16:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2013-07-20 23:14:25 +04:00
|
|
|
// Forwarded nsIDocumentObserver method, to handle restyling (and
|
|
|
|
// passing the notification to the frame).
|
2017-03-19 14:00:50 +03:00
|
|
|
void ContentStateChanged(nsIContent* aContent,
|
|
|
|
EventStates aStateMask);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
|
|
|
// Forwarded nsIMutationObserver method, to handle restyling.
|
|
|
|
void AttributeWillChange(Element* aElement,
|
|
|
|
int32_t aNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
2015-07-22 06:54:07 +03:00
|
|
|
int32_t aModType,
|
|
|
|
const nsAttrValue* aNewValue);
|
2013-07-20 23:14:25 +04:00
|
|
|
// Forwarded nsIMutationObserver method, to handle restyling (and
|
|
|
|
// passing the notification to the frame).
|
|
|
|
void AttributeChanged(Element* aElement,
|
|
|
|
int32_t aNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
2015-07-22 06:54:07 +03:00
|
|
|
int32_t aModType,
|
|
|
|
const nsAttrValue* aOldValue);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2014-10-03 08:53:23 +04:00
|
|
|
// Whether rule matching should skip styles associated with animation
|
Bug 960465 patch 17 - Remove separate animation and non-animation phases of restyling. r=birtles
Note that this means that when we start transitions, we post restyles
that are processed during the current restyling operation, rather than
in a later phase. This depends on patch 11, which makes the transition
manager skip style changes that it posts while starting transitions, to
ensure that this doesn't lead to an infinite loop. This also depends on
patch 16, which only consumes restyle data for the primary frame, to
ensure that the animation restyles posted are processed properly. It
also depends on patch 14, which makes us retain data on finished
transitions, to avoid triggering extra transitions on descendants when
both an ancestor and a descendant transition an inherited property, and
the descendant does so faster.
This fixes a known failure in layout/style/test/test_animations.html and
test_animations_omta.html (as visible in the patch). I believe this is
because this patch changes us to compute keyframe values for animations
on top of a style context *with* animation data rather than one without,
which means what we're computing them on top of changes each time. (The
purpose of patch 3 was to avoid this in the case where avoiding it
matters, i.e., implicit 0% and 100% keyframes.)
2015-02-17 01:15:05 +03:00
|
|
|
bool SkipAnimationRules() const { return mSkipAnimationRules; }
|
2014-10-03 08:53:23 +04:00
|
|
|
|
2015-02-17 01:15:01 +03:00
|
|
|
void SetSkipAnimationRules(bool aSkipAnimationRules) {
|
|
|
|
mSkipAnimationRules = aSkipAnimationRules;
|
|
|
|
}
|
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
/**
|
|
|
|
* Reparent the style contexts of this frame subtree. The parent frame of
|
|
|
|
* aFrame must be changed to the new parent before this function is called;
|
|
|
|
* the new parent style context will be automatically computed based on the
|
|
|
|
* new position in the frame tree.
|
|
|
|
*
|
|
|
|
* @param aFrame the root of the subtree to reparent. Must not be null.
|
|
|
|
*/
|
2014-06-02 16:08:21 +04:00
|
|
|
nsresult ReparentStyleContext(nsIFrame* aFrame);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2017-09-01 07:53:33 +03:00
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Reparent the descendants of aFrame. This is used by ReparentStyleContext
|
|
|
|
* and shouldn't be called by anyone else. aProviderChild, if non-null, is a
|
|
|
|
* child that was the style parent for aFrame and hence shouldn't be
|
|
|
|
* reparented.
|
|
|
|
*/
|
|
|
|
void ReparentFrameDescendants(nsIFrame* aFrame, nsIFrame* aProviderChild);
|
|
|
|
|
|
|
|
public:
|
2015-08-05 15:42:21 +03:00
|
|
|
void ClearSelectors() {
|
|
|
|
mPendingRestyles.ClearSelectors();
|
|
|
|
}
|
|
|
|
|
2017-03-30 11:37:58 +03:00
|
|
|
void PostRestyleEventForLazyConstruction() { PostRestyleEventInternal(); }
|
|
|
|
|
2014-08-14 02:39:00 +04:00
|
|
|
private:
|
2017-03-30 11:37:58 +03:00
|
|
|
void PostRestyleEventInternal();
|
2017-03-30 11:24:44 +03:00
|
|
|
|
2014-11-20 21:24:10 +03:00
|
|
|
// Used when restyling an element with a frame.
|
2015-08-05 15:42:20 +03:00
|
|
|
void ComputeAndProcessStyleChange(nsIFrame* aFrame,
|
|
|
|
nsChangeHint aMinChange,
|
|
|
|
RestyleTracker& aRestyleTracker,
|
|
|
|
nsRestyleHint aRestyleHint,
|
|
|
|
const RestyleHintData& aRestyleHintData);
|
2016-07-08 10:08:46 +03:00
|
|
|
|
2014-11-20 21:24:10 +03:00
|
|
|
// Used when restyling a display:contents element.
|
2017-07-21 04:22:00 +03:00
|
|
|
void ComputeAndProcessStyleChange(GeckoStyleContext* aNewContext,
|
2015-08-05 15:42:20 +03:00
|
|
|
Element* aElement,
|
|
|
|
nsChangeHint aMinChange,
|
|
|
|
RestyleTracker& aRestyleTracker,
|
|
|
|
nsRestyleHint aRestyleHint,
|
|
|
|
const RestyleHintData& aRestyleHintData);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2014-08-14 02:39:00 +04:00
|
|
|
public:
|
|
|
|
|
2014-08-14 02:39:01 +04:00
|
|
|
/**
|
|
|
|
* In order to start CSS transitions on elements that are being
|
|
|
|
* reframed, we need to stash their style contexts somewhere during
|
|
|
|
* the reframing process.
|
|
|
|
*
|
|
|
|
* In all cases, the content node in the hash table is the real
|
|
|
|
* content node, not the anonymous content node we create for ::before
|
2014-08-14 02:39:01 +04:00
|
|
|
* or ::after. The content node passed to the Get and Put methods is,
|
|
|
|
* however, the content node to be associate with the frame's style
|
|
|
|
* context.
|
2014-08-14 02:39:01 +04:00
|
|
|
*/
|
2017-07-21 04:22:00 +03:00
|
|
|
typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIContent>, GeckoStyleContext>
|
2014-08-14 02:39:01 +04:00
|
|
|
ReframingStyleContextTable;
|
2015-03-21 19:28:04 +03:00
|
|
|
class MOZ_STACK_CLASS ReframingStyleContexts final {
|
2014-08-14 02:39:01 +04:00
|
|
|
public:
|
2015-01-14 08:03:13 +03:00
|
|
|
/**
|
|
|
|
* Construct a ReframingStyleContexts object. The caller must
|
|
|
|
* ensure that aRestyleManager lives at least as long as the
|
|
|
|
* object. (This is generally easy since the caller is typically a
|
|
|
|
* method of RestyleManager.)
|
|
|
|
*/
|
2017-02-13 06:21:32 +03:00
|
|
|
explicit ReframingStyleContexts(GeckoRestyleManager* aRestyleManager);
|
2015-01-14 08:03:13 +03:00
|
|
|
~ReframingStyleContexts();
|
2015-01-14 08:03:13 +03:00
|
|
|
|
2017-07-21 04:22:00 +03:00
|
|
|
void Put(nsIContent* aContent, GeckoStyleContext* aStyleContext) {
|
2014-08-14 02:39:01 +04:00
|
|
|
MOZ_ASSERT(aContent);
|
2016-02-17 23:37:00 +03:00
|
|
|
CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
|
2016-02-17 01:07:00 +03:00
|
|
|
if (pseudoType == CSSPseudoElementType::NotPseudo) {
|
2014-08-14 02:39:01 +04:00
|
|
|
mElementContexts.Put(aContent, aStyleContext);
|
2016-02-17 01:07:00 +03:00
|
|
|
} else if (pseudoType == CSSPseudoElementType::before) {
|
2015-03-03 14:09:00 +03:00
|
|
|
MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
|
2014-08-14 02:39:01 +04:00
|
|
|
mBeforePseudoContexts.Put(aContent->GetParent(), aStyleContext);
|
2016-02-17 01:07:00 +03:00
|
|
|
} else if (pseudoType == CSSPseudoElementType::after) {
|
2015-03-03 14:09:00 +03:00
|
|
|
MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
|
2014-08-14 02:39:01 +04:00
|
|
|
mAfterPseudoContexts.Put(aContent->GetParent(), aStyleContext);
|
|
|
|
}
|
|
|
|
}
|
2014-08-14 02:39:02 +04:00
|
|
|
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* Get(nsIContent* aContent,
|
2016-02-17 23:37:00 +03:00
|
|
|
CSSPseudoElementType aPseudoType) {
|
2014-08-14 02:39:02 +04:00
|
|
|
MOZ_ASSERT(aContent);
|
2016-02-17 01:07:00 +03:00
|
|
|
if (aPseudoType == CSSPseudoElementType::NotPseudo) {
|
2014-08-14 02:39:02 +04:00
|
|
|
return mElementContexts.GetWeak(aContent);
|
|
|
|
}
|
2016-02-17 01:07:00 +03:00
|
|
|
if (aPseudoType == CSSPseudoElementType::before) {
|
2015-03-03 14:09:00 +03:00
|
|
|
MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
|
2014-08-14 02:39:02 +04:00
|
|
|
return mBeforePseudoContexts.GetWeak(aContent->GetParent());
|
|
|
|
}
|
2016-02-17 01:07:00 +03:00
|
|
|
if (aPseudoType == CSSPseudoElementType::after) {
|
2015-03-03 14:09:00 +03:00
|
|
|
MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
|
2014-08-14 02:39:02 +04:00
|
|
|
return mAfterPseudoContexts.GetWeak(aContent->GetParent());
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(false, "unexpected aPseudoType");
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-08-14 02:39:01 +04:00
|
|
|
private:
|
2017-02-13 06:21:32 +03:00
|
|
|
GeckoRestyleManager* mRestyleManager;
|
2015-01-14 08:03:13 +03:00
|
|
|
AutoRestore<ReframingStyleContexts*> mRestorePointer;
|
2014-08-14 02:39:01 +04:00
|
|
|
ReframingStyleContextTable mElementContexts;
|
|
|
|
ReframingStyleContextTable mBeforePseudoContexts;
|
|
|
|
ReframingStyleContextTable mAfterPseudoContexts;
|
|
|
|
};
|
|
|
|
|
2014-08-14 02:39:01 +04:00
|
|
|
/**
|
|
|
|
* Return the current ReframingStyleContexts struct, or null if we're
|
|
|
|
* not currently in a restyling operation.
|
|
|
|
*/
|
|
|
|
ReframingStyleContexts* GetReframingStyleContexts() {
|
|
|
|
return mReframingStyleContexts;
|
|
|
|
}
|
|
|
|
|
2014-08-14 02:39:01 +04:00
|
|
|
/**
|
2016-10-19 09:16:52 +03:00
|
|
|
* Try initiating a transition for an element or a ::before or ::after
|
2014-08-14 02:39:01 +04:00
|
|
|
* pseudo-element, given an old and new style context. This may
|
2015-03-04 08:08:00 +03:00
|
|
|
* change the new style context if a transition is started. Returns
|
2016-10-19 09:16:52 +03:00
|
|
|
* true if it does change aNewStyleContext.
|
2014-08-14 02:39:01 +04:00
|
|
|
*
|
|
|
|
* For the pseudo-elements, aContent must be the anonymous content
|
|
|
|
* that we're creating for that pseudo-element, not the real element.
|
|
|
|
*/
|
2015-03-04 08:08:00 +03:00
|
|
|
static bool
|
2016-10-19 09:16:52 +03:00
|
|
|
TryInitiatingTransition(nsPresContext* aPresContext, nsIContent* aContent,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aOldStyleContext,
|
|
|
|
RefPtr<GeckoStyleContext>* aNewStyleContext /* inout */);
|
2014-08-14 02:39:01 +04:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
public:
|
|
|
|
// Process any pending restyles. This should be called after
|
|
|
|
// CreateNeededFrames.
|
|
|
|
// Note: It's the caller's responsibility to make sure to wrap a
|
|
|
|
// ProcessPendingRestyles call in a view update batch and a script blocker.
|
|
|
|
// This function does not call ProcessAttachedQueue() on the binding manager.
|
|
|
|
// If the caller wants that to happen synchronously, it needs to handle that
|
|
|
|
// itself.
|
|
|
|
void ProcessPendingRestyles();
|
|
|
|
|
2015-10-30 02:57:47 +03:00
|
|
|
private:
|
2013-07-31 04:36:08 +04:00
|
|
|
// ProcessPendingRestyles calls into one of our RestyleTracker
|
|
|
|
// objects. It then calls back to these functions at the beginning
|
|
|
|
// and end of its work.
|
2015-01-14 08:03:12 +03:00
|
|
|
void BeginProcessingRestyles(RestyleTracker& aRestyleTracker);
|
2013-07-31 04:36:08 +04:00
|
|
|
void EndProcessingRestyles();
|
|
|
|
|
2017-08-14 16:16:28 +03:00
|
|
|
public:
|
2017-08-14 16:16:28 +03:00
|
|
|
// Update styles for animations that are running on the compositor and
|
|
|
|
// whose updating is suppressed on the main thread (to save
|
|
|
|
// unnecessary work), while leaving all other aspects of style
|
|
|
|
// out-of-date.
|
2014-08-07 09:58:44 +04:00
|
|
|
//
|
2017-08-14 16:16:28 +03:00
|
|
|
// Performs an animation-only style flush to make styles from
|
|
|
|
// throttled transitions up-to-date prior to processing an unrelated
|
|
|
|
// style change, so that any transitions triggered by that style
|
|
|
|
// change produce correct results.
|
2014-08-07 09:58:44 +04:00
|
|
|
//
|
|
|
|
// In more detail: when we're able to run animations on the
|
|
|
|
// compositor, we sometimes "throttle" these animations by skipping
|
|
|
|
// updating style data on the main thread. However, whenever we
|
|
|
|
// process a normal (non-animation) style change, any changes in
|
|
|
|
// computed style on elements that have transition-* properties set
|
|
|
|
// may need to trigger new transitions; this process requires knowing
|
|
|
|
// both the old and new values of the property. To do this correctly,
|
|
|
|
// we need to have an up-to-date *old* value of the property on the
|
|
|
|
// primary frame. So the purpose of the mini-flush is to update the
|
|
|
|
// style for all throttled transitions and animations to the current
|
|
|
|
// animation state without making any other updates, so that when we
|
|
|
|
// process the queued style updates we'll have correct old data to
|
|
|
|
// compare against. When we do this, we don't bother touching frames
|
|
|
|
// other than primary frames.
|
2017-08-14 16:16:28 +03:00
|
|
|
void UpdateOnlyAnimationStyles();
|
2014-07-25 08:35:34 +04:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
// Rebuilds all style data by throwing out the old rule tree and
|
|
|
|
// building a new one, and additionally applying aExtraHint (which
|
|
|
|
// must not contain nsChangeHint_ReconstructFrame) to the root frame.
|
2014-10-09 01:26:57 +04:00
|
|
|
//
|
|
|
|
// aRestyleHint says which restyle hint to use for the computation;
|
|
|
|
// the only sensible values to use are eRestyle_Subtree (which says
|
|
|
|
// that the rebuild must run selector matching) and nsRestyleHint(0)
|
|
|
|
// (which says that rerunning selector matching is not required. (The
|
|
|
|
// method adds eRestyle_ForceDescendants internally, and including it
|
|
|
|
// in the restyle hint is harmless; some callers (e.g.,
|
|
|
|
// nsPresContext::MediaFeatureValuesChanged) might do this for their
|
|
|
|
// own reasons.)
|
|
|
|
void RebuildAllStyleData(nsChangeHint aExtraHint,
|
|
|
|
nsRestyleHint aRestyleHint);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
Bug 960465 patch 17 - Remove separate animation and non-animation phases of restyling. r=birtles
Note that this means that when we start transitions, we post restyles
that are processed during the current restyling operation, rather than
in a later phase. This depends on patch 11, which makes the transition
manager skip style changes that it posts while starting transitions, to
ensure that this doesn't lead to an infinite loop. This also depends on
patch 16, which only consumes restyle data for the primary frame, to
ensure that the animation restyles posted are processed properly. It
also depends on patch 14, which makes us retain data on finished
transitions, to avoid triggering extra transitions on descendants when
both an ancestor and a descendant transition an inherited property, and
the descendant does so faster.
This fixes a known failure in layout/style/test/test_animations.html and
test_animations_omta.html (as visible in the patch). I believe this is
because this patch changes us to compute keyframe values for animations
on top of a style context *with* animation data rather than one without,
which means what we're computing them on top of changes each time. (The
purpose of patch 3 was to avoid this in the case where avoiding it
matters, i.e., implicit 0% and 100% keyframes.)
2015-02-17 01:15:05 +03:00
|
|
|
/**
|
|
|
|
* Notify the frame constructor that an element needs to have its
|
|
|
|
* style recomputed.
|
|
|
|
* @param aElement: The element to be restyled.
|
|
|
|
* @param aRestyleHint: Which nodes need to have selector matching run
|
|
|
|
* on them.
|
|
|
|
* @param aMinChangeHint: A minimum change hint for aContent and its
|
|
|
|
* descendants.
|
2015-08-05 15:42:20 +03:00
|
|
|
* @param aRestyleHintData: Additional data to go with aRestyleHint.
|
Bug 960465 patch 17 - Remove separate animation and non-animation phases of restyling. r=birtles
Note that this means that when we start transitions, we post restyles
that are processed during the current restyling operation, rather than
in a later phase. This depends on patch 11, which makes the transition
manager skip style changes that it posts while starting transitions, to
ensure that this doesn't lead to an infinite loop. This also depends on
patch 16, which only consumes restyle data for the primary frame, to
ensure that the animation restyles posted are processed properly. It
also depends on patch 14, which makes us retain data on finished
transitions, to avoid triggering extra transitions on descendants when
both an ancestor and a descendant transition an inherited property, and
the descendant does so faster.
This fixes a known failure in layout/style/test/test_animations.html and
test_animations_omta.html (as visible in the patch). I believe this is
because this patch changes us to compute keyframe values for animations
on top of a style context *with* animation data rather than one without,
which means what we're computing them on top of changes each time. (The
purpose of patch 3 was to avoid this in the case where avoiding it
matters, i.e., implicit 0% and 100% keyframes.)
2015-02-17 01:15:05 +03:00
|
|
|
*/
|
2013-07-20 23:14:25 +04:00
|
|
|
void PostRestyleEvent(Element* aElement,
|
|
|
|
nsRestyleHint aRestyleHint,
|
2015-08-05 15:42:20 +03:00
|
|
|
nsChangeHint aMinChangeHint,
|
|
|
|
const RestyleHintData* aRestyleHintData = nullptr);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Asynchronously clear style data from the root frame downwards and ensure
|
|
|
|
* it will all be rebuilt. This is safe to call anytime; it will schedule
|
|
|
|
* a restyle and take effect next time style changes are flushed.
|
|
|
|
* This method is used to recompute the style data when some change happens
|
|
|
|
* outside of any style rules, like a color preference change or a change
|
|
|
|
* in a system font size, or to fix things up when an optimization in the
|
|
|
|
* style data has become invalid. We assume that the root frame will not
|
|
|
|
* need to be reframed.
|
2014-10-09 01:27:02 +04:00
|
|
|
*
|
|
|
|
* For parameters, see RebuildAllStyleData.
|
2013-07-20 23:14:25 +04:00
|
|
|
*/
|
2014-10-09 01:27:02 +04:00
|
|
|
void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
|
|
|
|
nsRestyleHint aRestyleHint);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2016-02-20 05:20:24 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
bool InRebuildAllStyleData() const { return mInRebuildAllStyleData; }
|
|
|
|
#endif
|
|
|
|
|
2014-09-25 09:45:36 +04:00
|
|
|
#ifdef RESTYLE_LOGGING
|
|
|
|
/**
|
|
|
|
* Returns whether a restyle event currently being processed by this
|
2017-02-13 06:21:32 +03:00
|
|
|
* GeckoRestyleManager should be logged.
|
2014-09-25 09:45:36 +04:00
|
|
|
*/
|
|
|
|
bool ShouldLogRestyle() {
|
2016-07-08 10:08:46 +03:00
|
|
|
return ShouldLogRestyle(PresContext());
|
2014-09-25 09:45:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether a restyle event currently being processed for the
|
|
|
|
* document with the specified nsPresContext should be logged.
|
|
|
|
*/
|
|
|
|
static bool ShouldLogRestyle(nsPresContext* aPresContext) {
|
|
|
|
return aPresContext->RestyleLoggingEnabled() &&
|
2015-02-17 01:15:04 +03:00
|
|
|
(!aPresContext->TransitionManager()->
|
|
|
|
InAnimationOnlyStyleUpdate() ||
|
2014-09-25 09:45:36 +04:00
|
|
|
AnimationRestyleLoggingEnabled());
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool RestyleLoggingInitiallyEnabled() {
|
|
|
|
static bool enabled = getenv("MOZ_DEBUG_RESTYLE") != 0;
|
|
|
|
return enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool AnimationRestyleLoggingEnabled() {
|
|
|
|
static bool animations = getenv("MOZ_DEBUG_RESTYLE_ANIMATIONS") != 0;
|
|
|
|
return animations;
|
|
|
|
}
|
|
|
|
|
2014-10-01 03:13:57 +04:00
|
|
|
// Set MOZ_DEBUG_RESTYLE_STRUCTS to a comma-separated string of
|
|
|
|
// style struct names -- such as "Font,SVGReset" -- to log the style context
|
|
|
|
// tree and those cached struct pointers before each restyle. This
|
|
|
|
// function returns a bitfield of the structs named in the
|
|
|
|
// environment variable.
|
|
|
|
static uint32_t StructsToLog();
|
|
|
|
|
2014-09-25 09:45:36 +04:00
|
|
|
static nsCString StructNamesToString(uint32_t aSIDs);
|
|
|
|
int32_t& LoggingDepth() { return mLoggingDepth; }
|
|
|
|
#endif
|
|
|
|
|
2017-03-09 12:15:08 +03:00
|
|
|
bool IsProcessingRestyles() { return mIsProcessingRestyles; }
|
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
private:
|
2016-07-08 10:08:46 +03:00
|
|
|
inline nsStyleSet* StyleSet() const {
|
|
|
|
MOZ_ASSERT(PresContext()->StyleSet()->IsGecko(),
|
2017-02-13 06:21:32 +03:00
|
|
|
"GeckoRestyleManager should only be used with a Gecko-flavored "
|
2016-07-08 10:08:46 +03:00
|
|
|
"style backend");
|
|
|
|
return PresContext()->StyleSet()->AsGecko();
|
|
|
|
}
|
2016-02-24 10:01:10 +03:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
/* aMinHint is the minimal change that should be made to the element */
|
|
|
|
// XXXbz do we really need the aPrimaryFrame argument here?
|
2013-07-20 23:14:25 +04:00
|
|
|
void RestyleElement(Element* aElement,
|
2013-07-20 23:14:25 +04:00
|
|
|
nsIFrame* aPrimaryFrame,
|
|
|
|
nsChangeHint aMinHint,
|
|
|
|
RestyleTracker& aRestyleTracker,
|
2015-08-05 15:42:20 +03:00
|
|
|
nsRestyleHint aRestyleHint,
|
|
|
|
const RestyleHintData& aRestyleHintData);
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2015-01-14 08:03:12 +03:00
|
|
|
void StartRebuildAllStyleData(RestyleTracker& aRestyleTracker);
|
2015-01-14 08:03:12 +03:00
|
|
|
void FinishRebuildAllStyleData();
|
|
|
|
|
2015-01-14 08:03:12 +03:00
|
|
|
bool ShouldStartRebuildAllFor(RestyleTracker& aRestyleTracker) {
|
|
|
|
// When we process our primary restyle tracker and we have a pending
|
|
|
|
// rebuild-all, we need to process it.
|
|
|
|
return mDoRebuildAllStyleData &&
|
|
|
|
&aRestyleTracker == &mPendingRestyles;
|
|
|
|
}
|
|
|
|
|
2015-01-14 08:03:12 +03:00
|
|
|
void ProcessRestyles(RestyleTracker& aRestyleTracker) {
|
|
|
|
// Fast-path the common case (esp. for the animation restyle
|
|
|
|
// tracker) of not having anything to do.
|
2015-01-14 08:03:12 +03:00
|
|
|
if (aRestyleTracker.Count() || ShouldStartRebuildAllFor(aRestyleTracker)) {
|
2016-07-08 10:08:46 +03:00
|
|
|
IncrementRestyleGeneration();
|
2015-01-14 08:03:12 +03:00
|
|
|
aRestyleTracker.DoProcessRestyles();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-20 23:14:24 +04:00
|
|
|
private:
|
2015-01-14 08:03:11 +03:00
|
|
|
// True if we need to reconstruct the rule tree the next time we
|
|
|
|
// process restyles.
|
|
|
|
bool mDoRebuildAllStyleData : 1;
|
2015-01-14 08:03:12 +03:00
|
|
|
// True if we're currently in the process of reconstructing the rule tree.
|
|
|
|
bool mInRebuildAllStyleData : 1;
|
2014-10-03 08:53:23 +04:00
|
|
|
// Whether rule matching should skip styles associated with animation
|
|
|
|
bool mSkipAnimationRules : 1;
|
2015-02-17 01:15:02 +03:00
|
|
|
bool mHavePendingNonAnimationRestyles : 1;
|
2014-10-03 08:53:23 +04:00
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
nsChangeHint mRebuildAllExtraHint;
|
2014-10-09 01:26:57 +04:00
|
|
|
nsRestyleHint mRebuildAllRestyleHint;
|
2013-07-20 23:14:25 +04:00
|
|
|
|
2014-08-14 02:39:01 +04:00
|
|
|
ReframingStyleContexts* mReframingStyleContexts;
|
|
|
|
|
2013-07-20 23:14:25 +04:00
|
|
|
RestyleTracker mPendingRestyles;
|
2014-09-25 09:45:36 +04:00
|
|
|
|
Bug 1245260 - Ignore redundant calls to RestyleManager::IncrementAnimationGeneration; r=dbaron
While processing restyles and starting transitions, we may trigger
a call to EffectCompositor::UpdateCascadeResults which may, in turn, call
EffectCompositor::RequestRestyle with RestyleType::Layer, which ultimately
results in a call to RestyleManager::IncrementAnimationGeneration().
Typically, nsTransitionManager::StyleContextChanged compares the animation
generation on its collection with that of the restyle manager and uses this
to ignore the restyle that it generates. However, given the sequence of events
above, that check may no longer help since the restyle manager's animation
generation will be out of step. As a result,
nsTransitionManager::StyleContextChanged will fail to ignore a subsequent
and redundant restyle. With certain combinations of content, this can mean that
restyles are posted in such a manner than an infinite cycle of restyles ensues.
This patch causes RestyleManager to ignore calls to IncrementAnimationGeneration
when it is already processing restyles such that the animation generation is
only ever updated once per restyle. This makes the check for a matching
animation generation in nsTransitionManager::StyleContextChanged work as
expected, preventing us from generating needless transitions which can produce
this endless loop.
MozReview-Commit-ID: 9HYDrknKPAI
--HG--
extra : rebase_source : f7d9f251d20805fcb4d0d9be04d4343336e69836
2016-03-16 10:05:10 +03:00
|
|
|
// Are we currently in the middle of a call to ProcessRestyles?
|
|
|
|
// This flag is used both as a debugging aid to assert that we are not
|
|
|
|
// performing nested calls to ProcessPendingRestyles, as well as to ignore
|
|
|
|
// redundant calls to IncrementAnimationGeneration.
|
2014-10-03 08:53:23 +04:00
|
|
|
bool mIsProcessingRestyles;
|
|
|
|
|
2014-09-25 09:45:36 +04:00
|
|
|
#ifdef RESTYLE_LOGGING
|
|
|
|
int32_t mLoggingDepth;
|
|
|
|
#endif
|
2013-07-20 23:14:24 +04:00
|
|
|
};
|
|
|
|
|
2013-07-31 04:36:09 +04:00
|
|
|
/**
|
|
|
|
* An ElementRestyler is created for *each* element in a subtree that we
|
|
|
|
* recompute styles for.
|
|
|
|
*/
|
2015-03-21 19:28:04 +03:00
|
|
|
class ElementRestyler final
|
2014-11-20 21:24:09 +03:00
|
|
|
{
|
2013-07-31 04:36:09 +04:00
|
|
|
public:
|
|
|
|
typedef mozilla::dom::Element Element;
|
|
|
|
|
2015-02-18 01:28:53 +03:00
|
|
|
struct ContextToClear {
|
2017-07-21 04:22:00 +03:00
|
|
|
RefPtr<GeckoStyleContext> mStyleContext;
|
2015-02-18 01:28:53 +03:00
|
|
|
uint32_t mStructs;
|
|
|
|
};
|
|
|
|
|
2013-07-31 04:36:09 +04:00
|
|
|
// Construct for the root of the subtree that we're restyling.
|
2013-07-31 04:36:09 +04:00
|
|
|
ElementRestyler(nsPresContext* aPresContext,
|
2013-07-31 04:36:09 +04:00
|
|
|
nsIFrame* aFrame,
|
2013-07-31 04:36:10 +04:00
|
|
|
nsStyleChangeList* aChangeList,
|
2013-07-31 04:36:10 +04:00
|
|
|
nsChangeHint aHintsHandledByAncestors,
|
2013-07-31 04:36:10 +04:00
|
|
|
RestyleTracker& aRestyleTracker,
|
2015-08-05 15:42:20 +03:00
|
|
|
nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
|
2013-07-31 04:36:10 +04:00
|
|
|
TreeMatchContext& aTreeMatchContext,
|
2015-02-18 01:28:53 +03:00
|
|
|
nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
|
|
|
|
nsTArray<ContextToClear>& aContextsToClear,
|
2017-07-21 04:22:00 +03:00
|
|
|
nsTArray<RefPtr<GeckoStyleContext>>& aSwappedStructOwners);
|
2013-07-31 04:36:09 +04:00
|
|
|
|
|
|
|
// Construct for an element whose parent is being restyled.
|
2013-07-31 04:36:10 +04:00
|
|
|
enum ConstructorFlags {
|
|
|
|
FOR_OUT_OF_FLOW_CHILD = 1<<0
|
|
|
|
};
|
2013-07-31 04:36:09 +04:00
|
|
|
ElementRestyler(const ElementRestyler& aParentRestyler,
|
2013-07-31 04:36:10 +04:00
|
|
|
nsIFrame* aFrame,
|
|
|
|
uint32_t aConstructorFlags);
|
2013-07-31 04:36:09 +04:00
|
|
|
|
|
|
|
// Construct for a frame whose parent is being restyled, but whose
|
|
|
|
// style context is the parent style context for its parent frame.
|
|
|
|
// (This is only used for table frames, whose style contexts are used
|
2016-06-16 15:14:08 +03:00
|
|
|
// as the parent style context for their table wrapper frame. We should
|
|
|
|
// probably try to get rid of this exception and have the inheritance go
|
|
|
|
// the other way.)
|
2013-07-31 04:36:09 +04:00
|
|
|
enum ParentContextFromChildFrame { PARENT_CONTEXT_FROM_CHILD_FRAME };
|
|
|
|
ElementRestyler(ParentContextFromChildFrame,
|
2013-07-31 04:36:09 +04:00
|
|
|
const ElementRestyler& aParentFrameRestyler,
|
|
|
|
nsIFrame* aFrame);
|
2013-07-31 04:36:09 +04:00
|
|
|
|
2014-11-20 21:24:10 +03:00
|
|
|
// For restyling undisplayed content only (mFrame==null).
|
|
|
|
ElementRestyler(nsPresContext* aPresContext,
|
|
|
|
nsIContent* aContent,
|
|
|
|
nsStyleChangeList* aChangeList,
|
|
|
|
nsChangeHint aHintsHandledByAncestors,
|
|
|
|
RestyleTracker& aRestyleTracker,
|
2015-08-05 15:42:20 +03:00
|
|
|
nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
|
2014-11-20 21:24:10 +03:00
|
|
|
TreeMatchContext& aTreeMatchContext,
|
2015-02-18 01:28:53 +03:00
|
|
|
nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
|
|
|
|
nsTArray<ContextToClear>& aContextsToClear,
|
2017-07-21 04:22:00 +03:00
|
|
|
nsTArray<RefPtr<GeckoStyleContext>>& aSwappedStructOwners);
|
2014-11-20 21:24:10 +03:00
|
|
|
|
2013-07-31 04:36:09 +04:00
|
|
|
/**
|
|
|
|
* Restyle our frame's element and its subtree.
|
|
|
|
*
|
|
|
|
* Use eRestyle_Self for the aRestyleHint argument to mean
|
|
|
|
* "reresolve our style context but not kids", use eRestyle_Subtree
|
|
|
|
* to mean "reresolve our style context and kids", and use
|
|
|
|
* nsRestyleHint(0) to mean recompute a new style context for our
|
|
|
|
* current parent and existing rulenode, and the same for kids.
|
|
|
|
*/
|
2013-07-31 04:36:10 +04:00
|
|
|
void Restyle(nsRestyleHint aRestyleHint);
|
2013-07-31 04:36:09 +04:00
|
|
|
|
2013-07-31 04:36:09 +04:00
|
|
|
/**
|
2017-03-21 11:33:05 +03:00
|
|
|
* mHintsHandledBySelf changes over time; it starts off as nsChangeHint(0),
|
|
|
|
* and by the end of Restyle it represents the hints that have been handled
|
|
|
|
* for this frame. This method is intended to be called after Restyle, to
|
|
|
|
* find out what hints have been handled for this frame.
|
2013-07-31 04:36:09 +04:00
|
|
|
*/
|
2017-03-21 11:33:05 +03:00
|
|
|
nsChangeHint HintsHandledForFrame() { return mHintsHandledBySelf; }
|
2013-07-31 04:36:09 +04:00
|
|
|
|
2014-11-20 21:24:10 +03:00
|
|
|
/**
|
2017-02-13 06:21:32 +03:00
|
|
|
* Called from GeckoRestyleManager::ComputeAndProcessStyleChange to restyle
|
2014-11-20 21:24:10 +03:00
|
|
|
* children of a display:contents element.
|
|
|
|
*/
|
|
|
|
void RestyleChildrenOfDisplayContentsElement(nsIFrame* aParentFrame,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aNewContext,
|
2014-11-20 21:24:10 +03:00
|
|
|
nsChangeHint aMinHint,
|
|
|
|
RestyleTracker& aRestyleTracker,
|
2015-08-05 15:42:20 +03:00
|
|
|
nsRestyleHint aRestyleHint,
|
|
|
|
const RestyleHintData&
|
|
|
|
aRestyleHintData);
|
2014-11-20 21:24:10 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Re-resolve the style contexts for a frame tree, building aChangeList
|
|
|
|
* based on the resulting style changes, plus aMinChange applied to aFrame.
|
|
|
|
*/
|
|
|
|
static void ComputeStyleChangeFor(nsIFrame* aFrame,
|
|
|
|
nsStyleChangeList* aChangeList,
|
|
|
|
nsChangeHint aMinChange,
|
|
|
|
RestyleTracker& aRestyleTracker,
|
2015-02-18 01:28:53 +03:00
|
|
|
nsRestyleHint aRestyleHint,
|
2015-08-05 15:42:20 +03:00
|
|
|
const RestyleHintData& aRestyleHintData,
|
2015-02-18 01:28:53 +03:00
|
|
|
nsTArray<ContextToClear>& aContextsToClear,
|
2017-07-21 04:22:00 +03:00
|
|
|
nsTArray<RefPtr<GeckoStyleContext>>&
|
2015-02-18 01:28:53 +03:00
|
|
|
aSwappedStructOwners);
|
2014-11-20 21:24:10 +03:00
|
|
|
|
2014-09-25 09:45:36 +04:00
|
|
|
#ifdef RESTYLE_LOGGING
|
|
|
|
bool ShouldLogRestyle() {
|
2017-02-13 06:21:32 +03:00
|
|
|
return GeckoRestyleManager::ShouldLogRestyle(mPresContext);
|
2014-09-25 09:45:36 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-07-31 04:36:09 +04:00
|
|
|
private:
|
2016-02-24 10:01:10 +03:00
|
|
|
inline nsStyleSet* StyleSet() const;
|
|
|
|
|
2016-07-19 16:10:59 +03:00
|
|
|
// Enum class for the result of RestyleSelf, which indicates whether the
|
2014-09-05 07:48:45 +04:00
|
|
|
// restyle procedure should continue to the children, and how.
|
|
|
|
//
|
|
|
|
// These values must be ordered so that later values imply that all
|
|
|
|
// the work of the earlier values is also done.
|
2016-07-19 16:10:59 +03:00
|
|
|
enum class RestyleResult : uint8_t {
|
2016-07-19 16:10:59 +03:00
|
|
|
// default initial value
|
2016-07-19 16:10:59 +03:00
|
|
|
eNone,
|
2014-09-05 07:48:45 +04:00
|
|
|
|
2015-08-28 23:13:48 +03:00
|
|
|
// we left the old style context on the frame; do not restyle children
|
2016-07-19 16:10:59 +03:00
|
|
|
eStop,
|
2014-09-05 07:48:45 +04:00
|
|
|
|
2015-08-28 23:13:48 +03:00
|
|
|
// we got a new style context on this frame, but we know that children
|
|
|
|
// do not depend on the changed values; do not restyle children
|
2016-07-19 16:10:59 +03:00
|
|
|
eStopWithStyleChange,
|
2015-08-28 23:13:48 +03:00
|
|
|
|
2014-09-05 07:48:45 +04:00
|
|
|
// continue restyling children
|
2016-07-19 16:10:59 +03:00
|
|
|
eContinue,
|
2014-09-05 07:48:45 +04:00
|
|
|
|
|
|
|
// continue restyling children with eRestyle_ForceDescendants set
|
2016-07-19 16:10:59 +03:00
|
|
|
eContinueAndForceDescendants
|
2014-09-05 07:48:45 +04:00
|
|
|
};
|
|
|
|
|
2015-08-28 23:13:48 +03:00
|
|
|
struct SwapInstruction
|
|
|
|
{
|
2017-07-21 04:22:00 +03:00
|
|
|
RefPtr<GeckoStyleContext> mOldContext;
|
|
|
|
RefPtr<GeckoStyleContext> mNewContext;
|
2015-08-28 23:13:48 +03:00
|
|
|
uint32_t mStructsToSwap;
|
|
|
|
};
|
|
|
|
|
2013-07-31 04:36:11 +04:00
|
|
|
/**
|
|
|
|
* First half of Restyle().
|
|
|
|
*/
|
2014-09-05 07:48:47 +04:00
|
|
|
RestyleResult RestyleSelf(nsIFrame* aSelf,
|
|
|
|
nsRestyleHint aRestyleHint,
|
2015-08-28 23:13:48 +03:00
|
|
|
uint32_t* aSwappedStructs,
|
|
|
|
nsTArray<SwapInstruction>& aSwaps);
|
2013-07-31 04:36:11 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Restyle the children of this frame (and, in turn, their children).
|
|
|
|
*
|
|
|
|
* Second half of Restyle().
|
|
|
|
*/
|
|
|
|
void RestyleChildren(nsRestyleHint aChildRestyleHint);
|
|
|
|
|
2015-08-05 15:42:20 +03:00
|
|
|
/**
|
|
|
|
* Returns true iff a selector in mSelectorsForDescendants matches aElement.
|
|
|
|
* This is called when processing a eRestyle_SomeDescendants restyle hint.
|
|
|
|
*/
|
|
|
|
bool SelectorMatchesForRestyle(Element* aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true iff aRestyleHint indicates that we should be restyling.
|
|
|
|
* Specifically, this will return true when eRestyle_Self or
|
|
|
|
* eRestyle_Subtree is present, or if eRestyle_SomeDescendants is
|
|
|
|
* present and the specified element matches one of the selectors in
|
|
|
|
* mSelectorsForDescendants.
|
|
|
|
*/
|
|
|
|
bool MustRestyleSelf(nsRestyleHint aRestyleHint, Element* aElement);
|
|
|
|
|
2015-08-05 15:42:21 +03:00
|
|
|
/**
|
|
|
|
* Returns true iff aRestyleHint indicates that we can call
|
|
|
|
* ReparentStyleContext rather than any other restyling method of
|
|
|
|
* nsStyleSet that looks up a new rule node, and if we are
|
|
|
|
* not in the process of reconstructing the whole rule tree.
|
|
|
|
* This is used to check whether it is appropriate to call
|
|
|
|
* ReparentStyleContext.
|
|
|
|
*/
|
|
|
|
bool CanReparentStyleContext(nsRestyleHint aRestyleHint);
|
|
|
|
|
2014-11-17 07:46:00 +03:00
|
|
|
/**
|
|
|
|
* Helpers for Restyle().
|
|
|
|
*/
|
2015-08-28 23:13:48 +03:00
|
|
|
bool MoveStyleContextsForContentChildren(nsIFrame* aParent,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aOldContext,
|
|
|
|
nsTArray<GeckoStyleContext*>& aContextsToMove);
|
|
|
|
bool MoveStyleContextsForChildren(GeckoStyleContext* aOldContext);
|
2015-08-28 23:13:48 +03:00
|
|
|
|
2013-07-31 04:36:11 +04:00
|
|
|
/**
|
2014-09-05 07:48:46 +04:00
|
|
|
* Helpers for RestyleSelf().
|
2013-07-31 04:36:11 +04:00
|
|
|
*/
|
2017-07-21 04:22:00 +03:00
|
|
|
void CaptureChange(GeckoStyleContext* aOldContext,
|
|
|
|
GeckoStyleContext* aNewContext,
|
2014-09-05 07:48:45 +04:00
|
|
|
nsChangeHint aChangeToAssume,
|
2015-08-28 23:13:47 +03:00
|
|
|
uint32_t* aEqualStructs,
|
|
|
|
uint32_t* aSamePointerStructs);
|
2015-08-28 23:13:48 +03:00
|
|
|
void ComputeRestyleResultFromFrame(nsIFrame* aSelf,
|
|
|
|
RestyleResult& aRestyleResult,
|
|
|
|
bool& aCanStopWithStyleChange);
|
|
|
|
void ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aNewContext,
|
2015-08-28 23:13:48 +03:00
|
|
|
RestyleResult& aRestyleResult,
|
|
|
|
bool& aCanStopWithStyleChange);
|
2013-07-31 04:36:09 +04:00
|
|
|
|
2015-08-28 23:13:47 +03:00
|
|
|
// Helpers for RestyleChildren().
|
2014-11-20 21:24:10 +03:00
|
|
|
void RestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint);
|
2015-09-04 03:00:14 +03:00
|
|
|
bool MustCheckUndisplayedContent(nsIFrame* aFrame,
|
|
|
|
nsIContent*& aUndisplayedParent);
|
2015-08-28 23:13:47 +03:00
|
|
|
|
2014-11-20 21:24:10 +03:00
|
|
|
/**
|
|
|
|
* In the following two methods, aParentStyleContext is either
|
|
|
|
* mFrame->StyleContext() if we have a frame, or a display:contents
|
|
|
|
* style context if we don't.
|
|
|
|
*/
|
2014-11-20 21:24:10 +03:00
|
|
|
void DoRestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint,
|
2014-11-20 21:24:10 +03:00
|
|
|
nsIContent* aParent,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aParentStyleContext);
|
2016-08-28 05:31:50 +03:00
|
|
|
void RestyleUndisplayedNodes(nsRestyleHint aChildRestyleHint,
|
|
|
|
UndisplayedNode* aUndisplayed,
|
|
|
|
nsIContent* aUndisplayedParent,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aParentStyleContext,
|
2016-08-28 05:31:50 +03:00
|
|
|
const StyleDisplay aDisplay);
|
2014-08-25 08:48:21 +04:00
|
|
|
void MaybeReframeForBeforePseudo();
|
|
|
|
void MaybeReframeForAfterPseudo(nsIFrame* aFrame);
|
2016-02-17 23:37:00 +03:00
|
|
|
void MaybeReframeForPseudo(CSSPseudoElementType aPseudoType,
|
2015-08-28 23:13:48 +03:00
|
|
|
nsIFrame* aGenConParentFrame,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIContent* aContent,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aStyleContext);
|
2015-08-28 23:13:48 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
bool MustReframeForBeforePseudo();
|
|
|
|
bool MustReframeForAfterPseudo(nsIFrame* aFrame);
|
|
|
|
#endif
|
2016-02-17 23:37:00 +03:00
|
|
|
bool MustReframeForPseudo(CSSPseudoElementType aPseudoType,
|
2015-08-28 23:13:48 +03:00
|
|
|
nsIFrame* aGenConParentFrame,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIContent* aContent,
|
2017-07-21 04:22:00 +03:00
|
|
|
GeckoStyleContext* aStyleContext);
|
2013-09-25 23:28:07 +04:00
|
|
|
void RestyleContentChildren(nsIFrame* aParent,
|
|
|
|
nsRestyleHint aChildRestyleHint);
|
2014-11-20 21:24:10 +03:00
|
|
|
void InitializeAccessibilityNotifications(nsStyleContext* aNewContext);
|
2013-07-31 04:36:11 +04:00
|
|
|
void SendAccessibilityNotifications();
|
|
|
|
|
2013-07-31 04:36:10 +04:00
|
|
|
enum DesiredA11yNotifications {
|
|
|
|
eSkipNotifications,
|
|
|
|
eSendAllNotifications,
|
|
|
|
eNotifyIfShown
|
|
|
|
};
|
|
|
|
|
|
|
|
enum A11yNotificationType {
|
|
|
|
eDontNotify,
|
|
|
|
eNotifyShown,
|
|
|
|
eNotifyHidden
|
|
|
|
};
|
|
|
|
|
2015-09-04 03:00:14 +03:00
|
|
|
// These methods handle the eRestyle_SomeDescendants hint by traversing
|
|
|
|
// down the frame tree (and then when reaching undisplayed content,
|
|
|
|
// the flattened content tree) find elements that match a selector
|
|
|
|
// in mSelectorsForDescendants and call AddPendingRestyle for them.
|
|
|
|
void ConditionallyRestyleChildren();
|
|
|
|
void ConditionallyRestyleChildren(nsIFrame* aFrame,
|
|
|
|
Element* aRestyleRoot);
|
|
|
|
void ConditionallyRestyleContentChildren(nsIFrame* aFrame,
|
|
|
|
Element* aRestyleRoot);
|
|
|
|
void ConditionallyRestyleUndisplayedDescendants(nsIFrame* aFrame,
|
|
|
|
Element* aRestyleRoot);
|
|
|
|
void DoConditionallyRestyleUndisplayedDescendants(nsIContent* aParent,
|
|
|
|
Element* aRestyleRoot);
|
|
|
|
void ConditionallyRestyleUndisplayedNodes(UndisplayedNode* aUndisplayed,
|
|
|
|
nsIContent* aUndisplayedParent,
|
2016-08-28 05:31:50 +03:00
|
|
|
const StyleDisplay aDisplay,
|
2015-09-04 03:00:14 +03:00
|
|
|
Element* aRestyleRoot);
|
|
|
|
void ConditionallyRestyleContentDescendants(Element* aElement,
|
|
|
|
Element* aRestyleRoot);
|
|
|
|
bool ConditionallyRestyle(nsIFrame* aFrame, Element* aRestyleRoot);
|
|
|
|
bool ConditionallyRestyle(Element* aElement, Element* aRestyleRoot);
|
2015-08-05 15:42:20 +03:00
|
|
|
|
2014-09-25 09:45:36 +04:00
|
|
|
#ifdef RESTYLE_LOGGING
|
|
|
|
int32_t& LoggingDepth() { return mLoggingDepth; }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
static nsCString RestyleResultToString(RestyleResult aRestyleResult);
|
|
|
|
#endif
|
|
|
|
|
2013-07-31 04:36:09 +04:00
|
|
|
private:
|
|
|
|
nsPresContext* const mPresContext;
|
2013-07-31 04:36:09 +04:00
|
|
|
nsIFrame* const mFrame;
|
2013-07-31 04:36:09 +04:00
|
|
|
nsIContent* const mParentContent;
|
|
|
|
// |mContent| is the node that we used for rule matching of
|
|
|
|
// normal elements (not pseudo-elements) and for which we generate
|
|
|
|
// framechange hints if we need them.
|
|
|
|
nsIContent* const mContent;
|
2013-07-31 04:36:10 +04:00
|
|
|
nsStyleChangeList* const mChangeList;
|
2017-03-21 11:33:05 +03:00
|
|
|
// Hints that we computed on an ancestor (and which we already have
|
|
|
|
// generated a change list entry for). When we traverse to children
|
|
|
|
// after restyling an element, this field accumulates the hints
|
|
|
|
// generated for that element.
|
|
|
|
const nsChangeHint mHintsHandledByAncestors;
|
|
|
|
// Hints that we have computed so far the current node. This is
|
|
|
|
// initially zero, and accumulates hints for each same-style continuation
|
|
|
|
// and {ib} split sibling we restyle for the node.
|
|
|
|
nsChangeHint mHintsHandledBySelf;
|
2013-07-31 04:36:10 +04:00
|
|
|
RestyleTracker& mRestyleTracker;
|
2015-08-05 15:42:20 +03:00
|
|
|
nsTArray<nsCSSSelector*>& mSelectorsForDescendants;
|
2013-07-31 04:36:10 +04:00
|
|
|
TreeMatchContext& mTreeMatchContext;
|
2013-07-31 04:36:11 +04:00
|
|
|
nsIFrame* mResolvedChild; // child that provides our parent style context
|
2015-02-18 01:28:53 +03:00
|
|
|
// Array of style context subtrees in which we need to clear out cached
|
|
|
|
// structs at the end of the restyle (after change hints have been
|
|
|
|
// processed).
|
|
|
|
nsTArray<ContextToClear>& mContextsToClear;
|
|
|
|
// Style contexts that had old structs swapped into it and which should
|
|
|
|
// stay alive until the end of the restyle. (See comment in
|
|
|
|
// ElementRestyler::Restyle.)
|
2017-07-21 04:22:00 +03:00
|
|
|
nsTArray<RefPtr<GeckoStyleContext>>& mSwappedStructOwners;
|
2015-08-28 23:13:47 +03:00
|
|
|
// Whether this is the root of the restyle.
|
|
|
|
bool mIsRootOfRestyle;
|
2013-07-31 04:36:10 +04:00
|
|
|
|
2013-08-01 06:15:19 +04:00
|
|
|
#ifdef ACCESSIBILITY
|
2013-07-31 04:36:10 +04:00
|
|
|
const DesiredA11yNotifications mDesiredA11yNotifications;
|
|
|
|
DesiredA11yNotifications mKidsDesiredA11yNotifications;
|
|
|
|
A11yNotificationType mOurA11yNotification;
|
2013-07-31 04:36:10 +04:00
|
|
|
nsTArray<nsIContent*>& mVisibleKidsOfHiddenElement;
|
2013-07-31 04:36:11 +04:00
|
|
|
bool mWasFrameVisible;
|
2013-08-01 06:15:19 +04:00
|
|
|
#endif
|
2014-09-25 09:45:36 +04:00
|
|
|
|
|
|
|
#ifdef RESTYLE_LOGGING
|
|
|
|
int32_t mLoggingDepth;
|
|
|
|
#endif
|
2013-07-31 04:36:09 +04:00
|
|
|
};
|
|
|
|
|
2014-11-20 21:24:09 +03:00
|
|
|
/**
|
|
|
|
* This pushes any display:contents nodes onto a TreeMatchContext.
|
|
|
|
* Use it before resolving style for kids of aParent where aParent
|
|
|
|
* (and further ancestors) may be display:contents nodes which have
|
|
|
|
* not yet been pushed onto TreeMatchContext.
|
|
|
|
*/
|
2016-03-28 15:34:26 +03:00
|
|
|
class MOZ_RAII AutoDisplayContentsAncestorPusher final
|
2014-11-20 21:24:09 +03:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef mozilla::dom::Element Element;
|
|
|
|
AutoDisplayContentsAncestorPusher(TreeMatchContext& aTreeMatchContext,
|
|
|
|
nsPresContext* aPresContext,
|
|
|
|
nsIContent* aParent);
|
|
|
|
~AutoDisplayContentsAncestorPusher();
|
|
|
|
bool IsEmpty() const { return mAncestors.Length() == 0; }
|
|
|
|
private:
|
|
|
|
TreeMatchContext& mTreeMatchContext;
|
|
|
|
nsPresContext* const mPresContext;
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<mozilla::dom::Element*, 4> mAncestors;
|
2014-11-20 21:24:09 +03:00
|
|
|
};
|
|
|
|
|
2013-07-20 23:14:24 +04:00
|
|
|
} // namespace mozilla
|
|
|
|
|
2017-02-13 06:21:32 +03:00
|
|
|
#endif /* mozilla_GeckoRestyleManager_h */
|