dom/gamepad/Gamepad.cpp
author Ted Mielczarek <ted@mielczarek.org>
Thu, 14 Dec 2017 10:20:33 -0600
changeset 448896 b5c9bb05168d5ce9c92f500d25516b19d0a3062a
parent 418206 7e194151d3691e523b1ba9d7a02e71915f06b1f9
child 478957 a97feb8161b7a4c60a539d83cb702a6e50fab1b1
permissions -rw-r--r--
bug 1401647 - use a 64-bit Rust toolchain for win32 builds. r=rillian We currently use a 32-bit Rust toolchain for win32 builds, but this can lead to OOM situations. This patch makes win32 builds use a 64-bit Rust toolchain, which requires a little bit of extra configuration because rustc needs to be able to find a link.exe that produces 64-bit binaries for building things like build scripts, which are host binaries. We will now generate a batch file that sets LIB to the paths to 64-bit libraries and invokes the x64-targeting link.exe, and add a section to the .cargo/config file to instruct cargo to use that batch file as the linker when producing 64-bit binaries. MozReview-Commit-ID: 9vKBbm7Gvra

/* -*- 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/dom/GamepadBinding.h"

namespace mozilla {
namespace 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)

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, uint32_t aIndex,
                 uint32_t aHashKey,
                 GamepadMappingType aMapping,
                 GamepadHand aHand,
                 uint32_t aDisplayID, uint32_t aNumButtons,
                 uint32_t aNumAxes, uint32_t aNumHaptics)
  : mParent(aParent),
    mID(aID),
    mIndex(aIndex),
    mHashKey(aHashKey),
    mDisplayId(aDisplayID),
    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, mHashKey, i));
  }
  UpdateTimestamp();
}

void
Gamepad::SetIndex(uint32_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;
    GamepadBinding::ClearCachedAxesValue(this);
  }
  UpdateTimestamp();
}

void
Gamepad::SetPose(const GamepadPoseState& aPose)
{
  mPose->SetPoseState(aPose);
  UpdateTimestamp();
}

void
Gamepad::SetHand(GamepadHand aHand)
{
  mHand = aHand;
}

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

  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) {
    GamepadBinding::ClearCachedAxesValue(this);
  }

  if (Preferences::GetBool(kGamepadExtEnabledPref)) {
    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]);
    }
  }

  UpdateTimestamp();
}

already_AddRefed<Gamepad>
Gamepad::Clone(nsISupports* aParent)
{
  RefPtr<Gamepad> out =
    new Gamepad(aParent, mID, mIndex, mHashKey, mMapping,
                mHand, mDisplayId, mButtons.Length(), mAxes.Length(),
                mHapticActuators.Length());
  out->SyncState(this);
  return out.forget();
}

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

} // namespace dom
} // namespace mozilla