Bug 734325 - implement compassneedscalibration event. r=jdm
authorDoug Turner <dougt@dougt.org>
Tue, 13 Mar 2012 16:57:09 -0700
changeset 92306 781e874d0ff50b2935db29dfd93dfb1e3f967ee2
parent 92305 2aef3c754ff563db50a09363f8ce802c5fe7be79
child 92307 fdb8a781820a40e2861c18a647b4706830063237
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs734325
milestone14.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 734325 - implement compassneedscalibration event. r=jdm
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/PContent.ipdl
dom/system/nsDeviceMotion.cpp
dom/system/nsDeviceMotion.h
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoEvent.java
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
widget/android/nsAppShell.cpp
xpcom/system/nsIDeviceMotion.idl
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -749,16 +749,26 @@ ContentChild::RecvDeviceMotionChanged(co
     nsCOMPtr<nsIDeviceMotionUpdate> dmu = 
         do_GetService(NS_DEVICE_MOTION_CONTRACTID);
     if (dmu)
         dmu->DeviceMotionChanged(type, x, y, z);
     return true;
 }
 
 bool
+ContentChild::RecvNeedsCalibration()
+{
+    nsCOMPtr<nsIDeviceMotionUpdate> dmu = 
+        do_GetService(NS_DEVICE_MOTION_CONTRACTID);
+    if (dmu)
+        dmu->NeedsCalibration();
+    return true;
+}
+
+bool
 ContentChild::RecvScreenSizeChanged(const gfxIntSize& size)
 {
 #ifdef ANDROID
     mScreenSize = size;
 #else
     NS_RUNTIMEABORT("Message currently only expected on android");
 #endif
   return true;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -157,16 +157,18 @@ public:
     virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);
 
     virtual bool RecvAddPermission(const IPC::Permission& permission);
 
     virtual bool RecvDeviceMotionChanged(const long int& type,
                                          const double& x, const double& y,
                                          const double& z);
 
+    virtual bool RecvNeedsCalibration();
+
     virtual bool RecvScreenSizeChanged(const gfxIntSize &size);
 
     virtual bool RecvFlushMemory(const nsString& reason);
 
     virtual bool RecvActivateA11y();
 
     virtual bool RecvGarbageCollect();
     virtual bool RecvCycleCollect();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1286,11 +1286,17 @@ ContentParent::OnMotionChange(nsIDeviceM
     aDeviceData->GetX(&x);
     aDeviceData->GetY(&y);
     aDeviceData->GetZ(&z);
 
     unused << SendDeviceMotionChanged(type, x, y, z);
     return NS_OK;
 }
 
+NS_IMETHODIMP
+ContentParent::NeedsCalibration() {
+    unused << SendNeedsCalibration();
+    return NS_OK;
+}
+
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -129,16 +129,17 @@ child:
     NotifyAlertsObserver(nsCString topic, nsString data);
 
     GeolocationUpdate(GeoPosition somewhere);
 
     // nsIPermissionManager messages
     AddPermission(Permission permission);
 
     DeviceMotionChanged(long type, double x, double y, double z);
+    NeedsCalibration();
 
     ScreenSizeChanged(gfxIntSize size);
 
     FlushMemory(nsString reason);
 
     GarbageCollect();
     CycleCollect();
     
