Bug 1402147 - Part 1: Fire VRDisplayConnect event for VR displays that are already enumerated when a page is loaded r=daoshengmu
authorKearwood "Kip" Gilbert <kgilbert@mozilla.com>
Thu, 04 Jan 2018 14:27:03 -0800
changeset 452712 a6cdc53b929fe19aaf820fc83a4b73e8488c806a
parent 452711 07859f6fa8cef9a54068215ea5570581de3f1ec7
child 452713 0123b237b26c24cf64caffa70f18811561bc2cbc
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaoshengmu
bugs1402147
milestone59.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 1402147 - Part 1: Fire VRDisplayConnect event for VR displays that are already enumerated when a page is loaded r=daoshengmu MozReview-Commit-ID: 7zQOSYJ6tkg
dom/base/nsGlobalWindowInner.cpp
dom/vr/VRDisplay.cpp
dom/vr/VREventObserver.cpp
dom/vr/VREventObserver.h
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRManagerChild.h
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -2113,16 +2113,20 @@ nsGlobalWindowInner::PostHandleEvent(Eve
       // Most of the time we could get a pres context to pass in here,
       // but not always (i.e. if this window is not shown there won't
       // be a pres context available). Since we're not firing a GUI
       // event we don't need a pres context anyway so we just pass
       // null as the pres context all the time here.
       EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
     }
 
