Bug 1829125 - Add a PHCExhaustion test r=glandium
[gecko.git] / dom / vr / XRInputSourceArray.cpp
blob2cc2c4537acb1372b8c72e3fb6bf70e846506791
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,
15 mInputSources)
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)
21 NS_INTERFACE_MAP_END
23 XRInputSourceArray::XRInputSourceArray(nsISupports* aParent)
24 : mParent(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) {
32 MOZ_ASSERT(aSession);
34 gfx::VRDisplayClient* displayClient = aSession->GetDisplayClient();
35 if (!displayClient) {
36 return;
39 XRInputSourcesChangeEventInit addInit;
40 nsTArray<RefPtr<XRInputSource>> removedInputs;
41 if (NS_WARN_IF(!addInit.mAdded.SetCapacity(gfx::kVRControllerMaxCount,
42 mozilla::fallible))) {
43 MOZ_ASSERT(false,
44 "'add' sequence in XRInputSourcesChangeEventInit SetCapacity() "
45 "failed.");
46 return;
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);
57 break;
60 continue;
63 bool found = false;
64 RefPtr<XRInputSource> inputSource = nullptr;
65 for (auto& input : mInputSources) {
66 if (input->GetIndex() == i) {
67 found = true;
68 inputSource = input;
69 break;
72 // Checking if it is added before.
73 if (!found &&
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)) {
83 MOZ_ASSERT(false,
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.
90 if (inputSource) {
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) {
116 if (!aSession) {
117 return;
120 XRInputSourcesChangeEventInit init;
121 if (NS_WARN_IF(
122 !init.mRemoved.SetCapacity(aInputs.Length(), mozilla::fallible))) {
123 MOZ_ASSERT(false,
124 "'removed' sequence in XRInputSourcesChangeEventInit "
125 "SetCapacity() failed.");
126 return;
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)) {
134 MOZ_ASSERT(false,
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,
159 bool& aFound) {
160 aFound = aIndex < mInputSources.Length();
161 if (!aFound) {
162 return nullptr;
164 return mInputSources[aIndex];
167 } // namespace mozilla::dom