--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -195,18 +195,19 @@ 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
+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;
@@ -216,16 +217,86 @@ uint32_t GamepadManager::GetGamepadIndex
default:
MOZ_ASSERT(false);
break;
}
return newIndex;
}
+template<typename... Storages, typename Method, typename... Args>
+void
+GamepadManager::FireEventsToListener(Method aMethod, uint32_t aIndex, Args&&... aArgs)
+{
+ static_assert(sizeof...(Storages) == sizeof...(Args),
+ "<Storages...> size should be equal to number of arguments");
+ // 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], aIndex);
+
+ RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
+ if (listenerGamepad) {
+ (listenerGamepad->*aMethod)(mozilla::Forward<Args>(aArgs)...);
+ if (firstTime) {
+ FireConnectionEvent(listeners[i], listenerGamepad, true);
+ }
+ }
+ }
+}
+
+template<typename... Storages, typename Method1, typename Method2, typename... Args>
+void
+GamepadManager::FireEventsToListener(Method1 aMethod1, Method2 aMethod2, uint32_t aIndex, Args&&... aArgs)
+{
+ static_assert(sizeof...(Storages) == sizeof...(Args),
+ "<Storages...> size should be equal to number of arguments");
+ // 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], aIndex);
+
+ RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
+ if (listenerGamepad) {
+ (listenerGamepad->*aMethod1)(mozilla::Forward<Args>(aArgs)...);
+ if (firstTime) {
+ FireConnectionEvent(listeners[i], listenerGamepad, true);
+ }
+ if (mNonstandardEventsEnabled) {
+ // // Fire event
+ (this->*aMethod2)(listeners[i], listenerGamepad, mozilla::Forward<Args>(aArgs)...);
+ }
+ }
+ }
+}
+
void
GamepadManager::AddGamepad(uint32_t aIndex,
const nsAString& aId,
GamepadMappingType aMapping,
GamepadHand aHand,
GamepadServiceType aServiceType,
uint32_t aNumButtons,
uint32_t aNumAxes,
@@ -279,54 +350,34 @@ GamepadManager::NewButtonEvent(uint32_t
uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
if (!gamepad) {
return;
}
gamepad->SetButton(aButton, aPressed, aTouched, aValue);
-
- // 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->SetButton(aButton, aPressed, aTouched, aValue);
- if (firstTime) {
- FireConnectionEvent(listeners[i], listenerGamepad, true);
- }
- if (mNonstandardEventsEnabled) {
- // Fire event
- FireButtonEvent(listeners[i], listenerGamepad, aButton, aValue);
- }
- }
- }
+ FireEventsToListener<uint32_t, bool, bool, double>(
+ &Gamepad::SetButton, &GamepadManager::FireButtonEvent,
+ newIndex, aButton, aPressed, aTouched, aValue);
}
void
GamepadManager::FireButtonEvent(EventTarget* aTarget,
Gamepad* aGamepad,
uint32_t aButton,
+ bool aPressed,
+ bool aTouched,
double aValue)
{
+ // Due to FireEventsToListener(), we have to send
+ // these unused arguments for simplifying the duplicated
+ // code of firing events to global window listeners.
+ Unused << aPressed;
+ Unused << aTouched;
nsString name = aValue == 1.0L ? NS_LITERAL_STRING("gamepadbuttondown") :
NS_LITERAL_STRING("gamepadbuttonup");
GamepadButtonEventInit init;
init.mBubbles = false;
init.mCancelable = false;
init.mGamepad = aGamepad;
init.mButton = aButton;
RefPtr<GamepadButtonEvent> event =
@@ -348,46 +399,19 @@ GamepadManager::NewAxisMoveEvent(uint32_
uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
if (!gamepad) {
return;
}
gamepad->SetAxis(aAxis, aValue);
-
- // 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->SetAxis(aAxis, aValue);
- if (firstTime) {
- FireConnectionEvent(listeners[i], listenerGamepad, true);
- }
- if (mNonstandardEventsEnabled) {
- // Fire event
- FireAxisMoveEvent(listeners[i], listenerGamepad, aAxis, aValue);
- }
- }
- }
+ FireEventsToListener<uint32_t, double>(
+ &Gamepad::SetAxis, &GamepadManager::FireAxisMoveEvent,
+ newIndex, aAxis, aValue);
}
void
GamepadManager::FireAxisMoveEvent(EventTarget* aTarget,
Gamepad* aGamepad,
uint32_t aAxis,
double aValue)
{
@@ -418,42 +442,18 @@ GamepadManager::NewPoseEvent(uint32_t aI
uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
if (!gamepad) {
return;
}
gamepad->SetPose(aPose);
-
- // 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->SetPose(aPose);
- if (firstTime) {
- FireConnectionEvent(listeners[i], listenerGamepad, true);
- }
- }
- }
+ FireEventsToListener<const GamepadPoseState&>(
+ &Gamepad::SetPose, newIndex, aPose);
}
void
GamepadManager::NewHandChangeEvent(uint32_t aIndex, GamepadServiceType aServiceType,
GamepadHand aHand)
{
if (mShuttingDown) {
return;
@@ -461,42 +461,17 @@ GamepadManager::NewHandChangeEvent(uint3
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);
- }
- }
- }
+ FireEventsToListener<GamepadHand>(&Gamepad::SetHand, newIndex, aHand);
}
void
GamepadManager::NewConnectionEvent(uint32_t aIndex, bool aConnected)
{
if (mShuttingDown) {
return;
}
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -111,16 +111,18 @@ class GamepadManager final : public nsIO
uint32_t axis,
double value);
// Fire one of gamepadbutton{up,down} event at the window at |aTarget| for
// |aGamepad|.
void FireButtonEvent(EventTarget* aTarget,
Gamepad* aGamepad,
uint32_t aButton,
+ bool aPressed,
+ bool aTouched,
double aValue);
// Fire one of gamepad{connected,disconnected} event at the window at
// |aTarget| for |aGamepad|.
void FireConnectionEvent(EventTarget* aTarget,
Gamepad* aGamepad,
bool aConnected);
@@ -148,16 +150,21 @@ class GamepadManager final : public nsIO
// 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);
+ // Fire events to global windows and connection events if it's the first time
+ template<typename... Storages, typename Method, typename... Args>
+ void FireEventsToListener(Method aMethod, uint32_t aIndex, Args&&... aArgs);
+ template<typename... Storages, typename Method1, typename Method2, typename... Args>
+ void FireEventsToListener(Method1 aMethod1, Method2 aMethod2, uint32_t aIndex, Args&&... aArgs);
// 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;
uint32_t mPromiseID;