bug 1313239 - Emit vrdisplayactivate event during document navigation
MozReview-Commit-ID: 92AvdabOzq6
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1482,17 +1482,18 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
mNetworkDownloadObserverEnabled(false),
#endif
mCleanedUp(false),
mDialogAbuseCount(0),
mAreDialogsEnabled(true),
#ifdef DEBUG
mIsValidatingTabGroup(false),
#endif
- mCanSkipCCGeneration(0)
+ mCanSkipCCGeneration(0),
+ mAutoActivateVRDisplayID(0)
{
AssertIsOnMainThread();
nsLayoutStatics::AddRef();
// Initialize the PRCList (this).
PR_INIT_CLIST(this);
@@ -3776,16 +3777,37 @@ nsGlobalWindow::PostHandleEvent(EventCha
nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
mozilla::Unused << kungFuDeathGrip2; // These aren't referred to through the function
if (aVisitor.mEvent->mMessage == eResize) {
mIsHandlingResizeEvent = false;
} else if (aVisitor.mEvent->mMessage == eUnload &&
aVisitor.mEvent->IsTrusted()) {
+
+ // If any VR display presentation is active at unload, the next page
+ // will receive a vrdisplayactive event to indicate that it should
+ // immediately begin vr presentation. This should occur when navigating
+ // forwards, navigating backwards, and on page reload.
+ for (auto display : mVRDisplays) {
+ if (display->IsPresenting()) {
+ // Save this VR display ID to trigger vrdisplayactivate event
+ // after the next load event.
+ nsGlobalWindow* outer = GetOuterWindowInternal();
+ if (outer) {
+ outer->SetAutoActivateVRDisplayID(display->DisplayId());
+ }
+
+ // XXX The WebVR 1.1 spec does not define which of multiple VR
+ // presenting VR displays will be chosen during navigation.
+ // As the underlying platform VR API's currently only allow a single
+ // VR display, it is safe to choose the first VR display for now.
+ break;
+ }
+ }
// Execute bindingdetached handlers before we tear ourselves
// down.
if (mDoc) {
mDoc->BindingManager()->ExecuteDetachedHandlers();
}
mIsDocumentLoaded = false;
} else if (aVisitor.mEvent->mMessage == eLoad &&
aVisitor.mEvent->IsTrusted()) {
@@ -3809,16 +3831,26 @@ nsGlobalWindow::PostHandleEvent(EventCha
// 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);
}
+
+ uint32_t autoActivateVRDisplayID = 0;
+ nsGlobalWindow* outer = GetOuterWindowInternal();
+ if (outer) {
+ autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
+ }
+ if (autoActivateVRDisplayID) {
+ DispatchVRDisplayActivate(autoActivateVRDisplayID,
+ VRDisplayEventReason::Navigation);
+ }
}
return NS_OK;
}
nsresult
nsGlobalWindow::DispatchDOMEvent(WidgetEvent* aEvent,
nsIDOMEvent* aDOMEvent,
@@ -13498,27 +13530,47 @@ nsGlobalWindow::NotifyActiveVRDisplaysCh
{
MOZ_ASSERT(IsInnerWindow());
if (mNavigator) {
mNavigator->NotifyActiveVRDisplaysChanged();
}
}
+uint32_t
+nsGlobalWindow::GetAutoActivateVRDisplayID()
+{
+ MOZ_ASSERT(IsOuterWindow());
+ uint32_t retVal = mAutoActivateVRDisplayID;
+ mAutoActivateVRDisplayID = 0;
+ return retVal;
+}
+
+void
+nsGlobalWindow::SetAutoActivateVRDisplayID(uint32_t aAutoActivateVRDisplayID)
+{
+ MOZ_ASSERT(IsOuterWindow());
+ mAutoActivateVRDisplayID = aAutoActivateVRDisplayID;
+}
+
void
nsGlobalWindow::DispatchVRDisplayActivate(uint32_t aDisplayID,
mozilla::dom::VRDisplayEventReason aReason)
{
// Search for the display identified with aDisplayID and fire the
// event if found.
for (auto display : mVRDisplays) {
- if (display->DisplayId() == aDisplayID
- && !display->IsAnyPresenting()) {
- // We only want to trigger this event if nobody is presenting to the
- // display already.
+ if (display->DisplayId() == aDisplayID) {
+ if (aReason != VRDisplayEventReason::Navigation &&
+ display->IsAnyPresenting()) {
+ // We only want to trigger this event if nobody is presenting to the
+ // display already or when a page is loaded by navigating away
+ // from a page with an active VR Presentation.
+ continue;
+ }
VRDisplayEventInit init;
init.mBubbles = false;
init.mCancelable = false;
init.mDisplay = display;
init.mReason.Construct(aReason);
RefPtr<VRDisplayEvent> event =
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -762,16 +762,21 @@ public:
// Update the VR displays for this window
bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
// Inner windows only.
// Called to inform that the set of active VR displays has changed.
void NotifyActiveVRDisplaysChanged();
+ // Outer windows only.
+ uint32_t GetAutoActivateVRDisplayID();
+ // Outer windows only.
+ void SetAutoActivateVRDisplayID(uint32_t aAutoActivateVRDisplayID);
+
void DispatchVRDisplayActivate(uint32_t aDisplayID,
mozilla::dom::VRDisplayEventReason aReason);
void DispatchVRDisplayDeactivate(uint32_t aDisplayID,
mozilla::dom::VRDisplayEventReason aReason);
void DispatchVRDisplayConnect(uint32_t aDisplayID);
void DispatchVRDisplayDisconnect(uint32_t aDisplayID);
void DispatchVRDisplayPresentChange(uint32_t aDisplayID);
@@ -2035,16 +2040,21 @@ protected:
// This is the CC generation the last time we called CanSkip.
uint32_t mCanSkipCCGeneration;
// The VR Displays for this window
nsTArray<RefPtr<mozilla::dom::VRDisplay>> mVRDisplays;
RefPtr<mozilla::dom::VREventObserver> mVREventObserver;
+ // When non-zero, the document should receive a vrdisplayactivate event
+ // after loading. The value is the ID of the VRDisplay that content should
+ // begin presentation on.
+ uint32_t mAutoActivateVRDisplayID; // Outer windows only
+
#ifdef ENABLE_INTL_API
RefPtr<mozilla::dom::IntlUtils> mIntlUtils;
#endif
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;
friend class mozilla::dom::PostMessageEvent;
friend class DesktopNotification;