Bug 1299928 - Part 1: Make GamepadManager knows the gamepad is from VRController when adding gamepads; r?kip, lenzak800 draft
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 04 Oct 2016 10:57:04 +0800
changeset 425938 f1272e91c9892a16f793677e59173c7a02041c1c
parent 425712 9079d167112122805f99f57bb8856e1b1675af0f
child 425939 1188d0db2c19b6382437f580c1315815932be891
push id32537
push userbmo:dmu@mozilla.com
push dateMon, 17 Oct 2016 10:06:25 +0000
reviewerskip, lenzak800
bugs1299928
milestone52.0a1
Bug 1299928 - Part 1: Make GamepadManager knows the gamepad is from VRController when adding gamepads; r?kip, lenzak800 MozReview-Commit-ID: IBFqj2JTHxh
dom/gamepad/Gamepad.h
dom/gamepad/GamepadManager.cpp
dom/gamepad/GamepadManager.h
dom/gamepad/GamepadPlatformService.cpp
dom/gamepad/GamepadServiceTest.cpp
dom/gamepad/GamepadServiceTest.h
dom/gamepad/ipc/GamepadEventTypes.ipdlh
dom/gamepad/ipc/GamepadMessageUtils.h
dom/gamepad/ipc/GamepadTestChannelParent.cpp
dom/gamepad/moz.build
gfx/vr/ipc/VRManagerChild.cpp
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -28,16 +28,25 @@ const int kStandardGamepadAxes = 4;
 const int kButtonLeftTrigger = 6;
 const int kButtonRightTrigger = 7;
 
 const int kLeftStickXAxis = 0;
 const int kLeftStickYAxis = 1;
 const int kRightStickXAxis = 2;
 const int kRightStickYAxis = 3;
 
+// Standard channel is used for managing gamepads that
+// are from GamepadPlatformService. VR channel
+// is for gamepads that are from VRManagerChild.
+enum class GamepadServiceType : uint16_t {
+  Standard,
+  VR,
+  NumGamepadServiceType
+};
+
 class Gamepad final : public nsISupports,
                       public nsWrapperCache
 {
 public:
   Gamepad(nsISupports* aParent,
           const nsAString& aID, uint32_t aIndex,
           GamepadMappingType aMapping,
           uint32_t aNumButtons, uint32_t aNumAxes);
--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -45,16 +45,17 @@ const char* kGamepadEventsEnabledPref =
   "dom.gamepad.non_standard_events.enabled";
 
 const nsTArray<RefPtr<nsGlobalWindow>>::index_type NoIndex =
   nsTArray<RefPtr<nsGlobalWindow>>::NoIndex;
 
 bool sShutdown = false;
 
 StaticRefPtr<GamepadManager> gGamepadManagerSingleton;
+const uint32_t VR_GAMEPAD_IDX_OFFSET = 0x01 << 16;
 
 } // namespace
 
 NS_IMPL_ISUPPORTS(GamepadManager, nsIObserver)
 
 GamepadManager::GamepadManager()
   : mEnabled(false),
     mNonstandardEventsEnabled(false),
@@ -183,50 +184,80 @@ GamepadManager::GetGamepad(uint32_t aInd
   RefPtr<Gamepad> gamepad;
   if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
     return gamepad.forget();
   }
 
   return nullptr;
 }
 
+uint32_t GamepadManager::GetGamepadIndexWithServiceType(uint32_t aIndex,
+                                                        GamepadServiceType aServiceType)
+{
+  uint32_t newIndex = 0;
+
+  switch (aServiceType) {
+    case GamepadServiceType::Standard:
+    {
+     MOZ_ASSERT(aIndex <= VR_GAMEPAD_IDX_OFFSET);
+     newIndex = aIndex;
+     break;
+    }
+    case GamepadServiceType::VR:
+    {
+     newIndex = aIndex + VR_GAMEPAD_IDX_OFFSET;
+     break;
+    }
+    default:
+     MOZ_ASSERT(false);
+     break;
+  }
+
+  return newIndex;
+}
+
 void
 GamepadManager::AddGamepad(uint32_t aIndex,
                            const nsAString& aId,
                            GamepadMappingType aMapping,
+                           GamepadServiceType aServiceType,
                            uint32_t aNumButtons,
                            uint32_t aNumAxes)
 {
   //TODO: bug 852258: get initial button/axis state
   RefPtr<Gamepad> gamepad =
     new Gamepad(nullptr,
                 aId,
                 0, // index is set by global window
                 aMapping,
                 aNumButtons,
                 aNumAxes);
 
+  uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
+
   // We store the gamepad related to its index given by the parent process,
   // and no duplicate index is allowed.
-  MOZ_ASSERT(!mGamepads.Get(aIndex, nullptr));
-  mGamepads.Put(aIndex, gamepad);
-  NewConnectionEvent(aIndex, true);
+  MOZ_ASSERT(!mGamepads.Get(newIndex, nullptr));
+  mGamepads.Put(newIndex, gamepad);
+  NewConnectionEvent(newIndex, true);
 }
 
 void