--- a/dom/system/nsDeviceMotion.cpp
+++ b/dom/system/nsDeviceMotion.cpp
@@ -256,16 +256,74 @@ nsDeviceMotion::DeviceMotionChanged(PRUi
         FireDOMMotionEvent(domdoc, target, x, y, z);
       else if (type == nsIDeviceMotionData::TYPE_ORIENTATION)
         FireDOMOrientationEvent(domdoc, target, x, y, z);
     }
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDeviceMotion::NeedsCalibration()
+{
+  if (!mEnabled)
+    return NS_ERROR_NOT_INITIALIZED;
+
+  nsCOMArray<nsIDeviceMotionListener> listeners = mListeners;
+  for (PRUint32 i = listeners.Count(); i > 0 ; ) {
+    --i;
+    listeners[i]->NeedsCalibration();
+  }
+
+  nsCOMArray<nsIDOMWindow> windowListeners;
+  for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) {
+    windowListeners.AppendObject(mWindowListeners[i]);
+  }
+
+  for (PRUint32 i = windowListeners.Count(); i > 0 ; ) {
+    --i;
+
+    // check to see if this window is in the background.  if
+    // it is, don't send any device motion to it.
+    nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(windowListeners[i]);
+    if (!pwindow ||
+        !pwindow->GetOuterWindow() ||
+        pwindow->GetOuterWindow()->IsBackground())
+      continue;
+
+    nsCOMPtr<nsIDOMDocument> domdoc;
+    windowListeners[i]->GetDocument(getter_AddRefs(domdoc));
+
+    if (domdoc) {
+	nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(windowListeners[i]);
+        FireNeedsCalibration(domdoc, target);
+    }
+  }
+
+  return NS_OK;
+}
+
+void
+nsDeviceMotion::FireNeedsCalibration(nsIDOMDocument *domdoc,
+				    nsIDOMEventTarget *target)
+{
+  nsCOMPtr<nsIDOMEvent> event;
+  domdoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
+  if (!event)
+    return;
+
+  event->InitEvent(NS_LITERAL_STRING("compassneedscalibration"), true, false);
+  nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
+  if (privateEvent)
+    privateEvent->SetTrusted(true);
+  
+  bool defaultActionEnabled = true;
+  target->DispatchEvent(event, &defaultActionEnabled);
+}
+
 void
 nsDeviceMotion::FireDOMOrientationEvent(nsIDOMDocument *domdoc,
                                         nsIDOMEventTarget *target,
                                         double alpha,
                                         double beta,
                                         double gamma)
 {
   nsCOMPtr<nsIDOMEvent> event;
--- a/dom/system/nsDeviceMotion.h
+++ b/dom/system/nsDeviceMotion.h
@@ -71,16 +71,19 @@ private:
 
   bool mStarted;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   static void TimeoutHandler(nsITimer *aTimer, void *aClosure);
 
  protected:
 
+  void FireNeedsCalibration(nsIDOMDocument *domdoc,
+			    nsIDOMEventTarget *target);
+
   void FireDOMOrientationEvent(class nsIDOMDocument *domDoc, 
                                class nsIDOMEventTarget *target,
                                double alpha,
                                double beta,
                                double gamma);
 
   void FireDOMMotionEvent(class nsIDOMDocument *domDoc, 
                           class nsIDOMEventTarget *target,
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -2603,16 +2603,18 @@ abstract public class GeckoApp
     }
 
     public GeckoSoftwareLayerClient getSoftwareLayerClient() { return mSoftwareLayerClient; }
     public LayerController getLayerController() { return mLayerController; }
 
     // accelerometer
     public void onAccuracyChanged(Sensor sensor, int accuracy)
     {
+        Log.w(LOGTAG, "onAccuracyChanged "+accuracy);
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorAccuracyEvent(accuracy));
     }
 
     public void onSensorChanged(SensorEvent event)
     {
         Log.w(LOGTAG, "onSensorChanged "+event);
         GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event));
     }
 
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -84,16 +84,17 @@ public class GeckoEvent {
     private static final int ACTIVITY_START = 17;
     private static final int BROADCAST = 19;
     private static final int VIEWPORT = 20;
     private static final int VISITED = 21;
     private static final int NETWORK_CHANGED = 22;
     private static final int PROXIMITY_EVENT = 23;
     private static final int ACTIVITY_RESUMING = 24;
     private static final int SCREENSHOT = 25;
+    private static final int SENSOR_ACCURACY = 26;
 
     public static final int IME_COMPOSITION_END = 0;
     public static final int IME_COMPOSITION_BEGIN = 1;
     public static final int IME_SET_TEXT = 2;
     public static final int IME_GET_TEXT = 3;
     public static final int IME_DELETE_TEXT = 4;
     public static final int IME_SET_SELECTION = 5;
     public static final int IME_GET_SELECTION = 6;
@@ -287,19 +288,19 @@ public class GeckoEvent {
             event = new GeckoEvent(ACCELERATION_EVENT);
             event.mX = s.values[0];
             event.mY = s.values[1];
             event.mZ = s.values[2];
             break;
             
         case Sensor.TYPE_ORIENTATION:
             event = new GeckoEvent(ORIENTATION_EVENT);
-            event.mAlpha = -s.values[0];
-            event.mBeta = -s.values[1];
-            event.mGamma = -s.values[2];
+            event.mAlpha = s.values[0];
+            event.mBeta  = s.values[1];
+            event.mGamma = s.values[2];
             break;
 
         case Sensor.TYPE_PROXIMITY:
             event = new GeckoEvent(PROXIMITY_EVENT);
             event.mDistance = s.values[0];
             break;
         }
         return event;
@@ -403,9 +404,15 @@ public class GeckoEvent {
     public static GeckoEvent createScreenshotEvent(int tabId, int sw, int sh, int dw, int dh) {
         GeckoEvent event = new GeckoEvent(SCREENSHOT);
         event.mPoints = new Point[2];
         event.mPoints[0] = new Point(sw, sh);
         event.mPoints[1] = new Point(dw, dh);
         event.mMetaState = tabId;
         return event;
     }
+
+    public static GeckoEvent createSensorAccuracyEvent(int accuracy) {
+        GeckoEvent event = new GeckoEvent(SENSOR_ACCURACY);
+        event.mFlags = accuracy;
+        return event;
+    }
 }
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -468,16 +468,17 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
             break;
         }
 
         case PROXIMITY_EVENT: {
             mDistance = jenv->GetDoubleField(jobj, jDistanceField);
             break;
         }
 
