Bug 1205649 - [2.4] Add AbsoluteDeviceOrientation DOM event for compass heading orientation data. r=smaug
authorEugen Sawin <esawin@mozilla.com>
Thu, 17 Dec 2015 23:14:51 +0100
changeset 281078 94904a47150f255d15e9e4481cbd53634b656605
parent 281077 6ce8e6c5364cd2003e714ab0ca27977006cfd543
child 281079 952331e23d98d9d5857ba31dbc6a9e5d088daf4c
push id29930
push usercbook@mozilla.com
push dateFri, 22 Jan 2016 11:05:50 +0000
treeherdermozilla-central@7104d650a97d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1205649
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1205649 - [2.4] Add AbsoluteDeviceOrientation DOM event for compass heading orientation data. r=smaug
dom/base/nsGkAtomList.h
dom/events/EventListenerManager.cpp
dom/events/EventNameList.h
dom/system/nsDeviceSensors.cpp
dom/webidl/Window.webidl
widget/EventMessageList.h
xpcom/system/nsIDeviceSensors.idl
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -1913,16 +1913,17 @@ GK_ATOM(onpointerout, "onpointerout")
 GK_ATOM(onpointerenter, "onpointerenter")
 GK_ATOM(onpointerleave, "onpointerleave")
 GK_ATOM(ongotpointercapture, "ongotpointercapture")
 GK_ATOM(onlostpointercapture, "onlostpointercapture")
 
 // orientation support
 GK_ATOM(ondevicemotion, "ondevicemotion")
 GK_ATOM(ondeviceorientation, "ondeviceorientation")
+GK_ATOM(onabsolutedeviceorientation, "onabsolutedeviceorientation")
 GK_ATOM(ondeviceproximity, "ondeviceproximity")
 GK_ATOM(onmozorientationchange, "onmozorientationchange")
 GK_ATOM(onuserproximity, "onuserproximity")
 
 // light sensor support
 GK_ATOM(ondevicelight, "ondevicelight")
 
 // Audio channel events
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -314,16 +314,18 @@ EventListenerManager::AddEventListenerIn
       // If aEventMessage is eLegacySubtreeModified, we need to listen all
       // mutations. nsContentUtils::HasMutationListeners relies on this.
       window->SetMutationListeners(
         (aEventMessage == eLegacySubtreeModified) ?
           kAllMutationBits : MutationBitForEventType(aEventMessage));
     }
   } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
     EnableDevice(eDeviceOrientation);