-GamepadManager::RemoveGamepad(uint32_t aIndex)
+GamepadManager::RemoveGamepad(uint32_t aIndex, GamepadServiceType aServiceType)
 {
-  RefPtr<Gamepad> gamepad = GetGamepad(aIndex);
+  uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
+
+  RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
   if (!gamepad) {
     NS_WARNING("Trying to delete gamepad with invalid index");
     return;
   }
   gamepad->SetConnected(false);
-  NewConnectionEvent(aIndex, false);
-  mGamepads.Remove(aIndex);
+  NewConnectionEvent(newIndex, false);
+  mGamepads.Remove(newIndex);
 }
 
 void
 GamepadManager::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
                                double aValue)
 {
   if (mShuttingDown) {
     return;
@@ -539,23 +570,23 @@ GamepadManager::SetWindowHasSeenGamepad(
 }
 
 void
 GamepadManager::Update(const GamepadChangeEvent& aEvent)
 {
   if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
     const GamepadAdded& a = aEvent.get_GamepadAdded();
     AddGamepad(a.index(), a.id(),
-               static_cast<GamepadMappingType>(a.mapping()),
+               a.mapping(), a.service_type(),
                a.num_buttons(), a.num_axes());
     return;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
     const GamepadRemoved& a = aEvent.get_GamepadRemoved();
-    RemoveGamepad(a.index());
+    RemoveGamepad(a.index(), a.service_type());
     return;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
     const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
     NewButtonEvent(a.index(), a.button(), a.pressed(), a.value());
     return;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -42,20 +42,20 @@ class GamepadManager final : public nsIO
 
   // Indicate that |aWindow| wants to receive gamepad events.
   void AddListener(nsGlobalWindow* aWindow);
   // Indicate that |aWindow| should no longer receive gamepad events.
   void RemoveListener(nsGlobalWindow* aWindow);
 
   // Add a gamepad to the list of known gamepads.
   void AddGamepad(uint32_t aIndex, const nsAString& aID, GamepadMappingType aMapping,
-                  uint32_t aNumButtons, uint32_t aNumAxes);
+                  GamepadServiceType aServiceType, uint32_t aNumButtons, uint32_t aNumAxes);
 
   // Remove the gamepad at |aIndex| from the list of known gamepads.
-  void RemoveGamepad(uint32_t aIndex);
+  void RemoveGamepad(uint32_t aIndex, GamepadServiceType aServiceType);
 
   // Update the state of |aButton| for the gamepad at |aIndex| for all
   // windows that are listening and visible, and fire one of
   // a gamepadbutton{up,down} event at them as well.
   // aPressed is used for digital buttons, aValue is for analog buttons.
   void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
                       double aValue);
 
@@ -122,16 +122,19 @@ class GamepadManager final : public nsIO
   // Returns true if we have already sent data from this gamepad
   // to this window. This should only return true if the user
   // explicitly interacted with a gamepad while this window
   // was focused, by pressing buttons or similar actions.
   bool WindowHasSeenGamepad(nsGlobalWindow* aWindow, uint32_t aIndex) const;
   // Indicate that a window has received data from a gamepad.
   void SetWindowHasSeenGamepad(nsGlobalWindow* aWindow, uint32_t aIndex,
                                bool aHasSeen = true);
+  // Our gamepad index has VR_GAMEPAD_IDX_OFFSET while GamepadChannelType
+  // is from VRManager.
+  uint32_t GetGamepadIndexWithServiceType(uint32_t aIndex, GamepadServiceType aServiceType);
 
   // Gamepads connected to the system. Copies of these are handed out
   // to each window.
   nsRefPtrHashtable<nsUint32HashKey, Gamepad> mGamepads;
   // Inner windows that are listening for gamepad events.
   // has been sent to that window.
   nsTArray<RefPtr<nsGlobalWindow>> mListeners;
 };
