blob: b1f81eb17e6f46a518364271d4274100f124ca5f [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_GAMEPAD_WGI_DATA_FETCHER_WIN_H_
#define DEVICE_GAMEPAD_WGI_DATA_FETCHER_WIN_H_
#include "device/gamepad/gamepad_data_fetcher.h"
#include <Windows.Gaming.Input.h>
#include <wrl/event.h>
#include <memory>
#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "device/gamepad/public/mojom/gamepad.mojom.h"
#include "device/gamepad/wgi_gamepad_device.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace device {
class DEVICE_GAMEPAD_EXPORT WgiDataFetcherWin final
: public GamepadDataFetcher {
public:
enum class InitializationState {
kUninitialized,
kInitialized,
kAddGamepadAddedFailed,
kAddGamepadRemovedFailed,
kRoGetActivationFactoryFailed,
kCoreWinrtStringDelayLoadFailed,
};
using Factory =
GamepadDataFetcherFactoryImpl<WgiDataFetcherWin, GAMEPAD_SOURCE_WIN_WGI>;
// Define test hooks to use a fake WinRT RoGetActivationFactory
// implementation to avoid dependencies on the OS for WGI testing.
using GetActivationFactoryFunction = HRESULT (*)(HSTRING class_id,
const IID& iid,
void** out_factory);
WgiDataFetcherWin();
WgiDataFetcherWin(const WgiDataFetcherWin&) = delete;
WgiDataFetcherWin& operator=(const WgiDataFetcherWin&) = delete;
~WgiDataFetcherWin() override;
// GamepadDataFetcher implementation.
GamepadSource source() override;
void OnAddedToProvider() override;
void GetGamepadData(bool devices_changed_hint) override;
void PlayEffect(int source_id,
mojom::GamepadHapticEffectType,
mojom::GamepadEffectParametersPtr,
mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback,
scoped_refptr<base::SequencedTaskRunner>) override;
void ResetVibration(
int source_id,
mojom::GamepadHapticsManager::ResetVibrationActuatorCallback,
scoped_refptr<base::SequencedTaskRunner>) override;
// Set fake ActivationFunction for test to avoid dependencies on the OS API.
using ActivationFactoryFunctionCallback =
base::RepeatingCallback<GetActivationFactoryFunction()>;
static void OverrideActivationFactoryFunctionForTesting(
ActivationFactoryFunctionCallback callback);
// Used to store gamepad devices indexed by its source id.
using DeviceMap = base::flat_map<int, std::unique_ptr<WgiGamepadDevice>>;
const DeviceMap& GetGamepadsForTesting() const { return devices_; }
InitializationState GetInitializationState() const;
private:
// Set the state of the new connected gamepad to initialized, update
// gamepad state connection status, and add a new controller mapping for
// `gamepad` to `gamepads_` on gamepad polling thread.
void OnGamepadAdded(IInspectable* /* sender */,
ABI::Windows::Gaming::Input::IGamepad* gamepad);
// Remove the corresponding controller mapping of `gamepad` in `gamepads_`
// on gamepad polling thread.
void OnGamepadRemoved(IInspectable* /* sender */,
ABI::Windows::Gaming::Input::IGamepad* gamepad);
static ActivationFactoryFunctionCallback&
GetActivationFactoryFunctionCallback();
std::u16string GetGamepadDisplayName(
ABI::Windows::Gaming::Input::IGamepad* gamepad);
Microsoft::WRL::ComPtr<ABI::Windows::Gaming::Input::IRawGameController>
GetRawGameController(ABI::Windows::Gaming::Input::IGamepad* gamepad);
void UnregisterEventHandlers();
int next_source_id_ = 0;
InitializationState initialization_state_ =
InitializationState::kUninitialized;
DeviceMap devices_;
Microsoft::WRL::ComPtr<ABI::Windows::Gaming::Input::IGamepadStatics>
gamepad_statics_;
GetActivationFactoryFunction get_activation_factory_function_;
absl::optional<EventRegistrationToken> added_event_token_;
absl::optional<EventRegistrationToken> removed_event_token_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<WgiDataFetcherWin> weak_factory_{this};
};
} // namespace device
#endif // DEVICE_GAMEPAD_WGI_DATA_FETCHER_WIN_H_