Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "Gamepad.h"
8 : #include "nsPIDOMWindow.h"
9 : #include "nsTArray.h"
10 : #include "nsVariant.h"
11 : #include "mozilla/dom/GamepadBinding.h"
12 :
13 : namespace mozilla {
14 : namespace dom {
15 :
16 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Gamepad)
17 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Gamepad)
18 :
19 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Gamepad)
20 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
21 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
22 0 : NS_INTERFACE_MAP_END
23 :
24 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons, mPose,
25 : mHapticActuators)
26 :
27 : void
28 0 : Gamepad::UpdateTimestamp()
29 : {
30 0 : nsCOMPtr<nsPIDOMWindowInner> newWindow(do_QueryInterface(mParent));
31 0 : if(newWindow) {
32 0 : Performance* perf = newWindow->GetPerformance();
33 0 : if (perf) {
34 0 : mTimestamp = perf->Now();
35 : }
36 : }
37 0 : }
38 :
39 0 : Gamepad::Gamepad(nsISupports* aParent,
40 : const nsAString& aID, uint32_t aIndex,
41 : uint32_t aHashKey,
42 : GamepadMappingType aMapping,
43 : GamepadHand aHand,
44 : uint32_t aNumButtons, uint32_t aNumAxes,
45 0 : uint32_t aNumHaptics)
46 : : mParent(aParent),
47 : mID(aID),
48 : mIndex(aIndex),
49 : mHashKey(aHashKey),
50 : mMapping(aMapping),
51 : mHand(aHand),
52 : mConnected(true),
53 : mButtons(aNumButtons),
54 : mAxes(aNumAxes),
55 0 : mTimestamp(0)
56 : {
57 0 : for (unsigned i = 0; i < aNumButtons; i++) {
58 0 : mButtons.InsertElementAt(i, new GamepadButton(mParent));
59 : }
60 0 : mAxes.InsertElementsAt(0, aNumAxes, 0.0f);
61 0 : mPose = new GamepadPose(aParent);
62 0 : for (uint32_t i = 0; i < aNumHaptics; ++i) {
63 0 : mHapticActuators.AppendElement(new GamepadHapticActuator(mParent, mHashKey, i));
64 : }
65 0 : UpdateTimestamp();
66 0 : }
67 :
68 : void
69 0 : Gamepad::SetIndex(uint32_t aIndex)
70 : {
71 0 : mIndex = aIndex;
72 0 : }
73 :
74 : void
75 0 : Gamepad::SetConnected(bool aConnected)
76 : {
77 0 : mConnected = aConnected;
78 0 : }
79 :
80 : void
81 0 : Gamepad::SetButton(uint32_t aButton, bool aPressed,
82 : bool aTouched, double aValue)
83 : {
84 0 : MOZ_ASSERT(aButton < mButtons.Length());
85 0 : mButtons[aButton]->SetPressed(aPressed);
86 0 : mButtons[aButton]->SetTouched(aTouched);
87 0 : mButtons[aButton]->SetValue(aValue);
88 0 : UpdateTimestamp();
89 0 : }
90 :
91 : void
92 0 : Gamepad::SetAxis(uint32_t aAxis, double aValue)
93 : {
94 0 : MOZ_ASSERT(aAxis < mAxes.Length());
95 0 : if (mAxes[aAxis] != aValue) {
96 0 : mAxes[aAxis] = aValue;
97 0 : GamepadBinding::ClearCachedAxesValue(this);
98 : }
99 0 : UpdateTimestamp();
100 0 : }
101 :
102 : void
103 0 : Gamepad::SetPose(const GamepadPoseState& aPose)
104 : {
105 0 : mPose->SetPoseState(aPose);
106 0 : UpdateTimestamp();
107 0 : }
108 :
109 : void
110 0 : Gamepad::SetHand(GamepadHand aHand)
111 : {
112 0 : mHand = aHand;
113 0 : }
114 :
115 : void
116 0 : Gamepad::SyncState(Gamepad* aOther)
117 : {
118 0 : const char* kGamepadExtEnabledPref = "dom.gamepad.extensions.enabled";
119 :
120 0 : if (mButtons.Length() != aOther->mButtons.Length() ||
121 0 : mAxes.Length() != aOther->mAxes.Length()) {
122 0 : return;
123 : }
124 :
125 0 : mConnected = aOther->mConnected;
126 0 : for (uint32_t i = 0; i < mButtons.Length(); ++i) {
127 0 : mButtons[i]->SetPressed(aOther->mButtons[i]->Pressed());
128 0 : mButtons[i]->SetTouched(aOther->mButtons[i]->Touched());
129 0 : mButtons[i]->SetValue(aOther->mButtons[i]->Value());
130 : }
131 :
132 0 : bool changed = false;
133 0 : for (uint32_t i = 0; i < mAxes.Length(); ++i) {
134 0 : changed = changed || (mAxes[i] != aOther->mAxes[i]);
135 0 : mAxes[i] = aOther->mAxes[i];
136 : }
137 0 : if (changed) {
138 0 : GamepadBinding::ClearCachedAxesValue(this);
139 : }
140 :
141 0 : if (Preferences::GetBool(kGamepadExtEnabledPref)) {
142 0 : MOZ_ASSERT(aOther->GetPose());
143 0 : mPose->SetPoseState(aOther->GetPose()->GetPoseState());
144 0 : mHand = aOther->Hand();
145 0 : for (uint32_t i = 0; i < mHapticActuators.Length(); ++i) {
146 0 : mHapticActuators[i]->Set(aOther->mHapticActuators[i]);
147 : }
148 : }
149 :
150 0 : UpdateTimestamp();
151 : }
152 :
153 : already_AddRefed<Gamepad>
154 0 : Gamepad::Clone(nsISupports* aParent)
155 : {
156 : RefPtr<Gamepad> out =
157 : new Gamepad(aParent, mID, mIndex, mHashKey, mMapping,
158 0 : mHand, mButtons.Length(), mAxes.Length(),
159 0 : mHapticActuators.Length());
160 0 : out->SyncState(this);
161 0 : return out.forget();
162 : }
163 :
164 : /* virtual */ JSObject*
165 0 : Gamepad::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
166 : {
167 0 : return GamepadBinding::Wrap(aCx, this, aGivenProto);
168 : }
169 :
170 : } // namespace dom
171 : } // namespace mozilla
|