--- a/dom/gamepad/GamepadPlatformService.cpp
+++ b/dom/gamepad/GamepadPlatformService.cpp
@@ -82,29 +82,29 @@ GamepadPlatformService::AddGamepad(const
 {
   // This method is called by monitor thread populated in
   // platform-dependent backends
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(!NS_IsMainThread());
 
   uint32_t index = ++mGamepadIndex;
   GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), index,
-                 (uint32_t)aMapping, aNumButtons, aNumAxes);
+                 aMapping, GamepadServiceType::Standard, aNumButtons, aNumAxes);
   NotifyGamepadChange<GamepadAdded>(a);
   return index;
 }
 
 void
 GamepadPlatformService::RemoveGamepad(uint32_t aIndex)
 {
   // This method is called by monitor thread populated in
   // platform-dependent backends
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(!NS_IsMainThread());
-  GamepadRemoved a(aIndex);
+  GamepadRemoved a(aIndex, GamepadServiceType::Standard);
   NotifyGamepadChange<GamepadRemoved>(a);
 }
 
 void
 GamepadPlatformService::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
                                        bool aPressed, double aValue)
 {
   // This method is called by monitor thread populated in
--- a/dom/gamepad/GamepadServiceTest.cpp
+++ b/dom/gamepad/GamepadServiceTest.cpp
@@ -117,18 +117,22 @@ GamepadServiceTest::AddGamepad(const nsA
                                uint32_t aNumButtons,
                                uint32_t aNumAxes,
                                ErrorResult& aRv)
 {
   if (mShuttingDown) {
     return nullptr;
   }
 
+  // Because GamepadServiceTest::AddGamepad() is opened for Web API,
+  // we need to convert aMapping from uint32_t to GamepadMappingType here.
   GamepadAdded a(nsString(aID), 0,
-                (uint32_t)aMapping, aNumButtons, aNumAxes);
+                 static_cast<GamepadMappingType>(aMapping),
+                 GamepadServiceType::Standard,
+                 aNumButtons, aNumAxes);
   GamepadChangeEvent e(a);
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
 
   RefPtr<Promise> p = Promise::Create(go, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
@@ -145,17 +149,17 @@ GamepadServiceTest::AddGamepad(const nsA
 
 void
 GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
 {
   if (mShuttingDown) {
     return;
   }
 
-  GamepadRemoved a(aIndex);
+  GamepadRemoved a(aIndex, GamepadServiceType::Standard);
   GamepadChangeEvent e(a);
 
   uint32_t id = ++mEventNumber;
   if (mChild) {
     mChild->SendGamepadTestEvent(id, e);
   } else {
     PendingOperation op(id, e);
     mPendingOperations.AppendElement(op);
--- a/dom/gamepad/GamepadServiceTest.h
+++ b/dom/gamepad/GamepadServiceTest.h
@@ -3,16 +3,17 @@
 /* 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_GamepadServiceTest_h_
 #define mozilla_dom_GamepadServiceTest_h_
 
 #include "nsIIPCBackgroundChildCreateCallback.h"
+#include "mozilla/dom/GamepadBinding.h"
 
 namespace mozilla {
 namespace dom {
 
 class GamepadChangeEvent;
 class GamepadManager;
 class GamepadTestChannelChild;
 class Promise;
--- a/dom/gamepad/ipc/GamepadEventTypes.ipdlh
+++ b/dom/gamepad/ipc/GamepadEventTypes.ipdlh
@@ -1,25 +1,31 @@
 /* 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/. */
 
+using mozilla::dom::GamepadMappingType from "mozilla/dom/GamepadMessageUtils.h";
+using mozilla::dom::GamepadServiceType from "mozilla/dom/GamepadMessageUtils.h";
+
+
 namespace mozilla {
 namespace dom {
 
 struct GamepadAdded {
   nsString id;
   uint32_t index;
-  uint32_t mapping;
+  GamepadMappingType mapping;
+  GamepadServiceType service_type;
   uint32_t num_buttons;
   uint32_t num_axes;
 };
 
 struct GamepadRemoved {
   uint32_t index;
+  GamepadServiceType service_type;
 };
 
 struct GamepadAxisInformation {
   uint32_t index;
   uint32_t axis;
   double value;
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/gamepad/ipc/GamepadMessageUtils.h
@@ -0,0 +1,24 @@
+
+#ifndef mozilla_dom_gamepad_GamepadMessageUtils_h
+#define mozilla_dom_gamepad_GamepadMessageUtils_h
+
+#include "ipc/IPCMessageUtils.h"
+#include "mozilla/dom/Gamepad.h"
+
+namespace IPC {
+
+template<>
+struct ParamTraits<mozilla::dom::GamepadMappingType> :
+  public ContiguousEnumSerializer<mozilla::dom::GamepadMappingType,
+                                  mozilla::dom::GamepadMappingType(mozilla::dom::GamepadMappingType::_empty),
+                                  mozilla::dom::GamepadMappingType(mozilla::dom::GamepadMappingType::EndGuard_)> {};
+
+template<>
+struct ParamTraits<mozilla::dom::GamepadServiceType> :
+  public ContiguousEnumSerializer<mozilla::dom::GamepadServiceType,
+                                  mozilla::dom::GamepadServiceType(0),
+                                  mozilla::dom::GamepadServiceType(
+                                  mozilla::dom::GamepadServiceType::NumGamepadServiceType)> {};
+} // namespace IPC
+
+#endif // mozilla_dom_gamepad_GamepadMessageUtils_h
\ No newline at end of file
--- a/dom/gamepad/ipc/GamepadTestChannelParent.cpp
+++ b/dom/gamepad/ipc/GamepadTestChannelParent.cpp
@@ -18,17 +18,17 @@ GamepadTestChannelParent::RecvGamepadTes
   RefPtr<GamepadPlatformService>  service =
     GamepadPlatformService::GetParentService();
   MOZ_ASSERT(service);
   if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
     const GamepadAdded& a = aEvent.get_GamepadAdded();
     nsCString gamepadID;
     LossyCopyUTF16toASCII(a.id(), gamepadID);
     uint32_t index = service->AddGamepad(gamepadID.get(),
-                                         (GamepadMappingType)a.mapping(),
+                                         a.mapping(),
                                          a.num_buttons(),
                                          a.num_axes());
     if (!mShuttingdown) {
       Unused << SendReplyGamepadIndex(aID, index);
     }
     return true;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
--- a/dom/gamepad/moz.build
+++ b/dom/gamepad/moz.build
@@ -15,16 +15,17 @@ if CONFIG['MOZ_GAMEPAD']:
         'Gamepad.h',
         'GamepadButton.h',
         'GamepadManager.h',
         'GamepadMonitoring.h',
         'GamepadPlatformService.h',
         'GamepadServiceTest.h',
         'ipc/GamepadEventChannelChild.h',
         'ipc/GamepadEventChannelParent.h',
+        'ipc/GamepadMessageUtils.h',
         'ipc/GamepadTestChannelChild.h',
         'ipc/GamepadTestChannelParent.h'
         ]
 
     UNIFIED_SOURCES = [
         'Gamepad.cpp',
         'GamepadButton.cpp',
         'GamepadManager.cpp',
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -32,16 +32,17 @@ static StaticRefPtr<VRManagerParent> sVR
 
 void ReleaseVRManagerParentSingleton() {
   sVRManagerParentSingleton = nullptr;
 }
 
 VRManagerChild::VRManagerChild()
   : TextureForwarder()
   , mDisplaysInitialized(false)
+  , mGamepadManager(nullptr)
   , mInputFrameID(-1)
   , mMessageLoop(MessageLoop::current())
   , mFrameRequestCallbackCounter(0)
   , mBackend(layers::LayersBackend::LAYERS_NONE)
 {
   MOZ_COUNT_CTOR(VRManagerChild);
   MOZ_ASSERT(NS_IsMainThread());