Bug 1356452 - Part 3: Support changing gamepad hand property in GamepadManager; r?Lenzak draft
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 18 Apr 2017 15:55:15 +0800
changeset 565713 61ca4770eb5c568a0e28bca0c2465f41272f043d
parent 565712 0ef7fa3c3e7b6afbbfbdd68b81495ed16a873b25
child 565714 8a8ea263bff0fc0d94a887a8a2c5bf81478a71fd
push id54979
push userbmo:dmu@mozilla.com
push dateThu, 20 Apr 2017 09:28:49 +0000
reviewersLenzak
bugs1356452
milestone55.0a1
Bug 1356452 - Part 3: Support changing gamepad hand property in GamepadManager; r?Lenzak MozReview-Commit-ID: KZx2qJqks6f
dom/gamepad/GamepadManager.cpp
dom/gamepad/GamepadManager.h
dom/gamepad/ipc/GamepadEventTypes.ipdlh
--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -447,16 +447,59 @@ GamepadManager::NewPoseEvent(uint32_t aI
       if (firstTime) {
         FireConnectionEvent(listeners[i], listenerGamepad, true);
       }
     }
   }
 }
 
 void
+GamepadManager::NewHandChangeEvent(uint32_t aIndex, GamepadServiceType aServiceType,
+                                   GamepadHand aHand)
+{
+  if (mShuttingDown) {
+    return;
+  }
+
+  uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
+
+  RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
+  if (!gamepad) {
+    return;
+  }
+  gamepad->SetHand(aHand);
+
+  // Hold on to listeners in a separate array because firing events
+  // can mutate the mListeners array.
+  nsTArray<RefPtr<nsGlobalWindow>> listeners(mListeners);
+  MOZ_ASSERT(!listeners.IsEmpty());
+
+  for (uint32_t i = 0; i < listeners.Length(); i++) {
+
+    MOZ_ASSERT(listeners[i]->IsInnerWindow());
+
+    // Only send events to non-background windows
+    if (!listeners[i]->AsInner()->IsCurrentInnerWindow() ||
+        listeners[i]->GetOuterWindow()->IsBackground()) {
+      continue;
+    }
+
+    bool firstTime = MaybeWindowHasSeenGamepad(listeners[i], newIndex);
+
+    RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(newIndex);
+    if (listenerGamepad) {
+      listenerGamepad->SetHand(aHand);
+      if (firstTime) {
+        FireConnectionEvent(listeners[i], listenerGamepad, true);
+      }
+    }
+  }
+}
+
+void
 GamepadManager::NewConnectionEvent(uint32_t aIndex, bool aConnected)
 {
   if (mShuttingDown) {
     return;
   }
 
   RefPtr<Gamepad> gamepad = GetGamepad(aIndex);
   if (!gamepad) {
@@ -659,16 +702,21 @@ GamepadManager::Update(const GamepadChan
     NewAxisMoveEvent(a.index(), a.service_type(), a.axis(), a.value());
     return;
   }
   if (aEvent.type() == GamepadChangeEvent::TGamepadPoseInformation) {
     const GamepadPoseInformation& a = aEvent.get_GamepadPoseInformation();
     NewPoseEvent(a.index(), a.service_type(), a.pose_state());
     return;
   }
+   if (aEvent.type() == GamepadChangeEvent::TGamepadHandInformation) {
+    const GamepadHandInformation& a = aEvent.get_GamepadHandInformation();
+    NewHandChangeEvent(a.index(), a.service_type(), a.hand());
+    return;
+  }
 
   MOZ_CRASH("We shouldn't be here!");
 
 }
 
 already_AddRefed<Promise>
 GamepadManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
                               double aIntensity, double aDuration,
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -70,16 +70,21 @@ class GamepadManager final : public nsIO
   void NewAxisMoveEvent(uint32_t aIndex, GamepadServiceType aServiceType,
                         uint32_t aAxis, double aValue);
 
   // Update the state of |aState| for the gamepad at |aIndex| for all
   // windows that are listening and visible.
   void NewPoseEvent(uint32_t aIndex, GamepadServiceType aServiceType,
                     const GamepadPoseState& aState);
 
+  // Update the hand of |aHand| for the gamepad at |aIndex| for all
+  // windows that are listening and visible.
+  void NewHandChangeEvent(uint32_t aIndex, GamepadServiceType aServiceType,
+                          GamepadHand aHand);
+
   // Synchronize the state of |aGamepad| to match the gamepad stored at |aIndex|
   void SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad);
 
   // Returns gamepad object if index exists, null otherwise
   already_AddRefed<Gamepad> GetGamepad(uint32_t aIndex) const;
 
   // Receive GamepadChangeEvent messages from parent process to fire DOM events
   void Update(const GamepadChangeEvent& aGamepadEvent);
--- a/dom/gamepad/ipc/GamepadEventTypes.ipdlh
+++ b/dom/gamepad/ipc/GamepadEventTypes.ipdlh
@@ -44,18 +44,25 @@ struct GamepadButtonInformation {
 };
 
 struct GamepadPoseInformation {
   uint32_t index;
   GamepadServiceType service_type;
   GamepadPoseState pose_state;
 };
 
+struct GamepadHandInformation {
+  uint32_t index;
+  GamepadServiceType service_type;
+  GamepadHand hand;
+};
+
 union GamepadChangeEvent {
   GamepadAdded;
   GamepadRemoved;
   GamepadAxisInformation;
   GamepadButtonInformation;
   GamepadPoseInformation;
+  GamepadHandInformation;
 };
 
 } // namespace dom
 } // namespace mozilla
\ No newline at end of file