Exemple #1
0
void
Animation::Tick()
{
  // Finish pending if we have a pending ready time, but only if we also
  // have an active timeline.
  if (mPendingState != PendingState::NotPending &&
      !mPendingReadyTime.IsNull() &&
      mTimeline &&
      !mTimeline->GetCurrentTime().IsNull()) {
    // Even though mPendingReadyTime is initialized using TimeStamp::Now()
    // during the *previous* tick of the refresh driver, it can still be
    // ahead of the *current* timeline time when we are using the
    // vsync timer so we need to clamp it to the timeline time.
    mPendingReadyTime.SetValue(std::min(mTimeline->GetCurrentTime().Value(),
                                        mPendingReadyTime.Value()));
    FinishPendingAt(mPendingReadyTime.Value());
    mPendingReadyTime.SetNull();
  }

  if (IsPossiblyOrphanedPendingAnimation()) {
    MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
               "Orphaned pending animtaions should have an active timeline");
    FinishPendingAt(mTimeline->GetCurrentTime().Value());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);

  // Update layers if we are newly finished.
  if (mEffect &&
      !mEffect->Properties().IsEmpty() &&
      !mFinishedAtLastComposeStyle &&
      PlayState() == AnimationPlayState::Finished) {
    PostUpdate();
  }
}
Exemple #2
0
void
Animation::ResumeAt(const TimeDuration& aReadyTime)
{
  // This method is only expected to be called for an animation that is
  // waiting to play. We can easily adapt it to handle other states
  // but it's currently not necessary.
  MOZ_ASSERT(mPendingState == PendingState::PlayPending,
             "Expected to resume a play-pending animation");
  MOZ_ASSERT(mHoldTime.IsNull() != mStartTime.IsNull(),
             "An animation in the play-pending state should have either a"
             " resolved hold time or resolved start time (but not both)");

  // If we aborted a pending pause operation we will already have a start time
  // we should use. In all other cases, we resolve it from the ready time.
  if (mStartTime.IsNull()) {
    if (mPlaybackRate != 0) {
      mStartTime.SetValue(aReadyTime -
                          (mHoldTime.Value().MultDouble(1 / mPlaybackRate)));
      mHoldTime.SetNull();
    } else {
      mStartTime.SetValue(aReadyTime);
    }
  }
  mPendingState = PendingState::NotPending;

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);

  if (mReady) {
    mReady->MaybeResolve(this);
  }
}
Exemple #3
0
// https://w3c.github.io/web-animations/#set-the-current-time
void
Animation::SetCurrentTime(const TimeDuration& aSeekTime)
{
  // Return early if the current time has not changed. However, if we
  // are pause-pending, then setting the current time to any value
  // including the current value has the effect of aborting the
  // pause so we should not return early in that case.
  if (mPendingState != PendingState::PausePending &&
      Nullable<TimeDuration>(aSeekTime) == GetCurrentTime()) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  SilentlySetCurrentTime(aSeekTime);

  if (mPendingState == PendingState::PausePending) {
    // Finish the pause operation
    mHoldTime.SetValue(aSeekTime);
    mStartTime.SetNull();

    if (mReady) {
      mReady->MaybeResolve(this);
    }
    CancelPendingTasks();
  }

  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemple #4
0
// https://w3c.github.io/web-animations/#cancel-an-animation
void
Animation::CancelNoUpdate()
{
  if (mPendingState != PendingState::NotPending) {
    CancelPendingTasks();
    if (mReady) {
      mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
    }
  }

  if (mFinished) {
    mFinished->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
  }
  ResetFinishedPromise();

  DispatchPlaybackEvent(NS_LITERAL_STRING("cancel"));

  mHoldTime.SetNull();
  mStartTime.SetNull();

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);

  if (mTimeline) {
    mTimeline->RemoveAnimation(this);
  }
}
Exemple #5
0
// https://w3c.github.io/web-animations/#set-the-animation-playback-rate
void
Animation::SetPlaybackRate(double aPlaybackRate)
{
  if (aPlaybackRate == mPlaybackRate) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  Nullable<TimeDuration> previousTime = GetCurrentTime();
  mPlaybackRate = aPlaybackRate;
  if (!previousTime.IsNull()) {
    SetCurrentTime(previousTime.Value());
  }

  // In the case where GetCurrentTime() returns the same result before and
  // after updating mPlaybackRate, SetCurrentTime will return early since,
  // as far as it can tell, nothing has changed.
  // As a result, we need to perform the following updates here:
  // - update timing (since, if the sign of the playback rate has changed, our
  //   finished state may have changed),
  // - dispatch a change notification for the changed playback rate, and
  // - update the playback rate on animations on layers.
  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemple #6
0
void
Animation::Tick()
{
  // Since we are not guaranteed to get only one call per refresh driver tick,
  // it's possible that mPendingReadyTime is set to a time in the future.
  // In that case, we should wait until the next refresh driver tick before
  // resuming.
  if (mPendingState != PendingState::NotPending &&
      !mPendingReadyTime.IsNull() &&
      mTimeline &&
      !mTimeline->GetCurrentTime().IsNull() &&
      mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) {
    FinishPendingAt(mPendingReadyTime.Value());
    mPendingReadyTime.SetNull();
  }

  if (IsPossiblyOrphanedPendingAnimation()) {
    MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
               "Orphaned pending animtaions should have an active timeline");
    FinishPendingAt(mTimeline->GetCurrentTime().Value());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);

  // FIXME: Detect the no-change case and don't request a restyle at all
  // FIXME: Detect changes to IsPlaying() state and request RestyleType::Layer
  //        so that layers get updated immediately
  AnimationCollection* collection = GetCollection();
  if (collection) {
    collection->RequestRestyle(CanThrottle() ?
      AnimationCollection::RestyleType::Throttled :
      AnimationCollection::RestyleType::Standard);
  }
}
Exemple #7
0
void
Animation::NotifyEffectTimingUpdated()
{
  MOZ_ASSERT(mEffect,
             "We should only update timing effect when we have a target "
             "effect");
  UpdateTiming(Animation::SeekFlag::NoSeek,
               Animation::SyncNotifyFlag::Async);
}
Exemple #8
0
// https://w3c.github.io/web-animations/#finish-an-animation
void
Animation::Finish(ErrorResult& aRv)
{
  if (mPlaybackRate == 0 ||
      (mPlaybackRate > 0 && EffectEnd() == TimeDuration::Forever())) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  // Seek to the end
  TimeDuration limit =
    mPlaybackRate > 0 ? TimeDuration(EffectEnd()) : TimeDuration(0);
  bool didChange = GetCurrentTime() != Nullable<TimeDuration>(limit);
  SilentlySetCurrentTime(limit);

  // If we are paused or play-pending we need to fill in the start time in
  // order to transition to the finished state.
  //
  // We only do this, however, if we have an active timeline. If we have an
  // inactive timeline we can't transition into the finished state just like
  // we can't transition to the running state (this finished state is really
  // a substate of the running state).
  if (mStartTime.IsNull() &&
      mTimeline &&
      !mTimeline->GetCurrentTime().IsNull()) {
    mStartTime.SetValue(mTimeline->GetCurrentTime().Value() -
                        limit.MultDouble(1.0 / mPlaybackRate));
    didChange = true;
  }

  // If we just resolved the start time for a pause or play-pending
  // animation, we need to clear the task. We don't do this as a branch of
  // the above however since we can have a play-pending animation with a
  // resolved start time if we aborted a pause operation.
  if (!mStartTime.IsNull() &&
      (mPendingState == PendingState::PlayPending ||
       mPendingState == PendingState::PausePending)) {
    if (mPendingState == PendingState::PausePending) {
      mHoldTime.SetNull();
    }
    CancelPendingTasks();
    didChange = true;
    if (mReady) {
      mReady->MaybeResolve(this);
    }
  }
  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Sync);
  if (didChange && IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemple #9
0
// https://w3c.github.io/web-animations/#pause-an-animation
void
Animation::DoPause(ErrorResult& aRv)
{
  if (IsPausedOrPausing()) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  // If we are transitioning from idle, fill in the current time
  if (GetCurrentTime().IsNull()) {
    if (mPlaybackRate >= 0.0) {
      mHoldTime.SetValue(TimeDuration(0));
    } else {
      if (EffectEnd() == TimeDuration::Forever()) {
        aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
        return;
      }
      mHoldTime.SetValue(TimeDuration(EffectEnd()));
    }
  }

  bool reuseReadyPromise = false;
  if (mPendingState == PendingState::PlayPending) {
    CancelPendingTasks();
    reuseReadyPromise = true;
  }

  if (!reuseReadyPromise) {
    // Clear ready promise. We'll create a new one lazily.
    mReady = nullptr;
  }

  mPendingState = PendingState::PausePending;

  nsIDocument* doc = GetRenderedDocument();
  if (doc) {
    PendingAnimationTracker* tracker =
      doc->GetOrCreatePendingAnimationTracker();
    tracker->AddPausePending(*this);
  } else {
    TriggerOnNextTick(Nullable<TimeDuration>());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
}
Exemple #10
0
// http://w3c.github.io/web-animations/#pause-an-animation
void
Animation::DoPause(ErrorResult& aRv)
{
  if (IsPausedOrPausing()) {
    return;
  }

  // If we are transitioning from idle, fill in the current time
  if (GetCurrentTime().IsNull()) {
    if (mPlaybackRate >= 0.0) {
      mHoldTime.SetValue(TimeDuration(0));
    } else {
      if (EffectEnd() == TimeDuration::Forever()) {
        aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
        return;
      }
      mHoldTime.SetValue(TimeDuration(EffectEnd()));
    }
  }

  bool reuseReadyPromise = false;
  if (mPendingState == PendingState::PlayPending) {
    CancelPendingTasks();
    reuseReadyPromise = true;
  }

  // Mark this as no longer running on the compositor so that next time
  // we update animations we won't throttle them and will have a chance
  // to remove the animation from any layer it might be on.
  mIsRunningOnCompositor = false;

  if (!reuseReadyPromise) {
    // Clear ready promise. We'll create a new one lazily.
    mReady = nullptr;
  }

  mPendingState = PendingState::PausePending;

  nsIDocument* doc = GetRenderedDocument();
  if (doc) {
    PendingAnimationTracker* tracker =
      doc->GetOrCreatePendingAnimationTracker();
    tracker->AddPausePending(*this);
  } else {
    TriggerOnNextTick(Nullable<TimeDuration>());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
}
Exemple #11
0
void
Animation::SetEffect(KeyframeEffectReadOnly* aEffect)
{
  RefPtr<Animation> kungFuDeathGrip(this);

  if (mEffect == aEffect) {
    return;
  }
  if (mEffect) {
    mEffect->SetAnimation(nullptr);
  }
  mEffect = aEffect;
  if (mEffect) {
    mEffect->SetAnimation(this);
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
}
void MouseHelper::UpdateState(bool isLeftButtonDown, int mouseX, int mouseY, bool drawCursor)
{
    bool currentWasLeftButtonDown = isLeftButtonDown;

    // If we're in full-screen mode, then we need to account for the screen scale.
    if (gIsFullscreen)
    {
        mouseX = (int)(mouseX / gScreenScale);
        mouseY = (int)(mouseY / gScreenScale);
    }

    previousMousePosition.SetX(mouseX);
    previousMousePosition.SetY(mouseY);

    UpdateTiming();

    if (!currentWasLeftButtonDown && previousWasLeftButtonDown)
    {
        // If a click is still possible now that the button has gone up,
        // and we weren't already expecting a double-click,
        // then we have a click, and we'll start considering the possibility
        // of a double-click. If on the other hand a double-click was expected,
        // then we now have a double-click.
        clicked = clickPossible && !doubleClickPossible;
        doubleClicked = clickPossible && doubleClickPossible;
        doubleClickPossible = clickPossible && !doubleClickPossible;
        clickPossible = false;

        if (doubleClickPossible)
        {
            initialClickTime = SDL_GetTicks();
        }
    }
    else if (currentWasLeftButtonDown && !previousWasLeftButtonDown)
    {
        initialLeftButtonDownTime = SDL_GetTicks();
        initialLeftButtonDownPosition = previousMousePosition;
        clickPossible = true;
        doubleClickWasPossible = doubleClickPossible;
    }

    previousWasLeftButtonDown = currentWasLeftButtonDown;
    MouseHelper::drawCursor = drawCursor;
}
Exemple #13
0
// https://w3c.github.io/web-animations/#set-the-animation-start-time
void
Animation::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
{
  if (aNewStartTime == mStartTime) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  Nullable<TimeDuration> timelineTime;
  if (mTimeline) {
    // The spec says to check if the timeline is active (has a resolved time)
    // before using it here, but we don't need to since it's harmless to set
    // the already null time to null.
    timelineTime = mTimeline->GetCurrentTime();
  }
  if (timelineTime.IsNull() && !aNewStartTime.IsNull()) {
    mHoldTime.SetNull();
  }

  Nullable<TimeDuration> previousCurrentTime = GetCurrentTime();
  mStartTime = aNewStartTime;
  if (!aNewStartTime.IsNull()) {
    if (mPlaybackRate != 0.0) {
      mHoldTime.SetNull();
    }
  } else {
    mHoldTime = previousCurrentTime;
  }

  CancelPendingTasks();
  if (mReady) {
    // We may have already resolved mReady, but in that case calling
    // MaybeResolve is a no-op, so that's okay.
    mReady->MaybeResolve(this);
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemple #14
0
void
Animation::PauseAt(const TimeDuration& aReadyTime)
{
  MOZ_ASSERT(mPendingState == PendingState::PausePending,
             "Expected to pause a pause-pending animation");

  if (!mStartTime.IsNull()) {
    mHoldTime.SetValue((aReadyTime - mStartTime.Value())
                        .MultDouble(mPlaybackRate));
  }
  mStartTime.SetNull();
  mPendingState = PendingState::NotPending;

  UpdateTiming();

  if (mReady) {
    mReady->MaybeResolve(this);
  }
}
Exemple #15
0
// https://w3c.github.io/web-animations/#setting-the-timeline
void
Animation::SetTimelineNoUpdate(AnimationTimeline* aTimeline)
{
  RefPtr<AnimationTimeline> oldTimeline = mTimeline;
  if (mTimeline == aTimeline) {
    return;
  }

  if (mTimeline) {
    mTimeline->RemoveAnimation(this);
  }

  mTimeline = aTimeline;
  if (!mStartTime.IsNull()) {
    mHoldTime.SetNull();
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
}
Exemple #16
0
// Implements http://w3c.github.io/web-animations/#set-the-current-time
void
Animation::SetCurrentTime(const TimeDuration& aSeekTime)
{
  SilentlySetCurrentTime(aSeekTime);

  if (mPendingState == PendingState::PausePending) {
    // Finish the pause operation
    mHoldTime.SetValue(aSeekTime);
    mStartTime.SetNull();

    if (mReady) {
      mReady->MaybeResolve(this);
    }
    CancelPendingTasks();
  }

  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
  PostUpdate();
}
Exemple #17
0
void
Animation::SetTimeline(AnimationTimeline* aTimeline)
{
  if (mTimeline == aTimeline) {
    return;
  }

  if (mTimeline) {
    mTimeline->NotifyAnimationUpdated(*this);
  }

  mTimeline = aTimeline;

  // FIXME(spec): Once we implement the seeking defined in the spec
  // surely this should be SeekFlag::DidSeek but the spec says otherwise.
  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);

  // FIXME: When we expose this method to script we'll need to call PostUpdate
  // (but *not* when this method gets called from style).
}
Exemple #18
0
void
Animation::Tick()
{
  // Since we are not guaranteed to get only one call per refresh driver tick,
  // it's possible that mPendingReadyTime is set to a time in the future.
  // In that case, we should wait until the next refresh driver tick before
  // resuming.
  if (mPendingState != PendingState::NotPending &&
      !mPendingReadyTime.IsNull() &&
      mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) {
    FinishPendingAt(mPendingReadyTime.Value());
    mPendingReadyTime.SetNull();
  }

  if (IsPossiblyOrphanedPendingAnimation()) {
    MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
               "Orphaned pending animtaions should have an active timeline");
    FinishPendingAt(mTimeline->GetCurrentTime().Value());
  }

  UpdateTiming();
}
Exemple #19
0
void
Animation::Tick()
{
  // Finish pending if we have a pending ready time, but only if we also
  // have an active timeline.
  if (mPendingState != PendingState::NotPending &&
      !mPendingReadyTime.IsNull() &&
      mTimeline &&
      !mTimeline->GetCurrentTime().IsNull()) {
    // Even though mPendingReadyTime is initialized using TimeStamp::Now()
    // during the *previous* tick of the refresh driver, it can still be
    // ahead of the *current* timeline time when we are using the
    // vsync timer so we need to clamp it to the timeline time.
    mPendingReadyTime.SetValue(std::min(mTimeline->GetCurrentTime().Value(),
                                        mPendingReadyTime.Value()));
    FinishPendingAt(mPendingReadyTime.Value());
    mPendingReadyTime.SetNull();
  }

  if (IsPossiblyOrphanedPendingAnimation()) {
    MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
               "Orphaned pending animtaions should have an active timeline");
    FinishPendingAt(mTimeline->GetCurrentTime().Value());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);

  // FIXME: Detect the no-change case and don't request a restyle at all
  // FIXME: Detect changes to IsPlaying() state and request RestyleType::Layer
  //        so that layers get updated immediately
  AnimationCollection* collection = GetCollection();
  if (collection) {
    collection->RequestRestyle(CanThrottle() ?
      AnimationCollection::RestyleType::Throttled :
      AnimationCollection::RestyleType::Standard);
  }
}
Exemple #20
0
// http://w3c.github.io/web-animations/#play-an-animation
void
Animation::DoPlay(LimitBehavior aLimitBehavior)
{
  bool abortedPause = mPendingState == PendingState::PausePending;

  bool reuseReadyPromise = false;
  if (mPendingState != PendingState::NotPending) {
    CancelPendingTasks();
    reuseReadyPromise = true;
  }

  Nullable<TimeDuration> currentTime = GetCurrentTime();
  if (mPlaybackRate > 0.0 &&
      (currentTime.IsNull() ||
       (aLimitBehavior == LimitBehavior::AutoRewind &&
        (currentTime.Value().ToMilliseconds() < 0.0 ||
         currentTime.Value() >= EffectEnd())))) {
    mHoldTime.SetValue(TimeDuration(0));
  } else if (mPlaybackRate < 0.0 &&
             (currentTime.IsNull() ||
              (aLimitBehavior == LimitBehavior::AutoRewind &&
               (currentTime.Value().ToMilliseconds() <= 0.0 ||
                currentTime.Value() > EffectEnd())))) {
    mHoldTime.SetValue(TimeDuration(EffectEnd()));
  } else if (mPlaybackRate == 0.0 && currentTime.IsNull()) {
    mHoldTime.SetValue(TimeDuration(0));
  }

  // If the hold time is null then we're either already playing normally (and
  // we can ignore this call) or we aborted a pending pause operation (in which
  // case, for consistency, we need to go through the motions of doing an
  // asynchronous start even though we already have a resolved start time).
  if (mHoldTime.IsNull() && !abortedPause) {
    return;
  }

  // Clear the start time until we resolve a new one. We do this except
  // for the case where we are aborting a pause and don't have a hold time.
  //
  // If we're aborting a pause and *do* have a hold time (e.g. because
  // the animation is finished or we just applied the auto-rewind behavior
  // above) we should respect it by clearing the start time. If we *don't*
  // have a hold time we should keep the current start time so that the
  // the animation continues moving uninterrupted by the aborted pause.
  //
  // (If we're not aborting a pause, mHoldTime must be resolved by now
  //  or else we would have returned above.)
  if (!mHoldTime.IsNull()) {
    mStartTime.SetNull();
  }

  if (!reuseReadyPromise) {
    // Clear ready promise. We'll create a new one lazily.
    mReady = nullptr;
  }

  mPendingState = PendingState::PlayPending;

  nsIDocument* doc = GetRenderedDocument();
  if (!doc) {
    TriggerOnNextTick(Nullable<TimeDuration>());
    return;
  }

  PendingAnimationTracker* tracker = doc->GetOrCreatePendingAnimationTracker();
  tracker->AddPlayPending(*this);

  // We may have updated the current time when we set the hold time above.
  UpdateTiming();
}
Exemple #21
0
// https://w3c.github.io/web-animations/#play-an-animation
void
Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior)
{
  AutoMutationBatchForAnimation mb(*this);

  bool abortedPause = mPendingState == PendingState::PausePending;

  Nullable<TimeDuration> currentTime = GetCurrentTime();
  if (mPlaybackRate > 0.0 &&
      (currentTime.IsNull() ||
       (aLimitBehavior == LimitBehavior::AutoRewind &&
        (currentTime.Value() < TimeDuration() ||
         currentTime.Value() >= EffectEnd())))) {
    mHoldTime.SetValue(TimeDuration(0));
  } else if (mPlaybackRate < 0.0 &&
             (currentTime.IsNull() ||
              (aLimitBehavior == LimitBehavior::AutoRewind &&
               (currentTime.Value() <= TimeDuration() ||
                currentTime.Value() > EffectEnd())))) {
    if (EffectEnd() == TimeDuration::Forever()) {
      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
      return;
    }
    mHoldTime.SetValue(TimeDuration(EffectEnd()));
  } else if (mPlaybackRate == 0.0 && currentTime.IsNull()) {
    mHoldTime.SetValue(TimeDuration(0));
  }

  bool reuseReadyPromise = false;
  if (mPendingState != PendingState::NotPending) {
    CancelPendingTasks();
    reuseReadyPromise = true;
  }

  // If the hold time is null then we're either already playing normally (and
  // we can ignore this call) or we aborted a pending pause operation (in which
  // case, for consistency, we need to go through the motions of doing an
  // asynchronous start even though we already have a resolved start time).
  if (mHoldTime.IsNull() && !abortedPause) {
    return;
  }

  // Clear the start time until we resolve a new one. We do this except
  // for the case where we are aborting a pause and don't have a hold time.
  //
  // If we're aborting a pause and *do* have a hold time (e.g. because
  // the animation is finished or we just applied the auto-rewind behavior
  // above) we should respect it by clearing the start time. If we *don't*
  // have a hold time we should keep the current start time so that the
  // the animation continues moving uninterrupted by the aborted pause.
  //
  // (If we're not aborting a pause, mHoldTime must be resolved by now
  //  or else we would have returned above.)
  if (!mHoldTime.IsNull()) {
    mStartTime.SetNull();
  }

  if (!reuseReadyPromise) {
    // Clear ready promise. We'll create a new one lazily.
    mReady = nullptr;
  }

  mPendingState = PendingState::PlayPending;

  nsIDocument* doc = GetRenderedDocument();
  if (doc) {
    PendingAnimationTracker* tracker =
      doc->GetOrCreatePendingAnimationTracker();
    tracker->AddPlayPending(*this);
  } else {
    TriggerOnNextTick(Nullable<TimeDuration>());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
}
Exemple #22
0
void
Animation::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
                        nsCSSPropertySet& aSetProperties,
                        bool& aNeedsRefreshes)
{
  if (!mEffect || mEffect->IsFinishedTransition()) {
    return;
  }

  AnimationPlayState playState = PlayState();
  if (playState == AnimationPlayState::Running ||
      playState == AnimationPlayState::Pending) {
    aNeedsRefreshes = true;
  }

  // In order to prevent flicker, there are a few cases where we want to use
  // a different time for rendering that would otherwise be returned by
  // GetCurrentTime. These are:
  //
  // (a) For animations that are pausing but which are still running on the
  //     compositor. In this case we send a layer transaction that removes the
  //     animation but which also contains the animation values calculated on
  //     the main thread. To prevent flicker when this occurs we want to ensure
  //     the timeline time used to calculate the main thread animation values
  //     does not lag far behind the time used on the compositor. Ideally we
  //     would like to use the "animation ready time" calculated at the end of
  //     the layer transaction as the timeline time but it will be too late to
  //     update the style rule at that point so instead we just use the current
  //     wallclock time.
  //
  // (b) For animations that are pausing that we have already taken off the
  //     compositor. In this case we record a pending ready time but we don't
  //     apply it until the next tick. However, while waiting for the next tick,
  //     we should still use the pending ready time as the timeline time. If we
  //     use the regular timeline time the animation may appear jump backwards
  //     if the main thread's timeline time lags behind the compositor.
  //
  // (c) For animations that are play-pending due to an aborted pause operation
  //     (i.e. a pause operation that was interrupted before we entered the
  //     paused state). When we cancel a pending pause we might momentarily take
  //     the animation off the compositor, only to re-add it moments later. In
  //     that case the compositor might have been ahead of the main thread so we
  //     should use the current wallclock time to ensure the animation doesn't
  //     temporarily jump backwards.
  //
  // To address each of these cases we temporarily tweak the hold time
  // immediately before updating the style rule and then restore it immediately
  // afterwards. This is purely to prevent visual flicker. Other behavior
  // such as dispatching events continues to rely on the regular timeline time.
  {
    AutoRestore<Nullable<TimeDuration>> restoreHoldTime(mHoldTime);
    bool updatedHoldTime = false;

    AnimationPlayState playState = PlayState();

    if (playState == AnimationPlayState::Pending &&
        mHoldTime.IsNull() &&
        !mStartTime.IsNull()) {
      Nullable<TimeDuration> timeToUse = mPendingReadyTime;
      if (timeToUse.IsNull() &&
          mTimeline &&
          !mTimeline->IsUnderTestControl()) {
        timeToUse = mTimeline->ToTimelineTime(TimeStamp::Now());
      }
      if (!timeToUse.IsNull()) {
        mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value())
                            .MultDouble(mPlaybackRate));
        // Push the change down to the effect
        UpdateEffect();
        updatedHoldTime = true;
      }
    }

    mEffect->ComposeStyle(aStyleRule, aSetProperties);

    if (updatedHoldTime) {
      UpdateTiming();
    }

    mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished);
  }
}
Exemple #23
0
void AUPWeapon::UP_UpdateTiming()
{
	UpdateTiming();
}
Exemple #24
0
void mwHandler( GLFWwindow* window,double posx,double posy)
{
	mouseWheelDelta=(int)posy;
	UpdateTiming(mouseWheelDelta);
}
Exemple #25
0
// https://w3c.github.io/web-animations/#setting-the-target-effect
void
Animation::SetEffectNoUpdate(AnimationEffectReadOnly* aEffect)
{
  RefPtr<Animation> kungFuDeathGrip(this);

  if (mEffect == aEffect) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);
  bool wasRelevant = mIsRelevant;

  if (mEffect) {
    if (!aEffect) {
      // If the new effect is null, call ResetPendingTasks before clearing
      // mEffect since ResetPendingTasks needs it to get the appropriate
      // PendingAnimationTracker.
      ResetPendingTasks();
    }

    // We need to notify observers now because once we set mEffect to null
    // we won't be able to find the target element to notify.
    if (mIsRelevant) {
      nsNodeUtils::AnimationRemoved(this);
    }

    // Break links with the old effect and then drop it.
    RefPtr<AnimationEffectReadOnly> oldEffect = mEffect;
    mEffect = nullptr;
    oldEffect->SetAnimation(nullptr);

    // The following will not do any notification because mEffect is null.
    UpdateRelevance();
  }

  if (aEffect) {
    // Break links from the new effect to its previous animation, if any.
    RefPtr<AnimationEffectReadOnly> newEffect = aEffect;
    Animation* prevAnim = aEffect->GetAnimation();
    if (prevAnim) {
      prevAnim->SetEffect(nullptr);
    }

    // Create links with the new effect. SetAnimation(this) will also update
    // mIsRelevant of this animation, and then notify mutation observer if
    // needed by calling Animation::UpdateRelevance(), so we don't need to
    // call it again.
    mEffect = newEffect;
    mEffect->SetAnimation(this);

    // Notify possible add or change.
    // If the target is different, the change notification will be ignored by
    // AutoMutationBatchForAnimation.
    if (wasRelevant && mIsRelevant) {
      nsNodeUtils::AnimationChanged(this);
    }

    // Reschedule pending pause or pending play tasks.
    // If we have a pending animation, it will either be registered
    // in the pending animation tracker and have a null pending ready time,
    // or, after it has been painted, it will be removed from the tracker
    // and assigned a pending ready time.
    // After updating the effect we'll typically need to repaint so if we've
    // already been assigned a pending ready time, we should clear it and put
    // the animation back in the tracker.
    if (!mPendingReadyTime.IsNull()) {
      mPendingReadyTime.SetNull();

      nsIDocument* doc = GetRenderedDocument();
      if (doc) {
        PendingAnimationTracker* tracker =
          doc->GetOrCreatePendingAnimationTracker();
        if (mPendingState == PendingState::PlayPending) {
          tracker->AddPlayPending(*this);
        } else {
          tracker->AddPausePending(*this);
        }
      }
    }
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
}