void GamepadService::SetWindowHasSeenGamepad(nsGlobalWindow* aWindow, uint32_t aIndex, bool aHasSeen) { MOZ_ASSERT(aWindow); MOZ_ASSERT(aWindow->IsInnerWindow()); if (mListeners.IndexOf(aWindow) == NoIndex) { // This window isn't even listening for gamepad events. return; } if (aHasSeen) { aWindow->SetHasSeenGamepadInput(true); nsCOMPtr<nsISupports> window = ToSupports(aWindow); RefPtr<Gamepad> gamepad = GetGamepad(aIndex); MOZ_ASSERT(gamepad); if (!gamepad) { return; } RefPtr<Gamepad> clonedGamepad = gamepad->Clone(window); aWindow->AddGamepad(aIndex, clonedGamepad); } else { aWindow->RemoveGamepad(aIndex); } }
void GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected) { RefPtr<Gamepad> gamepad = GetGamepad(aIndex); if (mShuttingDown || !gamepad) { return; } // Hold on to listeners in a separate array because firing events // can mutate the mListeners array. nsTArray<RefPtr<nsGlobalWindow> > listeners(mListeners); if (aConnected) { for (uint32_t i = listeners.Length(); i > 0 ; ) { --i; MOZ_ASSERT(listeners[i]->IsInnerWindow()); // Only send events to non-background windows if (!listeners[i]->AsInner()->IsCurrentInnerWindow() || listeners[i]->GetOuterWindow()->IsBackground()) { continue; } // We don't fire a connected event here unless the window // has seen input from at least one device. if (!listeners[i]->HasSeenGamepadInput()) { continue; } SetWindowHasSeenGamepad(listeners[i], aIndex); RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex); if (listenerGamepad) { // Fire event FireConnectionEvent(listeners[i], listenerGamepad, aConnected); } } } else { // For disconnection events, fire one at every window that has received // data from this gamepad. for (uint32_t i = listeners.Length(); i > 0 ; ) { --i; // Even background windows get these events, so we don't have to // deal with the hassle of syncing the state of removed gamepads. if (WindowHasSeenGamepad(listeners[i], aIndex)) { RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex); if (listenerGamepad) { listenerGamepad->SetConnected(false); // Fire event FireConnectionEvent(listeners[i], listenerGamepad, false); listeners[i]->RemoveGamepad(aIndex); } } } } }
void GamepadService::SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad) { RefPtr<Gamepad> gamepad = GetGamepad(aIndex); if (mShuttingDown || !mEnabled || !gamepad) { return; } aGamepad->SyncState(gamepad); }
void GamepadService::RemoveGamepad(uint32_t aIndex) { RefPtr<Gamepad> gamepad = GetGamepad(aIndex); if (!gamepad) { NS_WARNING("Trying to delete gamepad with invalid index"); return; } gamepad->SetConnected(false); NewConnectionEvent(aIndex, false); mGamepads.Remove(aIndex); }
void GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, double aValue) { RefPtr<Gamepad> gamepad = GetGamepad(aIndex); if (mShuttingDown || !gamepad) { return; } gamepad->SetButton(aButton, aPressed, aValue); // Hold on to listeners in a separate array because firing events // can mutate the mListeners array. nsTArray<RefPtr<nsGlobalWindow>> listeners(mListeners); for (uint32_t i = listeners.Length(); i > 0 ; ) { --i; MOZ_ASSERT(listeners[i]->IsInnerWindow()); // Only send events to non-background windows if (!listeners[i]->AsInner()->IsCurrentInnerWindow() || listeners[i]->GetOuterWindow()->IsBackground()) { continue; } bool first_time = false; if (!WindowHasSeenGamepad(listeners[i], aIndex)) { // This window hasn't seen this gamepad before, so // send a connection event first. SetWindowHasSeenGamepad(listeners[i], aIndex); first_time = true; } RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex); if (listenerGamepad) { listenerGamepad->SetButton(aButton, aPressed, aValue); if (first_time) { FireConnectionEvent(listeners[i], listenerGamepad, true); } if (mNonstandardEventsEnabled) { // Fire event FireButtonEvent(listeners[i], listenerGamepad, aButton, aValue); } } } }
XBoxGamepad& XBoxGamepadManager::operator[](uint32_t index) const { return GetGamepad(index); }