diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/gamepad/Gamepad.cpp | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/gamepad/Gamepad.cpp')
-rw-r--r-- | dom/gamepad/Gamepad.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/dom/gamepad/Gamepad.cpp b/dom/gamepad/Gamepad.cpp new file mode 100644 index 0000000000..aaeafecc07 --- /dev/null +++ b/dom/gamepad/Gamepad.cpp @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Gamepad.h" +#include "nsPIDOMWindow.h" +#include "nsTArray.h" +#include "nsVariant.h" +#include "mozilla/StaticPrefs_dom.h" +#include "mozilla/dom/GamepadBinding.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTING_ADDREF(Gamepad) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Gamepad) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Gamepad) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons, mPose, + mHapticActuators, mLightIndicators, + mTouchEvents) + +void Gamepad::UpdateTimestamp() { + nsCOMPtr<nsPIDOMWindowInner> newWindow(do_QueryInterface(mParent)); + if (newWindow) { + Performance* perf = newWindow->GetPerformance(); + if (perf) { + mTimestamp = perf->Now(); + } + } +} + +Gamepad::Gamepad(nsISupports* aParent, const nsAString& aID, int32_t aIndex, + GamepadHandle aHandle, GamepadMappingType aMapping, + GamepadHand aHand, uint32_t aDisplayID, uint32_t aNumButtons, + uint32_t aNumAxes, uint32_t aNumHaptics, + uint32_t aNumLightIndicator, uint32_t aNumTouchEvents) + : mParent(aParent), + mID(aID), + mIndex(aIndex), + mHandle(aHandle), + mDisplayId(aDisplayID), + mTouchIdHashValue(0), + mMapping(aMapping), + mHand(aHand), + mConnected(true), + mButtons(aNumButtons), + mAxes(aNumAxes), + mTimestamp(0) { + for (unsigned i = 0; i < aNumButtons; i++) { + mButtons.InsertElementAt(i, new GamepadButton(mParent)); + } + mAxes.InsertElementsAt(0, aNumAxes, 0.0f); + mPose = new GamepadPose(aParent); + for (uint32_t i = 0; i < aNumHaptics; ++i) { + mHapticActuators.AppendElement( + new GamepadHapticActuator(mParent, mHandle, i)); + } + for (uint32_t i = 0; i < aNumLightIndicator; ++i) { + mLightIndicators.AppendElement( + new GamepadLightIndicator(mParent, mHandle, i)); + } + for (uint32_t i = 0; i < aNumTouchEvents; ++i) { + mTouchEvents.AppendElement(new GamepadTouch(mParent)); + } + + // Mapping touchId(0) to touchIdHash(0) by default. + mTouchIdHash.Put(0, mTouchIdHashValue); + ++mTouchIdHashValue; + UpdateTimestamp(); +} + +void Gamepad::SetIndex(int32_t aIndex) { mIndex = aIndex; } + +void Gamepad::SetConnected(bool aConnected) { mConnected = aConnected; } + +void Gamepad::SetButton(uint32_t aButton, bool aPressed, bool aTouched, + double aValue) { + MOZ_ASSERT(aButton < mButtons.Length()); + mButtons[aButton]->SetPressed(aPressed); + mButtons[aButton]->SetTouched(aTouched); + mButtons[aButton]->SetValue(aValue); + UpdateTimestamp(); +} + +void Gamepad::SetAxis(uint32_t aAxis, double aValue) { + MOZ_ASSERT(aAxis < mAxes.Length()); + if (mAxes[aAxis] != aValue) { + mAxes[aAxis] = aValue; + Gamepad_Binding::ClearCachedAxesValue(this); + } + UpdateTimestamp(); +} + +void Gamepad::SetPose(const GamepadPoseState& aPose) { + mPose->SetPoseState(aPose); + UpdateTimestamp(); +} + +void Gamepad::SetLightIndicatorType(uint32_t aLightIndex, + GamepadLightIndicatorType aType) { + mLightIndicators[aLightIndex]->SetType(aType); + UpdateTimestamp(); +} + +void Gamepad::SetTouchEvent(uint32_t aTouchIndex, + const GamepadTouchState& aTouch) { + if (aTouchIndex >= mTouchEvents.Length()) { + MOZ_CRASH("Touch index exceeds the event array."); + return; + } + + // Handling cross-origin tracking. + GamepadTouchState touchState(aTouch); + if (auto hashValue = mTouchIdHash.GetValue(touchState.touchId)) { + touchState.touchId = *hashValue; + } else { + touchState.touchId = mTouchIdHashValue; + mTouchIdHash.Put(aTouch.touchId, mTouchIdHashValue); + ++mTouchIdHashValue; + } + mTouchEvents[aTouchIndex]->SetTouchState(touchState); + UpdateTimestamp(); +} + +void Gamepad::SetHand(GamepadHand aHand) { mHand = aHand; } + +void Gamepad::SyncState(Gamepad* aOther) { + if (mButtons.Length() != aOther->mButtons.Length() || + mAxes.Length() != aOther->mAxes.Length()) { + return; + } + + mConnected = aOther->mConnected; + for (uint32_t i = 0; i < mButtons.Length(); ++i) { + mButtons[i]->SetPressed(aOther->mButtons[i]->Pressed()); + mButtons[i]->SetTouched(aOther->mButtons[i]->Touched()); + mButtons[i]->SetValue(aOther->mButtons[i]->Value()); + } + + bool changed = false; + for (uint32_t i = 0; i < mAxes.Length(); ++i) { + changed = changed || (mAxes[i] != aOther->mAxes[i]); + mAxes[i] = aOther->mAxes[i]; + } + if (changed) { + Gamepad_Binding::ClearCachedAxesValue(this); + } + + if (StaticPrefs::dom_gamepad_extensions_enabled()) { + MOZ_ASSERT(aOther->GetPose()); + mPose->SetPoseState(aOther->GetPose()->GetPoseState()); + mHand = aOther->Hand(); + for (uint32_t i = 0; i < mHapticActuators.Length(); ++i) { + mHapticActuators[i]->Set(aOther->mHapticActuators[i]); + } + + if (StaticPrefs::dom_gamepad_extensions_lightindicator()) { + for (uint32_t i = 0; i < mLightIndicators.Length(); ++i) { + mLightIndicators[i]->Set(aOther->mLightIndicators[i]); + } + } + if (StaticPrefs::dom_gamepad_extensions_multitouch()) { + for (uint32_t i = 0; i < mTouchEvents.Length(); ++i) { + mTouchEvents[i]->Set(aOther->mTouchEvents[i]); + } + } + } + + UpdateTimestamp(); +} + +already_AddRefed<Gamepad> Gamepad::Clone(nsISupports* aParent) { + RefPtr<Gamepad> out = + new Gamepad(aParent, mID, mIndex, mHandle, mMapping, mHand, mDisplayId, + mButtons.Length(), mAxes.Length(), mHapticActuators.Length(), + mLightIndicators.Length(), mTouchEvents.Length()); + out->SyncState(this); + return out.forget(); +} + +/* virtual */ +JSObject* Gamepad::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return Gamepad_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom |