Skip to content

Commit 358e55b

Browse files
committed
Bug 852944 - Gamepad API IPC; r=ted, r=baku
--HG-- extra : rebase_source : 34ca0c1e1b7fcc312b5d7c97d5bd2086af2bc7ce
1 parent 595b328 commit 358e55b

33 files changed

+754
-368
lines changed

dom/base/nsGlobalWindow.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
#include "mozilla/dom/StructuredCloneTags.h"
188188

189189
#ifdef MOZ_GAMEPAD
190+
#include "mozilla/dom/Gamepad.h"
190191
#include "mozilla/dom/GamepadService.h"
191192
#endif
192193

@@ -13367,13 +13368,28 @@ void
1336713368
nsGlobalWindow::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
1336813369
{
1336913370
MOZ_ASSERT(IsInnerWindow());
13371+
// Create the index we will present to content based on which indices are
13372+
// already taken, as required by the spec.
13373+
// https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
13374+
int index = 0;
13375+
while(mGamepadIndexSet.Contains(index)) {
13376+
++index;
13377+
}
13378+
mGamepadIndexSet.Put(index);
13379+
aGamepad->SetIndex(index);
1337013380
mGamepads.Put(aIndex, aGamepad);
1337113381
}
1337213382

1337313383
void
1337413384
nsGlobalWindow::RemoveGamepad(uint32_t aIndex)
1337513385
{
1337613386
MOZ_ASSERT(IsInnerWindow());
13387+
nsRefPtr<Gamepad> gamepad;
13388+
if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
13389+
return;
13390+
}
13391+
// Free up the index we were using so it can be reused
13392+
mGamepadIndexSet.Remove(gamepad->Index());
1337713393
mGamepads.Remove(aIndex);
1337813394
}
1337913395

@@ -13384,8 +13400,8 @@ nsGlobalWindow::EnumGamepadsForGet(const uint32_t& aKey, Gamepad* aData,
1338413400
{
1338513401
nsTArray<nsRefPtr<Gamepad> >* array =
1338613402
static_cast<nsTArray<nsRefPtr<Gamepad> >*>(aUserArg);
13387-
array->EnsureLengthAtLeast(aKey + 1);
13388-
(*array)[aKey] = aData;
13403+
array->EnsureLengthAtLeast(aData->Index() + 1);
13404+
(*array)[aData->Index()] = aData;
1338913405
return PL_DHASH_NEXT;
1339013406
}
1339113407

@@ -13404,6 +13420,7 @@ nsGlobalWindow::GetGamepad(uint32_t aIndex)
1340413420
{
1340513421
MOZ_ASSERT(IsInnerWindow());
1340613422
nsRefPtr<Gamepad> gamepad;
13423+
1340713424
if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
1340813425
return gamepad.forget();
1340913426
}

dom/base/nsGlobalWindow.h

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "Units.h"
5353
#include "nsComponentManagerUtils.h"
5454
#include "nsSize.h"
55+
#include "nsCheapSets.h"
5556

5657
#define DEFAULT_HOME_PAGE "www.mozilla.org"
5758
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
@@ -1590,6 +1591,7 @@ class nsGlobalWindow : public mozilla::dom::EventTarget,
15901591
// Indicates whether this window wants gamepad input events
15911592
bool mHasGamepad : 1;
15921593
#ifdef MOZ_GAMEPAD
1594+
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
15931595
nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
15941596
bool mHasSeenGamepadInput;
15951597
#endif

dom/gamepad/GamepadFunctions.cpp

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
#include "mozilla/dom/GamepadFunctions.h"
6+
#include "mozilla/dom/GamepadService.h"
7+
#include "nsHashKeys.h"
8+
#include "mozilla/dom/ContentParent.h"
9+
#include "mozilla/unused.h"
10+
11+
namespace mozilla {
12+
namespace dom {
13+
namespace GamepadFunctions {
14+
15+
namespace {
16+
// Increments as gamepads are added
17+
uint32_t gGamepadIndex = 0;
18+
}
19+
20+
template<class T>
21+
void
22+
NotifyGamepadChange(const T& aInfo)
23+
{
24+
MOZ_ASSERT(NS_IsMainThread());
25+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
26+
GamepadChangeEvent e(aInfo);
27+
nsTArray<ContentParent*> t;
28+
ContentParent::GetAll(t);
29+
for(uint32_t i = 0; i < t.Length(); ++i) {
30+
unused << t[i]->SendGamepadUpdate(e);
31+
}
32+
// If we have a GamepadService in the main process, send directly to it.
33+
if (GamepadService::IsServiceRunning()) {
34+
nsRefPtr<GamepadService> svc = GamepadService::GetService();
35+
svc->Update(e);
36+
}
37+
}
38+
39+
uint32_t
40+
AddGamepad(const char* aID,
41+
GamepadMappingType aMapping,
42+
uint32_t aNumButtons, uint32_t aNumAxes)
43+
{
44+
MOZ_ASSERT(NS_IsMainThread());
45+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
46+
47+
int index = gGamepadIndex;
48+
gGamepadIndex++;
49+
GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), index,
50+
(uint32_t)aMapping, aNumButtons, aNumAxes);
51+
gGamepadIndex++;
52+
NotifyGamepadChange<GamepadAdded>(a);
53+
return index;
54+
}
55+
56+
void
57+
RemoveGamepad(uint32_t aIndex)
58+
{
59+
MOZ_ASSERT(NS_IsMainThread());
60+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
61+
GamepadRemoved a(aIndex);
62+
NotifyGamepadChange<GamepadRemoved>(a);
63+
}
64+
65+
void
66+
NewButtonEvent(uint32_t aIndex, uint32_t aButton,
67+
bool aPressed, double aValue)
68+
{
69+
MOZ_ASSERT(NS_IsMainThread());
70+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
71+
GamepadButtonInformation a(aIndex, aButton, aPressed, aValue);
72+
NotifyGamepadChange<GamepadButtonInformation>(a);
73+
}
74+
75+
void
76+
NewButtonEvent(uint32_t aIndex, uint32_t aButton,
77+
bool aPressed)
78+
{
79+
MOZ_ASSERT(NS_IsMainThread());
80+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
81+
// When only a digital button is available the value will be synthesized.
82+
NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L);
83+
}
84+
85+
void
86+
NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
87+
double aValue)
88+
{
89+
MOZ_ASSERT(NS_IsMainThread());
90+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
91+
GamepadAxisInformation a(aIndex, aAxis, aValue);
92+
NotifyGamepadChange<GamepadAxisInformation>(a);
93+
}
94+
95+
void
96+
ResetGamepadIndexes()
97+
{
98+
MOZ_ASSERT(NS_IsMainThread());
99+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
100+
gGamepadIndex = 0;
101+
}
102+
103+
} // namespace GamepadFunctions
104+
} // namespace dom
105+
} // namespace mozilla

