1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_RestyleManagerHandle_h 8 #define mozilla_RestyleManagerHandle_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/EventStates.h" 12 #include "mozilla/HandleRefPtr.h" 13 #include "mozilla/RefCountType.h" 14 #include "mozilla/StyleBackendType.h" 15 #include "nsChangeHint.h" 16 17 namespace mozilla { 18 class RestyleManager; 19 class ServoRestyleManager; 20 namespace dom { 21 class Element; 22 } // namespace dom 23 } // namespace mozilla 24 class nsAttrValue; 25 class nsIAtom; 26 class nsIContent; 27 class nsIFrame; 28 class nsStyleChangeList; 29 30 namespace mozilla { 31 32 #define SERVO_BIT 0x1 33 34 /** 35 * Smart pointer class that can hold a pointer to either a RestyleManager 36 * or a ServoRestyleManager. 37 */ 38 class RestyleManagerHandle 39 { 40 public: 41 typedef HandleRefPtr<RestyleManagerHandle> RefPtr; 42 43 // We define this Ptr class with a RestyleManager API that forwards on to the 44 // wrapped pointer, rather than putting these methods on RestyleManagerHandle 45 // itself, so that we can have RestyleManagerHandle behave like a smart 46 // pointer and be dereferenced with operator->. 47 class Ptr 48 { 49 public: 50 friend class ::mozilla::RestyleManagerHandle; 51 IsGecko()52 bool IsGecko() const { return !IsServo(); } IsServo()53 bool IsServo() const 54 { 55 MOZ_ASSERT(mValue, "RestyleManagerHandle null pointer dereference"); 56 #ifdef MOZ_STYLO 57 return mValue & SERVO_BIT; 58 #else 59 return false; 60 #endif 61 } 62 BackendType()63 StyleBackendType BackendType() const 64 { 65 return IsGecko() ? StyleBackendType::Gecko : 66 StyleBackendType::Servo; 67 } 68 AsGecko()69 RestyleManager* AsGecko() 70 { 71 MOZ_ASSERT(IsGecko()); 72 return reinterpret_cast<RestyleManager*>(mValue); 73 } 74 AsServo()75 ServoRestyleManager* AsServo() 76 { 77 MOZ_ASSERT(IsServo()); 78 return reinterpret_cast<ServoRestyleManager*>(mValue & ~SERVO_BIT); 79 } 80 GetAsGecko()81 RestyleManager* GetAsGecko() { return IsGecko() ? AsGecko() : nullptr; } GetAsServo()82 ServoRestyleManager* GetAsServo() { return IsServo() ? AsServo() : nullptr; } 83 AsGecko()84 const RestyleManager* AsGecko() const 85 { 86 return const_cast<Ptr*>(this)->AsGecko(); 87 } 88 AsServo()89 const ServoRestyleManager* AsServo() const 90 { 91 MOZ_ASSERT(IsServo()); 92 return const_cast<Ptr*>(this)->AsServo(); 93 } 94 GetAsGecko()95 const RestyleManager* GetAsGecko() const { return IsGecko() ? AsGecko() : nullptr; } GetAsServo()96 const ServoRestyleManager* GetAsServo() const { return IsServo() ? AsServo() : nullptr; } 97 98 // These inline methods are defined in RestyleManagerHandleInlines.h. 99 inline MozExternalRefCountType AddRef(); 100 inline MozExternalRefCountType Release(); 101 102 // Restyle manager interface. These inline methods are defined in 103 // RestyleManagerHandleInlines.h and just forward to the underlying 104 // RestyleManager or ServoRestyleManager. See corresponding comments in 105 // RestyleManager.h for descriptions of these methods. 106 107 inline void Disconnect(); 108 inline void PostRestyleEvent(dom::Element* aElement, 109 nsRestyleHint aRestyleHint, 110 nsChangeHint aMinChangeHint); 111 inline void PostRestyleEventForLazyConstruction(); 112 inline void RebuildAllStyleData(nsChangeHint aExtraHint, 113 nsRestyleHint aRestyleHint); 114 inline void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint, 115 nsRestyleHint aRestyleHint); 116 inline void ProcessPendingRestyles(); 117 inline void ContentInserted(nsINode* aContainer, 118 nsIContent* aChild); 119 inline void ContentAppended(nsIContent* aContainer, 120 nsIContent* aFirstNewContent); 121 inline void ContentRemoved(nsINode* aContainer, 122 nsIContent* aOldChild, 123 nsIContent* aFollowingSibling); 124 inline void RestyleForInsertOrChange(nsINode* aContainer, 125 nsIContent* aChild); 126 inline void RestyleForAppend(nsIContent* aContainer, 127 nsIContent* aFirstNewContent); 128 inline nsresult ContentStateChanged(nsIContent* aContent, 129 EventStates aStateMask); 130 inline void AttributeWillChange(dom::Element* aElement, 131 int32_t aNameSpaceID, 132 nsIAtom* aAttribute, 133 int32_t aModType, 134 const nsAttrValue* aNewValue); 135 inline void AttributeChanged(dom::Element* aElement, 136 int32_t aNameSpaceID, 137 nsIAtom* aAttribute, 138 int32_t aModType, 139 const nsAttrValue* aOldValue); 140 inline nsresult ReparentStyleContext(nsIFrame* aFrame); 141 inline bool HasPendingRestyles(); 142 inline uint64_t GetRestyleGeneration() const; 143 inline uint32_t GetHoverGeneration() const; 144 inline void SetObservingRefreshDriver(bool aObserving); 145 inline nsresult ProcessRestyledFrames(nsStyleChangeList& aChangeList); 146 inline void FlushOverflowChangedTracker(); 147 inline void NotifyDestroyingFrame(nsIFrame* aFrame); 148 149 private: 150 // Stores a pointer to an RestyleManager or a ServoRestyleManager. The least 151 // significant bit is 0 for the former, 1 for the latter. This is 152 // valid as the least significant bit will never be used for a pointer 153 // value on platforms we care about. 154 uintptr_t mValue; 155 }; 156 decltype(nullptr)157 MOZ_IMPLICIT RestyleManagerHandle(decltype(nullptr) = nullptr) 158 { 159 mPtr.mValue = 0; 160 } RestyleManagerHandle(const RestyleManagerHandle & aOth)161 RestyleManagerHandle(const RestyleManagerHandle& aOth) 162 { 163 mPtr.mValue = aOth.mPtr.mValue; 164 } RestyleManagerHandle(RestyleManager * aManager)165 MOZ_IMPLICIT RestyleManagerHandle(RestyleManager* aManager) 166 { 167 *this = aManager; 168 } RestyleManagerHandle(ServoRestyleManager * aManager)169 MOZ_IMPLICIT RestyleManagerHandle(ServoRestyleManager* aManager) 170 { 171 *this = aManager; 172 } 173 decltype(nullptr)174 RestyleManagerHandle& operator=(decltype(nullptr)) 175 { 176 mPtr.mValue = 0; 177 return *this; 178 } 179 180 RestyleManagerHandle& operator=(RestyleManager* aManager) 181 { 182 MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aManager) & SERVO_BIT), 183 "least significant bit shouldn't be set; we use it for state"); 184 mPtr.mValue = reinterpret_cast<uintptr_t>(aManager); 185 return *this; 186 } 187 188 RestyleManagerHandle& operator=(ServoRestyleManager* aManager) 189 { 190 #ifdef MOZ_STYLO 191 MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aManager) & SERVO_BIT), 192 "least significant bit shouldn't be set; we use it for state"); 193 mPtr.mValue = 194 aManager ? (reinterpret_cast<uintptr_t>(aManager) | SERVO_BIT) : 0; 195 return *this; 196 #else 197 MOZ_CRASH("should not have a ServoRestyleManager object when MOZ_STYLO is " 198 "disabled"); 199 #endif 200 } 201 202 // Make RestyleManagerHandle usable in boolean contexts. 203 explicit operator bool() const { return !!mPtr.mValue; } 204 bool operator!() const { return !mPtr.mValue; } 205 206 // Make RestyleManagerHandle behave like a smart pointer. 207 Ptr* operator->() { return &mPtr; } 208 const Ptr* operator->() const { return &mPtr; } 209 210 private: 211 Ptr mPtr; 212 }; 213 214 #undef SERVO_BIT 215 216 } // namespace mozilla 217 218 #endif // mozilla_RestyleManagerHandle_h 219