Bug 1523351 - Part 3: Handling GamepadTouch and GamepadLightIndicator events in Gamepad service. r=baku

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Daosheng Mu 2019-05-29 22:15:23 +00:00
Родитель fc4437c39c
Коммит 21043eccbc
17 изменённых файлов: 210 добавлений и 36 удалений

Просмотреть файл

@ -225,14 +225,17 @@ void GamepadManager::AddGamepad(uint32_t aIndex, const nsAString& aId,
GamepadMappingType aMapping, GamepadHand aHand,
GamepadServiceType aServiceType,
uint32_t aDisplayID, uint32_t aNumButtons,
uint32_t aNumAxes, uint32_t aNumHaptics) {
uint32_t aNumAxes, uint32_t aNumHaptics,
uint32_t aNumLightIndicator,
uint32_t aNumTouchEvents) {
uint32_t newIndex = GetGamepadIndexWithServiceType(aIndex, aServiceType);
// TODO: bug 852258: get initial button/axis state
RefPtr<Gamepad> gamepad = new Gamepad(nullptr, aId,
0, // index is set by global window
newIndex, aMapping, aHand, aDisplayID,
aNumButtons, aNumAxes, aNumHaptics);
RefPtr<Gamepad> gamepad =
new Gamepad(nullptr, aId,
0, // index is set by global window
newIndex, aMapping, aHand, aDisplayID, aNumButtons, aNumAxes,
aNumHaptics, aNumLightIndicator, aNumTouchEvents);
// We store the gamepad related to its index given by the parent process,
// and no duplicate index is allowed.
@ -471,7 +474,8 @@ void GamepadManager::Update(const GamepadChangeEvent& aEvent) {
const GamepadAdded& a = body.get_GamepadAdded();
AddGamepad(index, a.id(), static_cast<GamepadMappingType>(a.mapping()),
static_cast<GamepadHand>(a.hand()), serviceType, a.display_id(),
a.num_buttons(), a.num_axes(), a.num_haptics());
a.num_buttons(), a.num_axes(), a.num_haptics(), a.num_lights(),
a.num_touches());
return;
}
if (body.type() == GamepadChangeEventBody::TGamepadRemoved) {
@ -561,6 +565,25 @@ bool GamepadManager::SetGamepadByEvent(const GamepadChangeEvent& aEvent,
gamepad->SetPose(a.pose_state());
break;
}
case GamepadChangeEventBody::TGamepadLightIndicatorTypeInformation: {
const GamepadLightIndicatorTypeInformation& a =
body.get_GamepadLightIndicatorTypeInformation();
gamepad->SetLightIndicatorType(a.light(), a.type());
break;
}
case GamepadChangeEventBody::TGamepadTouchInformation: {
// Avoid GamepadTouch's touchId be accessed in cross-origin tracking.
for (uint32_t i = 0; i < mListeners.Length(); i++) {
RefPtr<Gamepad> listenerGamepad = mListeners[i]->GetGamepad(index);
if (listenerGamepad && mListeners[i]->IsCurrentInnerWindow() &&
!mListeners[i]->GetOuterWindow()->IsBackground()) {
const GamepadTouchInformation& a =
body.get_GamepadTouchInformation();
listenerGamepad->SetTouchEvent(a.index(), a.touch_state());
}
}
break;
}
case GamepadChangeEventBody::TGamepadHandInformation: {
const GamepadHandInformation& a = body.get_GamepadHandInformation();
gamepad->SetHand(a.hand());
@ -583,13 +606,12 @@ bool GamepadManager::SetGamepadByEvent(const GamepadChangeEvent& aEvent,
already_AddRefed<Promise> GamepadManager::VibrateHaptic(
uint32_t aControllerIdx, uint32_t aHapticIndex, double aIntensity,
double aDuration, nsIGlobalObject* aGlobal, ErrorResult& aRv) {
const char* kGamepadHapticEnabledPref = "dom.gamepad.haptic_feedback.enabled";
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
if (NS_WARN_IF(aRv.Failed())) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
if (Preferences::GetBool(kGamepadHapticEnabledPref)) {
if (StaticPrefs::dom_gamepad_haptic_feedback_enabled()) {
if (aControllerIdx >= VR_GAMEPAD_IDX_OFFSET) {
if (gfx::VRManagerChild::IsCreated()) {
const uint32_t index = aControllerIdx - VR_GAMEPAD_IDX_OFFSET;
@ -612,8 +634,7 @@ already_AddRefed<Promise> GamepadManager::VibrateHaptic(
}
void GamepadManager::StopHaptics() {
const char* kGamepadHapticEnabledPref = "dom.gamepad.haptic_feedback.enabled";
if (!Preferences::GetBool(kGamepadHapticEnabledPref)) {
if (!StaticPrefs::dom_gamepad_haptic_feedback_enabled()) {
return;
}
@ -633,5 +654,32 @@ void GamepadManager::StopHaptics() {
}
}
already_AddRefed<Promise> GamepadManager::SetLightIndicatorColor(
uint32_t aControllerIdx, uint32_t aLightColorIndex, uint8_t aRed,
uint8_t aGreen, uint8_t aBlue, nsIGlobalObject* aGlobal, ErrorResult& aRv) {
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
if (NS_WARN_IF(aRv.Failed())) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
if (StaticPrefs::dom_gamepad_extensions_lightindicator()) {
for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
const uint32_t gamepadIndex = iter.UserData()->HashKey();
if (gamepadIndex >= VR_GAMEPAD_IDX_OFFSET) {
MOZ_ASSERT(false && "We don't support light indicator in VR.");
} else {
for (auto& channelChild : mChannelChildren) {
channelChild->AddPromise(mPromiseID, promise);
channelChild->SendLightIndicatorColor(aControllerIdx,
aLightColorIndex, aRed, aGreen,
aBlue, mPromiseID);
}
}
}
}
++mPromiseID;
return promise.forget();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -49,8 +49,8 @@ class GamepadManager final : public nsIObserver {
void AddGamepad(uint32_t aIndex, const nsAString& aID,
GamepadMappingType aMapping, GamepadHand aHand,
GamepadServiceType aServiceType, uint32_t aDisplayID,
uint32_t aNumButtons, uint32_t aNumAxes,
uint32_t aNumHaptics);
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aNumHaptics,
uint32_t aNumLightIndicator, uint32_t aNumTouchEvents);
// Remove the gamepad at |aIndex| from the list of known gamepads.
void RemoveGamepad(uint32_t aIndex, GamepadServiceType aServiceType);
@ -78,6 +78,14 @@ class GamepadManager final : public nsIObserver {
// Send stop haptic events to gamepad channels.
void StopHaptics();
// Set light indicator color event to gamepad channels.
already_AddRefed<Promise> SetLightIndicatorColor(uint32_t aControllerIdx,
uint32_t aLightColorIndex,
uint8_t aRed, uint8_t aGreen,
uint8_t aBlue,
nsIGlobalObject* aGlobal,
ErrorResult& aRv);
protected:
GamepadManager();
~GamepadManager(){};

Просмотреть файл

@ -17,6 +17,9 @@ void MaybeStopGamepadMonitoring();
// (linux/LinuxGamepad.cpp, cocoa/CocoaGamepad.cpp, etc)
void StartGamepadMonitoring();
void StopGamepadMonitoring();
void SetGamepadLightIndicatorColor(uint32_t aControllerIdx,
uint32_t aLightColorIndex, uint8_t aRed,
uint8_t aGreen, uint8_t aBlue);
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -79,7 +79,8 @@ void GamepadPlatformService::NotifyGamepadChange(uint32_t aIndex,
uint32_t GamepadPlatformService::AddGamepad(
const char* aID, GamepadMappingType aMapping, GamepadHand aHand,
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aHaptics) {
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aHaptics,
uint32_t aNumLightIndicator, uint32_t aNumTouchEvents) {
// This method is called by monitor thread populated in
// platform-dependent backends
MOZ_ASSERT(XRE_IsParentProcess());
@ -89,7 +90,8 @@ uint32_t GamepadPlatformService::AddGamepad(
// Only VR controllers has displayID, we give 0 to the general gamepads.
GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), aMapping,
aHand, 0, aNumButtons, aNumAxes, aHaptics);
aHand, 0, aNumButtons, aNumAxes, aHaptics, aNumLightIndicator,
aNumTouchEvents);
NotifyGamepadChange<GamepadAdded>(index, a);
return index;
@ -145,16 +147,38 @@ void GamepadPlatformService::NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
NotifyGamepadChange<GamepadAxisInformation>(aIndex, a);
}
void GamepadPlatformService::NewPoseEvent(uint32_t aIndex,
const GamepadPoseState& aPose) {
void GamepadPlatformService::NewLightIndicatorTypeEvent(
uint32_t aIndex, uint32_t aLight, GamepadLightIndicatorType aType) {
// This method is called by monitor thread populated in
// platform-dependent backends
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(!NS_IsMainThread());
GamepadPoseInformation a(aPose);
GamepadLightIndicatorTypeInformation a(aLight, aType);
NotifyGamepadChange<GamepadLightIndicatorTypeInformation>(aIndex, a);
}
void GamepadPlatformService::NewPoseEvent(uint32_t aIndex,
const GamepadPoseState& aState) {
// This method is called by monitor thread populated in
// platform-dependent backends
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(!NS_IsMainThread());
GamepadPoseInformation a(aState);
NotifyGamepadChange<GamepadPoseInformation>(aIndex, a);
}
void GamepadPlatformService::NewMultiTouchEvent(
uint32_t aIndex, uint32_t aTouchArrayIndex,
const GamepadTouchState& aState) {
// This method is called by monitor thread populated in
// platform-dependent backends
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(!NS_IsMainThread());
GamepadTouchInformation a(aTouchArrayIndex, aState);
NotifyGamepadChange<GamepadTouchInformation>(aIndex, a);
}
void GamepadPlatformService::ResetGamepadIndexes() {
// This method is called by monitor thread populated in
// platform-dependent backends

Просмотреть файл

@ -38,7 +38,8 @@ class GamepadPlatformService final {
// Add a gamepad to the list of known gamepads, and return its index.
uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping,
GamepadHand aHand, uint32_t aNumButtons,
uint32_t aNumAxes, uint32_t aNumHaptics);
uint32_t aNumAxes, uint32_t aNumHaptics,
uint32_t aNumLightIndicator, uint32_t aNumTouchEvents);
// Remove the gamepad at |aIndex| from the list of known gamepads.
void RemoveGamepad(uint32_t aIndex);
@ -62,6 +63,14 @@ class GamepadPlatformService final {
// Update the state of |aState| for the gamepad at |aIndex| for all
// windows that are listening and visible.
void NewPoseEvent(uint32_t aIndex, const GamepadPoseState& aState);
// Update the type of |aType| for the gamepad at |aIndex| for all
// windows that are listening and visible.
void NewLightIndicatorTypeEvent(uint32_t aIndex, uint32_t aLight,
GamepadLightIndicatorType aType);
// Update the state of |aState| for the gamepad at |aIndex| with
// |aTouchArrayIndex| for all windows that are listening and visible.
void NewMultiTouchEvent(uint32_t aIndex, uint32_t aTouchArrayIndex,
const GamepadTouchState& aState);
// When shutting down the platform communications for gamepad, also reset the
// indexes.

Просмотреть файл

@ -26,8 +26,10 @@ class AndroidGamepadManager final
if (aAdded) {
const int svc_id = service->AddGamepad(
"android", GamepadMappingType::Standard, GamepadHand::_empty,
kStandardGamepadButtons, kStandardGamepadAxes,
0); // TODO: Bug 680289, implement gamepad haptics for Android
kStandardGamepadButtons, kStandardGamepadAxes, 0, 0,
0); // TODO: Bug 680289, implement gamepad haptics for Android.
// TODO: Bug 1523355, implement gamepad lighindicator and touch for
// Android.
java::AndroidGamepadManager::OnGamepadAdded(aID, svc_id);
} else {

Просмотреть файл

@ -304,8 +304,9 @@ void DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device) {
uint32_t index = service->AddGamepad(
buffer, mozilla::dom::GamepadMappingType::_empty,
mozilla::dom::GamepadHand::_empty, (int)mGamepads[slot].numButtons(),
(int)mGamepads[slot].numAxes(),
0); // TODO: Bug 680289, implement gamepad haptics for cocoa
(int)mGamepads[slot].numAxes(), 0, 0,
0); // TODO: Bug 680289, implement gamepad haptics for cocoa.
// TODO: Bug 1523355, implement gamepad lighindicator and touch for cocoa.
mGamepads[slot].mSuperIndex = index;
}

Просмотреть файл

@ -43,7 +43,7 @@ void GamepadEventChannelChild::AddPromise(const uint32_t& aID,
mPromiseList.Put(aID, aPromise);
}
mozilla::ipc::IPCResult GamepadEventChannelChild::RecvReplyGamepadVibrateHaptic(
mozilla::ipc::IPCResult GamepadEventChannelChild::RecvReplyGamepadPromise(
const uint32_t& aPromiseID) {
RefPtr<dom::Promise> p;
if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {

Просмотреть файл

@ -17,8 +17,7 @@ class GamepadEventChannelChild final : public PGamepadEventChannelChild {
~GamepadEventChannelChild() {}
mozilla::ipc::IPCResult RecvGamepadUpdate(
const GamepadChangeEvent& aGamepadEvent);
mozilla::ipc::IPCResult RecvReplyGamepadVibrateHaptic(
const uint32_t& aPromiseID);
mozilla::ipc::IPCResult RecvReplyGamepadPromise(const uint32_t& aPromiseID);
void AddPromise(const uint32_t& aID, dom::Promise* aPromise);
private:

Просмотреть файл

@ -76,19 +76,37 @@ mozilla::ipc::IPCResult GamepadEventChannelParent::RecvVibrateHaptic(
const uint32_t& aPromiseID) {
// TODO: Bug 680289, implement for standard gamepads
if (SendReplyGamepadVibrateHaptic(aPromiseID)) {
if (SendReplyGamepadPromise(aPromiseID)) {
return IPC_OK();
}
return IPC_FAIL(this, "SendReplyGamepadVibrateHaptic fail.");
return IPC_FAIL(this, "SendReplyGamepadPromise fail.");
}
mozilla::ipc::IPCResult GamepadEventChannelParent::RecvStopVibrateHaptic(
const uint32_t& aGamepadIndex) {
const uint32_t& aControllerIdx) {
// TODO: Bug 680289, implement for standard gamepads
return IPC_OK();
}
mozilla::ipc::IPCResult GamepadEventChannelParent::RecvLightIndicatorColor(
const uint32_t& aControllerIdx, const uint32_t& aLightColorIndex,
const uint8_t& aRed, const uint8_t& aGreen, const uint8_t& aBlue,
const uint32_t& aPromiseID) {
// It may be called because IPDL child side crashed, we'll
// not receive RecvGamepadListenerRemoved in that case
if (mHasGamepadListener) {
SetGamepadLightIndicatorColor(aControllerIdx, aLightColorIndex, aRed,
aGreen, aBlue);
}
if (SendReplyGamepadPromise(aPromiseID)) {
return IPC_OK();
}
return IPC_FAIL(this, "SendReplyGamepadPromise fail.");
}
void GamepadEventChannelParent::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnBackgroundThread();

Просмотреть файл

@ -23,7 +23,11 @@ class GamepadEventChannelParent final : public PGamepadEventChannelParent {
const double& aIntensity,
const double& aDuration,
const uint32_t& aPromiseID);
mozilla::ipc::IPCResult RecvStopVibrateHaptic(const uint32_t& aGamepadIndex);
mozilla::ipc::IPCResult RecvStopVibrateHaptic(const uint32_t& aControllerIdx);
mozilla::ipc::IPCResult RecvLightIndicatorColor(
const uint32_t& aControllerIdx, const uint32_t& aLightColorIndex,
const uint8_t& aRed, const uint8_t& aGreen, const uint8_t& aBlue,
const uint32_t& aPromiseID);
void DispatchUpdateEvent(const GamepadChangeEvent& aEvent);
bool HasGamepadListener() const { return mHasGamepadListener; }

Просмотреть файл

@ -4,6 +4,8 @@
using mozilla::dom::GamepadServiceType from "mozilla/dom/GamepadMessageUtils.h";
using mozilla::dom::GamepadPoseState from "mozilla/dom/GamepadMessageUtils.h";
using mozilla::dom::GamepadTouchState from "mozilla/dom/GamepadMessageUtils.h";
using mozilla::dom::GamepadLightIndicatorType from "mozilla/dom/GamepadMessageUtils.h";
using mozilla::dom::GamepadMappingType from "mozilla/dom/GamepadMessageUtils.h";
using mozilla::dom::GamepadHand from "mozilla/dom/GamepadMessageUtils.h";
@ -19,6 +21,8 @@ struct GamepadAdded {
uint32_t num_buttons;
uint32_t num_axes;
uint32_t num_haptics;
uint32_t num_lights;
uint32_t num_touches;
};
struct GamepadRemoved {};
@ -39,17 +43,29 @@ struct GamepadPoseInformation {
GamepadPoseState pose_state;
};
struct GamepadLightIndicatorTypeInformation {
uint32_t light;
GamepadLightIndicatorType type;
};
struct GamepadHandInformation {
GamepadHand hand;
};
struct GamepadTouchInformation {
uint32_t index;
GamepadTouchState touch_state;
};
union GamepadChangeEventBody {
GamepadAdded;
GamepadRemoved;
GamepadAxisInformation;
GamepadButtonInformation;
GamepadPoseInformation;
GamepadHandInformation;
GamepadLightIndicatorTypeInformation;
GamepadPoseInformation;
GamepadTouchInformation;
};
struct GamepadChangeEvent {

Просмотреть файл

@ -9,11 +9,21 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/dom/GamepadBinding.h"
#include "mozilla/dom/GamepadLightIndicatorBinding.h"
#include "mozilla/dom/GamepadPoseState.h"
#include "mozilla/dom/GamepadServiceType.h"
#include "mozilla/dom/GamepadTouchState.h"
namespace IPC {
template <>
struct ParamTraits<mozilla::dom::GamepadLightIndicatorType>
: public ContiguousEnumSerializer<
mozilla::dom::GamepadLightIndicatorType,
mozilla::dom::GamepadLightIndicatorType(0),
mozilla::dom::GamepadLightIndicatorType(
mozilla::dom::GamepadLightIndicatorType::EndGuard_)> {};
template <>
struct ParamTraits<mozilla::dom::GamepadMappingType>
: public ContiguousEnumSerializer<
@ -99,6 +109,35 @@ struct ParamTraits<mozilla::dom::GamepadPoseState> {
}
};
template <>
struct ParamTraits<mozilla::dom::GamepadTouchState> {
typedef mozilla::dom::GamepadTouchState paramType;
static void Write(Message* aMsg, const paramType& aParam) {
WriteParam(aMsg, aParam.touchId);
WriteParam(aMsg, aParam.surfaceId);
WriteParam(aMsg, aParam.position[0]);
WriteParam(aMsg, aParam.position[1]);
WriteParam(aMsg, aParam.surfaceDimensions[0]);
WriteParam(aMsg, aParam.surfaceDimensions[1]);
WriteParam(aMsg, aParam.isSurfaceDimensionsValid);
}
static bool Read(const Message* aMsg, PickleIterator* aIter,
paramType* aResult) {
if (!ReadParam(aMsg, aIter, &(aResult->touchId)) ||
!ReadParam(aMsg, aIter, &(aResult->surfaceId)) ||
!ReadParam(aMsg, aIter, &(aResult->position[0])) ||
!ReadParam(aMsg, aIter, &(aResult->position[1])) ||
!ReadParam(aMsg, aIter, &(aResult->surfaceDimensions[0])) ||
!ReadParam(aMsg, aIter, &(aResult->surfaceDimensions[1])) ||
!ReadParam(aMsg, aIter, &(aResult->isSurfaceDimensionsValid))) {
return false;
}
return true;
}
};
} // namespace IPC
#endif // mozilla_dom_gamepad_GamepadMessageUtils_h

Просмотреть файл

@ -14,12 +14,14 @@ async protocol PGamepadEventChannel {
async GamepadListenerRemoved();
async VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, uint32_t aPromiseID);
async StopVibrateHaptic(uint32_t aGamepadIndex);
async StopVibrateHaptic(uint32_t aControllerIdx);
async LightIndicatorColor(uint32_t aControllerIdx, uint32_t aLightColorIndex,
uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint32_t aPromiseID);
child:
async __delete__();
async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
async ReplyGamepadVibrateHaptic(uint32_t aPromiseID);
async ReplyGamepadPromise(uint32_t aPromiseID);
};
}

Просмотреть файл

@ -138,8 +138,9 @@ void LinuxGamepadService::AddDevice(struct udev_device* dev) {
gamepad.index = service->AddGamepad(
gamepad.idstring, mozilla::dom::GamepadMappingType::_empty,
mozilla::dom::GamepadHand::_empty, gamepad.numButtons, gamepad.numAxes,
0); // TODO: Bug 680289, implement gamepad haptics for Linux.
mozilla::dom::GamepadHand::_empty, gamepad.numButtons, gamepad.numAxes, 0,
0, 0); // TODO: Bug 680289, implement gamepad haptics for Linux.
// TODO: Bug 1523355, implement gamepad lighindicator and touch for Linux.
gamepad.source_id =
g_io_add_watch(channel, GIOCondition(G_IO_IN | G_IO_ERR | G_IO_HUP),

Просмотреть файл

@ -161,7 +161,7 @@ void VRDisplayClient::FireGamepadEvents() {
dom::GamepadAdded info(NS_ConvertUTF8toUTF16(state.controllerName),
dom::GamepadMappingType::_empty, state.hand,
mDisplayInfo.mDisplayID, state.numButtons,
state.numAxes, state.numHaptics);
state.numAxes, state.numHaptics, 0, 0);
dom::GamepadChangeEventBody body(info);
dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR,
body);

Просмотреть файл

@ -122,7 +122,7 @@ void VRSystemManager::AddGamepad(const VRControllerInfo& controllerInfo) {
NS_ConvertUTF8toUTF16(controllerInfo.GetControllerName()),
controllerInfo.GetMappingType(), controllerInfo.GetHand(),
controllerInfo.GetDisplayID(), controllerInfo.GetNumButtons(),
controllerInfo.GetNumAxes(), controllerInfo.GetNumHaptics());
controllerInfo.GetNumAxes(), controllerInfo.GetNumHaptics(), 0, 0);
VRManager* vm = VRManager::Get();
vm->NotifyGamepadChange<dom::GamepadAdded>(mControllerCount, a);