+  } else if (aTypeAtom == nsGkAtoms::onabsolutedeviceorientation) {
+    EnableDevice(eAbsoluteDeviceOrientation);
   } else if (aTypeAtom == nsGkAtoms::ondeviceproximity || aTypeAtom == nsGkAtoms::onuserproximity) {
     EnableDevice(eDeviceProximity);
   } else if (aTypeAtom == nsGkAtoms::ondevicelight) {
     EnableDevice(eDeviceLight);
   } else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
     EnableDevice(eDeviceMotion);
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
   } else if (aTypeAtom == nsGkAtoms::onorientationchange) {
@@ -426,16 +428,17 @@ EventListenerManager::AddEventListenerIn
   }
 }
 
 bool
 EventListenerManager::IsDeviceType(EventMessage aEventMessage)
 {
   switch (aEventMessage) {
     case eDeviceOrientation:
+    case eAbsoluteDeviceOrientation:
     case eDeviceMotion:
     case eDeviceLight:
     case eDeviceProximity:
     case eUserProximity:
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
     case eOrientationChange:
 #endif
       return true;
@@ -458,16 +461,24 @@ EventListenerManager::EnableDevice(Event
 #ifdef MOZ_WIDGET_ANDROID
       // Falls back to SENSOR_ROTATION_VECTOR and SENSOR_ORIENTATION if
       // unavailable on device.
       window->EnableDeviceSensor(SENSOR_GAME_ROTATION_VECTOR);
 #else
       window->EnableDeviceSensor(SENSOR_ORIENTATION);
 #endif
       break;
+    case eAbsoluteDeviceOrientation:
+#ifdef MOZ_WIDGET_ANDROID
+      // Falls back to SENSOR_ORIENTATION if unavailable on device.
+      window->EnableDeviceSensor(SENSOR_ROTATION_VECTOR);
+#else
+      window->EnableDeviceSensor(SENSOR_ORIENTATION);
+#endif
+      break;
     case eDeviceProximity:
     case eUserProximity:
       window->EnableDeviceSensor(SENSOR_PROXIMITY);
       break;
     case eDeviceLight:
       window->EnableDeviceSensor(SENSOR_LIGHT);
       break;
     case eDeviceMotion:
@@ -492,20 +503,27 @@ EventListenerManager::DisableDevice(Even
   nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
   if (!window) {
     return;
   }
 
   switch (aEventMessage) {
     case eDeviceOrientation:
 #ifdef MOZ_WIDGET_ANDROID
+      // Disable all potential fallback sensors.
+      window->DisableDeviceSensor(SENSOR_GAME_ROTATION_VECTOR);
       window->DisableDeviceSensor(SENSOR_ROTATION_VECTOR);
-#else
+#endif
       window->DisableDeviceSensor(SENSOR_ORIENTATION);
+      break;
+    case eAbsoluteDeviceOrientation:
+#ifdef MOZ_WIDGET_ANDROID
+      window->DisableDeviceSensor(SENSOR_ROTATION_VECTOR);
 #endif
+      window->DisableDeviceSensor(SENSOR_ORIENTATION);
       break;
     case eDeviceMotion:
       window->DisableDeviceSensor(SENSOR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
       window->DisableDeviceSensor(SENSOR_GYROSCOPE);
       break;
     case eDeviceProximity:
     case eUserProximity:
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -542,16 +542,20 @@ WINDOW_EVENT(unload,
 WINDOW_ONLY_EVENT(devicemotion,
                   eDeviceMotion,
                   EventNameType_None,
                   eBasicEventClass)
 WINDOW_ONLY_EVENT(deviceorientation,
                   eDeviceOrientation,
                   EventNameType_None,
                   eBasicEventClass)
+WINDOW_ONLY_EVENT(absolutedeviceorientation,
+                  eAbsoluteDeviceOrientation,
+                  EventNameType_None,
+                  eBasicEventClass)
 WINDOW_ONLY_EVENT(deviceproximity,
                   eDeviceProximity,
                   EventNameType_None,
                   eBasicEventClass)
 WINDOW_ONLY_EVENT(userproximity,
                   eUserProximity,
                   EventNameType_None,
                   eBasicEventClass)
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -385,27 +385,45 @@ nsDeviceSensors::FireDOMOrientationEvent
   DeviceOrientationEventInit init;
   init.mBubbles = true;
   init.mCancelable = false;
   init.mAlpha.SetValue(aAlpha);
   init.mBeta.SetValue(aBeta);
   init.mGamma.SetValue(aGamma);
   init.mAbsolute = aIsAbsolute;
 
-  RefPtr<DeviceOrientationEvent> event =
-    DeviceOrientationEvent::Constructor(aTarget,
-                                        NS_LITERAL_STRING("deviceorientation"),
-                                        init);
-  event->SetTrusted(true);
+  auto Dispatch = [&](EventTarget* aEventTarget, const nsAString& aType)
+  {
+    RefPtr<DeviceOrientationEvent> event =
+      DeviceOrientationEvent::Constructor(aEventTarget, aType, init);
+    event->SetTrusted(true);
+    bool dummy;
+    aEventTarget->DispatchEvent(event, &dummy);
+  };
+
+  Dispatch(aTarget, aIsAbsolute ? NS_LITERAL_STRING("absolutedeviceorientation") :
+                                  NS_LITERAL_STRING("deviceorientation"));
 
-  bool dummy;
-  aTarget->DispatchEvent(event, &dummy);
+  // This is used to determine whether relative events have been dispatched
+  // during the current session, in which case we don't dispatch the additional
+  // compatibility events.
+  static bool sIsDispatchingRelativeEvents = false;
+  sIsDispatchingRelativeEvents = sIsDispatchingRelativeEvents || !aIsAbsolute;
+
+  // Android devices with SENSOR_GAME_ROTATION_VECTOR support dispatch
+  // relative events for "deviceorientation" by default, while other platforms
+  // and devices without such support dispatch absolute events by default.
+  if (aIsAbsolute && !sIsDispatchingRelativeEvents) {
+    // For absolute events on devices without support for relative events,
+    // we need to additionally dispatch type "deviceorientation" to keep
+    // backwards-compatibility.
+    Dispatch(aTarget, NS_LITERAL_STRING("deviceorientation"));
+  }
 }
 
-
 void
 nsDeviceSensors::FireDOMMotionEvent(nsIDOMDocument *domdoc,
                                     EventTarget* target,
                                     uint32_t type,
                                     double x,
                                     double y,
                                     double z)
 {
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -349,16 +349,17 @@ partial interface Window {
    */
   [ChromeOnly, Throws] readonly attribute MozSelfSupport MozSelfSupport;
 
   [Pure]
            attribute EventHandler onwheel;
 
            attribute EventHandler ondevicemotion;
            attribute EventHandler ondeviceorientation;
+           attribute EventHandler onabsolutedeviceorientation;
            attribute EventHandler ondeviceproximity;
            attribute EventHandler onuserproximity;
            attribute EventHandler ondevicelight;
 
 #ifdef MOZ_B2G
            attribute EventHandler onmoztimechange;
            attribute EventHandler onmoznetworkupload;
            attribute EventHandler onmoznetworkdownload;
--- a/widget/EventMessageList.h
+++ b/widget/EventMessageList.h
@@ -334,16 +334,17 @@ NS_EVENT_MESSAGE(eAfterPrint)
 
 NS_EVENT_MESSAGE(eMessage)
 
 // Menu open event
 NS_EVENT_MESSAGE(eOpen)
 
 // Device motion and orientation
 NS_EVENT_MESSAGE(eDeviceOrientation)
+NS_EVENT_MESSAGE(eAbsoluteDeviceOrientation)
 NS_EVENT_MESSAGE(eDeviceMotion)
 NS_EVENT_MESSAGE(eDeviceProximity)
 NS_EVENT_MESSAGE(eUserProximity)
 NS_EVENT_MESSAGE(eDeviceLight)
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
 NS_EVENT_MESSAGE(eOrientationChange)
 #endif
 
--- a/xpcom/system/nsIDeviceSensors.idl
+++ b/xpcom/system/nsIDeviceSensors.idl
@@ -1,20 +1,27 @@
 /* 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 "nsISupports.idl"
 
 interface nsIDOMWindow;
 
-[scriptable, uuid(72e64e64-2004-4601-a36a-9d3387d0c525)]
+[scriptable, uuid(0462247e-fe8c-4aa5-b675-3752547e485f)]
 interface nsIDeviceSensorData : nsISupports
 {
   // Keep in sync with hal/HalSensor.h
+
+  // 1. TYPE_ORIENTATION: absolute device orientation, not spec-conform and
+  // deprecated on Android.
+  // 2. TYPE_ROTATION_VECTOR: absolute device orientation affected by drift.
+  // 3. TYPE_GAME_ROTATION_VECTOR: relative device orientation less affected by drift.
+  // Preferred fallback priorities on Android are [3, 2, 1] for the general case
+  // and [2, 1] if absolute orientation (compass heading) is required.
   const unsigned long TYPE_ORIENTATION = 0;
   const unsigned long TYPE_ACCELERATION = 1;
   const unsigned long TYPE_PROXIMITY = 2;
   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;