#include "config.h"
#include "Vibration.h"
#if ENABLE(VIBRATION)
#include "VibrationClient.h"
namespace WebCore {
const unsigned MaxVibrationPatternLength = 99;
const unsigned MaxVibrationDuration = 10000;
Vibration::Vibration(VibrationClient* client)
: m_vibrationClient(client)
, m_timer(*this, &Vibration::timerFired)
, m_state(State::Idle)
{
}
Vibration::~Vibration()
{
m_vibrationClient->vibrationDestroyed();
}
bool Vibration::vibrate(const VibrationPattern& pattern)
{
VibrationPattern& sanitized = const_cast<VibrationPattern&>(pattern);
size_t length = sanitized.size();
if (length > MaxVibrationPatternLength) {
sanitized.shrink(MaxVibrationPatternLength);
length = MaxVibrationPatternLength;
}
if (length && !(length % 2)) {
sanitized.removeLast();
length--;
}
for (auto& duration : sanitized)
duration = std::min(duration, MaxVibrationDuration);
if (isVibrating())
cancelVibration();
if (!length || (length == 1 && !sanitized[0])) {
cancelVibration();
return true;
}
m_pattern = sanitized;
m_timer.startOneShot(0);
m_state = State::Waiting;
return true;
}
void Vibration::cancelVibration()
{
m_pattern.clear();
if (isVibrating()) {
m_timer.stop();
m_state = State::Idle;
m_vibrationClient->cancelVibration();
}
}
void Vibration::timerFired()
{
m_timer.stop();
if (m_pattern.isEmpty()) {
m_state = State::Idle;
return;
}
switch (m_state) {
case State::Vibrating:
m_state = State::Waiting;
break;
case State::Waiting:
case State::Idle:
m_state = State::Vibrating;
m_vibrationClient->vibrate(m_pattern[0]);
break;
}
m_timer.startOneShot(m_pattern[0] / 1000.0);
m_pattern.remove(0);
}
const char* Vibration::supplementName()
{
return "Vibration";
}
void provideVibrationTo(Page* page, VibrationClient* client)
{
Vibration::provideTo(page, Vibration::supplementName(), std::make_unique<Vibration>(client));
}
}
#endif // ENABLE(VIBRATION)