Bug 1073224 - [1.2] Use SENSOR_ROTATION_VECTOR for DOM DeviceOrientation events on Android. r=vlad

This commit is contained in:
Eugen Sawin 2015-12-15 02:03:56 +01:00
parent b11daccf30
commit 8a206627a5
3 changed files with 77 additions and 6 deletions

View File

@ -455,7 +455,11 @@ EventListenerManager::EnableDevice(EventMessage aEventMessage)
switch (aEventMessage) {
case eDeviceOrientation:
#ifdef MOZ_WIDGET_ANDROID
window->EnableDeviceSensor(SENSOR_ROTATION_VECTOR);
#else
window->EnableDeviceSensor(SENSOR_ORIENTATION);
#endif
break;
case eDeviceProximity:
case eUserProximity:
@ -490,7 +494,11 @@ EventListenerManager::DisableDevice(EventMessage aEventMessage)
switch (aEventMessage) {
case eDeviceOrientation:
#ifdef MOZ_WIDGET_ANDROID
window->DisableDeviceSensor(SENSOR_ROTATION_VECTOR);
#else
window->DisableDeviceSensor(SENSOR_ORIENTATION);
#endif
break;
case eDeviceMotion:
window->DisableDeviceSensor(SENSOR_ACCELERATION);

View File

@ -25,6 +25,8 @@
#include "mozilla/dom/DeviceProximityEvent.h"
#include "mozilla/dom/UserProximityEvent.h"
#include <cmath>
using namespace mozilla;
using namespace mozilla::dom;
using namespace hal;
@ -193,6 +195,61 @@ WindowCannotReceiveSensorEvent (nsPIDOMWindow* aWindow)
return false;
}
// Holds the device orientation in Euler angle degrees (azimuth, pitch, roll).
struct Orientation
{
static Orientation RadToDeg(const Orientation& aOrient)
{
const static double kRadToDeg = 180.0 / M_PI;
return { aOrient.alpha * kRadToDeg,
aOrient.beta * kRadToDeg,
aOrient.gamma * kRadToDeg };
}
double alpha;
double beta;
double gamma;
};
static Orientation
RotationVectorToOrientation(double aX, double aY, double aZ, double aW)
{
static const double kFuzzyOne = 1.0 - 1e-6;
static const double kCircleRad = 2.0 * M_PI;
Orientation orient = { 2.0 * std::atan2(aY, aW),
M_PI_2,
0.0 };
const double sqX = aX * aX;
const double sqY = aY * aY;
const double sqZ = aZ * aZ;
const double sqW = aW * aW;
const double unitLength = sqX + sqY + sqZ + sqW;
const double xwyz = 2.0 * (aX * aW + aY * aZ) / unitLength;
if (xwyz < -kFuzzyOne) {
orient.alpha *= -1.0;
orient.beta *= -1.0;
} else if (xwyz <= kFuzzyOne) {
const double gammaX = -sqX - sqY + sqZ + sqW;
const double gammaY = 2.0 * (aY * aW - aX * aZ);
const double alphaX = -sqX + sqY - sqZ + sqW;
const double alphaY = 2.0 * (aZ * aW - aX * aY);
const double fac = gammaX > 0 ? 1.0 : -1.0;
orient.alpha = std::fmod(kCircleRad + std::atan2(fac * alphaY, fac * alphaX),
kCircleRad);
orient.beta = fac * std::asin(xwyz);
orient.gamma = std::atan2(fac * gammaY, fac * gammaX);
if (fac < 0.0) {
orient.beta = fmod(M_PI + orient.beta, M_PI);
}
}
return Orientation::RadToDeg(orient);
}
void
nsDeviceSensors::Notify(const mozilla::hal::SensorData& aSensorData)
{
@ -203,6 +260,7 @@ nsDeviceSensors::Notify(const mozilla::hal::SensorData& aSensorData)
double x = len > 0 ? values[0] : 0.0;
double y = len > 1 ? values[1] : 0.0;
double z = len > 2 ? values[2] : 0.0;
double w = len > 3 ? values[3] : 0.0;
nsCOMArray<nsIDOMWindow> windowListeners;
for (uint32_t i = 0; i < mWindowListeners[type]->Length(); i++) {
@ -221,15 +279,18 @@ nsDeviceSensors::Notify(const mozilla::hal::SensorData& aSensorData)
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(windowListeners[i]);
if (type == nsIDeviceSensorData::TYPE_ACCELERATION ||
type == nsIDeviceSensorData::TYPE_LINEAR_ACCELERATION ||
type == nsIDeviceSensorData::TYPE_GYROSCOPE)
type == nsIDeviceSensorData::TYPE_GYROSCOPE) {
FireDOMMotionEvent(domDoc, target, type, x, y, z);
else if (type == nsIDeviceSensorData::TYPE_ORIENTATION)
} else if (type == nsIDeviceSensorData::TYPE_ORIENTATION) {
FireDOMOrientationEvent(target, x, y, z);
else if (type == nsIDeviceSensorData::TYPE_PROXIMITY)
} else if (type == nsIDeviceSensorData::TYPE_ROTATION_VECTOR) {
const Orientation orient = RotationVectorToOrientation(x, y, z, w);
FireDOMOrientationEvent(target, orient.alpha, orient.beta, orient.gamma);
} else if (type == nsIDeviceSensorData::TYPE_PROXIMITY) {
FireDOMProximityEvent(target, x, y, z);
else if (type == nsIDeviceSensorData::TYPE_LIGHT)
} else if (type == nsIDeviceSensorData::TYPE_LIGHT) {
FireDOMLightEvent(target, x);
}
}
}
}

View File

@ -6,7 +6,7 @@
interface nsIDOMWindow;
[scriptable, uuid(1B406E32-CF42-471E-A470-6FD600BF4C7B)]
[scriptable, uuid(72e64e64-2004-4601-a36a-9d3387d0c525)]
interface nsIDeviceSensorData : nsISupports
{
// Keep in sync with hal/HalSensor.h
@ -16,6 +16,8 @@ interface nsIDeviceSensorData : nsISupports
const unsigned long TYPE_LINEAR_ACCELERATION = 3;
const unsigned long TYPE_GYROSCOPE = 4;
const unsigned long TYPE_LIGHT = 5;
const unsigned long TYPE_ROTATION_VECTOR = 6;
const unsigned long TYPE_GAME_ROTATION_VECTOR = 7;
readonly attribute unsigned long type;