Bug 1250244 - Part 8: Implement WebVR DOM Events,r=bz

MozReview-Commit-ID: 4Fk0WszVTBR
This commit is contained in:
kearwood 2016-07-04 15:46:49 -07:00
Родитель 434f167559
Коммит 905f496ed5
14 изменённых файлов: 289 добавлений и 14 удалений

Просмотреть файл

@ -2044,14 +2044,17 @@ Navigator::GetVRDisplays(ErrorResult& aRv)
return nullptr;
}
nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
win->NotifyVREventListenerAdded();
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();
@ -2068,9 +2071,9 @@ Navigator::NotifyVRDisplaysUpdated()
// mVRGetDisplaysPromises
nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
nsTArray<RefPtr<VRDisplay>> vrDisplays;
if (win->UpdateVRDisplays(vrDisplays)) {
for (auto p : mVRGetDisplaysPromises) {
nsTArray<RefPtr<VRDisplay>> vrDisplays;
if (win->UpdateVRDisplays(vrDisplays)) {
for (auto p : mVRGetDisplaysPromises) {
p->MaybeResolve(vrDisplays);
}
} else {

Просмотреть файл

@ -948,6 +948,9 @@ GK_ATOM(onussdreceived, "onussdreceived")
GK_ATOM(onversionchange, "onversionchange")
GK_ATOM(onvoicechange, "onvoicechange")
GK_ATOM(onvoiceschanged, "onvoiceschanged")
GK_ATOM(onvrdisplayconnect, "onvrdisplayconnect")
GK_ATOM(onvrdisplaydisconnect, "onvrdisplaydisconnect")
GK_ATOM(onvrdisplaypresentchange, "onvrdisplaypresentchange")
GK_ATOM(onwebkitAnimationEnd, "onwebkitAnimationEnd")
GK_ATOM(onwebkitAnimationIteration, "onwebkitAnimationIteration")
GK_ATOM(onwebkitAnimationStart, "onwebkitAnimationStart")

Просмотреть файл

@ -193,6 +193,7 @@
#endif
#include "mozilla/dom/VRDisplay.h"
#include "mozilla/dom/VREventObserver.h"
#include "nsRefreshDriver.h"
#include "Layers.h"
@ -1200,6 +1201,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mShowFocusRingForContent(false),
mFocusByKeyOccurred(false),
mHasGamepad(false),
mHasVREvents(false),
#ifdef MOZ_GAMEPAD
mHasSeenGamepadInput(false),
#endif
@ -1599,11 +1601,14 @@ nsGlobalWindow::CleanUp()
if (IsInnerWindow()) {
DisableGamepadUpdates();
mHasGamepad = false;
DisableVRUpdates();
mHasVREvents = false;
#ifdef MOZ_B2G
DisableTimeChangeNotifications();
#endif
} else {
MOZ_ASSERT(!mHasGamepad);
MOZ_ASSERT(!mHasVREvents);
}
if (mCleanMessageManager) {
@ -1743,6 +1748,8 @@ nsGlobalWindow::FreeInnerObjects()
mHasGamepad = false;
mGamepads.Clear();
#endif
DisableVRUpdates();
mHasVREvents = false;
mVRDisplays.Clear();
}
@ -9883,6 +9890,24 @@ nsGlobalWindow::DisableGamepadUpdates()
}
}
void
nsGlobalWindow::EnableVRUpdates()
{
MOZ_ASSERT(IsInnerWindow());
if (mHasVREvents && !mVREventObserver) {
mVREventObserver = new VREventObserver(this);
}
}
void
nsGlobalWindow::DisableVRUpdates()
{
MOZ_ASSERT(IsInnerWindow());
mVREventObserver = nullptr;
}
void
nsGlobalWindow::SetChromeEventHandler(EventTarget* aChromeEventHandler)
{
@ -12933,6 +12958,7 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
ac->RemoveWindowListener(mEnabledSensors[i], this);
}
DisableGamepadUpdates();
DisableVRUpdates();
// Freeze or suspend all of the workers for this window.
if (aFreezeWorkers) {
@ -13019,6 +13045,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren, bool aThawWorkers)
ac->AddWindowListener(mEnabledSensors[i], this);
}
EnableGamepadUpdates();
EnableVRUpdates();
// Resume all of the AudioContexts for this window
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
@ -13209,6 +13236,25 @@ nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
}
}
void
nsGlobalWindow::EventListenerAdded(nsIAtom* aType)
{
if (aType == nsGkAtoms::onvrdisplayconnect ||
aType == nsGkAtoms::onvrdisplaydisconnect ||
aType == nsGkAtoms::onvrdisplaypresentchange) {
NotifyVREventListenerAdded();
}
}
void
nsGlobalWindow::NotifyVREventListenerAdded()
{
MOZ_ASSERT(IsInnerWindow());
mHasVREvents = true;
EnableVRUpdates();
}
void
nsGlobalWindow::EnableTimeChangeNotifications()
{

Просмотреть файл

@ -123,6 +123,7 @@ class Selection;
class SpeechSynthesis;
class U2F;
class VRDisplay;
class VREventObserver;
class WakeLock;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
class WindowOrientationObserver;
@ -496,6 +497,8 @@ public:
// Inner windows only.
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
void NotifyVREventListenerAdded();
virtual void EventListenerAdded(nsIAtom* aType) override;
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
@ -801,6 +804,11 @@ public:
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);
@ -1766,6 +1774,10 @@ protected:
// 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;
@ -1911,6 +1923,8 @@ protected:
// 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;

