ViewTransition.h (8545B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef mozilla_dom_ViewTransition_h 6 #define mozilla_dom_ViewTransition_h 7 8 #include "mozilla/Attributes.h" 9 #include "mozilla/layers/IpcResourceUpdateQueue.h" 10 #include "nsAtomHashKeys.h" 11 #include "nsClassHashtable.h" 12 #include "nsRect.h" 13 #include "nsRefPtrHashtable.h" 14 #include "nsWrapperCache.h" 15 16 class nsIGlobalObject; 17 class nsITimer; 18 19 namespace mozilla { 20 21 class ErrorResult; 22 struct Keyframe; 23 struct PseudoStyleRequest; 24 struct StyleLockedDeclarationBlock; 25 26 namespace layers { 27 class RenderRootStateManager; 28 } 29 30 namespace wr { 31 struct ImageKey; 32 class IpcResourceUpdateQueue; 33 } // namespace wr 34 35 namespace dom { 36 37 class ViewTransitionTypeSet; 38 extern LazyLogModule gViewTransitionsLog; 39 40 #define VT_LOG(...) \ 41 MOZ_LOG(mozilla::dom::gViewTransitionsLog, mozilla::LogLevel::Debug, \ 42 (__VA_ARGS__)) 43 44 #ifdef DEBUG 45 # define VT_LOG_DEBUG(...) VT_LOG(__VA_ARGS__) 46 #else 47 # define VT_LOG_DEBUG(...) 48 #endif 49 50 class Document; 51 class Element; 52 class Promise; 53 class ViewTransitionUpdateCallback; 54 55 enum class SkipTransitionReason : uint8_t { 56 JS, 57 DocumentHidden, 58 RootRemoved, 59 ClobberedActiveTransition, 60 Timeout, 61 UpdateCallbackRejected, 62 DuplicateTransitionNameCapturingOldState, 63 DuplicateTransitionNameCapturingNewState, 64 PseudoUpdateFailure, 65 Resize, 66 PageSwap, 67 // Can happen due to various recoverable internal errors such as GPU process 68 // crashes or GPU device resets. 69 ResetRendering, 70 }; 71 72 // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-phase 73 enum class ViewTransitionPhase : uint8_t { 74 PendingCapture = 0, 75 UpdateCallbackCalled, 76 Animating, 77 Done, 78 }; 79 80 class ViewTransition final : public nsISupports, public nsWrapperCache { 81 public: 82 using Phase = ViewTransitionPhase; 83 using TypeList = nsTArray<RefPtr<nsAtom>>; 84 85 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 86 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ViewTransition) 87 88 ViewTransition(Document&, ViewTransitionUpdateCallback*, TypeList&&); 89 90 Promise* GetUpdateCallbackDone(ErrorResult&); 91 Promise* GetReady(ErrorResult&); 92 Promise* GetFinished(ErrorResult&); 93 ViewTransitionTypeSet* Types(); 94 const TypeList& GetTypeList() const { return mTypeList; } 95 TypeList& GetTypeList() { return mTypeList; } 96 97 void SkipTransition(SkipTransitionReason = SkipTransitionReason::JS); 98 MOZ_CAN_RUN_SCRIPT void PerformPendingOperations(); 99 100 // Get the snapshot containing block, which is the top-layer for rendering the 101 // view transition tree. 102 Element* GetSnapshotContainingBlock() const { 103 return mSnapshotContainingBlock; 104 } 105 // Get ::view-transition pseudo element, which is the view transition tree 106 // root. We find the pseudo element of this tree from this node. 107 Element* GetViewTransitionTreeRoot() const; 108 // Get all currently captured element frames if accessible. 109 void GetCapturedFrames(nsTArray<nsIFrame*>& aCapturedFrames) const; 110 111 Maybe<nsRect> GetOldInkOverflowRect(nsAtom* aName) const; 112 Maybe<nsRect> GetNewInkOverflowRect(nsAtom* aName) const; 113 Maybe<nsSize> GetOldBorderBoxSize(nsAtom* aName) const; 114 Maybe<nsSize> GetNewBorderBoxSize(nsAtom* aName) const; 115 Maybe<nsRect> GetOldActiveRect(nsAtom* aName) const; 116 Maybe<nsRect> GetNewActiveRect(nsAtom* aName) const; 117 // Use this to generate the old state image key for use in a stacking context. 118 // Do not use the returned image key in an image display item, use 119 // ReadOldImageKey instead. 120 const wr::ImageKey* GetOrCreateOldImageKey(nsAtom* aName, 121 layers::RenderRootStateManager*, 122 wr::IpcResourceUpdateQueue&) const; 123 // Use this to get the already-created old state image key for use in an image 124 // display item. 125 // This marks the old state image key as used which influences the how eagerly 126 // it can be deleted. 127 const wr::ImageKey* ReadOldImageKey(nsAtom* aName, 128 layers::RenderRootStateManager*, 129 wr::IpcResourceUpdateQueue&) const; 130 const wr::ImageKey* GetNewImageKey(nsAtom* aName) const; 131 const wr::ImageKey* GetImageKeyForCapturedFrame( 132 nsIFrame* aFrame, layers::RenderRootStateManager*, 133 wr::IpcResourceUpdateQueue&) const; 134 void UpdateActiveRectForCapturedFrame( 135 nsIFrame* capturedFrame, const gfx::MatrixScales& aInheritedScale, 136 nsRect& aOutCapturedRect); 137 138 Element* FindPseudo(const PseudoStyleRequest&) const; 139 140 const StyleLockedDeclarationBlock* GetDynamicRuleFor(const Element&) const; 141 142 static constexpr nsLiteralString kGroupAnimPrefix = 143 u"-ua-view-transition-group-anim-"_ns; 144 145 [[nodiscard]] bool GetGroupKeyframes(nsAtom* aAnimationName, 146 const StyleComputedTimingFunction&, 147 nsTArray<Keyframe>&); 148 149 bool MatchClassList(nsAtom*, const nsTArray<StyleAtom>&) const; 150 151 nsIGlobalObject* GetParentObject() const; 152 JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override; 153 154 struct CapturedElement; 155 156 static nsRect SnapshotContainingBlockRect(nsPresContext*); 157 static nsRect CapturedInkOverflowRectForFrame(nsIFrame*, bool aIsRoot); 158 MOZ_CAN_RUN_SCRIPT void CallUpdateCallback(ErrorResult&); 159 160 private: 161 MOZ_CAN_RUN_SCRIPT void MaybeScheduleUpdateCallback(); 162 void Activate(); 163 164 void ClearActiveTransition(bool aIsDocumentHidden); 165 void Timeout(); 166 MOZ_CAN_RUN_SCRIPT void Setup(); 167 [[nodiscard]] MOZ_CAN_RUN_SCRIPT Maybe<SkipTransitionReason> 168 CaptureOldState(); 169 [[nodiscard]] Maybe<SkipTransitionReason> CaptureNewState(); 170 void SetupTransitionPseudoElements(); 171 [[nodiscard]] bool UpdatePseudoElementStyles(bool aNeedsInvalidation); 172 void ClearNamedElements(); 173 void HandleFrame(); 174 bool CheckForActiveAnimations() const; 175 void SkipTransition(SkipTransitionReason, JS::Handle<JS::Value>); 176 void ClearTimeoutTimer(); 177 178 nsRect SnapshotContainingBlockRect() const; 179 180 Maybe<uint64_t> GetElementIdentifier(Element* aElement) const; 181 uint64_t EnsureElementIdentifier(Element* aElement); 182 183 already_AddRefed<nsAtom> DocumentScopedTransitionNameFor(nsIFrame* aFrame); 184 185 ~ViewTransition(); 186 187 // Stored for the whole lifetime of the object (until CC). 188 RefPtr<Document> mDocument; 189 RefPtr<ViewTransitionUpdateCallback> mUpdateCallback; 190 191 // https://drafts.csswg.org/css-view-transitions/#viewtransition-named-elements 192 using NamedElements = nsClassHashtable<nsAtomHashKey, CapturedElement>; 193 NamedElements mNamedElements; 194 // mNamedElements is an unordered map, we need to keep the tree order. This 195 // also keeps the strong reference to the view-transition-name which may be 196 // auto-generated for this view transition. 197 AutoTArray<RefPtr<nsAtom>, 8> mNames; 198 199 using OldCaptureFramesArray = 200 AutoTArray<std::pair<nsIFrame*, RefPtr<nsAtom>>, 32>; 201 // Short lived array pointer used to mark old captures for DL building. 202 OldCaptureFramesArray* mOldCaptureElements = nullptr; 203 204 // The element identifier for the elements which need the auto-generated 205 // view-transition-name. The lifetime of those element identifiers is 206 // element’s node document’s active view transition. 207 // Note: Use a non-owning element pointer because we never dereference it. 208 // It is just a key to map an id. The size of this hashmap is fixed after we 209 // capture the old state and new state, 210 using ElementIdentifiers = nsTHashMap<Element*, uint64_t>; 211 ElementIdentifiers mElementIdentifiers; 212 213 // https://drafts.csswg.org/css-view-transitions/#viewtransition-initial-snapshot-containing-block-size 214 nsSize mInitialSnapshotContainingBlockSize; 215 216 // Allocated lazily, but same object once allocated (again until CC). 217 RefPtr<Promise> mUpdateCallbackDonePromise; 218 RefPtr<Promise> mReadyPromise; 219 RefPtr<Promise> mFinishedPromise; 220 221 TypeList mTypeList; 222 RefPtr<ViewTransitionTypeSet> mTypes; 223 224 static void TimeoutCallback(nsITimer*, void*); 225 RefPtr<nsITimer> mTimeoutTimer; 226 227 Phase mPhase = Phase::PendingCapture; 228 // The wrapper of the pseudo-elements tree, to make sure it is always 229 // out-of-flow. This is the top-layer for rendering the view transition tree. 230 // So in general, its child (and only one) is the transition root 231 // pseudo-element. 232 RefPtr<Element> mSnapshotContainingBlock; 233 }; 234 235 } // namespace dom 236 } // namespace mozilla 237 238 #endif