summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
authorGravatar Lioncash2020-08-27 15:16:47 -0400
committerGravatar Lioncash2020-08-27 16:11:17 -0400
commit9e1b0af25907f7a8b960aa5c1e7d931691f40196 (patch)
tree9bfda0b559cb025da3bc65168d28ee78144daa20 /src/input_common
parentMerge pull request #4530 from Morph1984/mjolnir-p1 (diff)
downloadyuzu-9e1b0af25907f7a8b960aa5c1e7d931691f40196.tar.gz
yuzu-9e1b0af25907f7a8b960aa5c1e7d931691f40196.tar.xz
yuzu-9e1b0af25907f7a8b960aa5c1e7d931691f40196.zip
input_common: Eliminate most global state
Abstracts most of the input mechanisms under an InputSubsystem class that is managed by the frontends, eliminating any static constructors and destructors. This gets rid of global accessor functions and also allows the frontends to have a more fine-grained control over the lifecycle of the input subsystem. This also makes it explicit which interfaces rely on the input subsystem instead of making it opaque in the interface functions. All that remains to migrate over is the factories, which can be done in a separate change.
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/main.cpp250
-rw-r--r--src/input_common/main.h130
2 files changed, 227 insertions, 153 deletions
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 8e67a7437..57e7a25fe 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -18,66 +18,166 @@
18 18
19namespace InputCommon { 19namespace InputCommon {
20 20
21static std::shared_ptr<Keyboard> keyboard; 21struct InputSubsystem::Impl {
22static std::shared_ptr<MotionEmu> motion_emu; 22 void Initialize() {
23 auto gcadapter = std::make_shared<GCAdapter::Adapter>();
24 gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
25 Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
26 gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
27 Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
28
29 keyboard = std::make_shared<Keyboard>();
30 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
31 Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
32 std::make_shared<AnalogFromButton>());
33 motion_emu = std::make_shared<MotionEmu>();
34 Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
35
23#ifdef HAVE_SDL2 36#ifdef HAVE_SDL2
24static std::unique_ptr<SDL::State> sdl; 37 sdl = SDL::Init();
25#endif 38#endif
26static std::unique_ptr<CemuhookUDP::State> udp;
27static std::shared_ptr<GCButtonFactory> gcbuttons;
28static std::shared_ptr<GCAnalogFactory> gcanalog;
29
30void Init() {
31 auto gcadapter = std::make_shared<GCAdapter::Adapter>();
32 gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
33 Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
34 gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
35 Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
36
37 keyboard = std::make_shared<Keyboard>();
38 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
39 Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
40 std::make_shared<AnalogFromButton>());
41 motion_emu = std::make_shared<MotionEmu>();
42 Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
43 39
40 udp = CemuhookUDP::Init();
41 }
42
43 void Shutdown() {
44 Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
45 keyboard.reset();
46 Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
47 Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
48 motion_emu.reset();
44#ifdef HAVE_SDL2 49#ifdef HAVE_SDL2
45 sdl = SDL::Init(); 50 sdl.reset();
46#endif 51#endif
47 udp = CemuhookUDP::Init(); 52 udp.reset();
48} 53 Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
54 Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
55
56 gcbuttons.reset();
57 gcanalog.reset();
58 }
59
60 [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
61 std::vector<Common::ParamPackage> devices = {
62 Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
63 Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
64 };
65#ifdef HAVE_SDL2
66 auto sdl_devices = sdl->GetInputDevices();
67 devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
68#endif
69 auto udp_devices = udp->GetInputDevices();
70 devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
71 return devices;
72 }
73
74 [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
75 const Common::ParamPackage& params) const {
76 if (!params.Has("class") || params.Get("class", "") == "any") {
77 return {};
78 }
79 if (params.Get("class", "") == "key") {
80 // TODO consider returning the SDL key codes for the default keybindings
81 return {};
82 }
83#ifdef HAVE_SDL2
84 if (params.Get("class", "") == "sdl") {
85 return sdl->GetAnalogMappingForDevice(params);
86 }
87#endif
88 return {};
89 }
90
91 [[nodiscard]] ButtonMapping GetButtonMappingForDevice(
92 const Common::ParamPackage& params) const {
93 if (!params.Has("class") || params.Get("class", "") == "any") {
94 return {};
95 }
96 if (params.Get("class", "") == "key") {
97 // TODO consider returning the SDL key codes for the default keybindings
98 return {};
99 }
100#ifdef HAVE_SDL2
101 if (params.Get("class", "") == "sdl") {
102 return sdl->GetButtonMappingForDevice(params);
103 }
104#endif
105 return {};
106 }
49 107
50void Shutdown() { 108 std::shared_ptr<Keyboard> keyboard;
51 Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); 109 std::shared_ptr<MotionEmu> motion_emu;
52 keyboard.reset();
53 Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
54 Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
55 motion_emu.reset();
56#ifdef HAVE_SDL2 110#ifdef HAVE_SDL2
57 sdl.reset(); 111 std::unique_ptr<SDL::State> sdl;
58#endif 112#endif
59 udp.reset(); 113 std::unique_ptr<CemuhookUDP::State> udp;
60 Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); 114 std::shared_ptr<GCButtonFactory> gcbuttons;
61 Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); 115 std::shared_ptr<GCAnalogFactory> gcanalog;
116};
117
118InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
119
120InputSubsystem::~InputSubsystem() = default;
121
122void InputSubsystem::Initialize() {
123 impl->Initialize();
124}
125
126void InputSubsystem::Shutdown() {
127 impl->Shutdown();
128}
129
130Keyboard* InputSubsystem::GetKeyboard() {
131 return impl->keyboard.get();
132}
133
134const Keyboard* InputSubsystem::GetKeyboard() const {
135 return impl->keyboard.get();
136}
137
138MotionEmu* InputSubsystem::GetMotionEmu() {
139 return impl->motion_emu.get();
140}
141
142const MotionEmu* InputSubsystem::GetMotionEmu() const {
143 return impl->motion_emu.get();
144}
145
146std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
147 return impl->GetInputDevices();
148}
149
150AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const {
151 return impl->GetAnalogMappingForDevice(device);
152}
62 153
63 gcbuttons.reset(); 154ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const {
64 gcanalog.reset(); 155 return impl->GetButtonMappingForDevice(device);
65} 156}
66 157
67Keyboard* GetKeyboard() { 158GCAnalogFactory* InputSubsystem::GetGCAnalogs() {
68 return keyboard.get(); 159 return impl->gcanalog.get();
69} 160}
70 161
71MotionEmu* GetMotionEmu() { 162const GCAnalogFactory* InputSubsystem::GetGCAnalogs() const {
72 return motion_emu.get(); 163 return impl->gcanalog.get();
73} 164}
74 165
75GCButtonFactory* GetGCButtons() { 166GCButtonFactory* InputSubsystem::GetGCButtons() {
76 return gcbuttons.get(); 167 return impl->gcbuttons.get();
77} 168}
78 169
79GCAnalogFactory* GetGCAnalogs() { 170const GCButtonFactory* InputSubsystem::GetGCButtons() const {
80 return gcanalog.get(); 171 return impl->gcbuttons.get();
172}
173
174std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers(
175 Polling::DeviceType type) const {
176#ifdef HAVE_SDL2
177 return impl->sdl->GetPollers(type);
178#else
179 return {};
180#endif
81} 181}
82 182
83std::string GenerateKeyboardParam(int key_code) { 183std::string GenerateKeyboardParam(int key_code) {
@@ -101,68 +201,4 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left,
101 }; 201 };
102 return circle_pad_param.Serialize(); 202 return circle_pad_param.Serialize();
103} 203}
104
105std::vector<Common::ParamPackage> GetInputDevices() {
106 std::vector<Common::ParamPackage> devices = {
107 Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
108 Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
109 };
110#ifdef HAVE_SDL2
111 auto sdl_devices = sdl->GetInputDevices();
112 devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
113#endif
114 auto udp_devices = udp->GetInputDevices();
115 devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
116 return devices;
117}
118
119std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> GetButtonMappingForDevice(
120 const Common::ParamPackage& params) {
121 std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> mappings;
122 if (!params.Has("class") || params.Get("class", "") == "any") {
123 return {};
124 }
125 if (params.Get("class", "") == "key") {
126 // TODO consider returning the SDL key codes for the default keybindings
127 return {};
128 }
129#ifdef HAVE_SDL2
130 if (params.Get("class", "") == "sdl") {
131 return sdl->GetButtonMappingForDevice(params);
132 }
133#endif
134 return {};
135}
136
137std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> GetAnalogMappingForDevice(
138 const Common::ParamPackage& params) {
139 std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> mappings;
140 if (!params.Has("class") || params.Get("class", "") == "any") {
141 return {};
142 }
143 if (params.Get("class", "") == "key") {
144 // TODO consider returning the SDL key codes for the default keybindings
145 return {};
146 }
147#ifdef HAVE_SDL2
148 if (params.Get("class", "") == "sdl") {
149 return sdl->GetAnalogMappingForDevice(params);
150 }
151#endif
152 return {};
153}
154
155namespace Polling {
156
157std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {
158 std::vector<std::unique_ptr<DevicePoller>> pollers;
159
160#ifdef HAVE_SDL2
161 pollers = sdl->GetPollers(type);
162#endif
163
164 return pollers;
165}
166
167} // namespace Polling
168} // namespace InputCommon 204} // namespace InputCommon
diff --git a/src/input_common/main.h b/src/input_common/main.h
index e706c3750..f66308163 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -16,52 +16,6 @@ class ParamPackage;
16} 16}
17 17
18namespace InputCommon { 18namespace InputCommon {
19
20/// Initializes and registers all built-in input device factories.
21void Init();
22
23/// Deregisters all built-in input device factories and shuts them down.
24void Shutdown();
25
26class Keyboard;
27
28/// Gets the keyboard button device factory.
29Keyboard* GetKeyboard();
30
31class MotionEmu;
32
33/// Gets the motion emulation factory.
34MotionEmu* GetMotionEmu();
35
36GCButtonFactory* GetGCButtons();
37
38GCAnalogFactory* GetGCAnalogs();
39
40/// Generates a serialized param package for creating a keyboard button device
41std::string GenerateKeyboardParam(int key_code);
42
43/// Generates a serialized param package for creating an analog device taking input from keyboard
44std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
45 int key_modifier, float modifier_scale);
46
47/**
48 * Return a list of available input devices that this Factory can create a new device with.
49 * Each returned Parampackage should have a `display` field used for display, a class field for
50 * backends to determine if this backend is meant to service the request and any other information
51 * needed to identify this in the backend later.
52 */
53std::vector<Common::ParamPackage> GetInputDevices();
54
55/**
56 * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
57 * mapping for the device. This is currently only implemented for the sdl backend devices.
58 */
59using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
60using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
61
62ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&);
63AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&);
64
65namespace Polling { 19namespace Polling {
66 20
67enum class DeviceType { Button, AnalogPreferred }; 21enum class DeviceType { Button, AnalogPreferred };
@@ -90,4 +44,88 @@ public:
90// Get all DevicePoller from all backends for a specific device type 44// Get all DevicePoller from all backends for a specific device type
91std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type); 45std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type);
92} // namespace Polling 46} // namespace Polling
47
48class GCAnalogFactory;
49class GCButtonFactory;
50class Keyboard;
51class MotionEmu;
52
53/**
54 * Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
55 * mapping for the device. This is currently only implemented for the SDL backend devices.
56 */
57using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
58using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
59
60class InputSubsystem {
61public:
62 explicit InputSubsystem();
63 ~InputSubsystem();
64
65 InputSubsystem(const InputSubsystem&) = delete;
66 InputSubsystem& operator=(const InputSubsystem&) = delete;
67
68 InputSubsystem(InputSubsystem&&) = delete;
69 InputSubsystem& operator=(InputSubsystem&&) = delete;
70
71 /// Initializes and registers all built-in input device factories.
72 void Initialize();
73
74 /// Unregisters all built-in input device factories and shuts them down.
75 void Shutdown();
76
77 /// Retrieves the underlying keyboard device.
78 [[nodiscard]] Keyboard* GetKeyboard();
79
80 /// Retrieves the underlying keyboard device.
81 [[nodiscard]] const Keyboard* GetKeyboard() const;
82
83 /// Retrieves the underlying motion emulation factory.
84 [[nodiscard]] MotionEmu* GetMotionEmu();
85
86 /// Retrieves the underlying motion emulation factory.
87 [[nodiscard]] const MotionEmu* GetMotionEmu() const;
88
89 /**
90 * Returns all available input devices that this Factory can create a new device with.
91 * Each returned ParamPackage should have a `display` field used for display, a class field for
92 * backends to determine if this backend is meant to service the request and any other
93 * information needed to identify this in the backend later.
94 */
95 [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const;
96
97 /// Retrieves the analog mappings for the given device.
98 [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& device) const;
99
100 /// Retrieves the button mappings for the given device.
101 [[nodiscard]] ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& device) const;
102
103 /// Retrieves the underlying GameCube analog handler.
104 [[nodiscard]] GCAnalogFactory* GetGCAnalogs();
105
106 /// Retrieves the underlying GameCube analog handler.
107 [[nodiscard]] const GCAnalogFactory* GetGCAnalogs() const;
108
109 /// Retrieves the underlying GameCube button handler.
110 [[nodiscard]] GCButtonFactory* GetGCButtons();
111
112 /// Retrieves the underlying GameCube button handler.
113 [[nodiscard]] const GCButtonFactory* GetGCButtons() const;
114
115 /// Get all DevicePoller from all backends for a specific device type
116 [[nodiscard]] std::vector<std::unique_ptr<Polling::DevicePoller>> GetPollers(
117 Polling::DeviceType type) const;
118
119private:
120 struct Impl;
121 std::unique_ptr<Impl> impl;
122};
123
124/// Generates a serialized param package for creating a keyboard button device
125std::string GenerateKeyboardParam(int key_code);
126
127/// Generates a serialized param package for creating an analog device taking input from keyboard
128std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
129 int key_modifier, float modifier_scale);
130
93} // namespace InputCommon 131} // namespace InputCommon