+    if (mVREventObserver) {
+      mVREventObserver->NotifyAfterLoad();
+    }
+
     uint32_t autoActivateVRDisplayID = 0;
     nsGlobalWindowOuter* outer = GetOuterWindowInternal();
     if (outer) {
       autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
     }
     if (autoActivateVRDisplayID) {
       DispatchVRDisplayActivate(autoActivateVRDisplayID,
                                 VRDisplayEventReason::Navigation);
@@ -7014,16 +7018,19 @@ nsGlobalWindowInner::NotifyActiveVRDispl
     mNavigator->NotifyActiveVRDisplaysChanged();
   }
 }
 
 void
 nsGlobalWindowInner::DispatchVRDisplayActivate(uint32_t aDisplayID,
                                                mozilla::dom::VRDisplayEventReason aReason)
 {
+  // Ensure that our list of displays is up to date
+  VRDisplay::UpdateVRDisplays(mVRDisplays, this);
+
   // Search for the display identified with aDisplayID and fire the
   // event if found.
   for (const auto& display : mVRDisplays) {
     if (display->DisplayId() == aDisplayID) {
       if (aReason != VRDisplayEventReason::Navigation &&
           display->IsAnyPresenting(gfx::kVRGroupContent)) {
         // We only want to trigger this event if nobody is presenting to the
         // display already or when a page is loaded by navigating away
@@ -7058,16 +7065,19 @@ nsGlobalWindowInner::DispatchVRDisplayAc
     }
   }
 }
 
 void
 nsGlobalWindowInner::DispatchVRDisplayDeactivate(uint32_t aDisplayID,
                                                  mozilla::dom::VRDisplayEventReason aReason)
 {
+  // Ensure that our list of displays is up to date
+  VRDisplay::UpdateVRDisplays(mVRDisplays, this);
+
   // Search for the display identified with aDisplayID and fire the
   // event if found.
   for (const auto& display : mVRDisplays) {
     if (display->DisplayId() == aDisplayID && display->IsPresenting()) {
       // We only want to trigger this event to content that is presenting to
       // the display already.
 
       VRDisplayEventInit init;
@@ -7088,16 +7098,19 @@ nsGlobalWindowInner::DispatchVRDisplayDe
       return;
     }
   }
 }
 
 void
 nsGlobalWindowInner::DispatchVRDisplayConnect(uint32_t aDisplayID)
 {
+  // Ensure that our list of displays is up to date
+  VRDisplay::UpdateVRDisplays(mVRDisplays, this);
+
   // Search for the display identified with aDisplayID and fire the
   // event if found.
   for (const auto& display : mVRDisplays) {
     if (display->DisplayId() == aDisplayID) {
       // Fire event even if not presenting to the display.
       VRDisplayEventInit init;
       init.mBubbles = false;
       init.mCancelable = false;
@@ -7116,16 +7129,19 @@ nsGlobalWindowInner::DispatchVRDisplayCo
       return;
     }
   }
 }
 
 void
 nsGlobalWindowInner::DispatchVRDisplayDisconnect(uint32_t aDisplayID)
 {
+  // Ensure that our list of displays is up to date
+  VRDisplay::UpdateVRDisplays(mVRDisplays, this);
+
   // Search for the display identified with aDisplayID and fire the
   // event if found.
   for (const auto& display : mVRDisplays) {
     if (display->DisplayId() == aDisplayID) {
       // Fire event even if not presenting to the display.
       VRDisplayEventInit init;
       init.mBubbles = false;
       init.mCancelable = false;
@@ -7144,16 +7160,19 @@ nsGlobalWindowInner::DispatchVRDisplayDi
       return;
     }
   }
 }
 
 void
 nsGlobalWindowInner::DispatchVRDisplayPresentChange(uint32_t aDisplayID)
 {
+  // Ensure that our list of displays is up to date
+  VRDisplay::UpdateVRDisplays(mVRDisplays, this);
+
   // Search for the display identified with aDisplayID and fire the
   // event if found.
   for (const auto& display : mVRDisplays) {
     if (display->DisplayId() == aDisplayID) {
       // Fire event even if not presenting to the display.
       VRDisplayEventInit init;
       init.mBubbles = false;
       init.mCancelable = false;
--- a/dom/vr/VRDisplay.cpp
+++ b/dom/vr/VRDisplay.cpp
@@ -95,17 +95,17 @@ VRDisplay::UpdateVRDisplays(nsTArray<Ref
 
   gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
   nsTArray<RefPtr<gfx::VRDisplayClient>> updatedDisplays;
   if (vm && vm->GetVRDisplays(updatedDisplays)) {
     for (size_t i = 0; i < updatedDisplays.Length(); i++) {
       RefPtr<gfx::VRDisplayClient> display = updatedDisplays[i];
       bool isNewDisplay = true;
       for (size_t j = 0; j < aDisplays.Length(); j++) {
-        if (aDisplays[j]->GetClient()->GetDisplayInfo() == display->GetDisplayInfo()) {
+        if (aDisplays[j]->GetClient()->GetDisplayInfo().GetDisplayID() == display->GetDisplayInfo().GetDisplayID()) {
           displays.AppendElement(aDisplays[j]);
           isNewDisplay = false;
         }
       }
 
       if (isNewDisplay) {
         displays.AppendElement(new VRDisplay(aWindow, display));
       }
--- a/dom/vr/VREventObserver.cpp
+++ b/dom/vr/VREventObserver.cpp
@@ -73,16 +73,25 @@ VREventObserver::UpdateSpentTimeIn2DTele
     mHasReset = false;
   } else if (!aUpdate) {
     mSpendTimeIn2DView = TimeStamp::Now();
     mHasReset = true;
   }
 }
 
 void
+VREventObserver::NotifyAfterLoad()
+{
+  if (VRManagerChild::IsCreated()) {
+    VRManagerChild* vmc = VRManagerChild::Get();
+    vmc->FireDOMVRDisplayConnectEventsForLoad(this);
+  }
+}
+
+void
 VREventObserver::NotifyVRDisplayMounted(uint32_t aDisplayID)
 {
   if (mWindow && mWindow->AsInner()->IsCurrentInnerWindow()) {
     MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
     mWindow->DispatchVRDisplayActivate(aDisplayID,
                                        VRDisplayEventReason::Mounted);
   }
 }
--- a/dom/vr/VREventObserver.h
+++ b/dom/vr/VREventObserver.h
@@ -16,16 +16,17 @@ namespace mozilla {
 namespace dom {
 
 class VREventObserver final
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(VREventObserver)
   explicit VREventObserver(nsGlobalWindowInner* aGlobalWindow);
 
+  void NotifyAfterLoad();
   void NotifyVRDisplayMounted(uint32_t aDisplayID);
   void NotifyVRDisplayUnmounted(uint32_t aDisplayID);
   void NotifyVRDisplayNavigation(uint32_t aDisplayID);
   void NotifyVRDisplayRequested(uint32_t aDisplayID);
   void NotifyVRDisplayConnect(uint32_t aDisplayID);
   void NotifyVRDisplayDisconnect(uint32_t aDisplayID);
   void NotifyVRDisplayPresentChange(uint32_t aDisplayID);
 
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -537,16 +537,43 @@ VRManagerChild::FireDOMVRDisplayPresentC
   nsTArray<RefPtr<dom::VREventObserver>> listeners;
   listeners = mListeners;
   for (auto& listener : listeners) {
     listener->NotifyVRDisplayPresentChange(aDisplayID);
   }
 }
 
 void
+VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal(uint32_t aDisplayID,
+                                                            dom::VREventObserver* aObserver)
+{
+  aObserver->NotifyVRDisplayConnect(aDisplayID);
+}
+
+void
+VRManagerChild::FireDOMVRDisplayConnectEventsForLoad(dom::VREventObserver* aObserver)
+{
+  // We need to fire the VRDisplayConnect event when a page is loaded
+  // for each VR Display that has already been enumerated
+  nsTArray<RefPtr<VRDisplayClient>> displays;
+  displays = mDisplays;
+  for (auto& display : displays) {
+    const VRDisplayInfo& info = display->GetDisplayInfo();
+    if (info.GetIsConnected()) {
+        nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t, RefPtr<dom::VREventObserver>>(
+      "gfx::VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal",
+      this,
+      &VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal,
+      info.GetDisplayID(),
+      aObserver));
+    }
+  }
+}
+
+void
 VRManagerChild::AddListener(dom::VREventObserver* aObserver)
 {
   MOZ_ASSERT(aObserver);
 
   if (mListeners.IndexOf(aObserver) != kNoIndex) {
     return; // already exists
   }
 
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -71,16 +71,17 @@ public:
   void RunFrameRequestCallbacks();
 
   void UpdateDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayUpdates);
   void FireDOMVRDisplayMountedEvent(uint32_t aDisplayID);
   void FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID);
   void FireDOMVRDisplayConnectEvent(uint32_t aDisplayID);
   void FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID);
   void FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID);
+  void FireDOMVRDisplayConnectEventsForLoad(dom::VREventObserver* aObserver);
 
   virtual void HandleFatalError(const char* aName, const char* aMsg) const override;
 
 protected:
   explicit VRManagerChild();
   ~VRManagerChild();
   void Destroy();
   static void DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild);
@@ -107,16 +108,18 @@ protected:
   }
 private:
 
   void FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayUnmountedEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayDisconnectEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayPresentChangeEventInternal(uint32_t aDisplayID);
+  void FireDOMVRDisplayConnectEventsForLoadInternal(uint32_t aDisplayID,
+                                                    dom::VREventObserver* aObserver);
 
   nsTArray<RefPtr<VRDisplayClient> > mDisplays;
   bool mDisplaysInitialized;
   nsTArray<uint64_t> mNavigatorCallbacks;
 
   MessageLoop* mMessageLoop;
 
   struct FrameRequest;