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::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); } } } }
void GamepadService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue) { if (mShuttingDown || aIndex >= mGamepads.Length()) { return; } mGamepads[aIndex]->SetAxis(aAxis, aValue); // Hold on to listeners in a separate array because firing events // can mutate the mListeners array. nsTArray<nsRefPtr<nsGlobalWindow> > listeners(mListeners); for (uint32_t i = listeners.Length(); i > 0 ; ) { --i; // Only send events to non-background windows if (!listeners[i]->GetOuterWindow() || 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; } nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex); if (gamepad) { gamepad->SetAxis(aAxis, aValue); if (first_time) { FireConnectionEvent(listeners[i], gamepad, true); } if (mNonstandardEventsEnabled) { // Fire event FireAxisMoveEvent(listeners[i], gamepad, aAxis, aValue); } } } }