dom/gamepad/GamepadFunctions.h

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
#ifndef mozilla_dom_GamepadFunctions_h_
6+
#define mozilla_dom_GamepadFunctions_h_
7+
8+
#include "mozilla/dom/GamepadBinding.h"
9+
10+
namespace mozilla {
11+
namespace dom {
12+
namespace GamepadFunctions {
13+
14+
// Functions for building and transmitting IPDL messages through the HAL
15+
// sandbox. Used by platform specific Gamepad implementations
16+
17+
// Add a gamepad to the list of known gamepads, and return its index.
18+
uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping,
19+
uint32_t aNumButtons, uint32_t aNumAxes);
20+
// Remove the gamepad at |aIndex| from the list of known gamepads.
21+
void RemoveGamepad(uint32_t aIndex);
22+
23+
// Update the state of |aButton| for the gamepad at |aIndex| for all
24+
// windows that are listening and visible, and fire one of
25+
// a gamepadbutton{up,down} event at them as well.
26+
// aPressed is used for digital buttons, aValue is for analog buttons.
27+
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
28+
double aValue);
29+
// When only a digital button is available the value will be synthesized.
30+
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
31+
32+
// Update the state of |aAxis| for the gamepad at |aIndex| for all
33+
// windows that are listening and visible, and fire a gamepadaxismove
34+
// event at them as well.
35+
void NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue);
36+
37+
// When shutting down the platform communications for gamepad, also reset the
38+
// indexes.
39+
void ResetGamepadIndexes();
40+
41+
} // namespace GamepadFunctions
42+
} // namespace dom
43+
} // namespace mozilla
44+
45+
#endif

dom/gamepad/GamepadMonitoring.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
#include "mozilla/dom/GamepadMonitoring.h"
6+
#include "mozilla/dom/GamepadFunctions.h"
7+
#include "mozilla/dom/PContentParent.h"
8+
9+
namespace mozilla {
10+
namespace dom {
11+
12+
using namespace GamepadFunctions;
13+
14+
void
15+
MaybeStopGamepadMonitoring()
16+
{
17+
MOZ_ASSERT(NS_IsMainThread());
18+
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
19+
nsTArray<ContentParent*> t;
20+
ContentParent::GetAll(t);
21+
for(uint32_t i = 0; i < t.Length(); ++i) {
22+
if (t[i]->HasGamepadListener()) {
23+
return;
24+
}
25+
}
26+
StopGamepadMonitoring();
27+
ResetGamepadIndexes();
28+
}
29+
30+
} // namespace dom
31+
} // namespace mozilla

dom/gamepad/GamepadMonitoring.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
* You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
#ifndef mozilla_dom_GamepadMonitoring_h_
6+
#define mozilla_dom_GamepadMonitoring_h_
7+
8+
namespace mozilla {
9+
namespace dom {
10+
// Functions for platform specific gamepad monitoring.
11+
12+
void MaybeStopGamepadMonitoring();
13+
14+
// These two functions are implemented in the platform specific service files
15+
// (linux/LinuxGamepad.cpp, cocoa/CocoaGamepad.cpp, etc)
16+
void StartGamepadMonitoring();
17+
void StopGamepadMonitoring();
18+
19+
} // namespace dom
20+
} // namespace mozilla
21+
22+
#endif

0 commit comments

Comments
 (0)