LCOV - code coverage report
Current view: top level - layout/base - GeckoRestyleManager.h (source / functions) Hit Total Coverage
Test: output.info Lines: 53 71 74.6 %
Date: 2017-07-14 16:53:18 Functions: 23 27 85.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /**
       7             :  * Code responsible for managing style changes: tracking what style
       8             :  * changes need to happen, scheduling them, and doing them.
       9             :  */
      10             : 
      11             : #ifndef mozilla_GeckoRestyleManager_h
      12             : #define mozilla_GeckoRestyleManager_h
      13             : 
      14             : #include "mozilla/RestyleLogging.h"
      15             : #include "mozilla/RestyleManager.h"
      16             : #include "nsISupportsImpl.h"
      17             : #include "nsChangeHint.h"
      18             : #include "RestyleTracker.h"
      19             : #include "nsPresContext.h"
      20             : #include "nsRefreshDriver.h"
      21             : #include "nsRefPtrHashtable.h"
      22             : #include "nsTransitionManager.h"
      23             : 
      24             : class nsIFrame;
      25             : class nsStyleChangeList;
      26             : struct TreeMatchContext;
      27             : 
      28             : namespace mozilla {
      29             :   enum class CSSPseudoElementType : uint8_t;
      30             :   class EventStates;
      31             :   struct UndisplayedNode;
      32             : 
      33             : namespace dom {
      34             :   class Element;
      35             : } // namespace dom
      36             : 
      37             : class GeckoRestyleManager final : public RestyleManager
      38             : {
      39             : public:
      40             :   typedef RestyleManager base_type;
      41             : 
      42             :   friend class RestyleTracker;
      43             :   friend class ElementRestyler;
      44             : 
      45             :   explicit GeckoRestyleManager(nsPresContext* aPresContext);
      46             : 
      47             : protected:
      48           8 :   ~GeckoRestyleManager() override
      49           8 :   {
      50           4 :     MOZ_ASSERT(!mReframingStyleContexts,
      51             :                "temporary member should be nulled out before destruction");
      52          12 :   }
      53             : 
      54             : public:
      55             :   // Forwarded nsIDocumentObserver method, to handle restyling (and
      56             :   // passing the notification to the frame).
      57             :   void ContentStateChanged(nsIContent* aContent,
      58             :                            EventStates aStateMask);
      59             : 
      60             :   // Forwarded nsIMutationObserver method, to handle restyling.
      61             :   void AttributeWillChange(Element* aElement,
      62             :                            int32_t  aNameSpaceID,
      63             :                            nsIAtom* aAttribute,
      64             :                            int32_t  aModType,
      65             :                            const nsAttrValue* aNewValue);
      66             :   // Forwarded nsIMutationObserver method, to handle restyling (and
      67             :   // passing the notification to the frame).
      68             :   void AttributeChanged(Element* aElement,
      69             :                         int32_t  aNameSpaceID,
      70             :                         nsIAtom* aAttribute,
      71             :                         int32_t  aModType,
      72             :                         const nsAttrValue* aOldValue);
      73             : 
      74             :   // Whether rule matching should skip styles associated with animation
      75       10560 :   bool SkipAnimationRules() const { return mSkipAnimationRules; }
      76             : 
      77          16 :   void SetSkipAnimationRules(bool aSkipAnimationRules) {
      78          16 :     mSkipAnimationRules = aSkipAnimationRules;
      79          16 :   }
      80             : 
      81             :   /**
      82             :    * Reparent the style contexts of this frame subtree.  The parent frame of
      83             :    * aFrame must be changed to the new parent before this function is called;
      84             :    * the new parent style context will be automatically computed based on the
      85             :    * new position in the frame tree.
      86             :    *
      87             :    * @param aFrame the root of the subtree to reparent.  Must not be null.
      88             :    */
      89             :   nsresult ReparentStyleContext(nsIFrame* aFrame);
      90             : 
      91          48 :   void ClearSelectors() {
      92          48 :     mPendingRestyles.ClearSelectors();
      93          48 :   }
      94             : 
      95          34 :   void PostRestyleEventForLazyConstruction() { PostRestyleEventInternal(); }
      96             : 
      97             : private:
      98             :   void PostRestyleEventInternal();
      99             : 
     100             :   // Used when restyling an element with a frame.
     101             :   void ComputeAndProcessStyleChange(nsIFrame*              aFrame,
     102             :                                     nsChangeHint           aMinChange,
     103             :                                     RestyleTracker&        aRestyleTracker,
     104             :                                     nsRestyleHint          aRestyleHint,
     105             :                                     const RestyleHintData& aRestyleHintData);
     106             : 
     107             :   // Used when restyling a display:contents element.
     108             :   void ComputeAndProcessStyleChange(nsStyleContext*        aNewContext,
     109             :                                     Element*               aElement,
     110             :                                     nsChangeHint           aMinChange,
     111             :                                     RestyleTracker&        aRestyleTracker,
     112             :                                     nsRestyleHint          aRestyleHint,
     113             :                                     const RestyleHintData& aRestyleHintData);
     114             : 
     115             : public:
     116             : 
     117             :   /**
     118             :    * In order to start CSS transitions on elements that are being
     119             :    * reframed, we need to stash their style contexts somewhere during
     120             :    * the reframing process.
     121             :    *
     122             :    * In all cases, the content node in the hash table is the real
     123             :    * content node, not the anonymous content node we create for ::before
     124             :    * or ::after.  The content node passed to the Get and Put methods is,
     125             :    * however, the content node to be associate with the frame's style
     126             :    * context.
     127             :    */
     128             :   typedef nsRefPtrHashtable<nsRefPtrHashKey<nsIContent>, nsStyleContext>
     129             :             ReframingStyleContextTable;
     130             :   class MOZ_STACK_CLASS ReframingStyleContexts final {
     131             :   public:
     132             :     /**
     133             :      * Construct a ReframingStyleContexts object.  The caller must
     134             :      * ensure that aRestyleManager lives at least as long as the
     135             :      * object.  (This is generally easy since the caller is typically a
     136             :      * method of RestyleManager.)
     137             :      */
     138             :     explicit ReframingStyleContexts(GeckoRestyleManager* aRestyleManager);
     139             :     ~ReframingStyleContexts();
     140             : 
     141         106 :     void Put(nsIContent* aContent, nsStyleContext* aStyleContext) {
     142         106 :       MOZ_ASSERT(aContent);
     143         106 :       CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
     144         106 :       if (pseudoType == CSSPseudoElementType::NotPseudo) {
     145         101 :         mElementContexts.Put(aContent, aStyleContext);
     146           5 :       } else if (pseudoType == CSSPseudoElementType::before) {
     147           0 :         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
     148           0 :         mBeforePseudoContexts.Put(aContent->GetParent(), aStyleContext);
     149           5 :       } else if (pseudoType == CSSPseudoElementType::after) {
     150           0 :         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
     151           0 :         mAfterPseudoContexts.Put(aContent->GetParent(), aStyleContext);
     152             :       }
     153         106 :     }
     154             : 
     155         190 :     nsStyleContext* Get(nsIContent* aContent,
     156             :                         CSSPseudoElementType aPseudoType) {
     157         190 :       MOZ_ASSERT(aContent);
     158         190 :       if (aPseudoType == CSSPseudoElementType::NotPseudo) {
     159         190 :         return mElementContexts.GetWeak(aContent);
     160             :       }
     161           0 :       if (aPseudoType == CSSPseudoElementType::before) {
     162           0 :         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore);
     163           0 :         return mBeforePseudoContexts.GetWeak(aContent->GetParent());
     164             :       }
     165           0 :       if (aPseudoType == CSSPseudoElementType::after) {
     166           0 :         MOZ_ASSERT(aContent->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter);
     167           0 :         return mAfterPseudoContexts.GetWeak(aContent->GetParent());
     168             :       }
     169           0 :       MOZ_ASSERT(false, "unexpected aPseudoType");
     170             :       return nullptr;
     171             :     }
     172             :   private:
     173             :     GeckoRestyleManager* mRestyleManager;
     174             :     AutoRestore<ReframingStyleContexts*> mRestorePointer;
     175             :     ReframingStyleContextTable mElementContexts;
     176             :     ReframingStyleContextTable mBeforePseudoContexts;
     177             :     ReframingStyleContextTable mAfterPseudoContexts;
     178             :   };
     179             : 
     180             :   /**
     181             :    * Return the current ReframingStyleContexts struct, or null if we're
     182             :    * not currently in a restyling operation.
     183             :    */
     184        1180 :   ReframingStyleContexts* GetReframingStyleContexts() {
     185        1180 :     return mReframingStyleContexts;
     186             :   }
     187             : 
     188             :   /**
     189             :    * Try initiating a transition for an element or a ::before or ::after
     190             :    * pseudo-element, given an old and new style context.  This may
     191             :    * change the new style context if a transition is started.  Returns
     192             :    * true if it does change aNewStyleContext.
     193             :    *
     194             :    * For the pseudo-elements, aContent must be the anonymous content
     195             :    * that we're creating for that pseudo-element, not the real element.
     196             :    */
     197             :   static bool
     198             :   TryInitiatingTransition(nsPresContext* aPresContext, nsIContent* aContent,
     199             :                           nsStyleContext* aOldStyleContext,
     200             :                           RefPtr<nsStyleContext>* aNewStyleContext /* inout */);
     201             : 
     202             : public:
     203             :   // Process any pending restyles. This should be called after
     204             :   // CreateNeededFrames.
     205             :   // Note: It's the caller's responsibility to make sure to wrap a
     206             :   // ProcessPendingRestyles call in a view update batch and a script blocker.
     207             :   // This function does not call ProcessAttachedQueue() on the binding manager.
     208             :   // If the caller wants that to happen synchronously, it needs to handle that
     209             :   // itself.
     210             :   void ProcessPendingRestyles();
     211             : 
     212             : private:
     213             :   // ProcessPendingRestyles calls into one of our RestyleTracker
     214             :   // objects.  It then calls back to these functions at the beginning
     215             :   // and end of its work.
     216             :   void BeginProcessingRestyles(RestyleTracker& aRestyleTracker);
     217             :   void EndProcessingRestyles();
     218             : 
     219             : public:
     220             :   // Update styles for animations that are running on the compositor and
     221             :   // whose updating is suppressed on the main thread (to save
     222             :   // unnecessary work), while leaving all other aspects of style
     223             :   // out-of-date.
     224             :   //
     225             :   // Performs an animation-only style flush to make styles from
     226             :   // throttled transitions up-to-date prior to processing an unrelated
     227             :   // style change, so that any transitions triggered by that style
     228             :   // change produce correct results.
     229             :   //
     230             :   // In more detail:  when we're able to run animations on the
     231             :   // compositor, we sometimes "throttle" these animations by skipping
     232             :   // updating style data on the main thread.  However, whenever we
     233             :   // process a normal (non-animation) style change, any changes in
     234             :   // computed style on elements that have transition-* properties set
     235             :   // may need to trigger new transitions; this process requires knowing
     236             :   // both the old and new values of the property.  To do this correctly,
     237             :   // we need to have an up-to-date *old* value of the property on the
     238             :   // primary frame.  So the purpose of the mini-flush is to update the
     239             :   // style for all throttled transitions and animations to the current
     240             :   // animation state without making any other updates, so that when we
     241             :   // process the queued style updates we'll have correct old data to
     242             :   // compare against.  When we do this, we don't bother touching frames
     243             :   // other than primary frames.
     244             :   void UpdateOnlyAnimationStyles();
     245             : 
     246             :   // Rebuilds all style data by throwing out the old rule tree and
     247             :   // building a new one, and additionally applying aExtraHint (which
     248             :   // must not contain nsChangeHint_ReconstructFrame) to the root frame.
     249             :   //
     250             :   // aRestyleHint says which restyle hint to use for the computation;
     251             :   // the only sensible values to use are eRestyle_Subtree (which says
     252             :   // that the rebuild must run selector matching) and nsRestyleHint(0)
     253             :   // (which says that rerunning selector matching is not required.  (The
     254             :   // method adds eRestyle_ForceDescendants internally, and including it
     255             :   // in the restyle hint is harmless; some callers (e.g.,
     256             :   // nsPresContext::MediaFeatureValuesChanged) might do this for their
     257             :   // own reasons.)
     258             :   void RebuildAllStyleData(nsChangeHint aExtraHint,
     259             :                            nsRestyleHint aRestyleHint);
     260             : 
     261             :   /**
     262             :    * Notify the frame constructor that an element needs to have its
     263             :    * style recomputed.
     264             :    * @param aElement: The element to be restyled.
     265             :    * @param aRestyleHint: Which nodes need to have selector matching run
     266             :    *                      on them.
     267             :    * @param aMinChangeHint: A minimum change hint for aContent and its
     268             :    *                        descendants.
     269             :    * @param aRestyleHintData: Additional data to go with aRestyleHint.
     270             :    */
     271             :   void PostRestyleEvent(Element* aElement,
     272             :                         nsRestyleHint aRestyleHint,
     273             :                         nsChangeHint aMinChangeHint,
     274             :                         const RestyleHintData* aRestyleHintData = nullptr);
     275             : 
     276             : public:
     277             :   /**
     278             :    * Asynchronously clear style data from the root frame downwards and ensure
     279             :    * it will all be rebuilt. This is safe to call anytime; it will schedule
     280             :    * a restyle and take effect next time style changes are flushed.
     281             :    * This method is used to recompute the style data when some change happens
     282             :    * outside of any style rules, like a color preference change or a change
     283             :    * in a system font size, or to fix things up when an optimization in the
     284             :    * style data has become invalid. We assume that the root frame will not
     285             :    * need to be reframed.
     286             :    *
     287             :    * For parameters, see RebuildAllStyleData.
     288             :    */
     289             :   void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
     290             :                                     nsRestyleHint aRestyleHint);
     291             : 
     292             : #ifdef DEBUG
     293           0 :   bool InRebuildAllStyleData() const { return mInRebuildAllStyleData; }
     294             : #endif
     295             : 
     296             : #ifdef RESTYLE_LOGGING
     297             :   /**
     298             :    * Returns whether a restyle event currently being processed by this
     299             :    * GeckoRestyleManager should be logged.
     300             :    */
     301         401 :   bool ShouldLogRestyle() {
     302         401 :     return ShouldLogRestyle(PresContext());
     303             :   }
     304             : 
     305             :   /**
     306             :    * Returns whether a restyle event currently being processed for the
     307             :    * document with the specified nsPresContext should be logged.
     308             :    */
     309       12245 :   static bool ShouldLogRestyle(nsPresContext* aPresContext) {
     310       12245 :     return aPresContext->RestyleLoggingEnabled() &&
     311           0 :            (!aPresContext->TransitionManager()->
     312           0 :                InAnimationOnlyStyleUpdate() ||
     313       12245 :             AnimationRestyleLoggingEnabled());
     314             :   }
     315             : 
     316          28 :   static bool RestyleLoggingInitiallyEnabled() {
     317          28 :     static bool enabled = getenv("MOZ_DEBUG_RESTYLE") != 0;
     318          28 :     return enabled;
     319             :   }
     320             : 
     321           0 :   static bool AnimationRestyleLoggingEnabled() {
     322           0 :     static bool animations = getenv("MOZ_DEBUG_RESTYLE_ANIMATIONS") != 0;
     323           0 :     return animations;
     324             :   }
     325             : 
     326             :   // Set MOZ_DEBUG_RESTYLE_STRUCTS to a comma-separated string of
     327             :   // style struct names -- such as "Font,SVGReset" -- to log the style context
     328             :   // tree and those cached struct pointers before each restyle.  This
     329             :   // function returns a bitfield of the structs named in the
     330             :   // environment variable.
     331             :   static uint32_t StructsToLog();
     332             : 
     333             :   static nsCString StructNamesToString(uint32_t aSIDs);
     334         355 :   int32_t& LoggingDepth() { return mLoggingDepth; }
     335             : #endif
     336             : 
     337           2 :   bool IsProcessingRestyles() { return mIsProcessingRestyles; }
     338             : 
     339             : private:
     340         657 :   inline nsStyleSet* StyleSet() const {
     341         657 :     MOZ_ASSERT(PresContext()->StyleSet()->IsGecko(),
     342             :                "GeckoRestyleManager should only be used with a Gecko-flavored "
     343             :                "style backend");
     344         657 :     return PresContext()->StyleSet()->AsGecko();
     345             :   }
     346             : 
     347             :   /* aMinHint is the minimal change that should be made to the element */
     348             :   // XXXbz do we really need the aPrimaryFrame argument here?
     349             :   void RestyleElement(Element*        aElement,
     350             :                       nsIFrame*       aPrimaryFrame,
     351             :                       nsChangeHint    aMinHint,
     352             :                       RestyleTracker& aRestyleTracker,
     353             :                       nsRestyleHint   aRestyleHint,
     354             :                       const RestyleHintData& aRestyleHintData);
     355             : 
     356             :   void StartRebuildAllStyleData(RestyleTracker& aRestyleTracker);
     357             :   void FinishRebuildAllStyleData();
     358             : 
     359         269 :   bool ShouldStartRebuildAllFor(RestyleTracker& aRestyleTracker) {
     360             :     // When we process our primary restyle tracker and we have a pending
     361             :     // rebuild-all, we need to process it.
     362         273 :     return mDoRebuildAllStyleData &&
     363         273 :            &aRestyleTracker == &mPendingRestyles;
     364             :   }
     365             : 
     366         267 :   void ProcessRestyles(RestyleTracker& aRestyleTracker) {
     367             :     // Fast-path the common case (esp. for the animation restyle
     368             :     // tracker) of not having anything to do.
     369         267 :     if (aRestyleTracker.Count() || ShouldStartRebuildAllFor(aRestyleTracker)) {
     370          25 :       IncrementRestyleGeneration();
     371          25 :       aRestyleTracker.DoProcessRestyles();
     372             :     }
     373         267 :   }
     374             : 
     375             : private:
     376             :   // True if we need to reconstruct the rule tree the next time we
     377             :   // process restyles.
     378             :   bool mDoRebuildAllStyleData : 1;
     379             :   // True if we're currently in the process of reconstructing the rule tree.
     380             :   bool mInRebuildAllStyleData : 1;
     381             :   // Whether rule matching should skip styles associated with animation
     382             :   bool mSkipAnimationRules : 1;
     383             :   bool mHavePendingNonAnimationRestyles : 1;
     384             : 
     385             :   nsChangeHint mRebuildAllExtraHint;
     386             :   nsRestyleHint mRebuildAllRestyleHint;
     387             : 
     388             :   ReframingStyleContexts* mReframingStyleContexts;
     389             : 
     390             :   RestyleTracker mPendingRestyles;
     391             : 
     392             :   // Are we currently in the middle of a call to ProcessRestyles?
     393             :   // This flag is used both as a debugging aid to assert that we are not
     394             :   // performing nested calls to ProcessPendingRestyles, as well as to ignore
     395             :   // redundant calls to IncrementAnimationGeneration.
     396             :   bool mIsProcessingRestyles;
     397             : 
     398             : #ifdef RESTYLE_LOGGING
     399             :   int32_t mLoggingDepth;
     400             : #endif
     401             : };
     402             : 
     403             : /**
     404             :  * An ElementRestyler is created for *each* element in a subtree that we
     405             :  * recompute styles for.
     406             :  */
     407             : class ElementRestyler final
     408             : {
     409             : public:
     410             :   typedef mozilla::dom::Element Element;
     411             : 
     412          66 :   struct ContextToClear {
     413             :     RefPtr<nsStyleContext> mStyleContext;
     414             :     uint32_t mStructs;
     415             :   };
     416             : 
     417             :   // Construct for the root of the subtree that we're restyling.
     418             :   ElementRestyler(nsPresContext* aPresContext,
     419             :                   nsIFrame* aFrame,
     420             :                   nsStyleChangeList* aChangeList,
     421             :                   nsChangeHint aHintsHandledByAncestors,
     422             :                   RestyleTracker& aRestyleTracker,
     423             :                   nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
     424             :                   TreeMatchContext& aTreeMatchContext,
     425             :                   nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
     426             :                   nsTArray<ContextToClear>& aContextsToClear,
     427             :                   nsTArray<RefPtr<nsStyleContext>>& aSwappedStructOwners);
     428             : 
     429             :   // Construct for an element whose parent is being restyled.
     430             :   enum ConstructorFlags {
     431             :     FOR_OUT_OF_FLOW_CHILD = 1<<0
     432             :   };
     433             :   ElementRestyler(const ElementRestyler& aParentRestyler,
     434             :                   nsIFrame* aFrame,
     435             :                   uint32_t aConstructorFlags);
     436             : 
     437             :   // Construct for a frame whose parent is being restyled, but whose
     438             :   // style context is the parent style context for its parent frame.
     439             :   // (This is only used for table frames, whose style contexts are used
     440             :   // as the parent style context for their table wrapper frame. We should
     441             :   // probably try to get rid of this exception and have the inheritance go
     442             :   // the other way.)
     443             :   enum ParentContextFromChildFrame { PARENT_CONTEXT_FROM_CHILD_FRAME };
     444             :   ElementRestyler(ParentContextFromChildFrame,
     445             :                   const ElementRestyler& aParentFrameRestyler,
     446             :                   nsIFrame* aFrame);
     447             : 
     448             :   // For restyling undisplayed content only (mFrame==null).
     449             :   ElementRestyler(nsPresContext* aPresContext,
     450             :                   nsIContent* aContent,
     451             :                   nsStyleChangeList* aChangeList,
     452             :                   nsChangeHint aHintsHandledByAncestors,
     453             :                   RestyleTracker& aRestyleTracker,
     454             :                   nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
     455             :                   TreeMatchContext& aTreeMatchContext,
     456             :                   nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
     457             :                   nsTArray<ContextToClear>& aContextsToClear,
     458             :                   nsTArray<RefPtr<nsStyleContext>>& aSwappedStructOwners);
     459             : 
     460             :   /**
     461             :    * Restyle our frame's element and its subtree.
     462             :    *
     463             :    * Use eRestyle_Self for the aRestyleHint argument to mean
     464             :    * "reresolve our style context but not kids", use eRestyle_Subtree
     465             :    * to mean "reresolve our style context and kids", and use
     466             :    * nsRestyleHint(0) to mean recompute a new style context for our
     467             :    * current parent and existing rulenode, and the same for kids.
     468             :    */
     469             :   void Restyle(nsRestyleHint aRestyleHint);
     470             : 
     471             :   /**
     472             :    * mHintsHandledBySelf changes over time; it starts off as nsChangeHint(0),
     473             :    * and by the end of Restyle it represents the hints that have been handled
     474             :    * for this frame.  This method is intended to be called after Restyle, to
     475             :    * find out what hints have been handled for this frame.
     476             :    */
     477          61 :   nsChangeHint HintsHandledForFrame() { return mHintsHandledBySelf; }
     478             : 
     479             :   /**
     480             :    * Called from GeckoRestyleManager::ComputeAndProcessStyleChange to restyle
     481             :    * children of a display:contents element.
     482             :    */
     483             :   void RestyleChildrenOfDisplayContentsElement(nsIFrame*       aParentFrame,
     484             :                                                nsStyleContext* aNewContext,
     485             :                                                nsChangeHint    aMinHint,
     486             :                                                RestyleTracker& aRestyleTracker,
     487             :                                                nsRestyleHint   aRestyleHint,
     488             :                                                const RestyleHintData&
     489             :                                                  aRestyleHintData);
     490             : 
     491             :   /**
     492             :    * Re-resolve the style contexts for a frame tree, building aChangeList
     493             :    * based on the resulting style changes, plus aMinChange applied to aFrame.
     494             :    */
     495             :   static void ComputeStyleChangeFor(nsIFrame*          aFrame,
     496             :                                     nsStyleChangeList* aChangeList,
     497             :                                     nsChangeHint       aMinChange,
     498             :                                     RestyleTracker&    aRestyleTracker,
     499             :                                     nsRestyleHint      aRestyleHint,
     500             :                                     const RestyleHintData& aRestyleHintData,
     501             :                                     nsTArray<ContextToClear>& aContextsToClear,
     502             :                                     nsTArray<RefPtr<nsStyleContext>>&
     503             :                                       aSwappedStructOwners);
     504             : 
     505             : #ifdef RESTYLE_LOGGING
     506       11844 :   bool ShouldLogRestyle() {
     507       11844 :     return GeckoRestyleManager::ShouldLogRestyle(mPresContext);
     508             :   }
     509             : #endif
     510             : 
     511             : private:
     512             :   inline nsStyleSet* StyleSet() const;
     513             : 
     514             :   // Enum class for the result of RestyleSelf, which indicates whether the
     515             :   // restyle procedure should continue to the children, and how.
     516             :   //
     517             :   // These values must be ordered so that later values imply that all
     518             :   // the work of the earlier values is also done.
     519             :   enum class RestyleResult : uint8_t {
     520             :     // default initial value
     521             :     eNone,
     522             : 
     523             :     // we left the old style context on the frame; do not restyle children
     524             :     eStop,
     525             : 
     526             :     // we got a new style context on this frame, but we know that children
     527             :     // do not depend on the changed values; do not restyle children
     528             :     eStopWithStyleChange,
     529             : 
     530             :     // continue restyling children
     531             :     eContinue,
     532             : 
     533             :     // continue restyling children with eRestyle_ForceDescendants set
     534             :     eContinueAndForceDescendants
     535             :   };
     536             : 
     537           0 :   struct SwapInstruction
     538             :   {
     539             :     RefPtr<nsStyleContext> mOldContext;
     540             :     RefPtr<nsStyleContext> mNewContext;
     541             :     uint32_t mStructsToSwap;
     542             :   };
     543             : 
     544             :   /**
     545             :    * First half of Restyle().
     546             :    */
     547             :   RestyleResult RestyleSelf(nsIFrame* aSelf,
     548             :                             nsRestyleHint aRestyleHint,
     549             :                             uint32_t* aSwappedStructs,
     550             :                             nsTArray<SwapInstruction>& aSwaps);
     551             : 
     552             :   /**
     553             :    * Restyle the children of this frame (and, in turn, their children).
     554             :    *
     555             :    * Second half of Restyle().
     556             :    */
     557             :   void RestyleChildren(nsRestyleHint aChildRestyleHint);
     558             : 
     559             :   /**
     560             :    * Returns true iff a selector in mSelectorsForDescendants matches aElement.
     561             :    * This is called when processing a eRestyle_SomeDescendants restyle hint.
     562             :    */
     563             :   bool SelectorMatchesForRestyle(Element* aElement);
     564             : 
     565             :   /**
     566             :    * Returns true iff aRestyleHint indicates that we should be restyling.
     567             :    * Specifically, this will return true when eRestyle_Self or
     568             :    * eRestyle_Subtree is present, or if eRestyle_SomeDescendants is
     569             :    * present and the specified element matches one of the selectors in
     570             :    * mSelectorsForDescendants.
     571             :    */
     572             :   bool MustRestyleSelf(nsRestyleHint aRestyleHint, Element* aElement);
     573             : 
     574             :   /**
     575             :    * Returns true iff aRestyleHint indicates that we can call
     576             :    * ReparentStyleContext rather than any other restyling method of
     577             :    * nsStyleSet that looks up a new rule node, and if we are
     578             :    * not in the process of reconstructing the whole rule tree.
     579             :    * This is used to check whether it is appropriate to call
     580             :    * ReparentStyleContext.
     581             :    */
     582             :   bool CanReparentStyleContext(nsRestyleHint aRestyleHint);
     583             : 
     584             :   /**
     585             :    * Helpers for Restyle().
     586             :    */
     587             :   bool MoveStyleContextsForContentChildren(nsIFrame* aParent,
     588             :                                            nsStyleContext* aOldContext,
     589             :                                            nsTArray<nsStyleContext*>& aContextsToMove);
     590             :   bool MoveStyleContextsForChildren(nsStyleContext* aOldContext);
     591             : 
     592             :   /**
     593             :    * Helpers for RestyleSelf().
     594             :    */
     595             :   void CaptureChange(nsStyleContext* aOldContext,
     596             :                      nsStyleContext* aNewContext,
     597             :                      nsChangeHint aChangeToAssume,
     598             :                      uint32_t* aEqualStructs,
     599             :                      uint32_t* aSamePointerStructs);
     600             :   void ComputeRestyleResultFromFrame(nsIFrame* aSelf,
     601             :                                      RestyleResult& aRestyleResult,
     602             :                                      bool& aCanStopWithStyleChange);
     603             :   void ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
     604             :                                           nsStyleContext* aNewContext,
     605             :                                           RestyleResult& aRestyleResult,
     606             :                                           bool& aCanStopWithStyleChange);
     607             : 
     608             :   // Helpers for RestyleChildren().
     609             :   void RestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint);
     610             :   bool MustCheckUndisplayedContent(nsIFrame* aFrame,
     611             :                                    nsIContent*& aUndisplayedParent);
     612             : 
     613             :   /**
     614             :    * In the following two methods, aParentStyleContext is either
     615             :    * mFrame->StyleContext() if we have a frame, or a display:contents
     616             :    * style context if we don't.
     617             :    */
     618             :   void DoRestyleUndisplayedDescendants(nsRestyleHint aChildRestyleHint,
     619             :                                        nsIContent* aParent,
     620             :                                        nsStyleContext* aParentStyleContext);
     621             :   void RestyleUndisplayedNodes(nsRestyleHint      aChildRestyleHint,
     622             :                                UndisplayedNode*   aUndisplayed,
     623             :                                nsIContent*        aUndisplayedParent,
     624             :                                nsStyleContext*    aParentStyleContext,
     625             :                                const StyleDisplay aDisplay);
     626             :   void MaybeReframeForBeforePseudo();
     627             :   void MaybeReframeForAfterPseudo(nsIFrame* aFrame);
     628             :   void MaybeReframeForPseudo(CSSPseudoElementType aPseudoType,
     629             :                              nsIFrame* aGenConParentFrame,
     630             :                              nsIFrame* aFrame,
     631             :                              nsIContent* aContent,
     632             :                              nsStyleContext* aStyleContext);
     633             : #ifdef DEBUG
     634             :   bool MustReframeForBeforePseudo();
     635             :   bool MustReframeForAfterPseudo(nsIFrame* aFrame);
     636             : #endif
     637             :   bool MustReframeForPseudo(CSSPseudoElementType aPseudoType,
     638             :                             nsIFrame* aGenConParentFrame,
     639             :                             nsIFrame* aFrame,
     640             :                             nsIContent* aContent,
     641             :                             nsStyleContext* aStyleContext);
     642             :   void RestyleContentChildren(nsIFrame* aParent,
     643             :                               nsRestyleHint aChildRestyleHint);
     644             :   void InitializeAccessibilityNotifications(nsStyleContext* aNewContext);
     645             :   void SendAccessibilityNotifications();
     646             : 
     647             :   enum DesiredA11yNotifications {
     648             :     eSkipNotifications,
     649             :     eSendAllNotifications,
     650             :     eNotifyIfShown
     651             :   };
     652             : 
     653             :   enum A11yNotificationType {
     654             :     eDontNotify,
     655             :     eNotifyShown,
     656             :     eNotifyHidden
     657             :   };
     658             : 
     659             :   // These methods handle the eRestyle_SomeDescendants hint by traversing
     660             :   // down the frame tree (and then when reaching undisplayed content,
     661             :   // the flattened content tree) find elements that match a selector
     662             :   // in mSelectorsForDescendants and call AddPendingRestyle for them.
     663             :   void ConditionallyRestyleChildren();
     664             :   void ConditionallyRestyleChildren(nsIFrame* aFrame,
     665             :                                     Element* aRestyleRoot);
     666             :   void ConditionallyRestyleContentChildren(nsIFrame* aFrame,
     667             :                                            Element* aRestyleRoot);
     668             :   void ConditionallyRestyleUndisplayedDescendants(nsIFrame* aFrame,
     669             :                                                   Element* aRestyleRoot);
     670             :   void DoConditionallyRestyleUndisplayedDescendants(nsIContent* aParent,
     671             :                                                     Element* aRestyleRoot);
     672             :   void ConditionallyRestyleUndisplayedNodes(UndisplayedNode* aUndisplayed,
     673             :                                             nsIContent* aUndisplayedParent,
     674             :                                             const StyleDisplay aDisplay,
     675             :                                             Element* aRestyleRoot);
     676             :   void ConditionallyRestyleContentDescendants(Element* aElement,
     677             :                                               Element* aRestyleRoot);
     678             :   bool ConditionallyRestyle(nsIFrame* aFrame, Element* aRestyleRoot);
     679             :   bool ConditionallyRestyle(Element* aElement, Element* aRestyleRoot);
     680             : 
     681             : #ifdef RESTYLE_LOGGING
     682        4480 :   int32_t& LoggingDepth() { return mLoggingDepth; }
     683             : #endif
     684             : 
     685             : #ifdef DEBUG
     686             :   static nsCString RestyleResultToString(RestyleResult aRestyleResult);
     687             : #endif
     688             : 
     689             : private:
     690             :   nsPresContext* const mPresContext;
     691             :   nsIFrame* const mFrame;
     692             :   nsIContent* const mParentContent;
     693             :   // |mContent| is the node that we used for rule matching of
     694             :   // normal elements (not pseudo-elements) and for which we generate
     695             :   // framechange hints if we need them.
     696             :   nsIContent* const mContent;
     697             :   nsStyleChangeList* const mChangeList;
     698             :   // Hints that we computed on an ancestor (and which we already have
     699             :   // generated a change list entry for).  When we traverse to children
     700             :   // after restyling an element, this field accumulates the hints
     701             :   // generated for that element.
     702             :   const nsChangeHint mHintsHandledByAncestors;
     703             :   // Hints that we have computed so far the current node.  This is
     704             :   // initially zero, and accumulates hints for each same-style continuation
     705             :   // and {ib} split sibling we restyle for the node.
     706             :   nsChangeHint mHintsHandledBySelf;
     707             :   RestyleTracker& mRestyleTracker;
     708             :   nsTArray<nsCSSSelector*>& mSelectorsForDescendants;
     709             :   TreeMatchContext& mTreeMatchContext;
     710             :   nsIFrame* mResolvedChild; // child that provides our parent style context
     711             :   // Array of style context subtrees in which we need to clear out cached
     712             :   // structs at the end of the restyle (after change hints have been
     713             :   // processed).
     714             :   nsTArray<ContextToClear>& mContextsToClear;
     715             :   // Style contexts that had old structs swapped into it and which should
     716             :   // stay alive until the end of the restyle.  (See comment in
     717             :   // ElementRestyler::Restyle.)
     718             :   nsTArray<RefPtr<nsStyleContext>>& mSwappedStructOwners;
     719             :   // Whether this is the root of the restyle.
     720             :   bool mIsRootOfRestyle;
     721             : 
     722             : #ifdef ACCESSIBILITY
     723             :   const DesiredA11yNotifications mDesiredA11yNotifications;
     724             :   DesiredA11yNotifications mKidsDesiredA11yNotifications;
     725             :   A11yNotificationType mOurA11yNotification;
     726             :   nsTArray<nsIContent*>& mVisibleKidsOfHiddenElement;
     727             :   bool mWasFrameVisible;
     728             : #endif
     729             : 
     730             : #ifdef RESTYLE_LOGGING
     731             :   int32_t mLoggingDepth;
     732             : #endif
     733             : };
     734             : 
     735             : /**
     736             :  * This pushes any display:contents nodes onto a TreeMatchContext.
     737             :  * Use it before resolving style for kids of aParent where aParent
     738             :  * (and further ancestors) may be display:contents nodes which have
     739             :  * not yet been pushed onto TreeMatchContext.
     740             :  */
     741             : class MOZ_RAII AutoDisplayContentsAncestorPusher final
     742             : {
     743             :  public:
     744             :   typedef mozilla::dom::Element Element;
     745             :   AutoDisplayContentsAncestorPusher(TreeMatchContext& aTreeMatchContext,
     746             :                                     nsPresContext*    aPresContext,
     747             :                                     nsIContent*       aParent);
     748             :   ~AutoDisplayContentsAncestorPusher();
     749         469 :   bool IsEmpty() const { return mAncestors.Length() == 0; }
     750             : private:
     751             :   TreeMatchContext& mTreeMatchContext;
     752             :   nsPresContext* const mPresContext;
     753             :   AutoTArray<mozilla::dom::Element*, 4> mAncestors;
     754             : };
     755             : 
     756             : } // namespace mozilla
     757             : 
     758             : #endif /* mozilla_GeckoRestyleManager_h */

Generated by: LCOV version 1.13