Bug 1658419 - Add a skeleton GamepadStateBroadcast r=handyman

Add the scaffolding to setup the shared memory GamepadState between the
GamepadPlatformService and GamepadManager. The next changeset will actually
integrate the new broadcast infrastructure into the gamepad code.

Differential Revision: https://phabricator.services.mozilla.com/D105128
This commit is contained in:
Chris Martin 2021-03-02 23:02:35 +00:00
Родитель 0c5f377529
Коммит dc719ee936
17 изменённых файлов: 646 добавлений и 5 удалений

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

@ -108,6 +108,9 @@ void GamepadManager::StopMonitoring() {
void GamepadManager::BeginShutdown() {
mShuttingDown = true;
StopMonitoring();
if (mMaybeGamepadStateReceiver) {
mMaybeGamepadStateReceiver = Nothing{};
}
// Don't let windows call back to unregister during shutdown
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->SetHasGamepadEventListener(false);
@ -661,4 +664,8 @@ already_AddRefed<Promise> GamepadManager::SetLightIndicatorColor(
++mPromiseID;
return promise.forget();
}
void GamepadManager::SetupRemoteInfo(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo) {
mMaybeGamepadStateReceiver = GamepadStateReceiver::Create(aReceiverInfo);
}
} // namespace mozilla::dom

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

@ -12,6 +12,7 @@
// Needed for GamepadMappingType
#include "mozilla/dom/GamepadBinding.h"
#include "mozilla/dom/GamepadHandle.h"
#include "mozilla/dom/GamepadStateReceiver.h"
#include <utility>
class nsGlobalWindowInner;
@ -83,6 +84,8 @@ class GamepadManager final : public nsIObserver {
nsIGlobalObject* aGlobal,
ErrorResult& aRv);
void SetupRemoteInfo(const GamepadStateBroadcastReceiverInfo& aReceiverInfo);
protected:
GamepadManager();
~GamepadManager() = default;
@ -148,6 +151,8 @@ class GamepadManager final : public nsIObserver {
// has been sent to that window.
nsTArray<RefPtr<nsGlobalWindowInner>> mListeners;
uint32_t mPromiseID;
Maybe<GamepadStateReceiver> mMaybeGamepadStateReceiver;
};
} // namespace dom

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

