Bug 1250244 - Part 9: Implement WebVR DOM Events
MozReview-Commit-ID: DLpd5T6a24l
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -2047,24 +2047,27 @@ Navigator::RequestGamepadServiceTest()
already_AddRefed<Promise>
Navigator::GetVRDisplays(ErrorResult& aRv)
{
if (!mWindow || !mWindow->GetDocShell()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
+ nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
+ win->SetHasVREventListener(true);
+
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
RefPtr<Promise> p = Promise::Create(go, aRv);
if (aRv.Failed()) {
return nullptr;
}
- // We pass ourself to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
- // be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
+ // We pass ourself to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
+ // be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
if (!VRDisplay::RefreshVRDisplays(this)) {
p->MaybeReject(NS_ERROR_FAILURE);
return p.forget();
}
mVRGetDisplaysPromises.AppendElement(p);
return p.forget();
}
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -941,16 +941,19 @@ GK_ATOM(onunderflow, "onunderflow")
GK_ATOM(onunload, "onunload")
GK_ATOM(onupdatefound, "onupdatefound")
GK_ATOM(onupdateready, "onupdateready")
GK_ATOM(onupgradeneeded, "onupgradeneeded")
GK_ATOM(onussdreceived, "onussdreceived")
GK_ATOM(onversionchange, "onversionchange")
GK_ATOM(onvoicechange, "onvoicechange")
GK_ATOM(onvoiceschanged, "onvoiceschanged")
+GK_ATOM(onvrdisplayconnected, "onvrdisplayconnected")
+GK_ATOM(onvrdisplaydisconnected, "onvrdisplaydisconnected")
+GK_ATOM(onvrdisplaypresentchange, "onvrdisplaypresentchange")
GK_ATOM(onwebkitAnimationEnd, "onwebkitAnimationEnd")
GK_ATOM(onwebkitAnimationIteration, "onwebkitAnimationIteration")
GK_ATOM(onwebkitAnimationStart, "onwebkitAnimationStart")
GK_ATOM(onwebkitTransitionEnd, "onwebkitTransitionEnd")
GK_ATOM(onwebsocket, "onwebsocket")
GK_ATOM(onwheel, "onwheel")
GK_ATOM(open, "open")
GK_ATOM(optgroup, "optgroup")
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -188,16 +188,17 @@
#include "mozilla/dom/Promise.h"
#ifdef MOZ_GAMEPAD
#include "mozilla/dom/Gamepad.h"
#include "mozilla/dom/GamepadManager.h"
#endif
#include "mozilla/dom/VRDisplay.h"
+#include "mozilla/dom/VREventObserver.h"
#include "nsRefreshDriver.h"
#include "Layers.h"
#include "mozilla/AddonPathService.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
@@ -1202,16 +1203,17 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
mCreatingInnerWindow(false),
mIsChrome(false),
mCleanMessageManager(false),
mNeedsFocus(true),
mHasFocus(false),
mShowFocusRingForContent(false),
mFocusByKeyOccurred(false),
mHasGamepad(false),
+ mHasVREvents(false),
#ifdef MOZ_GAMEPAD
mHasSeenGamepadInput(false),
#endif
mNotifiedIDDestroyed(false),
mAllowScriptsToClose(false),
mTimeoutInsertionPoint(nullptr),
mTimeoutPublicIdCounter(1),
mTimeoutFiringDepth(0),
@@ -1581,16 +1583,18 @@ nsGlobalWindow::CleanUp()
#ifdef MOZ_WEBSPEECH
mSpeechSynthesis = nullptr;
#endif
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
mOrientationChangeObserver = nullptr;
#endif
+ mVREventObserver = nullptr;
+
ClearControllers();
mOpener = nullptr; // Forces Release
if (mContext) {
mContext = nullptr; // Forces Release
}
mChromeEventHandler = nullptr; // Forces Release
mParentTarget = nullptr;
@@ -1600,21 +1604,24 @@ nsGlobalWindow::CleanUp()
if (inner) {
inner->CleanUp();
}
}
if (IsInnerWindow()) {
DisableGamepadUpdates();
mHasGamepad = false;
+ DisableVRUpdates();
+ mHasVREvents = false;
#ifdef MOZ_B2G
DisableTimeChangeNotifications();
#endif
} else {
MOZ_ASSERT(!mHasGamepad);
+ MOZ_ASSERT(!mHasVREvents);
}
if (mCleanMessageManager) {
MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this);
if (asChrome->mMessageManager) {
static_cast<nsFrameMessageManager*>(
asChrome->mMessageManager.get())->Disconnect();
@@ -1705,16 +1712,18 @@ nsGlobalWindow::FreeInnerObjects()
if (mScreen) {
mScreen = nullptr;
}
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
mOrientationChangeObserver = nullptr;
#endif
+ mVREventObserver = nullptr;
+
if (mDoc) {
// Remember the document's principal and URI.
mDocumentPrincipal = mDoc->NodePrincipal();
mDocumentURI = mDoc->GetDocumentURI();
mDocBaseURI = mDoc->GetDocBaseURI();
while (mDoc->EventHandlingSuppressed()) {
mDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, false);
@@ -1743,16 +1752,18 @@ nsGlobalWindow::FreeInnerObjects()
}
mAudioContexts.Clear();
#ifdef MOZ_GAMEPAD
DisableGamepadUpdates();
mHasGamepad = false;
mGamepads.Clear();
#endif
+ DisableVRUpdates();
+ mHasVREvents = false;
mVRDisplays.Clear();
}
//*****************************************************************************
// nsGlobalWindow::nsISupports
//*****************************************************************************
// QueryInterface implementation for nsGlobalWindow
@@ -9938,16 +9949,34 @@ nsGlobalWindow::DisableGamepadUpdates()
if (gamepadManager) {
gamepadManager->RemoveListener(this);
}
#endif
}
}
void
+nsGlobalWindow::EnableVRUpdates()
+{
+ MOZ_ASSERT(IsInnerWindow());
+
+ if (mHasVREvents && !mVREventObserver) {
+ mVREventObserver = new mozilla::dom::VREventObserver(this);
+ }
+}
+
+void
+nsGlobalWindow::DisableVRUpdates()
+{
+ MOZ_ASSERT(IsInnerWindow());
+
+ mVREventObserver = nullptr;
+}
+
+void
nsGlobalWindow::SetChromeEventHandler(EventTarget* aChromeEventHandler)
{
MOZ_ASSERT(IsOuterWindow());
SetChromeEventHandlerInternal(aChromeEventHandler);
// update the chrome event handler on all our inner windows
for (nsGlobalWindow *inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
inner != this;
@@ -13069,16 +13098,17 @@ nsGlobalWindow::ResumeTimeouts(bool aTha
if (shouldResume) {
nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
if (ac) {
for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
ac->AddWindowListener(mEnabledSensors[i], this);
}
EnableGamepadUpdates();
+ EnableVRUpdates();
// Resume all of the AudioContexts for this window
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
ErrorResult dummy;
RefPtr<Promise> d = mAudioContexts[i]->Resume(dummy);
}
// Thaw or resume all of the workers for this window.
@@ -13258,16 +13288,26 @@ nsGlobalWindow::SetHasGamepadEventListen
MOZ_ASSERT(IsInnerWindow());
mHasGamepad = aHasGamepad;
if (aHasGamepad) {
EnableGamepadUpdates();
}
}
void
+nsGlobalWindow::SetHasVREventListener(bool aHasVREvents/* = true*/)
+{
+ MOZ_ASSERT(IsInnerWindow());
+ mHasVREvents = aHasVREvents;
+ if (aHasVREvents) {
+ EnableVRUpdates();
+ }
+}
+
+void
nsGlobalWindow::EnableTimeChangeNotifications()
{
mozilla::time::AddWindowListener(AsInner());
}
void
nsGlobalWindow::DisableTimeChangeNotifications()
{
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -117,16 +117,17 @@ class OwningExternalOrWindowProxy;
class Promise;
class PostMessageEvent;
struct RequestInit;
class RequestOrUSVString;
class Selection;
class SpeechSynthesis;
class U2F;
class VRDisplay;
+class VREventObserver;
class WakeLock;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
class WindowOrientationObserver;
#endif
namespace cache {
class CacheStorage;
} // namespace cache
class IDBFactory;
@@ -491,16 +492,17 @@ public:
FullscreenReason aReason, bool aIsFullscreen) override final;
virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
nsIWidget* aWidget, nsIScreen* aScreen);
bool FullScreen() const;
// Inner windows only.
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
+ virtual void SetHasVREventListener(bool aHasVREvents = true) override;
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
// WebIDL interface.
already_AddRefed<nsPIDOMWindowOuter> IndexedGetterOuter(uint32_t aIndex);
already_AddRefed<nsPIDOMWindowOuter> IndexedGetter(uint32_t aIndex);
@@ -796,16 +798,21 @@ public:
void SyncGamepadState();
#endif
// Inner windows only.
// Enable/disable updates for gamepad input.
void EnableGamepadUpdates();
void DisableGamepadUpdates();
+ // Inner windows only.
+ // Enable/disable updates for VR
+ void EnableVRUpdates();
+ void DisableVRUpdates();
+
// Update the VR displays for this window
bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
#define EVENT(name_, id_, type_, struct_) \
mozilla::dom::EventHandlerNonNull* GetOn##name_() \
{ \
mozilla::EventListenerManager* elm = GetExistingListenerManager(); \
return elm ? elm->GetEventHandler(nsGkAtoms::on##name_, EmptyString()) \
@@ -1760,16 +1767,20 @@ protected:
// true if tab navigation has occurred for this window. Focus rings
// should be displayed.
bool mFocusByKeyOccurred : 1;
// Inner windows only.
// Indicates whether this window wants gamepad input events
bool mHasGamepad : 1;
+
+ // Inner windows only.
+ // Indicates whether this window wants VR events
+ bool mHasVREvents : 1;
#ifdef MOZ_GAMEPAD
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
bool mHasSeenGamepadInput;
#endif
// whether we've sent the destroy notification for our window id
bool mNotifiedIDDestroyed : 1;
@@ -1904,16 +1915,18 @@ protected:
#endif
// 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;
+ nsAutoPtr<mozilla::dom::VREventObserver> mVREventObserver;
+
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;
friend class mozilla::dom::PostMessageEvent;
friend class DesktopNotification;
static WindowByIdTable* sWindowsById;
static bool sWarnedAboutWindowInternal;
};
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -466,16 +466,23 @@ public:
/**
* Tell this window that there is an observer for gamepad input
*
* Inner windows only.
*/
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) = 0;
/**
+ * Tell this window that there is an observer for VR events
+ *
+ * Inner windows only.
+ */
+ virtual void SetHasVREventListener(bool aHasVREvents = true) = 0;
+
+ /**
* Set a arguments for this window. This will be set on the window
* right away (if there's an existing document) and it will also be
* installed on the window when the next document is loaded.
*
* This function serves double-duty for passing both |arguments| and
* |dialogArguments| back from nsWindowWatcher to nsGlobalWindow. For the
* latter, the array is an array of length 0 whose only element is a
* DialogArgumentsHolder representing the JS value passed to showModalDialog.
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -414,16 +414,22 @@ EventListenerManager::AddEventListenerIn
}
} else if (aTypeAtom == nsGkAtoms::oncompositionend ||
aTypeAtom == nsGkAtoms::oncompositionstart ||
aTypeAtom == nsGkAtoms::oncompositionupdate ||
aTypeAtom == nsGkAtoms::oninput) {
if (!aFlags.mInSystemGroup) {
mMayHaveInputOrCompositionEventListener = true;
}
+ } else if (aTypeAtom == nsGkAtoms::onvrdisplayconnected ||
+ aTypeAtom == nsGkAtoms::onvrdisplaydisconnected ||
+ aTypeAtom == nsGkAtoms::onvrdisplaypresentchange) {
+ if (nsPIDOMWindowInner* window = GetInnerWindowForTarget()) {
+ window->SetHasVREventListener();
+ }
}
if (IsApzAwareListener(listener)) {
ProcessApzAwareEventListenerAdd();
}
if (aTypeAtom && mTarget) {
mTarget->EventListenerAdded(aTypeAtom);
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -583,16 +583,28 @@ WINDOW_ONLY_EVENT(userproximity,
eUserProximity,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(devicelight,
eDeviceLight,
EventNameType_None,
eBasicEventClass)
+WINDOW_ONLY_EVENT(vrdisplayconnected,
+ eVRDisplayConnected,
+ EventNameType_None,
+ eBasicEventClass)
+WINDOW_ONLY_EVENT(vrdisplaydisconnected,
+ eVRDisplayDisconnected,
+ EventNameType_None,
+ eBasicEventClass)
+WINDOW_ONLY_EVENT(vrdisplaypresentchange,
+ eVRDisplayPresentChange,
+ EventNameType_None,
+ eBasicEventClass)
// Install events as per W3C Manifest spec
WINDOW_ONLY_EVENT(install,
eInstall,
EventNameType_None,
eBasicEventClass)
#ifdef MOZ_B2G
new file mode 100644
--- /dev/null
+++ b/dom/vr/VREventObserver.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "VREventObserver.h"
+
+#include "nsGlobalWindow.h"
+#include "VRManagerChild.h"
+
+using namespace mozilla::dom;
+
+/**
+* This class is used by nsGlobalWindow to implement window.onvrdisplayconnected,
+* window.onvrdisplaydisconnected, and window.onvrdisplaypresentchange.
+*/
+VREventObserver::VREventObserver(
+ nsGlobalWindow* aGlobalWindow)
+ : mWindow(aGlobalWindow)
+{
+ MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
+
+ gfx::VRManagerChild* vmc = gfx::VRManagerChild::Get();
+ if (vmc) {
+ vmc->AddListener(this);
+ }
+}
+
+VREventObserver::~VREventObserver()
+{
+ gfx::VRManagerChild* vmc = gfx::VRManagerChild::Get();
+ if (vmc) {
+ vmc->RemoveListener(this);
+ }
+}
+
+void
+VREventObserver::NotifyVRDisplayConnected()
+{
+ if (mWindow->AsInner()->IsCurrentInnerWindow()) {
+ mWindow->GetOuterWindow()->DispatchCustomEvent(NS_LITERAL_STRING("vrdisplayconnected"));
+ }
+}
+
+void
+VREventObserver::NotifyVRDisplayDisconnected()
+{
+ if (mWindow->AsInner()->IsCurrentInnerWindow()) {
+ mWindow->GetOuterWindow()->DispatchCustomEvent(NS_LITERAL_STRING("vrdisplaydisconnected"));
+ }
+}
+
+void
+VREventObserver::NotifyVRDisplayPresentChange()
+{
+ // Background tabs should not be allowed to see when a foreground tab
+ // has started or ended vr presentation.
+ if (mWindow->AsInner()->IsCurrentInnerWindow() && !mWindow->GetOuterWindow()->IsBackground()) {
+ mWindow->GetOuterWindow()->DispatchCustomEvent(NS_LITERAL_STRING("vrdisplaypresentchange"));
+ }
+}
new file mode 100644
--- /dev/null
+++ b/dom/vr/VREventObserver.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_VREventObserver_h
+#define mozilla_dom_VREventObserver_h
+
+class nsGlobalWindow;
+
+namespace mozilla {
+namespace dom {
+class VREventObserver final
+{
+public:
+ ~VREventObserver();
+ explicit VREventObserver(nsGlobalWindow* aGlobalWindow);
+
+ void NotifyVRDisplayConnected();
+ void NotifyVRDisplayDisconnected();
+ void NotifyVRDisplayPresentChange();
+
+private:
+
+ // Weak pointer, instance is owned by mWindow.
+ nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_VREventObserver_h
--- a/dom/vr/moz.build
+++ b/dom/vr/moz.build
@@ -1,20 +1,22 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS.mozilla.dom += [
'VRDisplay.h',
+ 'VREventObserver.h',
]
UNIFIED_SOURCES = [
'VRDisplay.cpp',
+ 'VREventObserver.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/dom/base'
]
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -496,11 +496,20 @@ interface ChromeWindow {
* The optional panel argument should be set when moving a panel.
*
* Throws NS_ERROR_NOT_IMPLEMENTED if the OS doesn't support this.
*/
[Throws, Func="nsGlobalWindow::IsPrivilegedChromeWindow"]
void beginWindowMove(Event mouseDownEvent, optional Element? panel = null);
};
+partial interface Window {
+ [Pref="dom.vr.enabled"]
+ attribute EventHandler onvrdisplayconnected;
+ [Pref="dom.vr.enabled"]
+ attribute EventHandler onvrdisplaydisconnected;
+ [Pref="dom.vr.enabled"]
+ attribute EventHandler onvrdisplaypresentchange;
+};
+
Window implements ChromeWindow;
Window implements GlobalFetch;
Window implements ImageBitmapFactories;
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -6,21 +6,27 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VRManagerChild.h"
#include "VRManagerParent.h"
#include "VRDisplayClient.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/layers/CompositorThread.h" // for CompositorThread
#include "mozilla/dom/Navigator.h"
+#include "mozilla/dom/VREventObserver.h"
#include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
#include "mozilla/layers/TextureClient.h"
using layers::TextureClient;
+namespace {
+const nsTArray<RefPtr<dom::VREventObserver> >::index_type NoIndex =
+ nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
+} // namespace
+
namespace mozilla {
namespace gfx {
static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton;
void ReleaseVRManagerParentSingleton() {
sVRManagerParentSingleton = nullptr;
@@ -453,21 +459,62 @@ VRManagerChild::RunFrameRequestCallbacks
for (auto& callback : callbacks) {
callback.mCallback->Call(timeStamp);
}
}
void
VRManagerChild::FireDOMVRDisplayConnectedEvent()
{
+ for (auto& listener : mListeners) {
+ listener->NotifyVRDisplayConnected();
+ }
}
void
VRManagerChild::FireDOMVRDisplayDisconnectedEvent()
{
+ for (auto& listener : mListeners) {
+ listener->NotifyVRDisplayDisconnected();
+ }
}
void
VRManagerChild::FireDOMVRDisplayPresentChangeEvent()
{
+ for (auto& listener : mListeners) {
+ listener->NotifyVRDisplayPresentChange();
+ }
}
+
+void
+VRManagerChild::AddListener(dom::VREventObserver* aObserver)
+{
+ MOZ_ASSERT(aObserver);
+
+ if (mListeners.IndexOf(aObserver) != NoIndex) {
+ return; // already exists
+ }
+
+ mListeners.AppendElement(aObserver);
+ if (mListeners.Length() == 1) {
+ Unused << SendSetHaveEventListener(true);
+ }
+}
+
+void
+VRManagerChild::RemoveListener(dom::VREventObserver* aObserver)
+{
+ MOZ_ASSERT(aObserver);
+
+ if (mListeners.IndexOf(aObserver) == NoIndex) {
+ return; // doesn't exist
+ }
+
+ mListeners.RemoveElement(aObserver);
+
+ if (mListeners.Length() == 0) {
+ Unused << SendSetHaveEventListener(false);
+ }
+}
+
} // namespace gfx
} // namespace mozilla
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -14,16 +14,17 @@
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
#include "mozilla/layers/LayersTypes.h" // for LayersBackend
#include "mozilla/layers/TextureForwarder.h"
namespace mozilla {
namespace dom {
class Navigator;
class VRDisplay;
+class VREventObserver;
} // namespace dom
namespace layers {
class PCompositableChild;
class TextureClient;
}
namespace gfx {
class VRLayerChild;
class VRDisplayClient;
@@ -32,16 +33,21 @@ class VRManagerChild : public PVRManager
, public layers::TextureForwarder
, public layers::ShmemAllocator
{
public:
// NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VRManagerChild)
static VRManagerChild* Get();
+ // Indicate that an observer wants to receive VR events.
+ void AddListener(dom::VREventObserver* aObserver);
+ // Indicate that an observer should no longer receive VR events.
+ void RemoveListener(dom::VREventObserver* aObserver);
+
int GetInputFrameID();
bool GetVRDisplays(nsTArray<RefPtr<VRDisplayClient> >& aDisplays);
bool RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator);
static VRManagerChild* StartUpInChildProcess(Transport* aTransport,
ProcessId aOtherProcess);
static void StartUpSameProcess();
static void ShutDown();
@@ -142,16 +148,20 @@ private:
nsTArray<FrameRequest> mFrameRequestCallbacks;
/**
* The current frame request callback handle
*/
int32_t mFrameRequestCallbackCounter;
mozilla::TimeStamp mStartTimeStamp;
+
+ // Array of Weak pointers, instance is owned by nsGlobalWindow::mVREventObserver.
+ nsTArray<dom::VREventObserver*> mListeners;
+
/**
* Hold TextureClients refs until end of their usages on host side.
* It defer calling of TextureClient recycle callback.
*/
nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
layers::LayersBackend mBackend;
--- a/widget/EventMessageList.h
+++ b/widget/EventMessageList.h
@@ -369,16 +369,21 @@ NS_EVENT_MESSAGE(eAbsoluteDeviceOrientat
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
+// WebVR events
+NS_EVENT_MESSAGE(eVRDisplayConnected)
+NS_EVENT_MESSAGE(eVRDisplayDisconnected)
+NS_EVENT_MESSAGE(eVRDisplayPresentChange)
+
NS_EVENT_MESSAGE(eShow)
// Fullscreen DOM API
NS_EVENT_MESSAGE(eFullscreenChange)
NS_EVENT_MESSAGE(eFullscreenError)
NS_EVENT_MESSAGE(eMozFullscreenChange)
NS_EVENT_MESSAGE(eMozFullscreenError)