Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/util/dinput_source.h
7360 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
#define DIRECTINPUT_VERSION 0x0800
6
#include "common/windows_headers.h"
7
#include "core/types.h"
8
#include "input_source.h"
9
#include <array>
10
#include <dinput.h>
11
#include <functional>
12
#include <mutex>
13
#include <vector>
14
#include <wrl/client.h>
15
16
class DInputSource final : public InputSource
17
{
18
public:
19
enum HAT_DIRECTION : u32
20
{
21
HAT_DIRECTION_UP = 0,
22
HAT_DIRECTION_DOWN = 1,
23
HAT_DIRECTION_LEFT = 2,
24
HAT_DIRECTION_RIGHT = 3,
25
NUM_HAT_DIRECTIONS = 4,
26
};
27
28
enum : u32
29
{
30
MAX_NUM_BUTTONS = 32,
31
};
32
33
DInputSource();
34
~DInputSource() override;
35
36
bool Initialize(const SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock) override;
37
void UpdateSettings(const SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock) override;
38
bool ReloadDevices() override;
39
void Shutdown() override;
40
41
void PollEvents() override;
42
std::optional<float> GetCurrentValue(InputBindingKey key) override;
43
InputManager::DeviceList EnumerateDevices() override;
44
InputManager::DeviceEffectList EnumerateEffects(std::optional<InputBindingInfo::Type> type,
45
std::optional<InputBindingKey> for_device) override;
46
u32 GetPollableDeviceCount() const override;
47
bool GetGenericBindingMapping(std::string_view device, GenericInputBindingMapping* mapping) override;
48
void UpdateMotorState(InputBindingKey key, float intensity) override;
49
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity,
50
float small_intensity) override;
51
void UpdateLEDState(InputBindingKey key, float intensity) override;
52
53
bool ContainsDevice(std::string_view device) const override;
54
std::optional<InputBindingKey> ParseKeyString(std::string_view device, std::string_view binding) override;
55
TinyString ConvertKeyToString(InputBindingKey key) override;
56
TinyString ConvertKeyToIcon(InputBindingKey key, InputManager::BindingIconMappingFunction mapper) override;
57
void SetSubclassPollDeviceList(InputSubclass subclass, const std::span<const InputBindingKey>* devices) override;
58
std::unique_ptr<ForceFeedbackDevice> CreateForceFeedbackDevice(std::string_view device, Error* error) override;
59
60
private:
61
template<typename T>
62
using ComPtr = Microsoft::WRL::ComPtr<T>;
63
64
struct ControllerData
65
{
66
ComPtr<IDirectInputDevice8W> device;
67
DIJOYSTATE last_state = {};
68
GUID guid = {};
69
std::vector<u32> axis_offsets;
70
u32 num_buttons = 0;
71
72
// NOTE: We expose hats as num_buttons + (hat_index * 4) + direction.
73
u32 num_hats = 0;
74
75
bool needs_poll = true;
76
};
77
78
using ControllerDataArray = std::vector<ControllerData>;
79
80
static std::array<bool, NUM_HAT_DIRECTIONS> GetHatButtons(DWORD hat);
81
static std::string GetDeviceIdentifier(u32 index);
82
83
bool AddDevice(ControllerData& cd, const std::string& name);
84
85
void CheckForStateChanges(size_t index, const DIJOYSTATE& new_state);
86
87
ControllerDataArray m_controllers;
88
89
HMODULE m_dinput_module{};
90
ComPtr<IDirectInput8W> m_dinput;
91
LPCDIDATAFORMAT m_joystick_data_format{};
92
HWND m_toplevel_window = NULL;
93
};
94
95