ScriptedAnimationController.cpp [plain text]
#include "config.h"
#include "ScriptedAnimationController.h"
#if ENABLE(REQUEST_ANIMATION_FRAME)
#include "Document.h"
#include "FrameView.h"
#include "InspectorInstrumentation.h"
#include "RequestAnimationFrameCallback.h"
#include "Settings.h"
#if USE(REQUEST_ANIMATION_FRAME_TIMER)
#include <algorithm>
#include <wtf/CurrentTime.h>
using namespace std;
#define MinimumAnimationInterval 0.015
#endif
namespace WebCore {
ScriptedAnimationController::ScriptedAnimationController(Document* document, PlatformDisplayID displayID)
: m_document(document)
, m_nextCallbackId(0)
, m_suspendCount(0)
#if USE(REQUEST_ANIMATION_FRAME_TIMER)
, m_animationTimer(this, &ScriptedAnimationController::animationTimerFired)
, m_lastAnimationFrameTime(0)
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
, m_useTimer(false)
#endif
#endif
{
windowScreenDidChange(displayID);
}
ScriptedAnimationController::~ScriptedAnimationController()
{
}
void ScriptedAnimationController::suspend()
{
++m_suspendCount;
}
void ScriptedAnimationController::resume()
{
if (m_suspendCount > 0)
--m_suspendCount;
if (!m_suspendCount && m_callbacks.size())
scheduleAnimation();
}
ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(PassRefPtr<RequestAnimationFrameCallback> callback)
{
ScriptedAnimationController::CallbackId id = m_nextCallbackId++;
callback->m_firedOrCancelled = false;
callback->m_id = id;
m_callbacks.append(callback);
InspectorInstrumentation::didRequestAnimationFrame(m_document, id);
if (!m_suspendCount)
scheduleAnimation();
return id;
}
void ScriptedAnimationController::cancelCallback(CallbackId id)
{
for (size_t i = 0; i < m_callbacks.size(); ++i) {
if (m_callbacks[i]->m_id == id) {
m_callbacks[i]->m_firedOrCancelled = true;
InspectorInstrumentation::didCancelAnimationFrame(m_document, id);
m_callbacks.remove(i);
return;
}
}
}
void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time)
{
if (!m_callbacks.size() || m_suspendCount || (m_document->settings() && !m_document->settings()->requestAnimationFrameEnabled()))
return;
CallbackList callbacks(m_callbacks);
RefPtr<ScriptedAnimationController> protector(this);
for (size_t i = 0; i < callbacks.size(); ++i) {
RequestAnimationFrameCallback* callback = callbacks[i].get();
if (!callback->m_firedOrCancelled) {
callback->m_firedOrCancelled = true;
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(m_document, callback->m_id);
callback->handleEvent(time);
InspectorInstrumentation::didFireAnimationFrame(cookie);
}
}
for (size_t i = 0; i < m_callbacks.size();) {
if (m_callbacks[i]->m_firedOrCancelled)
m_callbacks.remove(i);
else
++i;
}
if (m_callbacks.size())
scheduleAnimation();
}
void ScriptedAnimationController::windowScreenDidChange(PlatformDisplayID displayID)
{
if (m_document->settings() && !m_document->settings()->requestAnimationFrameEnabled())
return;
#if USE(REQUEST_ANIMATION_FRAME_TIMER) && USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
DisplayRefreshMonitorManager::sharedManager()->windowScreenDidChange(displayID, this);
#else
UNUSED_PARAM(displayID);
#endif
}
void ScriptedAnimationController::scheduleAnimation()
{
if (!m_document || (m_document->settings() && !m_document->settings()->requestAnimationFrameEnabled()))
return;
#if USE(REQUEST_ANIMATION_FRAME_TIMER)
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
if (!m_useTimer) {
if (DisplayRefreshMonitorManager::sharedManager()->scheduleAnimation(this))
return;
m_useTimer = true;
}
#endif
if (m_animationTimer.isActive())
return;
double scheduleDelay = max<double>(MinimumAnimationInterval - (currentTime() - m_lastAnimationFrameTime), 0);
m_animationTimer.startOneShot(scheduleDelay);
#else
if (FrameView* frameView = m_document->view())
frameView->scheduleAnimation();
#endif
}
#if USE(REQUEST_ANIMATION_FRAME_TIMER)
void ScriptedAnimationController::animationTimerFired(Timer<ScriptedAnimationController>*)
{
m_lastAnimationFrameTime = currentTime();
serviceScriptedAnimations(convertSecondsToDOMTimeStamp(m_lastAnimationFrameTime));
}
#endif
}
#endif