Commit f1193f9f authored by Daosheng Mu's avatar Daosheng Mu
Browse files

Bug 1523351 - Part 1: GamepadTouch and GamepadLightIndicator WebAPI implementation. r=baku

Differential Revision: https://phabricator.services.mozilla.com/D20744

--HG--
extra : moz-landing-system : lando
parent f9e9ef7a
Loading
Loading
Loading
Loading
+53 −6
Original line number Original line Diff line number Diff line
@@ -22,7 +22,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Gamepad)
NS_INTERFACE_MAP_END
NS_INTERFACE_MAP_END


NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons, mPose,
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Gamepad, mParent, mButtons, mPose,
                                      mHapticActuators)
                                      mHapticActuators, mLightIndicators,
                                      mTouchEvents)


void Gamepad::UpdateTimestamp() {
void Gamepad::UpdateTimestamp() {
  nsCOMPtr<nsPIDOMWindowInner> newWindow(do_QueryInterface(mParent));
  nsCOMPtr<nsPIDOMWindowInner> newWindow(do_QueryInterface(mParent));
@@ -37,12 +38,14 @@ void Gamepad::UpdateTimestamp() {
Gamepad::Gamepad(nsISupports* aParent, const nsAString& aID, uint32_t aIndex,
Gamepad::Gamepad(nsISupports* aParent, const nsAString& aID, uint32_t aIndex,
                 uint32_t aHashKey, GamepadMappingType aMapping,
                 uint32_t aHashKey, GamepadMappingType aMapping,
                 GamepadHand aHand, uint32_t aDisplayID, uint32_t aNumButtons,
                 GamepadHand aHand, uint32_t aDisplayID, uint32_t aNumButtons,
                 uint32_t aNumAxes, uint32_t aNumHaptics)
                 uint32_t aNumAxes, uint32_t aNumHaptics,
                 uint32_t aNumLightIndicator, uint32_t aNumTouchEvents)
    : mParent(aParent),
    : mParent(aParent),
      mID(aID),
      mID(aID),
      mIndex(aIndex),
      mIndex(aIndex),
      mHashKey(aHashKey),
      mHashKey(aHashKey),
      mDisplayId(aDisplayID),
      mDisplayId(aDisplayID),
      mTouchIdHashValue(0),
      mMapping(aMapping),
      mMapping(aMapping),
      mHand(aHand),
      mHand(aHand),
      mConnected(true),
      mConnected(true),
@@ -58,6 +61,14 @@ Gamepad::Gamepad(nsISupports* aParent, const nsAString& aID, uint32_t aIndex,
    mHapticActuators.AppendElement(
    mHapticActuators.AppendElement(
        new GamepadHapticActuator(mParent, mHashKey, i));
        new GamepadHapticActuator(mParent, mHashKey, i));
  }
  }
  for (uint32_t i = 0; i < aNumLightIndicator; ++i) {
    mLightIndicators.AppendElement(
        new GamepadLightIndicator(mParent, mHashKey, i));
  }
  for (uint32_t i = 0; i < aNumTouchEvents; ++i) {
    mTouchEvents.AppendElement(new GamepadTouch(mParent));
  }

  UpdateTimestamp();
  UpdateTimestamp();
}
}


