GamepadManager.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/GamepadManager.h"
  6. #include "mozilla/dom/Gamepad.h"
  7. #include "mozilla/dom/GamepadAxisMoveEvent.h"
  8. #include "mozilla/dom/GamepadButtonEvent.h"
  9. #include "mozilla/dom/GamepadEvent.h"
  10. #include "mozilla/dom/GamepadEventChannelChild.h"
  11. #include "mozilla/dom/GamepadMonitoring.h"
  12. #include "mozilla/ipc/BackgroundChild.h"
  13. #include "mozilla/ipc/PBackgroundChild.h"
  14. #include "mozilla/ClearOnShutdown.h"
  15. #include "mozilla/Preferences.h"
  16. #include "mozilla/StaticPtr.h"
  17. #include "nsAutoPtr.h"
  18. #include "nsIDOMEvent.h"
  19. #include "nsIDOMDocument.h"
  20. #include "nsIDOMWindow.h"
  21. #include "nsIObserver.h"
  22. #include "nsIObserverService.h"
  23. #include "nsIServiceManager.h"
  24. #include "nsThreadUtils.h"
  25. #include "mozilla/Services.h"
  26. #include "mozilla/Unused.h"
  27. #include <cstddef>
  28. using namespace mozilla::ipc;
  29. namespace mozilla {
  30. namespace dom {
  31. namespace {
  32. const char* kGamepadEnabledPref = "dom.gamepad.enabled";
  33. const char* kGamepadEventsEnabledPref =
  34. "dom.gamepad.non_standard_events.enabled";
  35. const nsTArray<RefPtr<nsGlobalWindow>>::index_type NoIndex =
  36. nsTArray<RefPtr<nsGlobalWindow>>::NoIndex;
  37. bool sShutdown = false;
  38. StaticRefPtr<GamepadManager> gGamepadManagerSingleton;
  39. const uint32_t VR_GAMEPAD_IDX_OFFSET = 0x01 << 16;
  40. } // namespace
  41. NS_IMPL_ISUPPORTS(GamepadManager, nsIObserver)
  42. GamepadManager::GamepadManager()
  43. : mEnabled(false),
  44. mNonstandardEventsEnabled(false),
  45. mShuttingDown(false)
  46. {}
  47. nsresult
  48. GamepadManager::Init()
  49. {
  50. mEnabled = IsAPIEnabled();
  51. mNonstandardEventsEnabled =
  52. Preferences::GetBool(kGamepadEventsEnabledPref, false);
  53. nsCOMPtr<nsIObserverService> observerService =
  54. mozilla::services::GetObserverService();
  55. if (NS_WARN_IF(!observerService)) {
  56. return NS_ERROR_FAILURE;
  57. }
  58. nsresult rv;
  59. rv = observerService->AddObserver(this,
  60. NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID,
  61. false);
  62. if (NS_WARN_IF(NS_FAILED(rv))) {
  63. return rv;
  64. }
  65. return NS_OK;
  66. }
  67. NS_IMETHODIMP
  68. GamepadManager::Observe(nsISupports* aSubject,
  69. const char* aTopic,
  70. const char16_t* aData)
  71. {
  72. nsCOMPtr<nsIObserverService> observerService =
  73. mozilla::services::GetObserverService();
  74. if (observerService) {
  75. observerService->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
  76. }
  77. BeginShutdown();
  78. return NS_OK;
  79. }
  80. void
  81. GamepadManager::StopMonitoring()
  82. {
  83. for (uint32_t i = 0; i < mChannelChildren.Length(); ++i) {
  84. mChannelChildren[i]->SendGamepadListenerRemoved();
  85. }
  86. mChannelChildren.Clear();
  87. mGamepads.Clear();
  88. }
  89. void
  90. GamepadManager::BeginShutdown()
  91. {
  92. mShuttingDown = true;
  93. StopMonitoring();
  94. // Don't let windows call back to unregister during shutdown
  95. for (uint32_t i = 0; i < mListeners.Length(); i++) {
  96. mListeners[i]->SetHasGamepadEventListener(false);
  97. }
  98. mListeners.Clear();
  99. sShutdown = true;
  100. }
  101. void
  102. GamepadManager::AddListener(nsGlobalWindow* aWindow)
  103. {
  104. MOZ_ASSERT(aWindow);
  105. MOZ_ASSERT(aWindow->IsInnerWindow());
  106. MOZ_ASSERT(NS_IsMainThread());
  107. if (!mEnabled || mShuttingDown) {
  108. return;
  109. }
  110. if (mListeners.IndexOf(aWindow) != NoIndex) {
  111. return; // already exists
  112. }
  113. mListeners.AppendElement(aWindow);
  114. // IPDL child has been created
  115. if (!mChannelChildren.IsEmpty()) {
  116. return;
  117. }
  118. PBackgroundChild *actor = BackgroundChild::GetForCurrentThread();
  119. //Try to get the PBackground Child actor
  120. if (actor) {
  121. ActorCreated(actor);
  122. } else {
  123. Unused << BackgroundChild::GetOrCreateForCurrentThread(this);
  124. }
  125. }
  126. void
  127. GamepadManager::RemoveListener(nsGlobalWindow* aWindow)
  128. {
  129. MOZ_ASSERT(aWindow);
  130. MOZ_ASSERT(aWindow->IsInnerWindow());
  131. if (mShuttingDown) {
  132. // Doesn't matter at this point. It's possible we're being called
  133. // as a result of our own destructor here, so just bail out.
  134. return;
  135. }
  136. if (mListeners.IndexOf(aWindow) == NoIndex) {
  137. return; // doesn't exist
  138. }
  139. for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
  140. aWindow->RemoveGamepad(iter.Key());
  141. }
  142. mListeners.RemoveElement(aWindow);
  143. if (mListeners.IsEmpty()) {
  144. StopMonitoring();
  145. }
  146. }
  147. already_AddRefed<Gamepad>
  148. GamepadManager::GetGamepad(uint32_t aIndex) const
  149. {
  150. RefPtr<Gamepad> gamepad;
  151. if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
  152. return gamepad.forget();
  153. }
  154. return nullptr;
  155. }
  156. uint32_t GamepadManager::GetGamepadIndexWithServiceType(uint32_t aIndex,
  157. GamepadServiceType aServiceType)
  158. {
  159. uint32_t newIndex = 0;
  160. switch (aServiceType) {
  161. case GamepadServiceType::Standard:
  162. {
  163. MOZ_ASSERT(aIndex <= VR_GAMEPAD_IDX_OFFSET);
  164. newIndex = aIndex;
  165. break;
  166. }
  167. default:
  168. MOZ_ASSERT(false);
  169. break;
  170. }
  171. return newIndex;
  172. }
  173. void
  174. GamepadManager::AddGamepad(uint32_t aIndex,
  175. const nsAString& aId,
  176. GamepadMappingType aMapping,
  177. GamepadServiceType aServiceType,
  178. uint32_t aNumButtons,
  179. uint32_t aNumAxes)
  180. {
  181. //TODO: bug 852258: get initial button/axis state
  182. RefPtr<Gamepad> gamepad =
  183. new Gamepad(nullptr,
  184. aId,
  185. 0, // index is set by global window
  186. aMapping,
  187. aNumButtons,
  188. aNumAxes);
  189. uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
  190. // We store the gamepad related to its index given by the parent process,
  191. // and no duplicate index is allowed.
  192. MOZ_ASSERT(!mGamepads.Get(newIndex, nullptr));
  193. mGamepads.Put(newIndex, gamepad);
  194. NewConnectionEvent(newIndex, true);
  195. }
  196. void
  197. GamepadManager::RemoveGamepad(uint32_t aIndex, GamepadServiceType aServiceType)
  198. {
  199. uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
  200. RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
  201. if (!gamepad) {
  202. NS_WARNING("Trying to delete gamepad with invalid index");
  203. return;
  204. }
  205. gamepad->SetConnected(false);
  206. NewConnectionEvent(newIndex, false);
  207. mGamepads.Remove(newIndex);
  208. }
  209. void
  210. GamepadManager::NewButtonEvent(uint32_t aIndex, GamepadServiceType aServiceType,
  211. uint32_t aButton, bool aPressed, double aValue)
  212. {
  213. if (mShuttingDown) {
  214. return;
  215. }
  216. uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
  217. RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
  218. if (!gamepad) {
  219. return;
  220. }
  221. gamepad->SetButton(aButton, aPressed, aValue);
  222. // Hold on to listeners in a separate array because firing events
  223. // can mutate the mListeners array.
  224. nsTArray<RefPtr<nsGlobalWindow>> listeners(mListeners);
  225. MOZ_ASSERT(!listeners.IsEmpty());
  226. for (uint32_t i = 0; i < listeners.Length(); i++) {
  227. MOZ_ASSERT(listeners[i]->IsInnerWindow());
  228. // Only send events to non-background windows
  229. if (!listeners[i]->AsInner()->IsCurrentInnerWindow() ||
  230. listeners[i]->GetOuterWindow()->IsBackground()) {
  231. continue;
  232. }
  233. bool firstTime = MaybeWindowHasSeenGamepad(listeners[i], newIndex);
  234. RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(newIndex);
  235. if (listenerGamepad) {
  236. listenerGamepad->SetButton(aButton, aPressed, aValue);
  237. if (firstTime) {
  238. FireConnectionEvent(listeners[i], listenerGamepad, true);
  239. }
  240. if (mNonstandardEventsEnabled) {
  241. // Fire event
  242. FireButtonEvent(listeners[i], listenerGamepad, aButton, aValue);
  243. }
  244. }
  245. }
  246. }
  247. void
  248. GamepadManager::FireButtonEvent(EventTarget* aTarget,
  249. Gamepad* aGamepad,
  250. uint32_t aButton,
  251. double aValue)
  252. {
  253. nsString name = aValue == 1.0L ? NS_LITERAL_STRING("gamepadbuttondown") :
  254. NS_LITERAL_STRING("gamepadbuttonup");
  255. GamepadButtonEventInit init;
  256. init.mBubbles = false;
  257. init.mCancelable = false;
  258. init.mGamepad = aGamepad;
  259. init.mButton = aButton;
  260. RefPtr<GamepadButtonEvent> event =
  261. GamepadButtonEvent::Constructor(aTarget, name, init);
  262. event->SetTrusted(true);
  263. bool defaultActionEnabled = true;
  264. aTarget->DispatchEvent(event, &defaultActionEnabled);
  265. }
  266. void
  267. GamepadManager::NewAxisMoveEvent(uint32_t aIndex, GamepadServiceType aServiceType,
  268. uint32_t aAxis, double aValue)
  269. {
  270. if (mShuttingDown) {
  271. return;
  272. }
  273. uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
  274. RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
  275. if (!gamepad) {
  276. return;
  277. }
  278. gamepad->SetAxis(aAxis, aValue);
  279. // Hold on to listeners in a separate array because firing events
  280. // can mutate the mListeners array.
  281. nsTArray<RefPtr<nsGlobalWindow>> listeners(mListeners);
  282. MOZ_ASSERT(!listeners.IsEmpty());
  283. for (uint32_t i = 0; i < listeners.Length(); i++) {
  284. MOZ_ASSERT(listeners[i]->IsInnerWindow());
  285. // Only send events to non-background windows
  286. if (!listeners[i]->AsInner()->IsCurrentInnerWindow() ||
  287. listeners[i]->GetOuterWindow()->IsBackground()) {
  288. continue;
  289. }
  290. bool firstTime = MaybeWindowHasSeenGamepad(listeners[i], newIndex);
  291. RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(newIndex);
  292. if (listenerGamepad) {
  293. listenerGamepad->SetAxis(aAxis, aValue);
  294. if (firstTime) {
  295. FireConnectionEvent(listeners[i], listenerGamepad, true);
  296. }
  297. if (mNonstandardEventsEnabled) {
  298. // Fire event
  299. FireAxisMoveEvent(listeners[i], listenerGamepad, aAxis, aValue);
  300. }
  301. }
  302. }
  303. }
  304. void
  305. GamepadManager::FireAxisMoveEvent(EventTarget* aTarget,
  306. Gamepad* aGamepad,
  307. uint32_t aAxis,
  308. double aValue)
  309. {
  310. GamepadAxisMoveEventInit init;
  311. init.mBubbles = false;
  312. init.mCancelable = false;
  313. init.mGamepad = aGamepad;
  314. init.mAxis = aAxis;
  315. init.mValue = aValue;
  316. RefPtr<GamepadAxisMoveEvent> event =
  317. GamepadAxisMoveEvent::Constructor(aTarget,
  318. NS_LITERAL_STRING("gamepadaxismove"),
  319. init);
  320. event->SetTrusted(true);
  321. bool defaultActionEnabled = true;
  322. aTarget->DispatchEvent(event, &defaultActionEnabled);
  323. }
  324. void
  325. GamepadManager::NewPoseEvent(uint32_t aIndex, GamepadServiceType aServiceType,
  326. const GamepadPoseState& aPose)
  327. {
  328. if (mShuttingDown) {
  329. return;
  330. }
  331. uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
  332. RefPtr<Gamepad> gamepad = GetGamepad(newIndex);
  333. if (!gamepad) {
  334. return;
  335. }
  336. gamepad->SetPose(aPose);
  337. // Hold on to listeners in a separate array because firing events
  338. // can mutate the mListeners array.
  339. nsTArray<RefPtr<nsGlobalWindow>> listeners(mListeners);
  340. MOZ_ASSERT(!listeners.IsEmpty());
  341. for (uint32_t i = 0; i < listeners.Length(); i++) {
  342. MOZ_ASSERT(listeners[i]->IsInnerWindow());
  343. // Only send events to non-background windows
  344. if (!listeners[i]->AsInner()->IsCurrentInnerWindow() ||
  345. listeners[i]->GetOuterWindow()->IsBackground()) {
  346. continue;
  347. }
  348. bool firstTime = MaybeWindowHasSeenGamepad(listeners[i], newIndex);
  349. RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(newIndex);
  350. if (listenerGamepad) {
  351. listenerGamepad->SetPose(aPose);
  352. if (firstTime) {
  353. FireConnectionEvent(listeners[i], listenerGamepad, true);
  354. }
  355. }
  356. }
  357. }
  358. void
  359. GamepadManager::NewConnectionEvent(uint32_t aIndex, bool aConnected)
  360. {
  361. if (mShuttingDown) {
  362. return;
  363. }
  364. RefPtr<Gamepad> gamepad = GetGamepad(aIndex);
  365. if (!gamepad) {
  366. return;
  367. }
  368. // Hold on to listeners in a separate array because firing events
  369. // can mutate the mListeners array.
  370. nsTArray<RefPtr<nsGlobalWindow>> listeners(mListeners);
  371. MOZ_ASSERT(!listeners.IsEmpty());
  372. if (aConnected) {
  373. for (uint32_t i = 0; i < listeners.Length(); i++) {
  374. MOZ_ASSERT(listeners[i]->IsInnerWindow());
  375. // Only send events to non-background windows
  376. if (!listeners[i]->AsInner()->IsCurrentInnerWindow() ||
  377. listeners[i]->GetOuterWindow()->IsBackground()) {
  378. continue;
  379. }
  380. // We don't fire a connected event here unless the window
  381. // has seen input from at least one device.
  382. if (!listeners[i]->HasSeenGamepadInput()) {
  383. continue;
  384. }
  385. SetWindowHasSeenGamepad(listeners[i], aIndex);
  386. RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
  387. if (listenerGamepad) {
  388. // Fire event
  389. FireConnectionEvent(listeners[i], listenerGamepad, aConnected);
  390. }
  391. }
  392. } else {
  393. // For disconnection events, fire one at every window that has received
  394. // data from this gamepad.
  395. for (uint32_t i = 0; i < listeners.Length(); i++) {
  396. // Even background windows get these events, so we don't have to
  397. // deal with the hassle of syncing the state of removed gamepads.
  398. if (WindowHasSeenGamepad(listeners[i], aIndex)) {
  399. RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
  400. if (listenerGamepad) {
  401. listenerGamepad->SetConnected(false);
  402. // Fire event
  403. FireConnectionEvent(listeners[i], listenerGamepad, false);
  404. listeners[i]->RemoveGamepad(aIndex);
  405. }
  406. }
  407. }
  408. }
  409. }
  410. void
  411. GamepadManager::FireConnectionEvent(EventTarget* aTarget,
  412. Gamepad* aGamepad,
  413. bool aConnected)
  414. {
  415. nsString name = aConnected ? NS_LITERAL_STRING("gamepadconnected") :
  416. NS_LITERAL_STRING("gamepaddisconnected");
  417. GamepadEventInit init;
  418. init.mBubbles = false;
  419. init.mCancelable = false;
  420. init.mGamepad = aGamepad;
  421. RefPtr<GamepadEvent> event =
  422. GamepadEvent::Constructor(aTarget, name, init);
  423. event->SetTrusted(true);
  424. bool defaultActionEnabled = true;
  425. aTarget->DispatchEvent(event, &defaultActionEnabled);
  426. }
  427. void
  428. GamepadManager::SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad)
  429. {
  430. if (mShuttingDown || !mEnabled) {
  431. return;
  432. }
  433. RefPtr<Gamepad> gamepad = GetGamepad(aIndex);
  434. if (!gamepad) {
  435. return;
  436. }
  437. aGamepad->SyncState(gamepad);
  438. }
  439. // static
  440. bool
  441. GamepadManager::IsServiceRunning()
  442. {
  443. return !!gGamepadManagerSingleton;
  444. }
  445. // static
  446. already_AddRefed<GamepadManager>
  447. GamepadManager::GetService()
  448. {
  449. if (sShutdown) {
  450. return nullptr;
  451. }
  452. if (!gGamepadManagerSingleton) {
  453. RefPtr<GamepadManager> manager = new GamepadManager();
  454. nsresult rv = manager->Init();
  455. if(NS_WARN_IF(NS_FAILED(rv))) {
  456. return nullptr;
  457. }
  458. gGamepadManagerSingleton = manager;
  459. ClearOnShutdown(&gGamepadManagerSingleton);
  460. }
  461. RefPtr<GamepadManager> service(gGamepadManagerSingleton);
  462. return service.forget();
  463. }
  464. // static
  465. bool
  466. GamepadManager::IsAPIEnabled() {
  467. return Preferences::GetBool(kGamepadEnabledPref, false);
  468. }
  469. bool
  470. GamepadManager::MaybeWindowHasSeenGamepad(nsGlobalWindow* aWindow, uint32_t aIndex)
  471. {
  472. if (!WindowHasSeenGamepad(aWindow, aIndex)) {
  473. // This window hasn't seen this gamepad before, so
  474. // send a connection event first.
  475. SetWindowHasSeenGamepad(aWindow, aIndex);
  476. return true;
  477. }
  478. return false;
  479. }
  480. bool
  481. GamepadManager::WindowHasSeenGamepad(nsGlobalWindow* aWindow, uint32_t aIndex) const
  482. {
  483. RefPtr<Gamepad> gamepad = aWindow->GetGamepad(aIndex);
  484. return gamepad != nullptr;
  485. }
  486. void
  487. GamepadManager::SetWindowHasSeenGamepad(nsGlobalWindow* aWindow,
  488. uint32_t aIndex,
  489. bool aHasSeen)
  490. {
  491. MOZ_ASSERT(aWindow);
  492. MOZ_ASSERT(aWindow->IsInnerWindow());
  493. if (mListeners.IndexOf(aWindow) == NoIndex) {
  494. // This window isn't even listening for gamepad events.
  495. return;
  496. }
  497. if (aHasSeen) {
  498. aWindow->SetHasSeenGamepadInput(true);
  499. nsCOMPtr<nsISupports> window = ToSupports(aWindow);
  500. RefPtr<Gamepad> gamepad = GetGamepad(aIndex);
  501. if (!gamepad) {
  502. return;
  503. }
  504. RefPtr<Gamepad> clonedGamepad = gamepad->Clone(window);
  505. aWindow->AddGamepad(aIndex, clonedGamepad);
  506. } else {
  507. aWindow->RemoveGamepad(aIndex);
  508. }
  509. }
  510. void
  511. GamepadManager::Update(const GamepadChangeEvent& aEvent)
  512. {
  513. if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
  514. const GamepadAdded& a = aEvent.get_GamepadAdded();
  515. AddGamepad(a.index(), a.id(),
  516. static_cast<GamepadMappingType>(a.mapping()),
  517. a.service_type(),
  518. a.num_buttons(), a.num_axes());
  519. return;
  520. }
  521. if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
  522. const GamepadRemoved& a = aEvent.get_GamepadRemoved();
  523. RemoveGamepad(a.index(), a.service_type());
  524. return;
  525. }
  526. if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
  527. const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
  528. NewButtonEvent(a.index(), a.service_type(), a.button(),
  529. a.pressed(), a.value());
  530. return;
  531. }
  532. if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
  533. const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation();
  534. NewAxisMoveEvent(a.index(), a.service_type(), a.axis(), a.value());
  535. return;
  536. }
  537. if (aEvent.type() == GamepadChangeEvent::TGamepadPoseInformation) {
  538. const GamepadPoseInformation& a = aEvent.get_GamepadPoseInformation();
  539. NewPoseEvent(a.index(), a.service_type(), a.pose_state());
  540. return;
  541. }
  542. MOZ_CRASH("We shouldn't be here!");
  543. }
  544. //Override nsIIPCBackgroundChildCreateCallback
  545. void
  546. GamepadManager::ActorCreated(PBackgroundChild *aActor)
  547. {
  548. MOZ_ASSERT(aActor);
  549. GamepadEventChannelChild *child = new GamepadEventChannelChild();
  550. PGamepadEventChannelChild *initedChild =
  551. aActor->SendPGamepadEventChannelConstructor(child);
  552. if (NS_WARN_IF(!initedChild)) {
  553. ActorFailed();
  554. return;
  555. }
  556. MOZ_ASSERT(initedChild == child);
  557. child->SendGamepadListenerAdded();
  558. mChannelChildren.AppendElement(child);
  559. }
  560. //Override nsIIPCBackgroundChildCreateCallback
  561. void
  562. GamepadManager::ActorFailed()
  563. {
  564. MOZ_CRASH("Gamepad IPC actor create failed!");
  565. }
  566. } // namespace dom
  567. } // namespace mozilla