--- a/dom/gamepad/GamepadManager.cpp
+++ b/dom/gamepad/GamepadManager.cpp
@@ -263,65 +263,16 @@ GamepadManager::RemoveGamepad(uint32_t a
return;
}
gamepad->SetConnected(false);
NewConnectionEvent(newIndex, false);
mGamepads.Remove(newIndex);
}
void
-GamepadManager::NewButtonEvent(uint32_t aIndex, GamepadServiceType aServiceType,
- uint32_t aButton, bool aPressed, bool aTouched,
- double aValue)
-{
- if (mShuttingDown) {
- return;
- }
-
- 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);
- }
- }
- }
-}
-
-void
GamepadManager::FireButtonEvent(EventTarget* aTarget,
Gamepad* aGamepad,
uint32_t aButton,
double aValue)
{
nsString name = aValue == 1.0L ? NS_LITERAL_STRING("gamepadbuttondown") :
NS_LITERAL_STRING("gamepadbuttonup");
GamepadButtonEventInit init;
@@ -334,63 +285,16 @@ GamepadManager::FireButtonEvent(EventTar
event->SetTrusted(true);
bool defaultActionEnabled = true;
aTarget->DispatchEvent(event, &defaultActionEnabled);
}
void
-GamepadManager::NewAxisMoveEvent(uint32_t aIndex, GamepadServiceType aServiceType,
- uint32_t aAxis, double aValue)
-{
- if (mShuttingDown) {
- return;
- }
-
- 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);
- }
- }
- }
-}
-
-void
GamepadManager::FireAxisMoveEvent(EventTarget* aTarget,
Gamepad* aGamepad,
uint32_t aAxis,
double aValue)
{
GamepadAxisMoveEventInit init;
init.mBubbles = false;
init.mCancelable = false;
@@ -404,102 +308,16 @@ GamepadManager::FireAxisMoveEvent(EventT
event->SetTrusted(true);
bool defaultActionEnabled = true;
aTarget->DispatchEvent(event, &defaultActionEnabled);
}
void
-GamepadManager::NewPoseEvent(uint32_t aIndex, GamepadServiceType aServiceType,
- const GamepadPoseState& aPose)
-{
- if (mShuttingDown) {
- return;
- }
-
- 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);
- }
- }
- }
-}
-
-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) {
@@ -671,55 +489,166 @@ GamepadManager::SetWindowHasSeenGamepad(
} else {
aWindow->RemoveGamepad(aIndex);
}
}
void
GamepadManager::Update(const GamepadChangeEvent& aEvent)
{
+ if (mShuttingDown) {
+ return;
+ }
+
if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
const GamepadAdded& a = aEvent.get_GamepadAdded();
AddGamepad(a.index(), a.id(),
static_cast<GamepadMappingType>(a.mapping()),
static_cast<GamepadHand>(a.hand()),
a.service_type(),
a.num_buttons(), a.num_axes(),
a.num_haptics());
return;
}
if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
const GamepadRemoved& a = aEvent.get_GamepadRemoved();
RemoveGamepad(a.index(), a.service_type());
return;
}
- if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
- const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
- NewButtonEvent(a.index(), a.service_type(), a.button(),
- a.pressed(), a.touched(), a.value());
+
+ if (!SetGamepadByEvent(aEvent)) {
return;
}
- if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
- const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation();
- NewAxisMoveEvent(a.index(), a.service_type(), a.axis(), a.value());
- return;
+
+ // 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;
+ }
+
+ SetGamepadByEvent(aEvent, listeners[i]);
+ MaybeConvertToNonstandardGamepadEvent(aEvent, listeners[i]);
}
- 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());
+}
+
+void
+GamepadManager::MaybeConvertToNonstandardGamepadEvent(const GamepadChangeEvent& aEvent,
+ nsGlobalWindow* aWindow)
+{
+ MOZ_ASSERT(aWindow);
+
+ if (!mNonstandardEventsEnabled) {
return;
}
- MOZ_CRASH("We shouldn't be here!");
+ RefPtr<Gamepad> gamepad;
+
+ switch (aEvent.type()) {
+ case GamepadChangeEvent::TGamepadButtonInformation:
+ {
+ const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
+ gamepad = aWindow->GetGamepad(a.index());
+ if (gamepad) {
+ FireButtonEvent(aWindow, gamepad, a.button(), a.value());
+ }
+ }
+ break;
+ case GamepadChangeEvent::TGamepadAxisInformation:
+ {
+ const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation();
+ gamepad = aWindow->GetGamepad(a.index());
+ if (gamepad) {
+ FireAxisMoveEvent(aWindow, gamepad, a.axis(), a.value());
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+bool
+GamepadManager::SetGamepadByEvent(const GamepadChangeEvent& aEvent, nsGlobalWindow *aWindow)
+{
+ uint32_t index;
+ RefPtr<Gamepad> gamepad;
+ bool ret = false;
+ bool firstTime = false;
+ switch (aEvent.type()) {
+ case GamepadChangeEvent::TGamepadButtonInformation:
+ {
+ const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
+ index = GetGamepadIndexWithServiceType(a.index(), a.service_type());
+ if (aWindow) {
+ firstTime = MaybeWindowHasSeenGamepad(aWindow, index);
+ }
+ gamepad = aWindow ? aWindow->GetGamepad(index) : GetGamepad(index);
+ if (gamepad) {
+ gamepad->SetButton(a.button(), a.pressed(), a.touched(), a.value());
+ ret = true;
+ }
+ } break;
+ case GamepadChangeEvent::TGamepadAxisInformation:
+ {
+ const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation();
+ index = GetGamepadIndexWithServiceType(a.index(), a.service_type());
+ if (aWindow) {
+ firstTime = MaybeWindowHasSeenGamepad(aWindow, index);
+ }
+ gamepad = aWindow ? aWindow->GetGamepad(index) : GetGamepad(index);
+ if (gamepad) {
+ gamepad->SetAxis(a.axis(), a.value());
+ ret = true;
+ }
+ } break;
+ case GamepadChangeEvent::TGamepadPoseInformation:
+ {
+ const GamepadPoseInformation& a = aEvent.get_GamepadPoseInformation();
+ index = GetGamepadIndexWithServiceType(a.index(), a.service_type());
+ if (aWindow) {
+ firstTime = MaybeWindowHasSeenGamepad(aWindow, index);
+ }
+ gamepad = aWindow ? aWindow->GetGamepad(index) : GetGamepad(index);
+ if (gamepad) {
+ gamepad->SetPose(a.pose_state());
+ ret = true;
+ }
+ } break;
+ case GamepadChangeEvent::TGamepadHandInformation:
+ {
+ const GamepadHandInformation& a = aEvent.get_GamepadHandInformation();
+ index = GetGamepadIndexWithServiceType(a.index(), a.service_type());
+ if (aWindow) {
+ firstTime = MaybeWindowHasSeenGamepad(aWindow, index);
+ }
+ gamepad = aWindow ? aWindow->GetGamepad(index) : GetGamepad(index);
+ if (gamepad) {
+ gamepad->SetHand(a.hand());
+ ret = true;
+ }
+ } break;
+ default:
+ MOZ_ASSERT(false);
+ break;
+ }
+
+ if (aWindow && firstTime) {
+ FireConnectionEvent(aWindow, gamepad, true);
+ }
+
+ return ret;
}
already_AddRefed<Promise>
GamepadManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration,
nsIGlobalObject* aGlobal, ErrorResult& aRv)
{
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
--- a/dom/gamepad/GamepadManager.h
+++ b/dom/gamepad/GamepadManager.h
@@ -52,39 +52,16 @@ class GamepadManager final : public nsIO
// Add a gamepad to the list of known gamepads.
void AddGamepad(uint32_t aIndex, const nsAString& aID, GamepadMappingType aMapping,
GamepadHand aHand, GamepadServiceType aServiceType,
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aNumHaptics);
// Remove the gamepad at |aIndex| from the list of known gamepads.
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, GamepadServiceType aServiceType, uint32_t aButton,
- bool aPressed, bool aTouched, double aValue);
-
- // Update the state of |aAxis| for the gamepad at |aIndex| for all
- // windows that are listening and visible, and fire a gamepadaxismove
- // event at them as well.
- 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);
@@ -136,16 +113,21 @@ class GamepadManager final : public nsIO
// will be destroyed during the IPDL shutdown chain, so we
// don't need to refcount it here.
nsTArray<GamepadEventChannelChild *> mChannelChildren;
private:
nsresult Init();
+ void MaybeConvertToNonstandardGamepadEvent(const GamepadChangeEvent& aEvent,
+ nsGlobalWindow* aWindow);
+
+ bool SetGamepadByEvent(const GamepadChangeEvent& aEvent, nsGlobalWindow* aWindow = nullptr);
+
bool MaybeWindowHasSeenGamepad(nsGlobalWindow* aWindow, uint32_t aIndex);
// 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,