@@ -88,11 +99,35 @@ void Gamepad::SetPose(const GamepadPoseState& aPose) {
  UpdateTimestamp();
  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::SetHand(GamepadHand aHand) { mHand = aHand; }


void Gamepad::SyncState(Gamepad* aOther) {
void Gamepad::SyncState(Gamepad* aOther) {
  const char* kGamepadExtEnabledPref = "dom.gamepad.extensions.enabled";

  if (mButtons.Length() != aOther->mButtons.Length() ||
  if (mButtons.Length() != aOther->mButtons.Length() ||
      mAxes.Length() != aOther->mAxes.Length()) {
      mAxes.Length() != aOther->mAxes.Length()) {
    return;
    return;
@@ -114,13 +149,24 @@ void Gamepad::SyncState(Gamepad* aOther) {
    Gamepad_Binding::ClearCachedAxesValue(this);
    Gamepad_Binding::ClearCachedAxesValue(this);
  }
  }


  if (Preferences::GetBool(kGamepadExtEnabledPref)) {
  if (StaticPrefs::dom_gamepad_extensions_enabled()) {
    MOZ_ASSERT(aOther->GetPose());
    MOZ_ASSERT(aOther->GetPose());
    mPose->SetPoseState(aOther->GetPose()->GetPoseState());
    mPose->SetPoseState(aOther->GetPose()->GetPoseState());
    mHand = aOther->Hand();
    mHand = aOther->Hand();
    for (uint32_t i = 0; i < mHapticActuators.Length(); ++i) {
    for (uint32_t i = 0; i < mHapticActuators.Length(); ++i) {
      mHapticActuators[i]->Set(aOther->mHapticActuators[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();
  UpdateTimestamp();
@@ -129,7 +175,8 @@ void Gamepad::SyncState(Gamepad* aOther) {
already_AddRefed<Gamepad> Gamepad::Clone(nsISupports* aParent) {
already_AddRefed<Gamepad> Gamepad::Clone(nsISupports* aParent) {
  RefPtr<Gamepad> out =
  RefPtr<Gamepad> out =
      new Gamepad(aParent, mID, mIndex, mHashKey, mMapping, mHand, mDisplayId,
      new Gamepad(aParent, mID, mIndex, mHashKey, mMapping, mHand, mDisplayId,
                  mButtons.Length(), mAxes.Length(), mHapticActuators.Length());
                  mButtons.Length(), mAxes.Length(), mHapticActuators.Length(),
                  mLightIndicators.Length(), mTouchEvents.Length());
  out->SyncState(this);
  out->SyncState(this);
  return out.forget();
  return out.forget();
}
}
+20 −1
Original line number Original line Diff line number Diff line
@@ -12,6 +12,8 @@
#include "mozilla/dom/GamepadButton.h"
#include "mozilla/dom/GamepadButton.h"
#include "mozilla/dom/GamepadPose.h"
#include "mozilla/dom/GamepadPose.h"
#include "mozilla/dom/GamepadHapticActuator.h"
#include "mozilla/dom/GamepadHapticActuator.h"
#include "mozilla/dom/GamepadLightIndicator.h"
#include "mozilla/dom/GamepadTouch.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/dom/Performance.h"
#include <stdint.h>
#include <stdint.h>
#include "nsCOMPtr.h"
#include "nsCOMPtr.h"
@@ -40,7 +42,8 @@ class Gamepad final : public nsISupports, public nsWrapperCache {
  Gamepad(nsISupports* aParent, const nsAString& aID, uint32_t aIndex,
  Gamepad(nsISupports* aParent, const nsAString& aID, uint32_t aIndex,
          uint32_t aHashKey, GamepadMappingType aMapping, GamepadHand aHand,
          uint32_t aHashKey, GamepadMappingType aMapping, GamepadHand aHand,
          uint32_t aDisplayID, uint32_t aNumButtons, uint32_t aNumAxes,
          uint32_t aDisplayID, uint32_t aNumButtons, uint32_t aNumAxes,
          uint32_t aNumHaptics);
          uint32_t aNumHaptics, uint32_t aNumLightIndicator,
          uint32_t aNumTouchEvents);


  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Gamepad)
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Gamepad)
@@ -50,6 +53,9 @@ class Gamepad final : public nsISupports, public nsWrapperCache {
  void SetAxis(uint32_t aAxis, double aValue);
  void SetAxis(uint32_t aAxis, double aValue);
  void SetIndex(uint32_t aIndex);
  void SetIndex(uint32_t aIndex);
  void SetPose(const GamepadPoseState& aPose);
  void SetPose(const GamepadPoseState& aPose);
  void SetLightIndicatorType(uint32_t aLightIndex,
                             GamepadLightIndicatorType aType);
  void SetTouchEvent(uint32_t aTouchIndex, const GamepadTouchState& aTouch);
  void SetHand(GamepadHand aHand);
  void SetHand(GamepadHand aHand);


  // Make the state of this gamepad equivalent to other.
  // Make the state of this gamepad equivalent to other.
@@ -93,6 +99,15 @@ class Gamepad final : public nsISupports, public nsWrapperCache {
    aHapticActuators = mHapticActuators;
    aHapticActuators = mHapticActuators;
  }
  }


  void GetLightIndicators(
      nsTArray<RefPtr<GamepadLightIndicator>>& aLightIndicators) const {
    aLightIndicators = mLightIndicators;
  }

  void GetTouchEvents(nsTArray<RefPtr<GamepadTouch>>& aTouchEvents) const {
    aTouchEvents = mTouchEvents;
  }

 private:
 private:
  virtual ~Gamepad() {}
  virtual ~Gamepad() {}
  void UpdateTimestamp();
  void UpdateTimestamp();
@@ -104,6 +119,7 @@ class Gamepad final : public nsISupports, public nsWrapperCache {
  // the gamepad hash key in GamepadManager
  // the gamepad hash key in GamepadManager
  uint32_t mHashKey;
  uint32_t mHashKey;
  uint32_t mDisplayId;
  uint32_t mDisplayId;
  uint32_t mTouchIdHashValue;
  // The mapping in use.
  // The mapping in use.
  GamepadMappingType mMapping;
  GamepadMappingType mMapping;
  GamepadHand mHand;
  GamepadHand mHand;
@@ -117,6 +133,9 @@ class Gamepad final : public nsISupports, public nsWrapperCache {
  DOMHighResTimeStamp mTimestamp;
  DOMHighResTimeStamp mTimestamp;
  RefPtr<GamepadPose> mPose;
  RefPtr<GamepadPose> mPose;
  nsTArray<RefPtr<GamepadHapticActuator>> mHapticActuators;
  nsTArray<RefPtr<GamepadHapticActuator>> mHapticActuators;
  nsTArray<RefPtr<GamepadLightIndicator>> mLightIndicators;
  nsTArray<RefPtr<GamepadTouch>> mTouchEvents;
  nsDataHashtable<nsUint32HashKey, uint32_t> mTouchIdHash;
};
};


}  // namespace dom
}  // namespace dom
+69 −0
Original line number Original line Diff line number Diff line
/* -*- 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 "mozilla/dom/GamepadLightIndicator.h"
#include "mozilla/dom/GamepadManager.h"
#include "mozilla/dom/Promise.h"

namespace mozilla {
namespace dom {

NS_IMPL_CYCLE_COLLECTING_ADDREF(GamepadLightIndicator)
NS_IMPL_CYCLE_COLLECTING_RELEASE(GamepadLightIndicator)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GamepadLightIndicator)
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(GamepadLightIndicator, mParent)

GamepadLightIndicator::GamepadLightIndicator(nsISupports* aParent,
                                             uint32_t aGamepadId,
                                             uint32_t aIndex)
    : mParent(aParent),
      mType(DefaultType()),
      mGamepadId(aGamepadId),
      mIndex(aIndex) {}

GamepadLightIndicator::~GamepadLightIndicator() {
  mozilla::DropJSObjects(this);
}

/* virtual */ JSObject* GamepadLightIndicator::WrapObject(
    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
  return GamepadLightIndicator_Binding::Wrap(aCx, this, aGivenProto);
}

nsISupports* GamepadLightIndicator::GetParentObject() const { return mParent; }

already_AddRefed<Promise> GamepadLightIndicator::SetColor(
    const GamepadLightColor& color, ErrorResult& aRv) {
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
  MOZ_ASSERT(global);

  RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
  MOZ_ASSERT(gamepadManager);

  RefPtr<Promise> promise = gamepadManager->SetLightIndicatorColor(
      mGamepadId, mIndex, color.mRed, color.mGreen, color.mBlue, global, aRv);
  if (!promise) {
    return nullptr;
  }
  return promise.forget();
}

GamepadLightIndicatorType GamepadLightIndicator::Type() const { return mType; }

void GamepadLightIndicator::Set(const GamepadLightIndicator* aOther) {
  MOZ_ASSERT(aOther);
  mGamepadId = aOther->mGamepadId;
  mType = aOther->mType;
  mIndex = aOther->mIndex;
}

}  // namespace dom
}  // namespace mozilla
+53 −0
Original line number Original line Diff line number Diff line
/* -*- 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/. */

#ifndef mozilla_dom_gamepad_GamepadLightIndicator_h
#define mozilla_dom_gamepad_GamepadLightIndicator_h

#include "mozilla/dom/GamepadLightIndicatorBinding.h"

namespace mozilla {
namespace dom {

class GamepadLightIndicator final : public nsISupports, public nsWrapperCache {
 public:
  GamepadLightIndicator(nsISupports* aParent, uint32_t aGamepadId,
                        uint32_t aIndex);

  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(GamepadLightIndicator)

  static GamepadLightIndicatorType DefaultType() {
    return GamepadLightIndicatorType::Rgb;
  }

  nsISupports* GetParentObject() const;

  virtual JSObject* WrapObject(JSContext* aCx,
                               JS::Handle<JSObject*> aGivenProto) override;

  already_AddRefed<Promise> SetColor(const GamepadLightColor& color,
                                     ErrorResult& aRv);

  void SetType(GamepadLightIndicatorType aType) { mType = aType; }

  GamepadLightIndicatorType Type() const;

  void Set(const GamepadLightIndicator* aOther);

 private:
  virtual ~GamepadLightIndicator();

  nsCOMPtr<nsISupports> mParent;
  GamepadLightIndicatorType mType;
  uint32_t mGamepadId;
  uint32_t mIndex;
};

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_gamepad_GamepadLightIndicator_h
+87 −0
Original line number Original line Diff line number Diff line
/* -*- 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 "mozilla/dom/GamepadTouch.h"
#include "mozilla/dom/GamepadManager.h"
#include "mozilla/dom/Promise.h"

namespace mozilla {
namespace dom {

NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadTouch)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GamepadTouch)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
  tmp->mPosition = nullptr;
  tmp->mSurfaceDimensions = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GamepadTouch)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(GamepadTouch)
  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPosition)
  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mSurfaceDimensions)
NS_IMPL_CYCLE_COLLECTION_TRACE_END

NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(GamepadTouch, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(GamepadTouch, Release)

GamepadTouch::GamepadTouch(nsISupports* aParent)
    : mParent(aParent), mPosition(nullptr), mSurfaceDimensions(nullptr) {
  mozilla::HoldJSObjects(this);
  mTouchState = GamepadTouchState();
}

GamepadTouch::~GamepadTouch() { mozilla::DropJSObjects(this); }

/* virtual */ JSObject* GamepadTouch::WrapObject(
    JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
  return GamepadTouch_Binding::Wrap(aCx, this, aGivenProto);
}

void GamepadTouch::GetPosition(JSContext* aCx,
                               JS::MutableHandle<JSObject*> aRetval,
                               ErrorResult& aRv) {
  mPosition = Float32Array::Create(aCx, this, 2, mTouchState.position);
  if (!mPosition) {
    aRv.NoteJSContextException(aCx);
    return;
  }

  aRetval.set(mPosition);
}

void GamepadTouch::GetSurfaceDimensions(JSContext* aCx,
                                        JS::MutableHandle<JSObject*> aRetval,
                                        ErrorResult& aRv) {
  mSurfaceDimensions = Uint32Array::Create(aCx, this, 2,
                                           mTouchState.isSurfaceDimensionsValid
                                               ? mTouchState.surfaceDimensions
                                               : nullptr);

  if (!mSurfaceDimensions) {
    aRv.NoteJSContextException(aCx);
    return;
  }

  aRetval.set(mSurfaceDimensions);
}

void GamepadTouch::SetTouchState(const GamepadTouchState& aTouch) {
  mTouchState = aTouch;
}

void GamepadTouch::Set(const GamepadTouch* aOther) {
  MOZ_ASSERT(aOther);
  mTouchState = aOther->mTouchState;
}

}  // namespace dom
}  // namespace mozilla
Loading