зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
0c5f377529
Коммит
dc719ee936
|
@ -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
|
Загрузка…
Ссылка в новой задаче