Просмотреть файл

@ -599,7 +599,18 @@ WINDOW_ONLY_EVENT(devicelight,
eDeviceLight,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(vrdisplayconnect,
eVRDisplayConnect,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(vrdisplaydisconnect,
eVRDisplayDisconnect,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(vrdisplaypresentchange,
eVRDisplayPresentChange,
EventNameType_None,
eBasicEventClass)
// Install events as per W3C Manifest spec
WINDOW_ONLY_EVENT(install,
eInstall,

Просмотреть файл

@ -0,0 +1,72 @@
/* -*- 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 "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "VRManagerChild.h"
namespace mozilla {
namespace dom {
using namespace gfx;
/**
* 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());
VRManagerChild* vmc = VRManagerChild::Get();
if (vmc) {
vmc->AddListener(this);
}
}
VREventObserver::~VREventObserver()
{
VRManagerChild* vmc = VRManagerChild::Get();
if (vmc) {
vmc->RemoveListener(this);
}
}
void
VREventObserver::NotifyVRDisplayConnect()
{
if (mWindow->AsInner()->IsCurrentInnerWindow()) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
mWindow->GetOuterWindow()->DispatchCustomEvent(
NS_LITERAL_STRING("vrdisplayconnected"));
}
}
void
VREventObserver::NotifyVRDisplayDisconnect()
{
if (mWindow->AsInner()->IsCurrentInnerWindow()) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
mWindow->GetOuterWindow()->DispatchCustomEvent(
NS_LITERAL_STRING("vrdisplaydisconnected"));
}
}
void
VREventObserver::NotifyVRDisplayPresentChange()
{
if (mWindow->AsInner()->IsCurrentInnerWindow()) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
mWindow->GetOuterWindow()->DispatchCustomEvent(
NS_LITERAL_STRING("vrdisplaypresentchange"));
}
}
} // namespace dom
} // namespace mozilla

33
dom/vr/VREventObserver.h Normal file
Просмотреть файл

@ -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 NotifyVRDisplayConnect();
void NotifyVRDisplayDisconnect();
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

Просмотреть файл

@ -6,10 +6,12 @@
EXPORTS.mozilla.dom += [
'VRDisplay.h',
'VREventObserver.h',
]
UNIFIED_SOURCES = [
'VRDisplay.cpp',
'VREventObserver.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')

Просмотреть файл

@ -503,6 +503,15 @@ interface ChromeWindow {
void beginWindowMove(Event mouseDownEvent, optional Element? panel = null);
};
partial interface Window {
[Pref="dom.vr.enabled"]
attribute EventHandler onvrdisplayconnect;
[Pref="dom.vr.enabled"]
attribute EventHandler onvrdisplaydisconnect;
[Pref="dom.vr.enabled"]
attribute EventHandler onvrdisplaypresentchange;
};
Window implements ChromeWindow;
Window implements GlobalFetch;
Window implements ImageBitmapFactories;

Просмотреть файл

@ -141,7 +141,7 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
if (bHaveEventListener) {
// If content has set an EventHandler to be notified of VR display events
// we must continually refresh the VR display enumeration to check
// for events that we must fire such as Window.onvrdisplayconnected
// for events that we must fire such as Window.onvrdisplayconnect
// Note that enumeration itself may activate display hardware, such
// as Oculus, so we only do this when we know we are displaying content
// that is looking for VR displays.

Просмотреть файл

@ -50,7 +50,7 @@ parent:
sync GetSensorState(uint32_t aDisplayID) returns(VRHMDSensorState aState);
sync GetImmediateSensorState(uint32_t aDisplayID) returns(VRHMDSensorState aState);
async SetHaveEventListener(bool aHaveEventListener);
sync SetHaveEventListener(bool aHaveEventListener);
child:

Просмотреть файл

@ -11,11 +11,18 @@
#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"
#include "nsContentUtils.h"
using layers::TextureClient;
namespace {
const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
} // namespace
namespace mozilla {
namespace gfx {
@ -241,10 +248,10 @@ VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
mNavigatorCallbacks.Clear();
if (bDisplayConnected) {
FireDOMVRDisplayConnectedEvent();
FireDOMVRDisplayConnectEvent();
}
if (bDisplayDisconnected) {
FireDOMVRDisplayDisconnectedEvent();
FireDOMVRDisplayDisconnectEvent();
}
return true;
@ -461,18 +468,75 @@ VRManagerChild::RunFrameRequestCallbacks()
}
void
VRManagerChild::FireDOMVRDisplayConnectedEvent()
VRManagerChild::FireDOMVRDisplayConnectEvent()
{
nsContentUtils::AddScriptRunner(NewRunnableMethod(this,
&VRManagerChild::FireDOMVRDisplayConnectEventInternal));
}
void
VRManagerChild::FireDOMVRDisplayDisconnectedEvent()
VRManagerChild::FireDOMVRDisplayDisconnectEvent()
{
nsContentUtils::AddScriptRunner(NewRunnableMethod(this,
&VRManagerChild::FireDOMVRDisplayDisconnectEventInternal));
}
void
VRManagerChild::FireDOMVRDisplayPresentChangeEvent()
{
nsContentUtils::AddScriptRunner(NewRunnableMethod(this,
&VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal));
}
void
VRManagerChild::FireDOMVRDisplayConnectEventInternal()
{
for (auto& listener : mListeners) {
listener->NotifyVRDisplayConnect();
}
}
void
VRManagerChild::FireDOMVRDisplayDisconnectEventInternal()
{
for (auto& listener : mListeners) {
listener->NotifyVRDisplayDisconnect();
}
}
void
VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal()
{
for (auto& listener : mListeners) {
listener->NotifyVRDisplayPresentChange();
}
}
void
VRManagerChild::AddListener(dom::VREventObserver* aObserver)
{
MOZ_ASSERT(aObserver);
if (mListeners.IndexOf(aObserver) != kNoIndex) {
return; // already exists
}
mListeners.AppendElement(aObserver);
if (mListeners.Length() == 1) {
Unused << SendSetHaveEventListener(true);
}
}
void
VRManagerChild::RemoveListener(dom::VREventObserver* aObserver)
{
MOZ_ASSERT(aObserver);
mListeners.RemoveElement(aObserver);
if (mListeners.IsEmpty()) {
Unused << SendSetHaveEventListener(false);
}
}
} // namespace gfx
} // namespace mozilla

Просмотреть файл

@ -19,6 +19,7 @@ namespace mozilla {
namespace dom {
class Navigator;
class VRDisplay;
class VREventObserver;
} // namespace dom
namespace layers {
class PCompositableChild;
@ -35,6 +36,11 @@ class VRManagerChild : public PVRManagerChild
public:
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);
@ -66,8 +72,8 @@ public:
void CancelFrameRequestCallback(int32_t aHandle);
void RunFrameRequestCallbacks();
void FireDOMVRDisplayConnectedEvent();
void FireDOMVRDisplayDisconnectedEvent();
void FireDOMVRDisplayConnectEvent();
void FireDOMVRDisplayDisconnectEvent();
void FireDOMVRDisplayPresentChangeEvent();
protected:
@ -124,6 +130,10 @@ protected:
private:
void FireDOMVRDisplayConnectEventInternal();
void FireDOMVRDisplayDisconnectEventInternal();
void FireDOMVRDisplayPresentChangeEventInternal();
void DeliverFence(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle);
/**
* Notify id of Texture When host side end its use. Transaction id is used to
@ -147,6 +157,9 @@ private:
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.

Просмотреть файл

@ -372,6 +372,11 @@ NS_EVENT_MESSAGE(eDeviceLight)
NS_EVENT_MESSAGE(eOrientationChange)
#endif
// WebVR events
NS_EVENT_MESSAGE(eVRDisplayConnect)
NS_EVENT_MESSAGE(eVRDisplayDisconnect)
NS_EVENT_MESSAGE(eVRDisplayPresentChange)
NS_EVENT_MESSAGE(eShow)
// Fullscreen DOM API