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/. */
7 #include "mozilla/dom/XRInputSourceArray.h"
8 #include "mozilla/dom/XRSession.h"
9 #include "mozilla/dom/XRInputSourcesChangeEvent.h"
10 #include "VRDisplayClient.h"
12 namespace mozilla::dom
{
14 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(XRInputSourceArray
, mParent
,
16 NS_IMPL_CYCLE_COLLECTING_ADDREF(XRInputSourceArray
)
17 NS_IMPL_CYCLE_COLLECTING_RELEASE(XRInputSourceArray
)
18 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XRInputSourceArray
)
19 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
20 NS_INTERFACE_MAP_ENTRY(nsISupports
)
23 XRInputSourceArray::XRInputSourceArray(nsISupports
* aParent
)
26 JSObject
* XRInputSourceArray::WrapObject(JSContext
* aCx
,
27 JS::Handle
<JSObject
*> aGivenProto
) {
28 return XRInputSourceArray_Binding::Wrap(aCx
, this, aGivenProto
);
31 void XRInputSourceArray::Update(XRSession
* aSession
) {
34 gfx::VRDisplayClient
* displayClient
= aSession
->GetDisplayClient();
39 XRInputSourcesChangeEventInit addInit
;
40 nsTArray
<RefPtr
<XRInputSource
>> removedInputs
;
41 if (NS_WARN_IF(!addInit
.mAdded
.SetCapacity(gfx::kVRControllerMaxCount
,
42 mozilla::fallible
))) {
44 "'add' sequence in XRInputSourcesChangeEventInit SetCapacity() "
49 for (int32_t i
= 0; i
< gfx::kVRControllerMaxCount
; ++i
) {
50 const gfx::VRControllerState
& controllerState
=
51 displayClient
->GetDisplayInfo().mControllerState
[i
];
52 if (controllerState
.controllerName
[0] == '\0') {
53 // Checking if exising controllers need to be removed.
54 for (auto& input
: mInputSources
) {
55 if (input
->GetIndex() == i
) {
56 removedInputs
.AppendElement(input
);
64 RefPtr
<XRInputSource
> inputSource
= nullptr;
65 for (auto& input
: mInputSources
) {
66 if (input
->GetIndex() == i
) {
72 // Checking if it is added before.
74 (controllerState
.numButtons
> 0 || controllerState
.numAxes
> 0)) {
75 inputSource
= new XRInputSource(mParent
);
76 inputSource
->Setup(aSession
, i
);
77 mInputSources
.AppendElement(inputSource
);
79 addInit
.mBubbles
= false;
80 addInit
.mCancelable
= false;
81 addInit
.mSession
= aSession
;
82 if (!addInit
.mAdded
.AppendElement(*inputSource
, mozilla::fallible
)) {
84 "'add' sequence in XRInputSourcesChangeEventInit "
85 "AppendElement() failed, it might be due to the"
86 "wrong size when SetCapacity().");
89 // If added, updating the current controller states.
91 inputSource
->Update(aSession
);
95 // Send `inputsourceschange` for new controllers.
96 if (addInit
.mAdded
.Length()) {
97 RefPtr
<XRInputSourcesChangeEvent
> event
=
98 XRInputSourcesChangeEvent::Constructor(
99 aSession
, u
"inputsourceschange"_ns
, addInit
);
101 event
->SetTrusted(true);
102 aSession
->DispatchEvent(*event
);
105 // If there's a controller is removed, dispatch `inputsourceschange`.
106 if (removedInputs
.Length()) {
107 DispatchInputSourceRemovedEvent(removedInputs
, aSession
);
109 for (auto& input
: removedInputs
) {
110 mInputSources
.RemoveElement(input
);
114 void XRInputSourceArray::DispatchInputSourceRemovedEvent(
115 const nsTArray
<RefPtr
<XRInputSource
>>& aInputs
, XRSession
* aSession
) {
120 XRInputSourcesChangeEventInit init
;
122 !init
.mRemoved
.SetCapacity(aInputs
.Length(), mozilla::fallible
))) {
124 "'removed' sequence in XRInputSourcesChangeEventInit "
125 "SetCapacity() failed.");
128 for (const auto& input
: aInputs
) {
129 input
->SetGamepadIsConnected(false, aSession
);
130 init
.mBubbles
= false;
131 init
.mCancelable
= false;
132 init
.mSession
= aSession
;
133 if (!init
.mRemoved
.AppendElement(*input
, mozilla::fallible
)) {
135 "'removed' sequence in XRInputSourcesChangeEventInit "
136 "AppendElement() failed, it might be due to the"
137 "wrong size when SetCapacity().");
141 if (init
.mRemoved
.Length()) {
142 RefPtr
<XRInputSourcesChangeEvent
> event
=
143 XRInputSourcesChangeEvent::Constructor(aSession
,
144 u
"inputsourceschange"_ns
, init
);
146 event
->SetTrusted(true);
147 aSession
->DispatchEvent(*event
);
151 void XRInputSourceArray::Clear(XRSession
* aSession
) {
152 DispatchInputSourceRemovedEvent(mInputSources
, aSession
);
153 mInputSources
.Clear();
156 uint32_t XRInputSourceArray::Length() { return mInputSources
.Length(); }
158 XRInputSource
* XRInputSourceArray::IndexedGetter(uint32_t aIndex
,
160 aFound
= aIndex
< mInputSources
.Length();
164 return mInputSources
[aIndex
];
167 } // namespace mozilla::dom