@ -8,6 +8,7 @@
#include "mozilla/dom/GamepadEventChannelParent.h"
#include "mozilla/dom/GamepadMonitoring.h"
#include "mozilla/dom/GamepadStateBroadcastReceiverInfo.h"
#include "mozilla/dom/GamepadTestChannelParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/Mutex.h"
@ -81,7 +82,8 @@ void GamepadMonitoringState::Set(bool aIsMonitoring) {
GamepadPlatformService::GamepadPlatformService()
: mNextGamepadHandleValue(1),
mMutex("mozilla::dom::GamepadPlatformService") {}
mMutex("mozilla::dom::GamepadPlatformService"),
mMaybeGamepadStateBroadcaster(GamepadStateBroadcaster::Create()) {}
GamepadPlatformService::~GamepadPlatformService() { Cleanup(); }
@ -255,6 +257,15 @@ void GamepadPlatformService::AddChannelParent(
MOZ_ASSERT(aParent);
MOZ_ASSERT(!mChannelParents.Contains(aParent));
// If we have working shared memory, attempt to set that up with the
// remote process
GamepadStateBroadcastReceiverInfo receiverInfo{};
if (mMaybeGamepadStateBroadcaster &&
mMaybeGamepadStateBroadcaster->AddReceiverAndGenerateRemoteInfo(
aParent, &receiverInfo)) {
Unused << aParent->SendSetupSharedMemory(receiverInfo);
}
// We use mutex here to prevent race condition with monitor thread
{
MutexAutoLock autoLock(mMutex);
@ -296,6 +307,11 @@ void GamepadPlatformService::RemoveChannelParent(
GamepadMonitoringState::GetSingleton().Set(false);
StopGamepadMonitoring();
if (mMaybeGamepadStateBroadcaster) {
mMaybeGamepadStateBroadcaster->RemoveReceiver(aParent);
}
ResetGamepadIndexes();
MaybeShutdown();
}

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

@ -9,6 +9,7 @@
#include "mozilla/dom/GamepadBinding.h"
#include "mozilla/dom/GamepadHandle.h"
#include "mozilla/dom/GamepadStateBroadcaster.h"
#include <map>
#include "mozilla/Mutex.h"
@ -144,6 +145,8 @@ class GamepadPlatformService final {
Mutex mMutex;
std::map<GamepadHandle, GamepadAdded> mGamepadAdded;
Maybe<GamepadStateBroadcaster> mMaybeGamepadStateBroadcaster;
};
} // namespace dom

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

@ -0,0 +1,113 @@
/* -*- 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/. */
// This is the receiving half of a pair. See GamepadStateReceiver.h for the
// receiving half of this.
// Implements single-broadcaster, multi-receiver shared memory for the gamepad
// system. Allows the gamepad monitor thread in the main process to directly
// update the shared memory to the latest state and trigger an event in all
// the content processes, causing them to read the shared memory and pass it
// to Javascript.
// This takes advantage of the fact that gamepad clients generally only care
// about the most recent state of the gamepad, not the stuff that happened
// while they weren't looking.
// This currently only does anything interesting on Windows, and it uses
// Pimpl idiom to avoid OS-specific types in this header.
#ifndef DOM_GAMEPAD_GAMEPADSTATEBROADCASTER_H_
#define DOM_GAMEPAD_GAMEPADSTATEBROADCASTER_H_
#include "mozilla/dom/GamepadBinding.h"
#include "mozilla/dom/GamepadHandle.h"
#include "mozilla/dom/GamepadLightIndicatorBinding.h"
#include "mozilla/dom/GamepadPoseState.h"
#include "mozilla/dom/GamepadTouchState.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
namespace mozilla::ipc {
class IProtocol;
} // namespace mozilla::ipc
namespace mozilla::dom {
// IPDL structure that knows how to initialize a receiver
class GamepadStateBroadcastReceiverInfo;
// The broadcasting half of the pair
//
// Can be used to deliver an event quickly and simultaneously to every
// receiver. Does not guarantee that every event will be seen by every
// receiver, but *does* guarantee that every receiver will see a coherent
// snapshot of the controller state at a point in time.
//
// (IE they will never see an unplugged controller with a button pressed)
//
// # Example:
//
// Maybe<GamepadStateBroadcaster> maybeBroadcaster =
// GamepadStateBroadcaster::Create();
// MOZ_ASSERT(maybeBroadcaster);
//
// GamepadStateBroadcastReceiverInfo remoteInfo{};
// bool result = maybeBroadcaster->AddReceiverAndGenerateRemoteInfo(
// aIPCActor, &remoteInfo);
// MOZ_ASSERT(result);
//
// result = aIPCActor->SendBroadcasterInfo(remoteInfo);
// MOZ_ASSERT(result);
//
class GamepadStateBroadcaster {
public:
// Create a new broadcaster
//
// Allocates the shared memory region for a new broadcaster that can
// be shared with others using `AddReceiverAndGenerateRemoteInfo()`
static Maybe<GamepadStateBroadcaster> Create();
// Add an IPDL actor as a new receiver and create remote info
//
// `aActor` will be added as a listener for events, and `aOut` will contain
// the remote info that must be passed via IPDL to the remote process.
//
// The info will only be valid within the context of `aActor`, and failure
// to deliver it will result in a handle leak until the remote actor's
// process dies.
bool AddReceiverAndGenerateRemoteInfo(
const mozilla::ipc::IProtocol* aActor,
GamepadStateBroadcastReceiverInfo* aOut);
// Removes an IPDL actor that was previously registered as a receiver
//
// This will free up any system resources that were required on the
// broadcaster side.
void RemoveReceiver(const mozilla::ipc::IProtocol* aActor);
// Allow move
GamepadStateBroadcaster(GamepadStateBroadcaster&& aOther) noexcept;
GamepadStateBroadcaster& operator=(GamepadStateBroadcaster&& aOther) noexcept;
// Disallow copy
GamepadStateBroadcaster(const GamepadStateBroadcaster&) = delete;
GamepadStateBroadcaster& operator=(const GamepadStateBroadcaster&) = delete;
~GamepadStateBroadcaster();
private:
class Impl;
GamepadStateBroadcaster();
explicit GamepadStateBroadcaster(UniquePtr<Impl> aImpl);
UniquePtr<Impl> mImpl;
};
} // namespace mozilla::dom
#endif // DOM_GAMEPAD_GAMEPADSTATEBROADCASTER_H_

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

@ -0,0 +1,90 @@
/* -*- 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/. */
// This is the receiving half of a pair. See GamepadStateBroadcaster.h for the
// transmitting half of this.
// Implements single-broadcaster, multi-receiver shared memory for the gamepad
// system. Allows the gamepad monitor thread in the main process to directly
// update the shared memory to the latest state and trigger an event in all
// the content processes, causing them to read the shared memory and pass it
// to Javascript.
// This takes advantage of the fact that gamepad clients generally only care
// about the most recent state of the gamepad, not the stuff that happened
// while they weren't looking.
// This currently only does anything interesting on Windows, and it uses
// Pimpl idiom to avoid OS-specific types in this header.
#ifndef DOM_GAMEPAD_GAMEPADSTATERECEIVER_H_
#define DOM_GAMEPAD_GAMEPADSTATERECEIVER_H_
#include "mozilla/dom/GamepadBinding.h"
#include "mozilla/dom/GamepadHandle.h"
#include "mozilla/dom/GamepadLightIndicatorBinding.h"
#include "mozilla/dom/GamepadPoseState.h"
#include "mozilla/dom/GamepadTouchState.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include <functional>
namespace mozilla::ipc {
class IProtocol;
} // namespace mozilla::ipc
namespace mozilla::dom {
// IPDL structure that knows how to initialize a receiver
class GamepadStateBroadcastReceiverInfo;
// The receiving half of the pair
//
// Spins up a thread that waits for changes to the shared memory to arrive
// from the other side, and generates GamepadChangeEvents that can be used to
// signal Javascript that the gamepad state has changed
//
// # Example
//
// mozilla::ipc::IPCResult RecvGamepadReceiverInfo(
// const GamepadStateBroadcastReceiverInfo& aReceiverInfo) {
// Maybe<GamepadStateReceiver> maybeReceiver =
// GamepadStateReceiver::Create(aReceiverInfo);
// MOZ_ASSERT(maybeReceiver);
// }
//
class GamepadStateReceiver {
public:
// Create the receiving side from info passed over IPDL
//
// The GamepadStateBroadcastReceiverInfo structure should have been obtained
// from a call to `AddReceiverAndGenerateRemoteInfo()` and passed via IPDL
// to this function in the remote process.
static Maybe<GamepadStateReceiver> Create(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo);
// Allow move
GamepadStateReceiver(GamepadStateReceiver&& aOther) noexcept;
GamepadStateReceiver& operator=(GamepadStateReceiver&& aOther) noexcept;
// Disallow copy
GamepadStateReceiver(const GamepadStateReceiver&) = delete;
GamepadStateReceiver& operator=(const GamepadStateReceiver&) = delete;
~GamepadStateReceiver();
private:
class Impl;
GamepadStateReceiver();
explicit GamepadStateReceiver(UniquePtr<Impl> aImpl);
UniquePtr<Impl> mImpl;
};
} // namespace mozilla::dom
#endif // DOM_GAMEPAD_GAMEPADSTATERECEIVER_H_

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

@ -0,0 +1,12 @@
/* 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/. */
namespace mozilla {
namespace dom {
struct GamepadStateBroadcastReceiverInfo {
};
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/GamepadStateBroadcaster.h"
namespace mozilla::dom {
class GamepadStateBroadcaster::Impl {
public:
Impl() = default;
~Impl() = default;
};
// static
Maybe<GamepadStateBroadcaster> GamepadStateBroadcaster::Create() {
return Nothing{};
}
GamepadStateBroadcaster::~GamepadStateBroadcaster() = default;
bool GamepadStateBroadcaster::AddReceiverAndGenerateRemoteInfo(
const mozilla::ipc::IProtocol* aActor,
GamepadStateBroadcastReceiverInfo* aOut) {
MOZ_CRASH("Should never be called");
}
void GamepadStateBroadcaster::RemoveReceiver(
const mozilla::ipc::IProtocol* aActor) {
MOZ_CRASH("Should never be called");
}
GamepadStateBroadcaster::GamepadStateBroadcaster(
GamepadStateBroadcaster&& aOther) = default;
GamepadStateBroadcaster& GamepadStateBroadcaster::operator=(
GamepadStateBroadcaster&& aOther) = default;
GamepadStateBroadcaster::GamepadStateBroadcaster() = default;
GamepadStateBroadcaster::GamepadStateBroadcaster(UniquePtr<Impl> aImpl)
: mImpl(std::move(aImpl)) {}
} // namespace mozilla::dom

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

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/GamepadStateReceiver.h"
namespace mozilla::dom {
class GamepadStateReceiver::Impl {
public:
Impl() = default;
~Impl() = default;
};
// static
Maybe<GamepadStateReceiver> GamepadStateReceiver::Create(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo) {
return Nothing{};
}
GamepadStateReceiver::~GamepadStateReceiver() = default;
GamepadStateReceiver::GamepadStateReceiver(GamepadStateReceiver&& aOther) =
default;
GamepadStateReceiver& GamepadStateReceiver::operator=(
GamepadStateReceiver&& aOther) = default;
GamepadStateReceiver::GamepadStateReceiver() = default;
GamepadStateReceiver::GamepadStateReceiver(UniquePtr<Impl> aImpl)
: mImpl(std::move(aImpl)) {}
} // namespace mozilla::dom

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

@ -34,6 +34,18 @@ already_AddRefed<GamepadEventChannelChild> GamepadEventChannelChild::Create() {
.forget();
}
mozilla::ipc::IPCResult GamepadEventChannelChild::RecvSetupSharedMemory(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo) {
NS_DispatchToMainThread(NS_NewRunnableFunction(
"GamepadEventChannelChild::RecvSetupSharedMemory", [aReceiverInfo] {
RefPtr<GamepadManager> svc(GamepadManager::GetService());
if (svc) {
svc->SetupRemoteInfo(aReceiverInfo);
}
}));
return IPC_OK();
}
mozilla::ipc::IPCResult GamepadEventChannelChild::RecvGamepadUpdate(
const GamepadChangeEvent& aGamepadEvent) {
DebugOnly<nsresult> rv =

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

@ -18,6 +18,8 @@ class GamepadEventChannelChild final : public PGamepadEventChannelChild {
static already_AddRefed<GamepadEventChannelChild> Create();
mozilla::ipc::IPCResult RecvSetupSharedMemory(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo);
mozilla::ipc::IPCResult RecvGamepadUpdate(
const GamepadChangeEvent& aGamepadEvent);
mozilla::ipc::IPCResult RecvReplyGamepadPromise(const uint32_t& aPromiseID);

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

@ -4,6 +4,7 @@
include protocol PBackground;
include "mozilla/dom/GamepadMessageUtils.h";
include GamepadEventTypes;
include GamepadStateBroadcastReceiverInfo;
using mozilla::dom::GamepadHandle from "mozilla/dom/GamepadHandle.h";
@ -22,6 +23,7 @@ refcounted protocol PGamepadEventChannel {
uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint32_t aPromiseID);
child:
async SetupSharedMemory(GamepadStateBroadcastReceiverInfo aReceiverInfo);
async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
async ReplyGamepadPromise(uint32_t aPromiseID);
};

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

@ -26,6 +26,8 @@ EXPORTS.mozilla.dom += [
"GamepadPoseState.h",
"GamepadRemapping.h",
"GamepadServiceTest.h",
"GamepadStateBroadcaster.h",
"GamepadStateReceiver.h",
"GamepadTouch.h",
"GamepadTouchState.h",
"ipc/GamepadEventChannelChild.h",
@ -66,11 +68,25 @@ else:
UNIFIED_SOURCES += ["fallback/FallbackGamepad.cpp"]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
IPDL_SOURCES += ["windows/SynchronizedSharedMemoryRemoteInfo.ipdlh"]
SOURCES += ["windows/SynchronizedSharedMemory.cpp"]
IPDL_SOURCES += [
"windows/GamepadStateBroadcastReceiverInfo.ipdlh",
"windows/SynchronizedSharedMemoryRemoteInfo.ipdlh",
]
SOURCES += [
"windows/GamepadStateBroadcaster.cpp",
"windows/GamepadStateReceiver.cpp",
"windows/SynchronizedSharedMemory.cpp",
]
else:
IPDL_SOURCES += ["fallback/SynchronizedSharedMemoryRemoteInfo.ipdlh"]
SOURCES += ["fallback/SynchronizedSharedMemory.cpp"]
IPDL_SOURCES += [
"fallback/GamepadStateBroadcastReceiverInfo.ipdlh",
"fallback/SynchronizedSharedMemoryRemoteInfo.ipdlh",
]
SOURCES += [
"fallback/GamepadStateBroadcaster.cpp",
"fallback/GamepadStateReceiver.cpp",
"fallback/SynchronizedSharedMemory.cpp",
]
LOCAL_INCLUDES += [
"ipc",

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

@ -0,0 +1,17 @@
/* 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 SynchronizedSharedMemoryRemoteInfo;
using mozilla::WindowsHandle from "mozilla/ipc/IPCTypes.h";
namespace mozilla {
namespace dom {
struct GamepadStateBroadcastReceiverInfo {
SynchronizedSharedMemoryRemoteInfo sharedMemoryInfo;
WindowsHandle eventHandle;
};
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,156 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/GamepadStateBroadcaster.h"
#include "GamepadStateLayout.h"
#include "GamepadWindowsUtil.h"
#include "mozilla/dom/GamepadStateBroadcastReceiverInfo.h"
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/SynchronizedSharedMemory.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/HashTable.h"
#include <inttypes.h>
#include <windows.h>
namespace mozilla::dom {
using SharedState = SynchronizedSharedMemory<GamepadSystemState>;
class GamepadStateBroadcaster::Impl {
public:
static UniquePtr<Impl> Create() {
Maybe<SharedState> sharedState = SharedState::CreateNew();
if (!sharedState) {
return nullptr;
}
return UniquePtr<Impl>(new Impl(std::move(*sharedState)));
}
bool AddReceiverAndGenerateRemoteInfo(
const mozilla::ipc::IProtocol* aActor,
GamepadStateBroadcastReceiverInfo* aOut) {
MOZ_ASSERT(aOut);
DWORD targetPID = aActor ? aActor->OtherPid() : ::GetCurrentProcessId();
// Create the NT event and a remote handle for it
UniqueHandle<NTEventHandleTraits> eventHandle(
::CreateEvent(nullptr /*no ACL*/, FALSE /*not manual*/, FALSE /*unset*/,
nullptr /*no name*/));
if (!eventHandle) {
return false;
}
HANDLE remoteEventHandle = nullptr;
if (!mozilla::ipc::DuplicateHandle(eventHandle.Get(), targetPID,
&remoteEventHandle, 0,
DUPLICATE_SAME_ACCESS)) {
return false;
}
// Generate a remote handle for the shared memory
SynchronizedSharedMemoryRemoteInfo sharedMemoryRemoteInfo;
if (!mSharedState.GenerateRemoteInfo(aActor, &sharedMemoryRemoteInfo)) {
// There is no reasonable way to clean up remoteEventHandle here, since
// our process doesn't own it
return false;
}
MOZ_ALWAYS_TRUE(mBroadcastEventHandles.append(
BroadcastEventHandle{aActor, std::move(eventHandle)}));
// The event and the shared memory are everything the remote side needs
aOut->sharedMemoryInfo() = std::move(sharedMemoryRemoteInfo);
aOut->eventHandle() = reinterpret_cast<WindowsHandle>(remoteEventHandle);
return true;
}
void RemoveReceiver(const mozilla::ipc::IProtocol* aActor) {
auto* ptr = [&]() -> BroadcastEventHandle* {
for (auto& x : mBroadcastEventHandles) {
if (x.actor == aActor) {
return &x;
}
}
return nullptr;
}();
if (!ptr) {
MOZ_ASSERT(false, "Tried to remove a receiver that was never added");
return;
}
// We don't care about order, so we can remove an entry by overwriting
// it with the last element and then popping the last element
if (ptr != &mBroadcastEventHandles.back()) {
(*ptr) = std::move(mBroadcastEventHandles.back());
}
mBroadcastEventHandles.popBack();
}
// Disallow copy/move
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
Impl(Impl&&) = delete;
Impl& operator=(Impl&&) = delete;
private:
struct BroadcastEventHandle {
const mozilla::ipc::IProtocol* actor;
UniqueHandle<NTEventHandleTraits> eventHandle;
};
explicit Impl(SharedState aSharedState)
: mSharedState(std::move(aSharedState)) {}
SharedState mSharedState;
Vector<BroadcastEventHandle> mBroadcastEventHandles;
};
//////////// Everything below this line is Pimpl boilerplate ///////////////////
// static
Maybe<GamepadStateBroadcaster> GamepadStateBroadcaster::Create() {
UniquePtr<Impl> impl = Impl::Create();
if (!impl) {
return Nothing{};
}
return Some(GamepadStateBroadcaster(std::move(impl)));
}
GamepadStateBroadcaster::~GamepadStateBroadcaster() = default;
bool GamepadStateBroadcaster::AddReceiverAndGenerateRemoteInfo(
const mozilla::ipc::IProtocol* aActor,
GamepadStateBroadcastReceiverInfo* aOut) {
return mImpl->AddReceiverAndGenerateRemoteInfo(aActor, aOut);
}
void GamepadStateBroadcaster::RemoveReceiver(
const mozilla::ipc::IProtocol* aActor) {
mImpl->RemoveReceiver(aActor);
}
GamepadStateBroadcaster::GamepadStateBroadcaster(
GamepadStateBroadcaster&& aOther) = default;
GamepadStateBroadcaster& GamepadStateBroadcaster::operator=(
GamepadStateBroadcaster&& aOther) = default;
GamepadStateBroadcaster::GamepadStateBroadcaster() = default;
GamepadStateBroadcaster::GamepadStateBroadcaster(UniquePtr<Impl> aImpl)
: mImpl(std::move(aImpl)) {}
} // namespace mozilla::dom

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

@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GAMEPAD_DOM_GAMEPADSTATELAYOUT_H_
#define GAMEPAD_DOM_GAMEPADSTATELAYOUT_H_
#include "mozilla/dom/GamepadBinding.h"
#include "mozilla/dom/GamepadHandle.h"
#include "mozilla/dom/GamepadLightIndicatorBinding.h"
#include "mozilla/dom/GamepadPoseState.h"
#include "mozilla/dom/GamepadTouchState.h"
#include "mozilla/Array.h"
#include <bitset>
#include <inttypes.h>
namespace mozilla::dom {
// Placeholder for the actual shared state in a later changelist
struct GamepadSystemState {
uint32_t placeholder;
};
} // namespace mozilla::dom
#endif // GAMEPAD_DOM_GAMEPADSTATELAYOUT_H_

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

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/GamepadStateReceiver.h"
#include "GamepadStateLayout.h"
#include "GamepadWindowsUtil.h"
#include "mozilla/dom/GamepadStateBroadcastReceiverInfo.h"
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/SynchronizedSharedMemory.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include <inttypes.h>
#include <windows.h>
namespace mozilla::dom {
using SharedState = SynchronizedSharedMemory<GamepadSystemState>;
class GamepadStateReceiver::Impl {
public:
static UniquePtr<Impl> Create(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo) {
Maybe<SharedState> sharedState =
SharedState::CreateFromRemoteInfo(aReceiverInfo.sharedMemoryInfo());
UniqueHandle<NTEventHandleTraits> eventHandle(
reinterpret_cast<HANDLE>(aReceiverInfo.eventHandle()));
if (!sharedState || !eventHandle) {
return nullptr;
}
return UniquePtr<Impl>(
new Impl(std::move(*sharedState), std::move(eventHandle)));
}
// Disallow copy/move
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
Impl(Impl&&) = delete;
Impl& operator=(Impl&&) = delete;
private:
explicit Impl(SharedState aSharedState,
UniqueHandle<NTEventHandleTraits> aEventHandle)
: mSharedState(std::move(aSharedState)),
mEventHandle(std::move(aEventHandle)) {}
SharedState mSharedState;
UniqueHandle<NTEventHandleTraits> mEventHandle;
};
//////////// Everything below this line is Pimpl boilerplate ///////////////////
// static
Maybe<GamepadStateReceiver> GamepadStateReceiver::Create(
const GamepadStateBroadcastReceiverInfo& aReceiverInfo) {
UniquePtr<Impl> impl = Impl::Create(aReceiverInfo);
if (!impl) {
return Nothing{};
}
return Some(GamepadStateReceiver(std::move(impl)));
}
GamepadStateReceiver::~GamepadStateReceiver() = default;
GamepadStateReceiver::GamepadStateReceiver(GamepadStateReceiver&& aOther) =
default;
GamepadStateReceiver& GamepadStateReceiver::operator=(
GamepadStateReceiver&& aOther) = default;
GamepadStateReceiver::GamepadStateReceiver() = default;
GamepadStateReceiver::GamepadStateReceiver(UniquePtr<Impl> aImpl)
: mImpl(std::move(aImpl)) {}
} // namespace mozilla::dom