+        case SENSOR_ACCURACY:
         case ACTIVITY_STOPPING:
         case ACTIVITY_START:
         case ACTIVITY_PAUSING:
         case ACTIVITY_RESUMING: {
             mFlags = jenv->GetIntField(jobj, jFlagsField);
             break;
         }
 
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -544,16 +544,17 @@ public:
         ACTIVITY_START = 17,
         BROADCAST = 19,
         VIEWPORT = 20,
         VISITED = 21,
         NETWORK_CHANGED = 22,
         PROXIMITY_EVENT = 23,
         ACTIVITY_RESUMING = 24,
         SCREENSHOT = 25,
+        SENSOR_ACCURACY = 26,
         dummy_java_enum_list_end
     };
 
     enum {
         IME_COMPOSITION_END = 0,
         IME_COMPOSITION_BEGIN = 1,
         IME_SET_TEXT = 2,
         IME_GET_TEXT = 3,
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -326,28 +326,33 @@ nsAppShell::ProcessNextNativeEvent(bool 
 
     EVLOG("nsAppShell: event %p %d [ndraws %d]", (void*)curEvent.get(), curEvent->Type(), mNumDraws);
 
     switch (curEvent->Type()) {
     case AndroidGeckoEvent::NATIVE_POKE:
         NativeEventCallback();
         break;
 
+    case AndroidGeckoEvent::SENSOR_ACCURACY:
+        if (curEvent->Flags() == 0)
+            gDeviceMotionSystem->NeedsCalibration();
+        break;
+
     case AndroidGeckoEvent::ACCELERATION_EVENT:
         gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ACCELERATION,
                                                  -curEvent->X(),
                                                  curEvent->Y(),
                                                  curEvent->Z());
         break;
 
     case AndroidGeckoEvent::ORIENTATION_EVENT:
         gDeviceMotionSystem->DeviceMotionChanged(nsIDeviceMotionData::TYPE_ORIENTATION,
-                                                 -curEvent->Alpha(),
-                                                 curEvent->Beta(),
-                                                 curEvent->Gamma());
+                                                 curEvent->Alpha(),
+                                                 -curEvent->Beta(),
+                                                 -curEvent->Gamma());
         mPendingOrientationEvents = false;
         break;
 
     case AndroidGeckoEvent::LOCATION_EVENT: {
         if (!gLocationCallback)
             break;
 
         nsGeoPosition* p = curEvent->GeoPosition();
--- a/xpcom/system/nsIDeviceMotion.idl
+++ b/xpcom/system/nsIDeviceMotion.idl
@@ -46,20 +46,21 @@ interface nsIDeviceMotionData : nsISuppo
 
   readonly attribute unsigned long type;
 
   readonly attribute double x;
   readonly attribute double y;
   readonly attribute double z;
 };
 
-[scriptable, uuid(f01774a2-3b7e-4630-954b-196dc178221f)]
+[scriptable, uuid(D29EA788-CCB6-4875-88E0-32A34BB71CBB)]
 interface nsIDeviceMotionListener : nsISupports
 {
   void onMotionChange(in nsIDeviceMotionData aMotionData);
+  void needsCalibration();
 };
 
 [scriptable, uuid(B6E5C463-AAA6-44E2-BD07-7A7DC6192E68)]
 interface nsIDeviceMotion : nsISupports
 {
   void addListener(in nsIDeviceMotionListener aListener);
   void removeListener(in nsIDeviceMotionListener aListener);
 
@@ -68,14 +69,15 @@ interface nsIDeviceMotion : nsISupports
   [noscript] void addWindowListener(in nsIDOMWindow aWindow);
   [noscript] void removeWindowListener(in nsIDOMWindow aWindow);
 
 };
 
 /* for use by IPC system to notify non-chrome processes of 
  * device motion events
  */
-[uuid(d3a56f08-b7b1-46bb-9dc1-fc3665a3631a)]
+[uuid(C12C0157-DCFF-41B5-83F3-89179BF6CA4E)]
 interface nsIDeviceMotionUpdate : nsIDeviceMotion
 {
   /* must be called on the main thread or else */
   void deviceMotionChanged(in unsigned long type, in double x, in double y, in double z);
+  void needsCalibration();
 };