mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 852944 - Gamepad API IPC; r=ted, r=baku
This commit is contained in:
parent
5fdce942ec
commit
b9e62b0591
@ -187,6 +187,7 @@
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/Gamepad.h"
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#endif
|
||||
|
||||
@ -13367,6 +13368,15 @@ void
|
||||
nsGlobalWindow::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
// Create the index we will present to content based on which indices are
|
||||
// already taken, as required by the spec.
|
||||
// https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
|
||||
int index = 0;
|
||||
while(mGamepadIndexSet.Contains(index)) {
|
||||
++index;
|
||||
}
|
||||
mGamepadIndexSet.Put(index);
|
||||
aGamepad->SetIndex(index);
|
||||
mGamepads.Put(aIndex, aGamepad);
|
||||
}
|
||||
|
||||
@ -13374,6 +13384,12 @@ void
|
||||
nsGlobalWindow::RemoveGamepad(uint32_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
nsRefPtr<Gamepad> gamepad;
|
||||
if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
|
||||
return;
|
||||
}
|
||||
// Free up the index we were using so it can be reused
|
||||
mGamepadIndexSet.Remove(gamepad->Index());
|
||||
mGamepads.Remove(aIndex);
|
||||
}
|
||||
|
||||
@ -13384,8 +13400,8 @@ nsGlobalWindow::EnumGamepadsForGet(const uint32_t& aKey, Gamepad* aData,
|
||||
{
|
||||
nsTArray<nsRefPtr<Gamepad> >* array =
|
||||
static_cast<nsTArray<nsRefPtr<Gamepad> >*>(aUserArg);
|
||||
array->EnsureLengthAtLeast(aKey + 1);
|
||||
(*array)[aKey] = aData;
|
||||
array->EnsureLengthAtLeast(aData->Index() + 1);
|
||||
(*array)[aData->Index()] = aData;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
@ -13404,6 +13420,7 @@ nsGlobalWindow::GetGamepad(uint32_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
nsRefPtr<Gamepad> gamepad;
|
||||
|
||||
if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
|
||||
return gamepad.forget();
|
||||
}
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "Units.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsCheapSets.h"
|
||||
|
||||
#define DEFAULT_HOME_PAGE "www.mozilla.org"
|
||||
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
|
||||
@ -1590,6 +1591,7 @@ protected:
|
||||
// Indicates whether this window wants gamepad input events
|
||||
bool mHasGamepad : 1;
|
||||
#ifdef MOZ_GAMEPAD
|
||||
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
|
||||
nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
|
||||
bool mHasSeenGamepadInput;
|
||||
#endif
|
||||
|
105
dom/gamepad/GamepadFunctions.cpp
Normal file
105
dom/gamepad/GamepadFunctions.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/* 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/GamepadFunctions.h"
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace GamepadFunctions {
|
||||
|
||||
namespace {
|
||||
// Increments as gamepads are added
|
||||
uint32_t gGamepadIndex = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
NotifyGamepadChange(const T& aInfo)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
GamepadChangeEvent e(aInfo);
|
||||
nsTArray<ContentParent*> t;
|
||||
ContentParent::GetAll(t);
|
||||
for(uint32_t i = 0; i < t.Length(); ++i) {
|
||||
unused << t[i]->SendGamepadUpdate(e);
|
||||
}
|
||||
// If we have a GamepadService in the main process, send directly to it.
|
||||
if (GamepadService::IsServiceRunning()) {
|
||||
nsRefPtr<GamepadService> svc = GamepadService::GetService();
|
||||
svc->Update(e);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AddGamepad(const char* aID,
|
||||
GamepadMappingType aMapping,
|
||||
uint32_t aNumButtons, uint32_t aNumAxes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
int index = gGamepadIndex;
|
||||
gGamepadIndex++;
|
||||
GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), index,
|
||||
(uint32_t)aMapping, aNumButtons, aNumAxes);
|
||||
gGamepadIndex++;
|
||||
NotifyGamepadChange<GamepadAdded>(a);
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
RemoveGamepad(uint32_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
GamepadRemoved a(aIndex);
|
||||
NotifyGamepadChange<GamepadRemoved>(a);
|
||||
}
|
||||
|
||||
void
|
||||
NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
bool aPressed, double aValue)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
GamepadButtonInformation a(aIndex, aButton, aPressed, aValue);
|
||||
NotifyGamepadChange<GamepadButtonInformation>(a);
|
||||
}
|
||||
|
||||
void
|
||||
NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
bool aPressed)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
// When only a digital button is available the value will be synthesized.
|
||||
NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L);
|
||||
}
|
||||
|
||||
void
|
||||
NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
|
||||
double aValue)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
GamepadAxisInformation a(aIndex, aAxis, aValue);
|
||||
NotifyGamepadChange<GamepadAxisInformation>(a);
|
||||
}
|
||||
|
||||
void
|
||||
ResetGamepadIndexes()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
gGamepadIndex = 0;
|
||||
}
|
||||
|
||||
} // namespace GamepadFunctions
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
45
dom/gamepad/GamepadFunctions.h
Normal file
45
dom/gamepad/GamepadFunctions.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* 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_GamepadFunctions_h_
|
||||
#define mozilla_dom_GamepadFunctions_h_
|
||||
|
||||
#include "mozilla/dom/GamepadBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace GamepadFunctions {
|
||||
|
||||
// Functions for building and transmitting IPDL messages through the HAL
|
||||
// sandbox. Used by platform specific Gamepad implementations
|
||||
|
||||
// Add a gamepad to the list of known gamepads, and return its index.
|
||||
uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping,
|
||||
uint32_t aNumButtons, uint32_t aNumAxes);
|
||||
// Remove the gamepad at |aIndex| from the list of known gamepads.
|
||||
void RemoveGamepad(uint32_t aIndex);
|
||||
|
||||
// Update the state of |aButton| for the gamepad at |aIndex| for all
|
||||
// windows that are listening and visible, and fire one of
|
||||
// a gamepadbutton{up,down} event at them as well.
|
||||
// aPressed is used for digital buttons, aValue is for analog buttons.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
|
||||
double aValue);
|
||||
// When only a digital button is available the value will be synthesized.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
|
||||
|
||||
// Update the state of |aAxis| for the gamepad at |aIndex| for all
|
||||
// windows that are listening and visible, and fire a gamepadaxismove
|
||||
// event at them as well.
|
||||
void NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue);
|
||||
|
||||
// When shutting down the platform communications for gamepad, also reset the
|
||||
// indexes.
|
||||
void ResetGamepadIndexes();
|
||||
|
||||
} // namespace GamepadFunctions
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
31
dom/gamepad/GamepadMonitoring.cpp
Normal file
31
dom/gamepad/GamepadMonitoring.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/GamepadMonitoring.h"
|
||||
#include "mozilla/dom/GamepadFunctions.h"
|
||||
#include "mozilla/dom/PContentParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using namespace GamepadFunctions;
|
||||
|
||||
void
|
||||
MaybeStopGamepadMonitoring()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
nsTArray<ContentParent*> t;
|
||||
ContentParent::GetAll(t);
|
||||
for(uint32_t i = 0; i < t.Length(); ++i) {
|
||||
if (t[i]->HasGamepadListener()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
StopGamepadMonitoring();
|
||||
ResetGamepadIndexes();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
22
dom/gamepad/GamepadMonitoring.h
Normal file
22
dom/gamepad/GamepadMonitoring.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* 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_GamepadMonitoring_h_
|
||||
#define mozilla_dom_GamepadMonitoring_h_
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
// Functions for platform specific gamepad monitoring.
|
||||
|
||||
void MaybeStopGamepadMonitoring();
|
||||
|
||||
// These two functions are implemented in the platform specific service files
|
||||
// (linux/LinuxGamepad.cpp, cocoa/CocoaGamepad.cpp, etc)
|
||||
void StartGamepadMonitoring();
|
||||
void StopGamepadMonitoring();
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -2,13 +2,18 @@
|
||||
* 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/Hal.h"
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/Gamepad.h"
|
||||
#include "mozilla/dom/GamepadAxisMoveEvent.h"
|
||||
#include "mozilla/dom/GamepadButtonEvent.h"
|
||||
#include "mozilla/dom/GamepadEvent.h"
|
||||
#include "mozilla/dom/GamepadMonitoring.h"
|
||||
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
#include "GamepadService.h"
|
||||
#include "Gamepad.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
@ -20,10 +25,6 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#include "mozilla/dom/GamepadAxisMoveEvent.h"
|
||||
#include "mozilla/dom/GamepadButtonEvent.h"
|
||||
#include "mozilla/dom/GamepadEvent.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace mozilla {
|
||||
@ -82,7 +83,11 @@ GamepadService::BeginShutdown()
|
||||
mTimer->Cancel();
|
||||
}
|
||||
if (mStarted) {
|
||||
mozilla::hal::StopMonitoringGamepadStatus();
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
MaybeStopGamepadMonitoring();
|
||||
} else {
|
||||
ContentChild::GetSingleton()->SendGamepadListenerRemoved();
|
||||
}
|
||||
mStarted = false;
|
||||
}
|
||||
// Don't let windows call back to unregister during shutdown
|
||||
@ -99,7 +104,6 @@ GamepadService::AddListener(nsGlobalWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsInnerWindow());
|
||||
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
@ -109,10 +113,13 @@ GamepadService::AddListener(nsGlobalWindow* aWindow)
|
||||
}
|
||||
|
||||
if (!mStarted && mEnabled) {
|
||||
mozilla::hal::StartMonitoringGamepadStatus();
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
StartGamepadMonitoring();
|
||||
} else {
|
||||
ContentChild::GetSingleton()->SendGamepadListenerAdded();
|
||||
}
|
||||
mStarted = true;
|
||||
}
|
||||
|
||||
mListeners.AppendElement(aWindow);
|
||||
}
|
||||
|
||||
@ -139,8 +146,20 @@ GamepadService::RemoveListener(nsGlobalWindow* aWindow)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GamepadService::AddGamepad(const char* aId,
|
||||
already_AddRefed<Gamepad>
|
||||
GamepadService::GetGamepad(uint32_t aIndex)
|
||||
{
|
||||
nsRefPtr<Gamepad> gamepad;
|
||||
if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
|
||||
return gamepad.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
GamepadService::AddGamepad(uint32_t aIndex,
|
||||
const nsAString& aId,
|
||||
GamepadMappingType aMapping,
|
||||
uint32_t aNumButtons,
|
||||
uint32_t aNumAxes)
|
||||
@ -148,63 +167,40 @@ GamepadService::AddGamepad(const char* aId,
|
||||
//TODO: bug 852258: get initial button/axis state
|
||||
nsRefPtr<Gamepad> gamepad =
|
||||
new Gamepad(nullptr,
|
||||
NS_ConvertUTF8toUTF16(nsDependentCString(aId)),
|
||||
0,
|
||||
aId,
|
||||
0, // index is set by global window
|
||||
aMapping,
|
||||
aNumButtons,
|
||||
aNumAxes);
|
||||
int index = -1;
|
||||
for (uint32_t i = 0; i < mGamepads.Length(); i++) {
|
||||
if (!mGamepads[i]) {
|
||||
mGamepads[i] = gamepad;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == -1) {
|
||||
mGamepads.AppendElement(gamepad);
|
||||
index = mGamepads.Length() - 1;
|
||||
}
|
||||
|
||||
gamepad->SetIndex(index);
|
||||
NewConnectionEvent(index, true);
|
||||
|
||||
return index;
|
||||
// We store the gamepad related to its index given by the parent process.
|
||||
mGamepads.Put(aIndex, gamepad);
|
||||
NewConnectionEvent(aIndex, true);
|
||||
}
|
||||
|
||||
void
|
||||
GamepadService::RemoveGamepad(uint32_t aIndex)
|
||||
{
|
||||
if (aIndex < mGamepads.Length()) {
|
||||
mGamepads[aIndex]->SetConnected(false);
|
||||
NewConnectionEvent(aIndex, false);
|
||||
// If this is the last entry in the list, just remove it.
|
||||
if (aIndex == mGamepads.Length() - 1) {
|
||||
mGamepads.RemoveElementAt(aIndex);
|
||||
} else {
|
||||
// Otherwise just null it out and leave it, so the
|
||||
// indices of the following entries remain valid.
|
||||
mGamepads[aIndex] = nullptr;
|
||||
}
|
||||
nsRefPtr<Gamepad> gamepad = GetGamepad(aIndex);
|
||||
if (!gamepad) {
|
||||
NS_WARNING("Trying to delete gamepad with invalid index");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed)
|
||||
{
|
||||
// Synthesize a value: 1.0 for pressed, 0.0 for unpressed.
|
||||
NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L);
|
||||
gamepad->SetConnected(false);
|
||||
NewConnectionEvent(aIndex, false);
|
||||
mGamepads.Remove(aIndex);
|
||||
}
|
||||
|
||||
void
|
||||
GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
|
||||
double aValue)
|
||||
{
|
||||
if (mShuttingDown || aIndex >= mGamepads.Length()) {
|
||||
nsRefPtr<Gamepad> gamepad = GetGamepad(aIndex);
|
||||
if (mShuttingDown || !gamepad) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGamepads[aIndex]->SetButton(aButton, aPressed, aValue);
|
||||
gamepad->SetButton(aButton, aPressed, aValue);
|
||||
|
||||
// Hold on to listeners in a separate array because firing events
|
||||
// can mutate the mListeners array.
|
||||
@ -227,15 +223,15 @@ GamepadService::NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
|
||||
first_time = true;
|
||||
}
|
||||
|
||||
nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (gamepad) {
|
||||
gamepad->SetButton(aButton, aPressed, aValue);
|
||||
nsRefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (listenerGamepad) {
|
||||
listenerGamepad->SetButton(aButton, aPressed, aValue);
|
||||
if (first_time) {
|
||||
FireConnectionEvent(listeners[i], gamepad, true);
|
||||
FireConnectionEvent(listeners[i], listenerGamepad, true);
|
||||
}
|
||||
if (mNonstandardEventsEnabled) {
|
||||
// Fire event
|
||||
FireButtonEvent(listeners[i], gamepad, aButton, aValue);
|
||||
FireButtonEvent(listeners[i], listenerGamepad, aButton, aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,10 +262,11 @@ GamepadService::FireButtonEvent(EventTarget* aTarget,
|
||||
void
|
||||
GamepadService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue)
|
||||
{
|
||||
if (mShuttingDown || aIndex >= mGamepads.Length()) {
|
||||
nsRefPtr<Gamepad> gamepad = GetGamepad(aIndex);
|
||||
if (mShuttingDown || !gamepad) {
|
||||
return;
|
||||
}
|
||||
mGamepads[aIndex]->SetAxis(aAxis, aValue);
|
||||
gamepad->SetAxis(aAxis, aValue);
|
||||
|
||||
// Hold on to listeners in a separate array because firing events
|
||||
// can mutate the mListeners array.
|
||||
@ -292,15 +289,15 @@ GamepadService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue)
|
||||
first_time = true;
|
||||
}
|
||||
|
||||
nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (gamepad) {
|
||||
gamepad->SetAxis(aAxis, aValue);
|
||||
nsRefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (listenerGamepad) {
|
||||
listenerGamepad->SetAxis(aAxis, aValue);
|
||||
if (first_time) {
|
||||
FireConnectionEvent(listeners[i], gamepad, true);
|
||||
FireConnectionEvent(listeners[i], listenerGamepad, true);
|
||||
}
|
||||
if (mNonstandardEventsEnabled) {
|
||||
// Fire event
|
||||
FireAxisMoveEvent(listeners[i], gamepad, aAxis, aValue);
|
||||
FireAxisMoveEvent(listeners[i], listenerGamepad, aAxis, aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,7 +329,9 @@ GamepadService::FireAxisMoveEvent(EventTarget* aTarget,
|
||||
void
|
||||
GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected)
|
||||
{
|
||||
if (mShuttingDown || aIndex >= mGamepads.Length()) {
|
||||
nsRefPtr<Gamepad> gamepad = GetGamepad(aIndex);
|
||||
|
||||
if (mShuttingDown || !gamepad) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -358,10 +357,10 @@ GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected)
|
||||
|
||||
SetWindowHasSeenGamepad(listeners[i], aIndex);
|
||||
|
||||
nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (gamepad) {
|
||||
nsRefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (listenerGamepad) {
|
||||
// Fire event
|
||||
FireConnectionEvent(listeners[i], gamepad, aConnected);
|
||||
FireConnectionEvent(listeners[i], listenerGamepad, aConnected);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -374,11 +373,11 @@ GamepadService::NewConnectionEvent(uint32_t aIndex, bool aConnected)
|
||||
// deal with the hassle of syncing the state of removed gamepads.
|
||||
|
||||
if (WindowHasSeenGamepad(listeners[i], aIndex)) {
|
||||
nsRefPtr<Gamepad> gamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (gamepad) {
|
||||
gamepad->SetConnected(false);
|
||||
nsRefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(aIndex);
|
||||
if (listenerGamepad) {
|
||||
listenerGamepad->SetConnected(false);
|
||||
// Fire event
|
||||
FireConnectionEvent(listeners[i], gamepad, false);
|
||||
FireConnectionEvent(listeners[i], listenerGamepad, false);
|
||||
listeners[i]->RemoveGamepad(aIndex);
|
||||
}
|
||||
}
|
||||
@ -409,11 +408,19 @@ GamepadService::FireConnectionEvent(EventTarget* aTarget,
|
||||
void
|
||||
GamepadService::SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad)
|
||||
{
|
||||
if (mShuttingDown || !mEnabled || aIndex > mGamepads.Length()) {
|
||||
nsRefPtr<Gamepad> gamepad = GetGamepad(aIndex);
|
||||
if (mShuttingDown || !mEnabled || !gamepad) {
|
||||
return;
|
||||
}
|
||||
|
||||
aGamepad->SyncState(mGamepads[aIndex]);
|
||||
aGamepad->SyncState(gamepad);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
GamepadService::IsServiceRunning()
|
||||
{
|
||||
return !!gGamepadServiceSingleton;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -461,8 +468,13 @@ GamepadService::SetWindowHasSeenGamepad(nsGlobalWindow* aWindow,
|
||||
if (aHasSeen) {
|
||||
aWindow->SetHasSeenGamepadInput(true);
|
||||
nsCOMPtr<nsISupports> window = ToSupports(aWindow);
|
||||
nsRefPtr<Gamepad> gamepad = mGamepads[aIndex]->Clone(window);
|
||||
aWindow->AddGamepad(aIndex, gamepad);
|
||||
nsRefPtr<Gamepad> gamepad = GetGamepad(aIndex);
|
||||
MOZ_ASSERT(gamepad);
|
||||
if (!gamepad) {
|
||||
return;
|
||||
}
|
||||
nsRefPtr<Gamepad> clonedGamepad = gamepad->Clone(window);
|
||||
aWindow->AddGamepad(aIndex, clonedGamepad);
|
||||
} else {
|
||||
aWindow->RemoveGamepad(aIndex);
|
||||
}
|
||||
@ -486,13 +498,16 @@ GamepadService::TimeoutHandler(nsITimer* aTimer, void* aClosure)
|
||||
}
|
||||
|
||||
if (self->mListeners.Length() == 0) {
|
||||
mozilla::hal::StopMonitoringGamepadStatus();
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
MaybeStopGamepadMonitoring();
|
||||
} else {
|
||||
ContentChild::GetSingleton()->SendGamepadListenerRemoved();
|
||||
}
|
||||
|
||||
self->mStarted = false;
|
||||
if (!self->mGamepads.IsEmpty()) {
|
||||
self->mGamepads.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GamepadService::StartCleanupTimer()
|
||||
@ -510,71 +525,26 @@ GamepadService::StartCleanupTimer()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of the test service. This is just to provide a simple binding
|
||||
* of the GamepadService to JavaScript via XPCOM so that we can write Mochitests
|
||||
* that add and remove fake gamepads, avoiding the platform-specific backends.
|
||||
*/
|
||||
NS_IMPL_ISUPPORTS(GamepadServiceTest, nsIGamepadServiceTest)
|
||||
|
||||
GamepadServiceTest* GamepadServiceTest::sSingleton = nullptr;
|
||||
|
||||
// static
|
||||
already_AddRefed<GamepadServiceTest>
|
||||
GamepadServiceTest::CreateService()
|
||||
void
|
||||
GamepadService::Update(const GamepadChangeEvent& aEvent)
|
||||
{
|
||||
if (sSingleton == nullptr) {
|
||||
sSingleton = new GamepadServiceTest();
|
||||
if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {
|
||||
const GamepadAdded& a = aEvent.get_GamepadAdded();
|
||||
AddGamepad(a.index(), a.id(),
|
||||
static_cast<GamepadMappingType>(a.mapping()),
|
||||
a.num_buttons(), a.num_axes());
|
||||
} else if (aEvent.type() == GamepadChangeEvent::TGamepadRemoved) {
|
||||
const GamepadRemoved& a = aEvent.get_GamepadRemoved();
|
||||
RemoveGamepad(a.index());
|
||||
} else if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
|
||||
const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
|
||||
NewButtonEvent(a.index(), a.button(), a.pressed(), a.value());
|
||||
} else if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
|
||||
const GamepadAxisInformation& a = aEvent.get_GamepadAxisInformation();
|
||||
NewAxisMoveEvent(a.index(), a.axis(), a.value());
|
||||
} else {
|
||||
MOZ_CRASH("We shouldn't be here!");
|
||||
}
|
||||
nsRefPtr<GamepadServiceTest> service = sSingleton;
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
GamepadServiceTest::GamepadServiceTest()
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
nsRefPtr<GamepadService> service = GamepadService::GetService();
|
||||
}
|
||||
|
||||
/* uint32_t addGamepad (in string id, in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); */
|
||||
NS_IMETHODIMP GamepadServiceTest::AddGamepad(const char* aID,
|
||||
uint32_t aMapping,
|
||||
uint32_t aNumButtons,
|
||||
uint32_t aNumAxes,
|
||||
uint32_t* aRetval)
|
||||
{
|
||||
*aRetval = gGamepadServiceSingleton->AddGamepad(aID,
|
||||
static_cast<GamepadMappingType>(aMapping),
|
||||
aNumButtons,
|
||||
aNumAxes);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void removeGamepad (in uint32_t index); */
|
||||
NS_IMETHODIMP GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
|
||||
{
|
||||
gGamepadServiceSingleton->RemoveGamepad(aIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void newButtonEvent (in uint32_t index, in uint32_t button,
|
||||
in boolean pressed); */
|
||||
NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
||||
uint32_t aButton,
|
||||
bool aPressed)
|
||||
{
|
||||
gGamepadServiceSingleton->NewButtonEvent(aIndex, aButton, aPressed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void newAxisMoveEvent (in uint32_t index, in uint32_t axis,
|
||||
in double value); */
|
||||
NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex,
|
||||
uint32_t aAxis,
|
||||
double aValue)
|
||||
{
|
||||
gGamepadServiceSingleton->NewAxisMoveEvent(aIndex, aAxis, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define mozilla_dom_GamepadService_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Gamepad.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIGamepadServiceTest.h"
|
||||
@ -15,11 +14,14 @@
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// Needed for GamepadMappingType
|
||||
#include "mozilla/dom/GamepadBinding.h"
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class EventTarget;
|
||||
class GamepadChangeEvent;
|
||||
class Gamepad;
|
||||
|
||||
class GamepadService : public nsIObserver
|
||||
{
|
||||
@ -27,6 +29,8 @@ class GamepadService : public nsIObserver
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// Returns true if we actually have a service up and running
|
||||
static bool IsServiceRunning();
|
||||
// Get the singleton service
|
||||
static already_AddRefed<GamepadService> GetService();
|
||||
// Return true if the API is preffed on.
|
||||
@ -39,9 +43,10 @@ class GamepadService : public nsIObserver
|
||||
// Indicate that |aWindow| should no longer receive gamepad events.
|
||||
void RemoveListener(nsGlobalWindow* aWindow);
|
||||
|
||||
// Add a gamepad to the list of known gamepads, and return its index.
|
||||
uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping,
|
||||
// Add a gamepad to the list of known gamepads.
|
||||
void AddGamepad(uint32_t aIndex, const nsAString& aID, GamepadMappingType aMapping,
|
||||
uint32_t aNumButtons, uint32_t aNumAxes);
|
||||
|
||||
// Remove the gamepad at |aIndex| from the list of known gamepads.
|
||||
void RemoveGamepad(uint32_t aIndex);
|
||||
|
||||
@ -51,8 +56,6 @@ class GamepadService : public nsIObserver
|
||||
// aPressed is used for digital buttons, aValue is for analog buttons.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
|
||||
double aValue);
|
||||
// When only a digital button is available the value will be synthesized.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
|
||||
|
||||
// Update the state of |aAxis| for the gamepad at |aIndex| for all
|
||||
// windows that are listening and visible, and fire a gamepadaxismove
|
||||
@ -62,6 +65,11 @@ class GamepadService : public nsIObserver
|
||||
// Synchronize the state of |aGamepad| to match the gamepad stored at |aIndex|
|
||||
void SyncGamepadState(uint32_t aIndex, Gamepad* aGamepad);
|
||||
|
||||
// Returns gamepad object if index exists, null otherwise
|
||||
already_AddRefed<Gamepad> GetGamepad(uint32_t aIndex);
|
||||
|
||||
// Receive GamepadChangeEvent messages from parent process to fire DOM events
|
||||
void Update(const GamepadChangeEvent& aGamepadEvent);
|
||||
protected:
|
||||
GamepadService();
|
||||
virtual ~GamepadService() {};
|
||||
@ -115,37 +123,13 @@ class GamepadService : public nsIObserver
|
||||
|
||||
// Gamepads connected to the system. Copies of these are handed out
|
||||
// to each window.
|
||||
nsTArray<nsRefPtr<Gamepad> > mGamepads;
|
||||
nsRefPtrHashtable<nsUint32HashKey, Gamepad> mGamepads;
|
||||
// Inner windows that are listening for gamepad events.
|
||||
// has been sent to that window.
|
||||
nsTArray<nsRefPtr<nsGlobalWindow> > mListeners;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIFocusManager> mFocusManager;
|
||||
nsCOMPtr<nsIObserver> mObserver;
|
||||
};
|
||||
|
||||
// Service for testing purposes
|
||||
class GamepadServiceTest : public nsIGamepadServiceTest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGAMEPADSERVICETEST
|
||||
|
||||
GamepadServiceTest();
|
||||
|
||||
static already_AddRefed<GamepadServiceTest> CreateService();
|
||||
|
||||
private:
|
||||
static GamepadServiceTest* sSingleton;
|
||||
virtual ~GamepadServiceTest() {};
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_GAMEPAD_TEST_CID \
|
||||
{ 0xfb1fcb57, 0xebab, 0x4cf4, \
|
||||
{ 0x96, 0x3b, 0x1e, 0x4d, 0xb8, 0x52, 0x16, 0x96 } }
|
||||
#define NS_GAMEPAD_TEST_CONTRACTID "@mozilla.org/gamepad-test;1"
|
||||
|
||||
#endif // mozilla_dom_GamepadService_h_
|
||||
|
92
dom/gamepad/GamepadServiceTest.cpp
Normal file
92
dom/gamepad/GamepadServiceTest.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/* 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 "GamepadServiceTest.h"
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/GamepadFunctions.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
/*
|
||||
* Implementation of the test service. This is just to provide a simple binding
|
||||
* of the GamepadService to JavaScript via XPCOM so that we can write Mochitests
|
||||
* that add and remove fake gamepads, avoiding the platform-specific backends.
|
||||
*/
|
||||
NS_IMPL_ISUPPORTS(GamepadServiceTest, nsIGamepadServiceTest)
|
||||
|
||||
GamepadServiceTest* GamepadServiceTest::sSingleton = nullptr;
|
||||
|
||||
// static
|
||||
already_AddRefed<GamepadServiceTest>
|
||||
GamepadServiceTest::CreateService()
|
||||
{
|
||||
if (sSingleton == nullptr) {
|
||||
sSingleton = new GamepadServiceTest();
|
||||
}
|
||||
nsRefPtr<GamepadServiceTest> service = sSingleton;
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
GamepadServiceTest::GamepadServiceTest() :
|
||||
mService(GamepadService::GetService())
|
||||
{
|
||||
}
|
||||
|
||||
GamepadServiceTest::~GamepadServiceTest()
|
||||
{
|
||||
}
|
||||
|
||||
/* uint32_t addGamepad(in unsigned long index, in string id, in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); */
|
||||
NS_IMETHODIMP
|
||||
GamepadServiceTest::AddGamepad(const char* aID,
|
||||
uint32_t aMapping,
|
||||
uint32_t aNumButtons,
|
||||
uint32_t aNumAxes,
|
||||
uint32_t* aGamepadIndex)
|
||||
{
|
||||
*aGamepadIndex = GamepadFunctions::AddGamepad(aID,
|
||||
static_cast<GamepadMappingType>(aMapping),
|
||||
aNumButtons,
|
||||
aNumAxes);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void removeGamepad (in uint32_t index); */
|
||||
NS_IMETHODIMP GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
|
||||
{
|
||||
GamepadFunctions::RemoveGamepad(aIndex);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void newButtonEvent (in uint32_t index, in uint32_t button,
|
||||
in boolean pressed); */
|
||||
NS_IMETHODIMP GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
||||
uint32_t aButton,
|
||||
bool aPressed)
|
||||
{
|
||||
GamepadFunctions::NewButtonEvent(aIndex, aButton, aPressed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void newButtonEvent (in uint32_t index, in uint32_t button,
|
||||
in boolean pressed, double value); */
|
||||
NS_IMETHODIMP GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
|
||||
uint32_t aButton,
|
||||
bool aPressed,
|
||||
double aValue)
|
||||
{
|
||||
GamepadFunctions::NewButtonEvent(aIndex, aButton, aPressed, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void newAxisMoveEvent (in uint32_t index, in uint32_t axis,
|
||||
in double value); */
|
||||
NS_IMETHODIMP GamepadServiceTest::NewAxisMoveEvent(uint32_t aIndex,
|
||||
uint32_t aAxis,
|
||||
double aValue)
|
||||
{
|
||||
GamepadFunctions::NewAxisMoveEvent(aIndex, aAxis, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
42
dom/gamepad/GamepadServiceTest.h
Normal file
42
dom/gamepad/GamepadServiceTest.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* 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_GamepadServiceTest_h_
|
||||
#define mozilla_dom_GamepadServiceTest_h_
|
||||
|
||||
#include "nsIGamepadServiceTest.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class GamepadService;
|
||||
|
||||
// Service for testing purposes
|
||||
class GamepadServiceTest : public nsIGamepadServiceTest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIGAMEPADSERVICETEST
|
||||
|
||||
GamepadServiceTest();
|
||||
|
||||
static already_AddRefed<GamepadServiceTest> CreateService();
|
||||
|
||||
private:
|
||||
static GamepadServiceTest* sSingleton;
|
||||
// Hold a reference to the gamepad service so we don't have to worry about
|
||||
// execution order in tests.
|
||||
nsRefPtr<GamepadService> mService;
|
||||
virtual ~GamepadServiceTest();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_GAMEPAD_TEST_CID \
|
||||
{ 0xfb1fcb57, 0xebab, 0x4cf4, \
|
||||
{ 0x96, 0x3b, 0x1e, 0x4d, 0xb8, 0x52, 0x16, 0x96 } }
|
||||
#define NS_GAMEPAD_TEST_CONTRACTID "@mozilla.org/gamepad-test;1"
|
||||
|
||||
#endif
|
@ -3,25 +3,20 @@
|
||||
* 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 "Hal.h"
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
using namespace mozilla::hal;
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
namespace dom {
|
||||
|
||||
void
|
||||
StartMonitoringGamepadStatus()
|
||||
void StartGamepadMonitoring()
|
||||
{
|
||||
widget::GeckoAppShell::StartMonitoringGamepad();
|
||||
}
|
||||
|
||||
void
|
||||
StopMonitoringGamepadStatus()
|
||||
void StopGamepadMonitoring()
|
||||
{
|
||||
widget::GeckoAppShell::StopMonitoringGamepad();
|
||||
}
|
||||
|
||||
} // hal_impl
|
||||
} // mozilla
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -6,7 +6,8 @@
|
||||
// mostly derived from the Allegro source code at:
|
||||
// http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.9/src/macosx/hidjoy.m?revision=13760&view=markup
|
||||
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/GamepadFunctions.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/hid/IOHIDBase.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
@ -17,8 +18,8 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using mozilla::dom::GamepadService;
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom::GamepadFunctions;
|
||||
using std::vector;
|
||||
|
||||
struct Button {
|
||||
@ -248,20 +249,18 @@ DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device)
|
||||
sizeof(product_name), kCFStringEncodingASCII);
|
||||
char buffer[256];
|
||||
sprintf(buffer, "%x-%x-%s", vendorId, productId, product_name);
|
||||
nsRefPtr<GamepadService> service(GamepadService::GetService());
|
||||
mGamepads[slot].mSuperIndex = service->AddGamepad(buffer,
|
||||
mozilla::dom::GamepadMappingType::_empty,
|
||||
(int)mGamepads[slot].numButtons(),
|
||||
(int)mGamepads[slot].numAxes());
|
||||
mGamepads[slot].mSuperIndex = AddGamepad(buffer,
|
||||
mozilla::dom::GamepadMappingType::_empty,
|
||||
(int)mGamepads[slot].numButtons(),
|
||||
(int)mGamepads[slot].numAxes());
|
||||
}
|
||||
|
||||
void
|
||||
DarwinGamepadService::DeviceRemoved(IOHIDDeviceRef device)
|
||||
{
|
||||
nsRefPtr<GamepadService> service(GamepadService::GetService());
|
||||
for (size_t i = 0; i < mGamepads.size(); i++) {
|
||||
if (mGamepads[i] == device) {
|
||||
service->RemoveGamepad(mGamepads[i].mSuperIndex);
|
||||
RemoveGamepad(mGamepads[i].mSuperIndex);
|
||||
mGamepads[i].clear();
|
||||
return;
|
||||
}
|
||||
@ -316,7 +315,6 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
|
||||
// massive (30+ byte) values and crash IOHIDValueGetIntegerValue
|
||||
return;
|
||||
}
|
||||
nsRefPtr<GamepadService> service(GamepadService::GetService());
|
||||
IOHIDElementRef element = IOHIDValueGetElement(value);
|
||||
IOHIDDeviceRef device = IOHIDElementGetDevice(element);
|
||||
for (unsigned i = 0; i < mGamepads.size(); i++) {
|
||||
@ -332,7 +330,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
|
||||
const int numButtons = gamepad.numButtons();
|
||||
for (unsigned b = 0; b < ArrayLength(newState); b++) {
|
||||
if (newState[b] != oldState[b]) {
|
||||
service->NewButtonEvent(i, numButtons - 4 + b, newState[b]);
|
||||
NewButtonEvent(i, numButtons - 4 + b, newState[b]);
|
||||
}
|
||||
}
|
||||
gamepad.setDpadState(newState);
|
||||
@ -340,7 +338,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
|
||||
double d = IOHIDValueGetIntegerValue(value);
|
||||
double v = 2.0f * (d - axis->min) /
|
||||
(double)(axis->max - axis->min) - 1.0f;
|
||||
service->NewAxisMoveEvent(i, axis->id, v);
|
||||
NewAxisMoveEvent(i, axis->id, v);
|
||||
} else if (const Button* button = gamepad.lookupButton(element)) {
|
||||
int iv = IOHIDValueGetIntegerValue(value);
|
||||
bool pressed = iv != 0;
|
||||
@ -351,7 +349,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
|
||||
} else {
|
||||
v = pressed ? 1.0 : 0.0;
|
||||
}
|
||||
service->NewButtonEvent(i, button->id, pressed, v);
|
||||
NewButtonEvent(i, button->id, pressed, v);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -495,28 +493,30 @@ void DarwinGamepadService::Shutdown()
|
||||
} // namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
namespace dom {
|
||||
|
||||
DarwinGamepadService* gService = nullptr;
|
||||
|
||||
void StartMonitoringGamepadStatus()
|
||||
void StartGamepadMonitoring()
|
||||
{
|
||||
if (gService)
|
||||
if (gService) {
|
||||
return;
|
||||
}
|
||||
|
||||
gService = new DarwinGamepadService();
|
||||
gService->Startup();
|
||||
}
|
||||
|
||||
void StopMonitoringGamepadStatus()
|
||||
void StopGamepadMonitoring()
|
||||
{
|
||||
if (!gService)
|
||||
if (!gService) {
|
||||
return;
|
||||
}
|
||||
|
||||
gService->Shutdown();
|
||||
delete gService;
|
||||
gService = nullptr;
|
||||
}
|
||||
|
||||
} // namespace hal_impl
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -4,16 +4,17 @@
|
||||
* 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 "Hal.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
namespace dom {
|
||||
|
||||
void StartMonitoringGamepadStatus()
|
||||
{}
|
||||
void StartGamepadMonitoring()
|
||||
{
|
||||
}
|
||||
|
||||
void StopMonitoringGamepadStatus()
|
||||
{}
|
||||
void StopGamepadMonitoring()
|
||||
{
|
||||
}
|
||||
|
||||
} // hal_impl
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -16,14 +16,13 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nscore.h"
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/GamepadFunctions.h"
|
||||
#include "udev.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using mozilla::dom::GamepadService;
|
||||
using namespace mozilla::dom::GamepadFunctions;
|
||||
using mozilla::udev_lib;
|
||||
using mozilla::udev_device;
|
||||
using mozilla::udev_list_entry;
|
||||
@ -138,11 +137,10 @@ LinuxGamepadService::AddDevice(struct udev_device* dev)
|
||||
ioctl(fd, JSIOCGBUTTONS, &numButtons);
|
||||
gamepad.numButtons = numButtons;
|
||||
|
||||
nsRefPtr<GamepadService> service(GamepadService::GetService());
|
||||
gamepad.index = service->AddGamepad(gamepad.idstring,
|
||||
mozilla::dom::GamepadMappingType::_empty,
|
||||
gamepad.numButtons,
|
||||
gamepad.numAxes);
|
||||
gamepad.index = AddGamepad(gamepad.idstring,
|
||||
mozilla::dom::GamepadMappingType::_empty,
|
||||
gamepad.numButtons,
|
||||
gamepad.numAxes);
|
||||
|
||||
gamepad.source_id =
|
||||
g_io_add_watch(channel,
|
||||
@ -162,11 +160,10 @@ LinuxGamepadService::RemoveDevice(struct udev_device* dev)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<GamepadService> service(GamepadService::GetService());
|
||||
for (unsigned int i = 0; i < mGamepads.Length(); i++) {
|
||||
if (strcmp(mGamepads[i].devpath, devpath) == 0) {
|
||||
g_source_remove(mGamepads[i].source_id);
|
||||
service->RemoveGamepad(mGamepads[i].index);
|
||||
RemoveGamepad(mGamepads[i].index);
|
||||
mGamepads.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
@ -319,14 +316,13 @@ LinuxGamepadService::OnGamepadData(GIOChannel* source,
|
||||
continue;
|
||||
}
|
||||
|
||||
nsRefPtr<GamepadService> service(GamepadService::GetService());
|
||||
switch (event.type) {
|
||||
case JS_EVENT_BUTTON:
|
||||
service->NewButtonEvent(index, event.number, !!event.value);
|
||||
NewButtonEvent(index, event.number, !!event.value);
|
||||
break;
|
||||
case JS_EVENT_AXIS:
|
||||
service->NewAxisMoveEvent(index, event.number,
|
||||
((float)event.value) / kMaxAxisValue);
|
||||
NewAxisMoveEvent(index, event.number,
|
||||
((float)event.value) / kMaxAxisValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -350,24 +346,26 @@ LinuxGamepadService::OnUdevMonitor(GIOChannel* source,
|
||||
} // namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
namespace dom {
|
||||
|
||||
void StartMonitoringGamepadStatus()
|
||||
{
|
||||
if (!gService) {
|
||||
gService = new LinuxGamepadService();
|
||||
gService->Startup();
|
||||
}
|
||||
}
|
||||
|
||||
void StopMonitoringGamepadStatus()
|
||||
void StartGamepadMonitoring()
|
||||
{
|
||||
if (gService) {
|
||||
gService->Shutdown();
|
||||
delete gService;
|
||||
gService = nullptr;
|
||||
return;
|
||||
}
|
||||
gService = new LinuxGamepadService();
|
||||
gService->Startup();
|
||||
}
|
||||
|
||||
} // namespace hal_impl
|
||||
void StopGamepadMonitoring()
|
||||
{
|
||||
if (!gService) {
|
||||
return;
|
||||
}
|
||||
gService->Shutdown();
|
||||
delete gService;
|
||||
gService = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -7,13 +7,40 @@
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Gamepad.h',
|
||||
'GamepadButton.h',
|
||||
'GamepadFunctions.h',
|
||||
'GamepadMonitoring.h',
|
||||
'GamepadService.h',
|
||||
'GamepadServiceTest.h'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES = [
|
||||
'Gamepad.cpp',
|
||||
'GamepadButton.cpp',
|
||||
'GamepadFunctions.cpp',
|
||||
'GamepadMonitoring.cpp',
|
||||
'GamepadService.cpp',
|
||||
'GamepadServiceTest.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_GAMEPAD_BACKEND'] == 'stub':
|
||||
UNIFIED_SOURCES += [
|
||||
'fallback/FallbackGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'cocoa':
|
||||
UNIFIED_SOURCES += [
|
||||
'cocoa/CocoaGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'windows/WindowsGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'linux':
|
||||
UNIFIED_SOURCES += [
|
||||
'linux/LinuxGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'android':
|
||||
UNIFIED_SOURCES += [
|
||||
'android/AndroidGamepad.cpp'
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
@ -25,3 +52,7 @@ LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
|
||||
CFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
@ -20,12 +20,13 @@
|
||||
#include "nsITimer.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/GamepadFunctions.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::GamepadFunctions;
|
||||
using mozilla::ArrayLength;
|
||||
|
||||
// USB HID usage tables, page 1 (Hat switch)
|
||||
@ -455,11 +456,6 @@ WindowsGamepadService::ScanForXInputDevices()
|
||||
{
|
||||
MOZ_ASSERT(mXInput, "XInput should be present!");
|
||||
|
||||
nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());
|
||||
if (!gamepadsvc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
XINPUT_STATE state = {};
|
||||
@ -480,10 +476,10 @@ WindowsGamepadService::ScanForXInputDevices()
|
||||
gamepad.userIndex = i;
|
||||
gamepad.numButtons = kStandardGamepadButtons;
|
||||
gamepad.numAxes = kStandardGamepadAxes;
|
||||
gamepad.id = gamepadsvc->AddGamepad("xinput",
|
||||
GamepadMappingType::Standard,
|
||||
kStandardGamepadButtons,
|
||||
kStandardGamepadAxes);
|
||||
gamepad.id = AddGamepad("xinput",
|
||||
GamepadMappingType::Standard,
|
||||
kStandardGamepadButtons,
|
||||
kStandardGamepadAxes);
|
||||
mGamepads.AppendElement(gamepad);
|
||||
}
|
||||
|
||||
@ -510,14 +506,10 @@ WindowsGamepadService::ScanForDevices()
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());
|
||||
if (!gamepadsvc) {
|
||||
return;
|
||||
}
|
||||
// Look for devices that are no longer present and remove them.
|
||||
for (int i = mGamepads.Length() - 1; i >= 0; i--) {
|
||||
if (!mGamepads[i].present) {
|
||||
gamepadsvc->RemoveGamepad(mGamepads[i].id);
|
||||
RemoveGamepad(mGamepads[i].id);
|
||||
mGamepads.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
@ -552,17 +544,16 @@ WindowsGamepadService::PollXInput()
|
||||
|
||||
void WindowsGamepadService::CheckXInputChanges(Gamepad& gamepad,
|
||||
XINPUT_STATE& state) {
|
||||
nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());
|
||||
// Handle digital buttons first
|
||||
for (size_t b = 0; b < kNumMappings; b++) {
|
||||
if (state.Gamepad.wButtons & kXIButtonMap[b].button &&
|
||||
!(gamepad.state.Gamepad.wButtons & kXIButtonMap[b].button)) {
|
||||
// Button pressed
|
||||
gamepadsvc->NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, true);
|
||||
NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, true);
|
||||
} else if (!(state.Gamepad.wButtons & kXIButtonMap[b].button) &&
|
||||
gamepad.state.Gamepad.wButtons & kXIButtonMap[b].button) {
|
||||
// Button released
|
||||
gamepadsvc->NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, false);
|
||||
NewButtonEvent(gamepad.id, kXIButtonMap[b].mapped, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,33 +561,33 @@ void WindowsGamepadService::CheckXInputChanges(Gamepad& gamepad,
|
||||
if (state.Gamepad.bLeftTrigger != gamepad.state.Gamepad.bLeftTrigger) {
|
||||
bool pressed =
|
||||
state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
|
||||
gamepadsvc->NewButtonEvent(gamepad.id, kButtonLeftTrigger,
|
||||
pressed, state.Gamepad.bLeftTrigger / 255.0);
|
||||
NewButtonEvent(gamepad.id, kButtonLeftTrigger,
|
||||
pressed, state.Gamepad.bLeftTrigger / 255.0);
|
||||
}
|
||||
if (state.Gamepad.bRightTrigger != gamepad.state.Gamepad.bRightTrigger) {
|
||||
bool pressed =
|
||||
state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
|
||||
gamepadsvc->NewButtonEvent(gamepad.id, kButtonRightTrigger,
|
||||
pressed, state.Gamepad.bRightTrigger / 255.0);
|
||||
NewButtonEvent(gamepad.id, kButtonRightTrigger,
|
||||
pressed, state.Gamepad.bRightTrigger / 255.0);
|
||||
}
|
||||
|
||||
// Finally deal with analog sticks
|
||||
// TODO: bug 1001955 - Support deadzones.
|
||||
if (state.Gamepad.sThumbLX != gamepad.state.Gamepad.sThumbLX) {
|
||||
gamepadsvc->NewAxisMoveEvent(gamepad.id, kLeftStickXAxis,
|
||||
state.Gamepad.sThumbLX / 32767.0);
|
||||
NewAxisMoveEvent(gamepad.id, kLeftStickXAxis,
|
||||
state.Gamepad.sThumbLX / 32767.0);
|
||||
}
|
||||
if (state.Gamepad.sThumbLY != gamepad.state.Gamepad.sThumbLY) {
|
||||
gamepadsvc->NewAxisMoveEvent(gamepad.id, kLeftStickYAxis,
|
||||
-1.0 * state.Gamepad.sThumbLY / 32767.0);
|
||||
NewAxisMoveEvent(gamepad.id, kLeftStickYAxis,
|
||||
-1.0 * state.Gamepad.sThumbLY / 32767.0);
|
||||
}
|
||||
if (state.Gamepad.sThumbRX != gamepad.state.Gamepad.sThumbRX) {
|
||||
gamepadsvc->NewAxisMoveEvent(gamepad.id, kRightStickXAxis,
|
||||
state.Gamepad.sThumbRX / 32767.0);
|
||||
NewAxisMoveEvent(gamepad.id, kRightStickXAxis,
|
||||
state.Gamepad.sThumbRX / 32767.0);
|
||||
}
|
||||
if (state.Gamepad.sThumbRY != gamepad.state.Gamepad.sThumbRY) {
|
||||
gamepadsvc->NewAxisMoveEvent(gamepad.id, kRightStickYAxis,
|
||||
-1.0 * state.Gamepad.sThumbRY / 32767.0);
|
||||
NewAxisMoveEvent(gamepad.id, kRightStickYAxis,
|
||||
-1.0 * state.Gamepad.sThumbRY / 32767.0);
|
||||
}
|
||||
gamepad.state = state;
|
||||
}
|
||||
@ -757,15 +748,10 @@ WindowsGamepadService::GetRawGamepad(HANDLE handle)
|
||||
gamepad.handle = handle;
|
||||
gamepad.present = true;
|
||||
|
||||
nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());
|
||||
if (!gamepadsvc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gamepad.id = gamepadsvc->AddGamepad(gamepad_id,
|
||||
GamepadMappingType::_empty,
|
||||
gamepad.numButtons,
|
||||
gamepad.numAxes);
|
||||
gamepad.id = GamepadFunctions::AddGamepad(gamepad_id,
|
||||
GamepadMappingType::_empty,
|
||||
gamepad.numButtons,
|
||||
gamepad.numAxes);
|
||||
mGamepads.AppendElement(gamepad);
|
||||
return true;
|
||||
}
|
||||
@ -776,10 +762,6 @@ WindowsGamepadService::HandleRawInput(HRAWINPUT handle)
|
||||
if (!mHID) {
|
||||
return false;
|
||||
}
|
||||
nsRefPtr<GamepadService> gamepadsvc(GamepadService::GetService());
|
||||
if (!gamepadsvc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, get data from the handle
|
||||
UINT size;
|
||||
@ -838,7 +820,7 @@ WindowsGamepadService::HandleRawInput(HRAWINPUT handle)
|
||||
|
||||
for (unsigned i = 0; i < gamepad->numButtons; i++) {
|
||||
if (gamepad->buttons[i] != buttons[i]) {
|
||||
gamepadsvc->NewButtonEvent(gamepad->id, i, buttons[i]);
|
||||
NewButtonEvent(gamepad->id, i, buttons[i]);
|
||||
gamepad->buttons[i] = buttons[i];
|
||||
}
|
||||
}
|
||||
@ -872,7 +854,7 @@ LONG value;
|
||||
gamepad->axes[i].caps.LogicalMax);
|
||||
}
|
||||
if (gamepad->axes[i].value != new_value) {
|
||||
gamepadsvc->NewAxisMoveEvent(gamepad->id, i, new_value);
|
||||
NewAxisMoveEvent(gamepad->id, i, new_value);
|
||||
gamepad->axes[i].value = new_value;
|
||||
}
|
||||
}
|
||||
@ -977,9 +959,9 @@ GamepadWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
} // namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal_impl {
|
||||
namespace dom {
|
||||
|
||||
void StartMonitoringGamepadStatus()
|
||||
void StartGamepadMonitoring()
|
||||
{
|
||||
if (gService) {
|
||||
return;
|
||||
@ -1007,7 +989,7 @@ void StartMonitoringGamepadStatus()
|
||||
}
|
||||
}
|
||||
|
||||
void StopMonitoringGamepadStatus()
|
||||
void StopGamepadMonitoring()
|
||||
{
|
||||
if (!gService) {
|
||||
return;
|
||||
@ -1024,6 +1006,6 @@ void StopMonitoringGamepadStatus()
|
||||
gService = nullptr;
|
||||
}
|
||||
|
||||
} // namespace hal_impl
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -9,18 +9,21 @@ interface nsIVariant;
|
||||
/*
|
||||
* This interface is intended only for use in tests.
|
||||
*/
|
||||
[scriptable, uuid(b6ed093c-6ea0-4141-a8eb-f99645162651)]
|
||||
[scriptable, uuid(c03ec4ed-8a7e-40e7-99da-c609f1760d0c)]
|
||||
interface nsIGamepadServiceTest : nsISupports
|
||||
{
|
||||
const unsigned long NO_MAPPING = 0;
|
||||
const unsigned long STANDARD_MAPPING = 1;
|
||||
|
||||
unsigned long addGamepad(in string id, in unsigned long mapping,
|
||||
unsigned long addGamepad(in string id,
|
||||
in unsigned long mapping,
|
||||
in unsigned long numButtons,
|
||||
in unsigned long numAxes);
|
||||
void removeGamepad(in unsigned long index);
|
||||
void newButtonEvent(in unsigned long index, in unsigned long button,
|
||||
in boolean pressed);
|
||||
void newButtonValueEvent(in unsigned long index, in unsigned long button,
|
||||
in boolean pressed, in double value);
|
||||
void newAxisMoveEvent(in unsigned long index, in unsigned long axis,
|
||||
in double value);
|
||||
};
|
||||
|
@ -155,6 +155,10 @@
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
|
||||
#include "mozilla/dom/icc/IccChild.h"
|
||||
@ -2775,6 +2779,18 @@ ContentChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
|
||||
{
|
||||
#ifdef MOZ_GAMEPAD
|
||||
nsRefPtr<GamepadService> svc(GamepadService::GetService());
|
||||
if (svc) {
|
||||
svc->Update(aGamepadEvent);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// This code goes here rather than nsGlobalWindow.cpp because nsGlobalWindow.cpp
|
||||
// can't include ContentChild.h since it includes windows.h.
|
||||
|
||||
|
@ -464,6 +464,8 @@ public:
|
||||
virtual bool
|
||||
DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) override;
|
||||
|
||||
virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
|
||||
|
||||
private:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
|
@ -226,6 +226,10 @@ using namespace mozilla::system;
|
||||
#include "nsIProfileSaveEvent.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/GamepadMonitoring.h"
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||
|
||||
using base::ChildPrivileges;
|
||||
@ -2157,6 +2161,7 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
||||
, mOpener(aOpener)
|
||||
, mIsForBrowser(aIsForBrowser)
|
||||
, mIsNuwaProcess(aIsNuwaProcess)
|
||||
, mHasGamepadListener(false)
|
||||
{
|
||||
InitializeMembers(); // Perform common initialization.
|
||||
|
||||
@ -4990,6 +4995,34 @@ ContentParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestP
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGamepadListenerAdded()
|
||||
{
|
||||
#ifdef MOZ_GAMEPAD
|
||||
if (mHasGamepadListener) {
|
||||
NS_WARNING("Gamepad listener already started, cannot start again!");
|
||||
return false;
|
||||
}
|
||||
mHasGamepadListener = true;
|
||||
StartGamepadMonitoring();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGamepadListenerRemoved()
|
||||
{
|
||||
#ifdef MOZ_GAMEPAD
|
||||
if (!mHasGamepadListener) {
|
||||
NS_WARNING("Gamepad listener already stopped, cannot stop again!");
|
||||
return false;
|
||||
}
|
||||
mHasGamepadListener = false;
|
||||
MaybeStopGamepadMonitoring();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -377,6 +377,8 @@ public:
|
||||
virtual bool
|
||||
DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) override;
|
||||
|
||||
bool HasGamepadListener() const { return mHasGamepadListener; }
|
||||
|
||||
protected:
|
||||
void OnChannelConnected(int32_t pid) override;
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
@ -840,6 +842,10 @@ private:
|
||||
|
||||
virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction,
|
||||
const uint32_t& aDropEffect) override;
|
||||
|
||||
virtual bool RecvGamepadListenerAdded() override;
|
||||
virtual bool RecvGamepadListenerRemoved() override;
|
||||
|
||||
// If you add strong pointers to cycle collected objects here, be sure to
|
||||
// release these objects in ShutDownProcess. See the comment there for more
|
||||
// details.
|
||||
@ -884,6 +890,7 @@ private:
|
||||
bool mSendDataStoreInfos;
|
||||
bool mIsForBrowser;
|
||||
bool mIsNuwaProcess;
|
||||
bool mHasGamepadListener;
|
||||
|
||||
// These variables track whether we've called Close(), CloseWithError()
|
||||
// and KillHard() on our channel.
|
||||
|
@ -368,6 +368,38 @@ struct DomainPolicyClone
|
||||
URIParams[] superWhitelist;
|
||||
};
|
||||
|
||||
struct GamepadAdded {
|
||||
nsString id;
|
||||
uint32_t index;
|
||||
uint32_t mapping;
|
||||
uint32_t num_buttons;
|
||||
uint32_t num_axes;
|
||||
};
|
||||
|
||||
struct GamepadRemoved {
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
struct GamepadAxisInformation {
|
||||
uint32_t index;
|
||||
uint32_t axis;
|
||||
double value;
|
||||
};
|
||||
|
||||
struct GamepadButtonInformation {
|
||||
uint32_t index;
|
||||
uint32_t button;
|
||||
bool pressed;
|
||||
double value;
|
||||
};
|
||||
|
||||
union GamepadChangeEvent {
|
||||
GamepadAdded;
|
||||
GamepadRemoved;
|
||||
GamepadAxisInformation;
|
||||
GamepadButtonInformation;
|
||||
};
|
||||
|
||||
prio(normal upto urgent) sync protocol PContent
|
||||
{
|
||||
parent spawns PPluginModule;
|
||||
@ -605,6 +637,10 @@ child:
|
||||
*/
|
||||
async UpdateWindow(uintptr_t aChildId);
|
||||
|
||||
/**
|
||||
* Send gamepad status update to child.
|
||||
*/
|
||||
GamepadUpdate(GamepadChangeEvent aGamepadEvent);
|
||||
parent:
|
||||
/**
|
||||
* Tell the parent process a new accessible document has been created.
|
||||
@ -992,6 +1028,16 @@ parent:
|
||||
PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal,
|
||||
TabId tabId);
|
||||
|
||||
/*
|
||||
* Tells the parent to start the gamepad listening service if it hasn't already.
|
||||
*/
|
||||
GamepadListenerAdded();
|
||||
|
||||
/**
|
||||
* Tells the parent to stop the gamepad listening service if it hasn't already.
|
||||
*/
|
||||
GamepadListenerRemoved();
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData,
|
||||
CpowEntry[] aCpows, Principal aPrincipal);
|
||||
|
@ -1,18 +1,13 @@
|
||||
[DEFAULT]
|
||||
skip-if=e10s || (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
support-files =
|
||||
gamepad_frame.html
|
||||
gamepad_frame_state.html
|
||||
mock_gamepad.js
|
||||
|
||||
[test_check_timestamp.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_gamepad.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_gamepad_connect_events.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_gamepad_frame_state_sync.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_gamepad_hidden_frame.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_navigator_gamepads.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
|
@ -11,6 +11,7 @@
|
||||
<script type="text/javascript" src="mock_gamepad.js"></script>
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var index = GamepadService.addGamepad("test gamepad", // id
|
||||
SpecialPowers.Ci.nsIGamepadServiceTest.NO_MAPPING,
|
||||
4, // buttons
|
||||
|
@ -17,19 +17,29 @@ var index = GamepadService.addGamepad("test gamepad", // id
|
||||
SpecialPowers.Ci.nsIGamepadServiceTest.STANDARD_MAPPING,
|
||||
4, // buttons
|
||||
2);// axes
|
||||
// Press a button
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
function connecthandler(e) {
|
||||
ok(e.gamepad.timestamp <= performance.now());
|
||||
is(e.gamepad.index, 0, "correct gamepad index");
|
||||
is(e.gamepad.id, "test gamepad", "correct gamepad name");
|
||||
is(e.gamepad.mapping, "standard", "standard mapping");
|
||||
is(e.gamepad.buttons.length, 4, "correct number of buttons");
|
||||
is(e.gamepad.axes.length, 2, "correct number of axes");
|
||||
// Press a button
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
gamepads = navigator.getGamepads();
|
||||
is(gamepads[0].buttons[0].pressed, true, "gamepad button should register as pressed")
|
||||
GamepadService.newButtonValueEvent(index, 1, true, 0.5);
|
||||
gamepads = navigator.getGamepads();
|
||||
is(gamepads[0].buttons[1].pressed, true, "gamepad button should register as pressed")
|
||||
is(gamepads[0].buttons[1].value, 0.5, "gamepad button value should be 0.5")
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
GamepadService.removeGamepad(index);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -37,49 +37,61 @@ function disconnecthandler(e) {
|
||||
window.addEventListener("gamepadconnected", connecthandler);
|
||||
window.addEventListener("gamepaddisconnected", disconnecthandler);
|
||||
// Add a gamepad
|
||||
var index1 = GamepadService.addGamepad("test gamepad 1", // id
|
||||
var internal_index1 = GamepadService.addGamepad("test gamepad 1", // id
|
||||
SpecialPowers.Ci.nsIGamepadServiceTest.NO_MAPPING,
|
||||
4, // buttons
|
||||
2);// axes
|
||||
var index2;
|
||||
var content_index1 = 0;
|
||||
var internal_index2;
|
||||
var content_index2 = 1;
|
||||
|
||||
// Press a button to make the gamepad visible to the page.
|
||||
GamepadService.newButtonEvent(index1, 0, true);
|
||||
GamepadService.newButtonEvent(internal_index1, 0, true);
|
||||
|
||||
function check_first_gamepad(e) {
|
||||
ok(true, "Checking first gamepad");
|
||||
// First gamepad gets added.
|
||||
is(e.gamepad.id, "test gamepad 1", "correct gamepad name");
|
||||
var gamepads = navigator.getGamepads();
|
||||
is(gamepads.length, 1, "should have one gamepad exposed");
|
||||
is(gamepads[e.gamepad.index], e.gamepad, "right gamepad exposed at index");
|
||||
is(gamepads[content_index1], e.gamepad, "gamepad counter working correctly");
|
||||
// Add a second gamepad, should automatically show up.
|
||||
index2 = GamepadService.addGamepad("test gamepad 2", // id
|
||||
internal_index2 = GamepadService.addGamepad("test gamepad 2", // id
|
||||
SpecialPowers.Ci.nsIGamepadServiceTest.NO_MAPPING,
|
||||
4, // buttons
|
||||
2);// axes
|
||||
ok(true, "Done checking first gamepad");
|
||||
}
|
||||
|
||||
function check_second_gamepad(e) {
|
||||
ok(true, "Checking seceond gamepad");
|
||||
// Second gamepad gets added.
|
||||
is(e.gamepad.index, 1, "gamepad index should be 1")
|
||||
is(e.gamepad.id, "test gamepad 2", "correct gamepad name");
|
||||
var gamepads = navigator.getGamepads();
|
||||
is(gamepads.length, 2, "should have two gamepads exposed");
|
||||
is(gamepads[e.gamepad.index], e.gamepad, "right gamepad exposed at index");
|
||||
is(gamepads[content_index2], e.gamepad, "gamepad counter working correctly");
|
||||
// Now remove the first one.
|
||||
GamepadService.removeGamepad(index1);
|
||||
GamepadService.removeGamepad(internal_index1);
|
||||
ok(true, "Done checking second gamepad");
|
||||
}
|
||||
|
||||
function check_gamepad_hole(e) {
|
||||
ok(true, "Checking gamepad hole");
|
||||
// First gamepad gets removed.
|
||||
var gamepads = navigator.getGamepads();
|
||||
is(gamepads.length, 2, "gamepads should have two entries");
|
||||
is(gamepads[index1], null, "should be a hole in the gamepad list");
|
||||
isnot(gamepads[index2], null, "second gamepad should exist");
|
||||
is(gamepads[content_index1], null, "should be a hole in the gamepad list");
|
||||
isnot(gamepads[content_index2], null, "second gamepad should exist");
|
||||
// Now remove the second one.
|
||||
GamepadService.removeGamepad(index2);
|
||||
GamepadService.removeGamepad(internal_index2);
|
||||
ok(true, "Done checking gamepad hole");
|
||||
}
|
||||
|
||||
function check_no_gamepads(e) {
|
||||
ok(true, "Checking no gamepads");
|
||||
// Second gamepad gets removed.
|
||||
var gamepads = navigator.getGamepads();
|
||||
is(gamepads.length, 0, "gamepads should be empty");
|
||||
|
10
hal/Hal.cpp
10
hal/Hal.cpp
@ -636,16 +636,6 @@ void StartForceQuitWatchdog(ShutdownMode aMode, int32_t aTimeoutSecs)
|
||||
PROXY_IF_SANDBOXED(StartForceQuitWatchdog(aMode, aTimeoutSecs));
|
||||
}
|
||||
|
||||
void StartMonitoringGamepadStatus()
|
||||
{
|
||||
PROXY_IF_SANDBOXED(StartMonitoringGamepadStatus());
|
||||
}
|
||||
|
||||
void StopMonitoringGamepadStatus()
|
||||
{
|
||||
PROXY_IF_SANDBOXED(StopMonitoringGamepadStatus());
|
||||
}
|
||||
|
||||
void
|
||||
RegisterWakeLockObserver(WakeLockObserver* aObserver)
|
||||
{
|
||||
|
11
hal/Hal.h
11
hal/Hal.h
@ -17,7 +17,6 @@
|
||||
#include "mozilla/dom/battery/Types.h"
|
||||
#include "mozilla/dom/network/Types.h"
|
||||
#include "mozilla/dom/power/Types.h"
|
||||
#include "mozilla/hal_sandbox/PHal.h"
|
||||
#include "mozilla/dom/ScreenOrientation.h"
|
||||
#include "mozilla/HalScreenConfiguration.h"
|
||||
|
||||
@ -598,16 +597,6 @@ void StartForceQuitWatchdog(hal::ShutdownMode aMode, int32_t aTimeoutSecs);
|
||||
*/
|
||||
void FactoryReset(mozilla::dom::FactoryResetReason& aReason);
|
||||
|
||||
/**
|
||||
* Start monitoring the status of gamepads attached to the system.
|
||||
*/
|
||||
void StartMonitoringGamepadStatus();
|
||||
|
||||
/**
|
||||
* Stop monitoring the status of gamepads attached to the system.
|
||||
*/
|
||||
void StopMonitoringGamepadStatus();
|
||||
|
||||
/**
|
||||
* Start monitoring disk space for low space situations.
|
||||
*
|
||||
|
@ -32,27 +32,6 @@ SOURCES += [
|
||||
'Hal.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_GAMEPAD_BACKEND'] == 'stub':
|
||||
UNIFIED_SOURCES += [
|
||||
'fallback/FallbackGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'cocoa':
|
||||
UNIFIED_SOURCES += [
|
||||
'cocoa/CocoaGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'windows/WindowsGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'linux':
|
||||
UNIFIED_SOURCES += [
|
||||
'linux/LinuxGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'android':
|
||||
UNIFIED_SOURCES += [
|
||||
'android/AndroidGamepad.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
UNIFIED_SOURCES += [
|
||||
'android/AndroidSensor.cpp',
|
||||
|
@ -271,13 +271,6 @@ DisableSensorNotifications(SensorType aSensor) {
|
||||
Hal()->SendDisableSensorNotifications(aSensor);
|
||||
}
|
||||
|
||||
//TODO: bug 852944 - IPC implementations of these
|
||||
void StartMonitoringGamepadStatus()
|
||||
{}
|
||||
|
||||
void StopMonitoringGamepadStatus()
|
||||
{}
|
||||
|
||||
void
|
||||
EnableWakeLockNotifications()
|
||||
{
|
||||
|
@ -209,7 +209,7 @@ static void Shutdown();
|
||||
#include "nsGeolocation.h"
|
||||
#include "nsDeviceSensors.h"
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/GamepadServiceTest.h"
|
||||
#endif
|
||||
#include "mozilla/dom/nsCSPService.h"
|
||||
#include "mozilla/dom/nsCSPContext.h"
|
||||
|
@ -41,7 +41,8 @@
|
||||
|
||||
#include "mozilla/dom/ScreenOrientation.h"
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/GamepadService.h"
|
||||
#include "mozilla/dom/GamepadFunctions.h"
|
||||
#include "mozilla/dom/Gamepad.h"
|
||||
#endif
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
@ -656,19 +657,15 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
|
||||
case AndroidGeckoEvent::GAMEPAD_ADDREMOVE: {
|
||||
#ifdef MOZ_GAMEPAD
|
||||
nsRefPtr<mozilla::dom::GamepadService> svc =
|
||||
mozilla::dom::GamepadService::GetService();
|
||||
if (svc) {
|
||||
if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_ADDED) {
|
||||
int svc_id = svc->AddGamepad("android",
|
||||
mozilla::dom::GamepadMappingType::Standard,
|
||||
mozilla::dom::kStandardGamepadButtons,
|
||||
mozilla::dom::kStandardGamepadAxes);
|
||||
int svc_id = dom::GamepadFunctions::AddGamepad("android",
|
||||
dom::GamepadMappingType::Standard,
|
||||
dom::kStandardGamepadButtons,
|
||||
dom::kStandardGamepadAxes);
|
||||
widget::GeckoAppShell::GamepadAdded(curEvent->ID(),
|
||||
svc_id);
|
||||
} else if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_REMOVED) {
|
||||
svc->RemoveGamepad(curEvent->ID());
|
||||
}
|
||||
dom::GamepadFunctions::RemoveGamepad(curEvent->ID());
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@ -676,12 +673,9 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
|
||||
case AndroidGeckoEvent::GAMEPAD_DATA: {
|
||||
#ifdef MOZ_GAMEPAD
|
||||
nsRefPtr<mozilla::dom::GamepadService> svc =
|
||||
mozilla::dom::GamepadService::GetService();
|
||||
if (svc) {
|
||||
int id = curEvent->ID();
|
||||
if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_BUTTON) {
|
||||
svc->NewButtonEvent(id, curEvent->GamepadButton(),
|
||||
dom::GamepadFunctions::NewButtonEvent(id, curEvent->GamepadButton(),
|
||||
curEvent->GamepadButtonPressed(),
|
||||
curEvent->GamepadButtonValue());
|
||||
} else if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_AXES) {
|
||||
@ -689,8 +683,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
|
||||
const nsTArray<float>& values = curEvent->GamepadValues();
|
||||
for (unsigned i = 0; i < values.Length(); i++) {
|
||||
if (valid & (1<<i)) {
|
||||
svc->NewAxisMoveEvent(id, i, values[i]);
|
||||
}
|
||||
dom::GamepadFunctions::NewAxisMoveEvent(id, i, values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user