forked from mirrors/gecko-dev
		
	This will make possible to animate custom properties on Gecko side. For now, the animation code keeps only dealing with nsCSSPropertyID, so behavior is unchanged. Co-authored-by: Frederic Wang <fred.wang@free.fr> Depends on D190816 Differential Revision: https://phabricator.services.mozilla.com/D191059
		
			
				
	
	
		
			143 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* 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/. */
 | 
						|
 | 
						|
#include "mozilla/AnimationEventDispatcher.h"
 | 
						|
 | 
						|
#include "mozilla/EventDispatcher.h"
 | 
						|
#include "nsPresContext.h"
 | 
						|
#include "nsRefreshDriver.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
 | 
						|
NS_IMPL_CYCLE_COLLECTION_CLASS(AnimationEventDispatcher)
 | 
						|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AnimationEventDispatcher)
 | 
						|
  tmp->ClearEventQueue();
 | 
						|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 | 
						|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationEventDispatcher)
 | 
						|
  for (auto& info : tmp->mPendingEvents) {
 | 
						|
    if (OwningAnimationTarget* target = info.GetOwningAnimationTarget()) {
 | 
						|
      ImplCycleCollectionTraverse(
 | 
						|
          cb, target->mElement,
 | 
						|
          "mozilla::AnimationEventDispatcher.mPendingEvents.mTarget");
 | 
						|
    } else {
 | 
						|
      ImplCycleCollectionTraverse(
 | 
						|
          cb, info.mData.as<AnimationEventInfo::WebAnimationData>().mEvent,
 | 
						|
          "mozilla::AnimationEventDispatcher.mPendingEvents.mEvent");
 | 
						|
    }
 | 
						|
    ImplCycleCollectionTraverse(
 | 
						|
        cb, info.mAnimation,
 | 
						|
        "mozilla::AnimationEventDispatcher.mPendingEvents.mAnimation");
 | 
						|
  }
 | 
						|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 | 
						|
 | 
						|
void AnimationEventDispatcher::Disconnect() {
 | 
						|
  if (mIsObserving) {
 | 
						|
    MOZ_ASSERT(mPresContext && mPresContext->RefreshDriver(),
 | 
						|
               "The pres context and the refresh driver should be still "
 | 
						|
               "alive if we haven't disassociated from the refresh driver");
 | 
						|
    mPresContext->RefreshDriver()->CancelPendingAnimationEvents(this);
 | 
						|
    mIsObserving = false;
 | 
						|
  }
 | 
						|
  mPresContext = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
void AnimationEventDispatcher::QueueEvent(AnimationEventInfo&& aEvent) {
 | 
						|
  mPendingEvents.AppendElement(std::move(aEvent));
 | 
						|
  mIsSorted = false;
 | 
						|
  ScheduleDispatch();
 | 
						|
}
 | 
						|
 | 
						|
void AnimationEventDispatcher::QueueEvents(
 | 
						|
    nsTArray<AnimationEventInfo>&& aEvents) {
 | 
						|
  mPendingEvents.AppendElements(std::move(aEvents));
 | 
						|
  mIsSorted = false;
 | 
						|
  ScheduleDispatch();
 | 
						|
}
 | 
						|
 | 
						|
void AnimationEventDispatcher::ScheduleDispatch() {
 | 
						|
  MOZ_ASSERT(mPresContext, "The pres context should be valid");
 | 
						|
  if (!mIsObserving) {
 | 
						|
    mPresContext->RefreshDriver()->ScheduleAnimationEventDispatch(this);
 | 
						|
    mIsObserving = true;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void AnimationEventInfo::MaybeAddMarker() const {
 | 
						|
  if (mData.is<CssAnimationData>()) {
 | 
						|
    const auto& data = mData.as<CssAnimationData>();
 | 
						|
    const EventMessage message = data.mMessage;
 | 
						|
    if (message != eAnimationCancel && message != eAnimationEnd &&
 | 
						|
        message != eAnimationIteration) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    nsAutoCString name;
 | 
						|
    data.mAnimationName->ToUTF8String(name);
 | 
						|
    const TimeStamp startTime = [&] {
 | 
						|
      if (message == eAnimationIteration) {
 | 
						|
        if (auto* effect = mAnimation->GetEffect()) {
 | 
						|
          return mScheduledEventTimeStamp -
 | 
						|
                 TimeDuration(effect->GetComputedTiming().mDuration);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      return mScheduledEventTimeStamp -
 | 
						|
             TimeDuration::FromSeconds(data.mElapsedTime);
 | 
						|
    }();
 | 
						|
 | 
						|
    nsCSSPropertyIDSet propertySet;
 | 
						|
    nsAutoString target;
 | 
						|
    if (dom::AnimationEffect* effect = mAnimation->GetEffect()) {
 | 
						|
      if (dom::KeyframeEffect* keyFrameEffect = effect->AsKeyframeEffect()) {
 | 
						|
        keyFrameEffect->GetTarget()->Describe(target, true);
 | 
						|
        for (const AnimationProperty& property : keyFrameEffect->Properties()) {
 | 
						|
          propertySet.AddProperty(property.mProperty.mID);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    PROFILER_MARKER(
 | 
						|
        message == eAnimationIteration
 | 
						|
            ? ProfilerString8View("CSS animation iteration")
 | 
						|
            : ProfilerString8View("CSS animation"),
 | 
						|
        DOM,
 | 
						|
        MarkerOptions(
 | 
						|
            MarkerTiming::Interval(startTime, mScheduledEventTimeStamp),
 | 
						|
            mAnimation->GetOwner()
 | 
						|
                ? MarkerInnerWindowId(mAnimation->GetOwner()->WindowID())
 | 
						|
                : MarkerInnerWindowId::NoId()),
 | 
						|
        CSSAnimationMarker, name, NS_ConvertUTF16toUTF8(target), propertySet);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mData.is<CssTransitionData>()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const auto& data = mData.as<CssTransitionData>();
 | 
						|
  const EventMessage message = data.mMessage;
 | 
						|
  if (message != eTransitionEnd && message != eTransitionCancel) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  nsAutoString target;
 | 
						|
  if (dom::AnimationEffect* effect = mAnimation->GetEffect()) {
 | 
						|
    if (dom::KeyframeEffect* keyFrameEffect = effect->AsKeyframeEffect()) {
 | 
						|
      keyFrameEffect->GetTarget()->Describe(target, true);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  PROFILER_MARKER(
 | 
						|
      "CSS transition", DOM,
 | 
						|
      MarkerOptions(
 | 
						|
          MarkerTiming::Interval(
 | 
						|
              mScheduledEventTimeStamp -
 | 
						|
                  TimeDuration::FromSeconds(data.mElapsedTime),
 | 
						|
              mScheduledEventTimeStamp),
 | 
						|
          mAnimation->GetOwner()
 | 
						|
              ? MarkerInnerWindowId(mAnimation->GetOwner()->WindowID())
 | 
						|
              : MarkerInnerWindowId::NoId()),
 | 
						|
      CSSTransitionMarker, NS_ConvertUTF16toUTF8(target), data.mProperty.mID,
 | 
						|
      message == eTransitionCancel);
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace mozilla
 |