Bug 1945643 - Update to mozilla-nimbus-schemas 2025.1.1 r=chumphreys
[gecko.git] / dom / animation / AnimationEventDispatcher.cpp
blob1e61989c8e25b4f6cfc514a5456a293cef993944
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/. */
7 #include "mozilla/AnimationEventDispatcher.h"
9 #include "mozilla/EventDispatcher.h"
10 #include "nsPresContext.h"
11 #include "nsRefreshDriver.h"
12 #include "nsCSSProps.h"
13 #include "mozilla/dom/AnimationEffect.h"
14 #include "nsGlobalWindowInner.h"
16 using namespace mozilla;
18 namespace geckoprofiler::markers {
20 struct CSSAnimationMarker {
21 static constexpr Span<const char> MarkerTypeName() {
22 return MakeStringSpan("CSSAnimation");
24 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
25 const nsCString& aName,
26 const nsCString& aTarget,
27 const nsCString& aProperties,
28 const nsCString& aOnCompositor) {
29 aWriter.StringProperty("Name", aName);
30 aWriter.StringProperty("Target", aTarget);
31 aWriter.StringProperty("properties", aProperties);
32 aWriter.StringProperty("oncompositor", aOnCompositor);
34 static MarkerSchema MarkerTypeDisplay() {
35 using MS = MarkerSchema;
36 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
37 schema.AddKeyFormatSearchable("Name", MS::Format::String,
38 MS::Searchable::Searchable);
39 schema.AddKeyLabelFormat("properties", "Animated Properties",
40 MS::Format::String);
41 schema.AddKeyLabelFormat("oncompositor", "Can Run on Compositor",
42 MS::Format::String);
43 schema.AddKeyFormat("Target", MS::Format::String);
44 schema.SetChartLabel("{marker.data.Name}");
45 schema.SetTableLabel(
46 "{marker.name} - {marker.data.Name}: {marker.data.properties}");
47 return schema;
51 struct CSSTransitionMarker {
52 static constexpr Span<const char> MarkerTypeName() {
53 return MakeStringSpan("CSSTransition");
55 static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
56 const nsCString& aTarget,
57 const nsCString& aProperty,
58 bool aOnCompositor, bool aCanceled) {
59 aWriter.StringProperty("Target", aTarget);
60 aWriter.StringProperty("property", aProperty);
61 aWriter.BoolProperty("oncompositor", aOnCompositor);
62 if (aCanceled) {
63 aWriter.BoolProperty("Canceled", aCanceled);
66 static MarkerSchema MarkerTypeDisplay() {
67 using MS = MarkerSchema;
68 MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
69 schema.AddKeyLabelFormat("property", "Animated Property",
70 MS::Format::String);
71 schema.AddKeyLabelFormat("oncompositor", "Can Run on Compositor",
72 MS::Format::String);
73 schema.AddKeyFormat("Canceled", MS::Format::String);
74 schema.AddKeyFormat("Target", MS::Format::String);
75 schema.SetChartLabel("{marker.data.property}");
76 schema.SetTableLabel("{marker.name} - {marker.data.property}");
77 return schema;
81 } // namespace geckoprofiler::markers
83 namespace mozilla {
85 NS_IMPL_CYCLE_COLLECTION_CLASS(AnimationEventDispatcher)
86 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AnimationEventDispatcher)
87 tmp->ClearEventQueue();
88 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
89 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationEventDispatcher)
90 for (auto& info : tmp->mPendingEvents) {
91 if (OwningAnimationTarget* target = info.GetOwningAnimationTarget()) {
92 ImplCycleCollectionTraverse(
93 cb, target->mElement,
94 "mozilla::AnimationEventDispatcher.mPendingEvents.mTarget");
96 ImplCycleCollectionTraverse(
97 cb, info.mAnimation,
98 "mozilla::AnimationEventDispatcher.mPendingEvents.mAnimation");
100 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
102 void AnimationEventDispatcher::Disconnect() {
103 if (mIsObserving) {
104 MOZ_ASSERT(mPresContext && mPresContext->RefreshDriver(),
105 "The pres context and the refresh driver should be still "
106 "alive if we haven't disassociated from the refresh driver");
107 mPresContext->RefreshDriver()->CancelPendingAnimationEvents(this);
108 mIsObserving = false;
110 mPresContext = nullptr;
113 void AnimationEventDispatcher::QueueEvent(AnimationEventInfo&& aEvent) {
114 mPendingEvents.AppendElement(std::move(aEvent));
115 mIsSorted = false;
116 ScheduleDispatch();
119 void AnimationEventDispatcher::QueueEvents(
120 nsTArray<AnimationEventInfo>&& aEvents) {
121 mPendingEvents.AppendElements(std::move(aEvents));
122 mIsSorted = false;
123 ScheduleDispatch();
126 void AnimationEventDispatcher::ScheduleDispatch() {
127 MOZ_ASSERT(mPresContext, "The pres context should be valid");
128 if (!mIsObserving) {
129 mPresContext->RefreshDriver()->ScheduleAnimationEventDispatch(this);
130 mIsObserving = true;
134 void AnimationEventInfo::MaybeAddMarker() const {
135 if (mData.is<CssAnimationData>()) {
136 const auto& data = mData.as<CssAnimationData>();
137 const EventMessage message = data.mMessage;
138 if (message != eAnimationCancel && message != eAnimationEnd &&
139 message != eAnimationIteration) {
140 return;
142 nsAutoCString name;
143 data.mAnimationName->ToUTF8String(name);
144 const TimeStamp startTime = [&] {
145 if (message == eAnimationIteration) {
146 if (auto* effect = mAnimation->GetEffect()) {
147 return mScheduledEventTimeStamp -
148 TimeDuration(effect->GetComputedTiming().mDuration);
151 return mScheduledEventTimeStamp -
152 TimeDuration::FromSeconds(data.mElapsedTime);
153 }();
155 AnimatedPropertyIDSet propertySet;
156 nsAutoString target;
157 if (dom::AnimationEffect* effect = mAnimation->GetEffect()) {
158 if (dom::KeyframeEffect* keyFrameEffect = effect->AsKeyframeEffect()) {
159 keyFrameEffect->GetTarget()->Describe(target, true);
160 for (const AnimationProperty& property : keyFrameEffect->Properties()) {
161 propertySet.AddProperty(property.mProperty);
165 nsAutoCString properties;
166 nsAutoCString oncompositor;
167 for (const AnimatedPropertyID& property : propertySet) {
168 if (!properties.IsEmpty()) {
169 properties.AppendLiteral(", ");
170 oncompositor.AppendLiteral(", ");
172 nsAutoCString prop;
173 property.ToString(prop);
174 properties.Append(prop);
175 oncompositor.Append(
176 !property.IsCustom() &&
177 nsCSSProps::PropHasFlags(property.mID,
178 CSSPropFlags::CanAnimateOnCompositor)
179 ? "true"
180 : "false");
182 PROFILER_MARKER(
183 message == eAnimationIteration
184 ? ProfilerString8View("CSS animation iteration")
185 : ProfilerString8View("CSS animation"),
186 DOM,
187 MarkerOptions(
188 MarkerTiming::Interval(startTime, mScheduledEventTimeStamp),
189 mAnimation->GetOwnerWindow()
190 ? MarkerInnerWindowId(mAnimation->GetOwnerWindow()->WindowID())
191 : MarkerInnerWindowId::NoId()),
192 CSSAnimationMarker, name, NS_ConvertUTF16toUTF8(target), properties,
193 oncompositor);
194 return;
197 if (!mData.is<CssTransitionData>()) {
198 return;
201 const auto& data = mData.as<CssTransitionData>();
202 const EventMessage message = data.mMessage;
203 if (message != eTransitionEnd && message != eTransitionCancel) {
204 return;
207 nsAutoString target;
208 if (dom::AnimationEffect* effect = mAnimation->GetEffect()) {
209 if (dom::KeyframeEffect* keyFrameEffect = effect->AsKeyframeEffect()) {
210 keyFrameEffect->GetTarget()->Describe(target, true);
213 nsAutoCString property;
214 data.mProperty.ToString(property);
216 // FIXME: This doesn't _really_ reflect whether the animation is actually run
217 // in the compositor. The effect has that information and we should use it
218 // probably.
219 const bool onCompositor =
220 !data.mProperty.IsCustom() &&
221 nsCSSProps::PropHasFlags(data.mProperty.mID,
222 CSSPropFlags::CanAnimateOnCompositor);
223 PROFILER_MARKER(
224 "CSS transition", DOM,
225 MarkerOptions(
226 MarkerTiming::Interval(
227 mScheduledEventTimeStamp -
228 TimeDuration::FromSeconds(data.mElapsedTime),
229 mScheduledEventTimeStamp),
230 mAnimation->GetOwnerWindow()
231 ? MarkerInnerWindowId(mAnimation->GetOwnerWindow()->WindowID())
232 : MarkerInnerWindowId::NoId()),
233 CSSTransitionMarker, NS_ConvertUTF16toUTF8(target), property,
234 onCompositor, message == eTransitionCancel);
237 } // namespace mozilla