summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2020-08-27 15:16:47 -0400
committerGravatar Lioncash2020-08-27 16:11:17 -0400
commit9e1b0af25907f7a8b960aa5c1e7d931691f40196 (patch)
tree9bfda0b559cb025da3bc65168d28ee78144daa20
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 '')
-rw-r--r--src/input_common/main.cpp250
-rw-r--r--src/input_common/main.h130
-rw-r--r--src/yuzu/bootmanager.cpp23
-rw-r--r--src/yuzu/bootmanager.h8
-rw-r--r--src/yuzu/configuration/configure_debug_controller.cpp5
-rw-r--r--src/yuzu/configuration/configure_debug_controller.h7
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp5
-rw-r--r--src/yuzu/configuration/configure_dialog.h7
-rw-r--r--src/yuzu/configuration/configure_input.cpp32
-rw-r--r--src/yuzu/configuration/configure_input.h9
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp34
-rw-r--r--src/yuzu/configuration/configure_input_player.h10
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.cpp8
-rw-r--r--src/yuzu/configuration/configure_mouse_advanced.h10
-rw-r--r--src/yuzu/main.cpp11
-rw-r--r--src/yuzu/main.h17
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp18
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h10
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp5
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h7
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp5
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h7
-rw-r--r--src/yuzu_cmd/yuzu.cpp9
-rw-r--r--src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp5
-rw-r--r--src/yuzu_tester/emu_window/emu_window_sdl2_hide.h6
25 files changed, 396 insertions, 242 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
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 8fc322b30..f1b428bde 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -304,8 +304,9 @@ static Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow*
304 return wsi; 304 return wsi;
305} 305}
306 306
307GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_) 307GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
308 : QWidget(parent_), emu_thread(emu_thread_) { 308 InputCommon::InputSubsystem* input_subsystem_)
309 : QWidget(parent), emu_thread(emu_thread_), input_subsystem{input_subsystem_} {
309 setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") 310 setWindowTitle(QStringLiteral("yuzu %1 | %2-%3")
310 .arg(QString::fromUtf8(Common::g_build_name), 311 .arg(QString::fromUtf8(Common::g_build_name),
311 QString::fromUtf8(Common::g_scm_branch), 312 QString::fromUtf8(Common::g_scm_branch),
@@ -314,15 +315,15 @@ GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_)
314 auto layout = new QHBoxLayout(this); 315 auto layout = new QHBoxLayout(this);
315 layout->setMargin(0); 316 layout->setMargin(0);
316 setLayout(layout); 317 setLayout(layout);
317 InputCommon::Init(); 318 input_subsystem->Initialize();
318 319
319 this->setMouseTracking(true); 320 this->setMouseTracking(true);
320 321
321 connect(this, &GRenderWindow::FirstFrameDisplayed, parent_, &GMainWindow::OnLoadComplete); 322 connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
322} 323}
323 324
324GRenderWindow::~GRenderWindow() { 325GRenderWindow::~GRenderWindow() {
325 InputCommon::Shutdown(); 326 input_subsystem->Shutdown();
326} 327}
327 328
328void GRenderWindow::PollEvents() { 329void GRenderWindow::PollEvents() {
@@ -391,11 +392,11 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
391} 392}
392 393
393void GRenderWindow::keyPressEvent(QKeyEvent* event) { 394void GRenderWindow::keyPressEvent(QKeyEvent* event) {
394 InputCommon::GetKeyboard()->PressKey(event->key()); 395 input_subsystem->GetKeyboard()->PressKey(event->key());
395} 396}
396 397
397void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { 398void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
398 InputCommon::GetKeyboard()->ReleaseKey(event->key()); 399 input_subsystem->GetKeyboard()->ReleaseKey(event->key());
399} 400}
400 401
401void GRenderWindow::mousePressEvent(QMouseEvent* event) { 402void GRenderWindow::mousePressEvent(QMouseEvent* event) {
@@ -409,7 +410,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
409 const auto [x, y] = ScaleTouch(pos); 410 const auto [x, y] = ScaleTouch(pos);
410 this->TouchPressed(x, y); 411 this->TouchPressed(x, y);
411 } else if (event->button() == Qt::RightButton) { 412 } else if (event->button() == Qt::RightButton) {
412 InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y()); 413 input_subsystem->GetMotionEmu()->BeginTilt(pos.x(), pos.y());
413 } 414 }
414 QWidget::mousePressEvent(event); 415 QWidget::mousePressEvent(event);
415} 416}
@@ -423,7 +424,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
423 auto pos = event->pos(); 424 auto pos = event->pos();
424 const auto [x, y] = ScaleTouch(pos); 425 const auto [x, y] = ScaleTouch(pos);
425 this->TouchMoved(x, y); 426 this->TouchMoved(x, y);
426 InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y()); 427 input_subsystem->GetMotionEmu()->Tilt(pos.x(), pos.y());
427 QWidget::mouseMoveEvent(event); 428 QWidget::mouseMoveEvent(event);
428} 429}
429 430
@@ -436,7 +437,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
436 if (event->button() == Qt::LeftButton) { 437 if (event->button() == Qt::LeftButton) {
437 this->TouchReleased(); 438 this->TouchReleased();
438 } else if (event->button() == Qt::RightButton) { 439 } else if (event->button() == Qt::RightButton) {
439 InputCommon::GetMotionEmu()->EndTilt(); 440 input_subsystem->GetMotionEmu()->EndTilt();
440 } 441 }
441} 442}
442 443
@@ -485,7 +486,7 @@ bool GRenderWindow::event(QEvent* event) {
485 486
486void GRenderWindow::focusOutEvent(QFocusEvent* event) { 487void GRenderWindow::focusOutEvent(QFocusEvent* event) {
487 QWidget::focusOutEvent(event); 488 QWidget::focusOutEvent(event);
488 InputCommon::GetKeyboard()->ReleaseAllKeys(); 489 input_subsystem->GetKeyboard()->ReleaseAllKeys();
489} 490}
490 491
491void GRenderWindow::resizeEvent(QResizeEvent* event) { 492void GRenderWindow::resizeEvent(QResizeEvent* event) {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 6c59b4d5c..ecb3b8135 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -23,6 +23,10 @@ class QKeyEvent;
23class QTouchEvent; 23class QTouchEvent;
24class QStringList; 24class QStringList;
25 25
26namespace InputCommon {
27class InputSubsystem;
28}
29
26namespace VideoCore { 30namespace VideoCore {
27enum class LoadCallbackStage; 31enum class LoadCallbackStage;
28} 32}
@@ -121,7 +125,8 @@ class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
121 Q_OBJECT 125 Q_OBJECT
122 126
123public: 127public:
124 GRenderWindow(GMainWindow* parent, EmuThread* emu_thread); 128 explicit GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
129 InputCommon::InputSubsystem* input_subsystem_);
125 ~GRenderWindow() override; 130 ~GRenderWindow() override;
126 131
127 // EmuWindow implementation. 132 // EmuWindow implementation.
@@ -183,6 +188,7 @@ private:
183 QStringList GetUnsupportedGLExtensions() const; 188 QStringList GetUnsupportedGLExtensions() const;
184 189
185 EmuThread* emu_thread; 190 EmuThread* emu_thread;
191 InputCommon::InputSubsystem* input_subsystem;
186 192
187 // Main context that will be shared with all other contexts that are requested. 193 // Main context that will be shared with all other contexts that are requested.
188 // If this is used in a shared context setting, then this should not be used directly, but 194 // If this is used in a shared context setting, then this should not be used directly, but
diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp
index 72885b4b8..0097c9a29 100644
--- a/src/yuzu/configuration/configure_debug_controller.cpp
+++ b/src/yuzu/configuration/configure_debug_controller.cpp
@@ -5,9 +5,10 @@
5#include "ui_configure_debug_controller.h" 5#include "ui_configure_debug_controller.h"
6#include "yuzu/configuration/configure_debug_controller.h" 6#include "yuzu/configuration/configure_debug_controller.h"
7 7
8ConfigureDebugController::ConfigureDebugController(QWidget* parent) 8ConfigureDebugController::ConfigureDebugController(QWidget* parent,
9 InputCommon::InputSubsystem* input_subsystem)
9 : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), 10 : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
10 debug_controller(new ConfigureInputPlayer(this, 9, nullptr, true)) { 11 debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) {
11 ui->setupUi(this); 12 ui->setupUi(this);
12 13
13 ui->controllerLayout->addWidget(debug_controller); 14 ui->controllerLayout->addWidget(debug_controller);
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h
index 36475bbea..34dcf705f 100644
--- a/src/yuzu/configuration/configure_debug_controller.h
+++ b/src/yuzu/configuration/configure_debug_controller.h
@@ -10,6 +10,10 @@
10 10
11class QPushButton; 11class QPushButton;
12 12
13namespace InputCommon {
14class InputSubsystem;
15}
16
13namespace Ui { 17namespace Ui {
14class ConfigureDebugController; 18class ConfigureDebugController;
15} 19}
@@ -18,7 +22,8 @@ class ConfigureDebugController : public QDialog {
18 Q_OBJECT 22 Q_OBJECT
19 23
20public: 24public:
21 explicit ConfigureDebugController(QWidget* parent); 25 explicit ConfigureDebugController(QWidget* parent,
26 InputCommon::InputSubsystem* input_subsystem);
22 ~ConfigureDebugController() override; 27 ~ConfigureDebugController() override;
23 28
24 void ApplyConfiguration(); 29 void ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 857577591..8186929a6 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -12,7 +12,8 @@
12#include "yuzu/configuration/configure_input_player.h" 12#include "yuzu/configuration/configure_input_player.h"
13#include "yuzu/hotkeys.h" 13#include "yuzu/hotkeys.h"
14 14
15ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) 15ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
16 InputCommon::InputSubsystem* input_subsystem)
16 : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { 17 : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) {
17 Settings::configuring_global = true; 18 Settings::configuring_global = true;
18 19
@@ -20,6 +21,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
20 ui->hotkeysTab->Populate(registry); 21 ui->hotkeysTab->Populate(registry);
21 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); 22 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
22 23
24 ui->inputTab->Initialize(input_subsystem);
25
23 SetConfiguration(); 26 SetConfiguration();
24 PopulateSelectionList(); 27 PopulateSelectionList();
25 28
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 4289bc225..570c3b941 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -9,6 +9,10 @@
9 9
10class HotkeyRegistry; 10class HotkeyRegistry;
11 11
12namespace InputCommon {
13class InputSubsystem;
14}
15
12namespace Ui { 16namespace Ui {
13class ConfigureDialog; 17class ConfigureDialog;
14} 18}
@@ -17,7 +21,8 @@ class ConfigureDialog : public QDialog {
17 Q_OBJECT 21 Q_OBJECT
18 22
19public: 23public:
20 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); 24 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
25 InputCommon::InputSubsystem* input_subsystem);
21 ~ConfigureDialog() override; 26 ~ConfigureDialog() override;
22 27
23 void ApplyConfiguration(); 28 void ApplyConfiguration();
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 0d004c2f7..5223eed1d 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -65,16 +65,20 @@ void OnDockedModeChanged(bool last_state, bool new_state) {
65ConfigureInput::ConfigureInput(QWidget* parent) 65ConfigureInput::ConfigureInput(QWidget* parent)
66 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { 66 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
67 ui->setupUi(this); 67 ui->setupUi(this);
68}
69
70ConfigureInput::~ConfigureInput() = default;
68 71
72void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) {
69 player_controllers = { 73 player_controllers = {
70 new ConfigureInputPlayer(this, 0, ui->consoleInputSettings), 74 new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem),
71 new ConfigureInputPlayer(this, 1, ui->consoleInputSettings), 75 new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem),
72 new ConfigureInputPlayer(this, 2, ui->consoleInputSettings), 76 new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem),
73 new ConfigureInputPlayer(this, 3, ui->consoleInputSettings), 77 new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem),
74 new ConfigureInputPlayer(this, 4, ui->consoleInputSettings), 78 new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem),
75 new ConfigureInputPlayer(this, 5, ui->consoleInputSettings), 79 new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem),
76 new ConfigureInputPlayer(this, 6, ui->consoleInputSettings), 80 new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem),
77 new ConfigureInputPlayer(this, 7, ui->consoleInputSettings), 81 new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem),
78 }; 82 };
79 83
80 player_tabs = { 84 player_tabs = {
@@ -115,10 +119,12 @@ ConfigureInput::ConfigureInput(QWidget* parent)
115 advanced = new ConfigureInputAdvanced(this); 119 advanced = new ConfigureInputAdvanced(this);
116 ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); 120 ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
117 ui->tabAdvanced->layout()->addWidget(advanced); 121 ui->tabAdvanced->layout()->addWidget(advanced);
118 connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, 122 connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] {
119 [this] { CallConfigureDialog<ConfigureDebugController>(*this); }); 123 CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem);
120 connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, 124 });
121 [this] { CallConfigureDialog<ConfigureMouseAdvanced>(*this); }); 125 connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
126 CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
127 });
122 connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog, 128 connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog,
123 [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); 129 [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); });
124 130
@@ -129,8 +135,6 @@ ConfigureInput::ConfigureInput(QWidget* parent)
129 LoadConfiguration(); 135 LoadConfiguration();
130} 136}
131 137
132ConfigureInput::~ConfigureInput() = default;
133
134QList<QWidget*> ConfigureInput::GetSubTabs() const { 138QList<QWidget*> ConfigureInput::GetSubTabs() const {
135 return { 139 return {
136 ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5, 140 ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5,
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index 78ca659da..d08a24f96 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -7,8 +7,8 @@
7#include <array> 7#include <array>
8#include <memory> 8#include <memory>
9 9
10#include <QDialog>
11#include <QKeyEvent> 10#include <QKeyEvent>
11#include <QWidget>
12 12
13#include "yuzu/configuration/configure_input_advanced.h" 13#include "yuzu/configuration/configure_input_advanced.h"
14#include "yuzu/configuration/configure_input_player.h" 14#include "yuzu/configuration/configure_input_player.h"
@@ -19,6 +19,10 @@ class QCheckBox;
19class QString; 19class QString;
20class QTimer; 20class QTimer;
21 21
22namespace InputCommon {
23class InputSubsystem;
24}
25
22namespace Ui { 26namespace Ui {
23class ConfigureInput; 27class ConfigureInput;
24} 28}
@@ -32,6 +36,9 @@ public:
32 explicit ConfigureInput(QWidget* parent = nullptr); 36 explicit ConfigureInput(QWidget* parent = nullptr);
33 ~ConfigureInput() override; 37 ~ConfigureInput() override;
34 38
39 /// Initializes the input dialog with the given input subsystem.
40 void Initialize(InputCommon::InputSubsystem* input_subsystem_);
41
35 /// Save all button configurations to settings file. 42 /// Save all button configurations to settings file.
36 void ApplyConfiguration(); 43 void ApplyConfiguration();
37 44
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index d3980eb49..80bf40acb 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -11,12 +11,12 @@
11#include <QMenu> 11#include <QMenu>
12#include <QMessageBox> 12#include <QMessageBox>
13#include <QTimer> 13#include <QTimer>
14#include "common/assert.h"
15#include "common/param_package.h" 14#include "common/param_package.h"
16#include "core/core.h" 15#include "core/core.h"
17#include "core/hle/service/hid/controllers/npad.h" 16#include "core/hle/service/hid/controllers/npad.h"
18#include "core/hle/service/hid/hid.h" 17#include "core/hle/service/hid/hid.h"
19#include "core/hle/service/sm/sm.h" 18#include "core/hle/service/sm/sm.h"
19#include "input_common/gcadapter/gc_poller.h"
20#include "input_common/main.h" 20#include "input_common/main.h"
21#include "ui_configure_input_player.h" 21#include "ui_configure_input_player.h"
22#include "yuzu/configuration/config.h" 22#include "yuzu/configuration/config.h"
@@ -229,9 +229,11 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
229} // namespace 229} // namespace
230 230
231ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, 231ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
232 QWidget* bottom_row, bool debug) 232 QWidget* bottom_row,
233 InputCommon::InputSubsystem* input_subsystem_,
234 bool debug)
233 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), 235 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index),
234 debug(debug), timeout_timer(std::make_unique<QTimer>()), 236 debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()),
235 poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { 237 poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) {
236 ui->setupUi(this); 238 ui->setupUi(this);
237 239
@@ -287,7 +289,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
287 params.Set("direction", "+"); 289 params.Set("direction", "+");
288 params.Set("threshold", "0.5"); 290 params.Set("threshold", "0.5");
289 } 291 }
290 (*param) = std::move(params); 292 *param = std::move(params);
291 }, 293 },
292 InputCommon::Polling::DeviceType::Button); 294 InputCommon::Polling::DeviceType::Button);
293 }); 295 });
@@ -401,15 +403,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
401 403
402 connect(poll_timer.get(), &QTimer::timeout, [this] { 404 connect(poll_timer.get(), &QTimer::timeout, [this] {
403 Common::ParamPackage params; 405 Common::ParamPackage params;
404 if (InputCommon::GetGCButtons()->IsPolling()) { 406 if (input_subsystem->GetGCButtons()->IsPolling()) {
405 params = InputCommon::GetGCButtons()->GetNextInput(); 407 params = input_subsystem->GetGCButtons()->GetNextInput();
406 if (params.Has("engine")) { 408 if (params.Has("engine")) {
407 SetPollingResult(params, false); 409 SetPollingResult(params, false);
408 return; 410 return;
409 } 411 }
410 } 412 }
411 if (InputCommon::GetGCAnalogs()->IsPolling()) { 413 if (input_subsystem->GetGCAnalogs()->IsPolling()) {
412 params = InputCommon::GetGCAnalogs()->GetNextInput(); 414 params = input_subsystem->GetGCAnalogs()->GetNextInput();
413 if (params.Has("engine")) { 415 if (params.Has("engine")) {
414 SetPollingResult(params, false); 416 SetPollingResult(params, false);
415 return; 417 return;
@@ -514,7 +516,7 @@ void ConfigureInputPlayer::LoadConfiguration() {
514} 516}
515 517
516void ConfigureInputPlayer::UpdateInputDevices() { 518void ConfigureInputPlayer::UpdateInputDevices() {
517 input_devices = InputCommon::GetInputDevices(); 519 input_devices = input_subsystem->GetInputDevices();
518 ui->comboDevices->clear(); 520 ui->comboDevices->clear();
519 for (auto device : input_devices) { 521 for (auto device : input_devices) {
520 ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); 522 ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
@@ -642,8 +644,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
642 return; 644 return;
643 } 645 }
644 const auto& device = input_devices[ui->comboDevices->currentIndex()]; 646 const auto& device = input_devices[ui->comboDevices->currentIndex()];
645 auto button_mapping = InputCommon::GetButtonMappingForDevice(device); 647 auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
646 auto analog_mapping = InputCommon::GetAnalogMappingForDevice(device); 648 auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
647 for (int i = 0; i < buttons_param.size(); ++i) { 649 for (int i = 0; i < buttons_param.size(); ++i) {
648 buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; 650 buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
649 } 651 }
@@ -666,7 +668,7 @@ void ConfigureInputPlayer::HandleClick(
666 668
667 input_setter = new_input_setter; 669 input_setter = new_input_setter;
668 670
669 device_pollers = InputCommon::Polling::GetPollers(type); 671 device_pollers = input_subsystem->GetPollers(type);
670 672
671 for (auto& poller : device_pollers) { 673 for (auto& poller : device_pollers) {
672 poller->Start(); 674 poller->Start();
@@ -676,9 +678,9 @@ void ConfigureInputPlayer::HandleClick(
676 QWidget::grabKeyboard(); 678 QWidget::grabKeyboard();
677 679
678 if (type == InputCommon::Polling::DeviceType::Button) { 680 if (type == InputCommon::Polling::DeviceType::Button) {
679 InputCommon::GetGCButtons()->BeginConfiguration(); 681 input_subsystem->GetGCButtons()->BeginConfiguration();
680 } else { 682 } else {
681 InputCommon::GetGCAnalogs()->BeginConfiguration(); 683 input_subsystem->GetGCAnalogs()->BeginConfiguration();
682 } 684 }
683 685
684 timeout_timer->start(2500); // Cancel after 2.5 seconds 686 timeout_timer->start(2500); // Cancel after 2.5 seconds
@@ -695,8 +697,8 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
695 QWidget::releaseMouse(); 697 QWidget::releaseMouse();
696 QWidget::releaseKeyboard(); 698 QWidget::releaseKeyboard();
697 699
698 InputCommon::GetGCButtons()->EndConfiguration(); 700 input_subsystem->GetGCButtons()->EndConfiguration();
699 InputCommon::GetGCAnalogs()->EndConfiguration(); 701 input_subsystem->GetGCAnalogs()->EndConfiguration();
700 702
701 if (!abort) { 703 if (!abort) {
702 (*input_setter)(params); 704 (*input_setter)(params);
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index 25d4cde5e..a25bc3bd9 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -10,12 +10,11 @@
10#include <optional> 10#include <optional>
11#include <string> 11#include <string>
12 12
13#include <QDialog> 13#include <QWidget>
14 14
15#include "common/param_package.h" 15#include "common/param_package.h"
16#include "core/settings.h" 16#include "core/settings.h"
17#include "ui_configure_input.h" 17#include "ui_configure_input.h"
18#include "yuzu/uisettings.h"
19 18
20class QCheckBox; 19class QCheckBox;
21class QKeyEvent; 20class QKeyEvent;
@@ -27,6 +26,10 @@ class QString;
27class QTimer; 26class QTimer;
28class QWidget; 27class QWidget;
29 28
29namespace InputCommon {
30class InputSubsystem;
31}
32
30namespace InputCommon::Polling { 33namespace InputCommon::Polling {
31class DevicePoller; 34class DevicePoller;
32enum class DeviceType; 35enum class DeviceType;
@@ -41,6 +44,7 @@ class ConfigureInputPlayer : public QWidget {
41 44
42public: 45public:
43 explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, 46 explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row,
47 InputCommon::InputSubsystem* input_subsystem_,
44 bool debug = false); 48 bool debug = false);
45 ~ConfigureInputPlayer() override; 49 ~ConfigureInputPlayer() override;
46 50
@@ -111,6 +115,8 @@ private:
111 std::size_t player_index; 115 std::size_t player_index;
112 bool debug; 116 bool debug;
113 117
118 InputCommon::InputSubsystem* input_subsystem;
119
114 std::unique_ptr<QTimer> timeout_timer; 120 std::unique_ptr<QTimer> timeout_timer;
115 std::unique_ptr<QTimer> poll_timer; 121 std::unique_ptr<QTimer> poll_timer;
116 122
diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp
index dcda8ab14..2af3afda8 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.cpp
+++ b/src/yuzu/configuration/configure_mouse_advanced.cpp
@@ -76,8 +76,10 @@ static QString ButtonToText(const Common::ParamPackage& param) {
76 return QObject::tr("[unknown]"); 76 return QObject::tr("[unknown]");
77} 77}
78 78
79ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) 79ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
80 : QDialog(parent), ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), 80 InputCommon::InputSubsystem* input_subsystem_)
81 : QDialog(parent),
82 ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_},
81 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { 83 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
82 ui->setupUi(this); 84 ui->setupUi(this);
83 setFocusPolicy(Qt::ClickFocus); 85 setFocusPolicy(Qt::ClickFocus);
@@ -209,7 +211,7 @@ void ConfigureMouseAdvanced::HandleClick(
209 211
210 input_setter = new_input_setter; 212 input_setter = new_input_setter;
211 213
212 device_pollers = InputCommon::Polling::GetPollers(type); 214 device_pollers = input_subsystem->GetPollers(type);
213 215
214 for (auto& poller : device_pollers) { 216 for (auto& poller : device_pollers) {
215 poller->Start(); 217 poller->Start();
diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h
index e7d27dab7..65b6fca9a 100644
--- a/src/yuzu/configuration/configure_mouse_advanced.h
+++ b/src/yuzu/configuration/configure_mouse_advanced.h
@@ -8,12 +8,14 @@
8#include <optional> 8#include <optional>
9#include <QDialog> 9#include <QDialog>
10 10
11#include "core/settings.h"
12
13class QCheckBox; 11class QCheckBox;
14class QPushButton; 12class QPushButton;
15class QTimer; 13class QTimer;
16 14
15namespace InputCommon {
16class InputSubsystem;
17}
18
17namespace Ui { 19namespace Ui {
18class ConfigureMouseAdvanced; 20class ConfigureMouseAdvanced;
19} 21}
@@ -22,7 +24,7 @@ class ConfigureMouseAdvanced : public QDialog {
22 Q_OBJECT 24 Q_OBJECT
23 25
24public: 26public:
25 explicit ConfigureMouseAdvanced(QWidget* parent); 27 explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_);
26 ~ConfigureMouseAdvanced() override; 28 ~ConfigureMouseAdvanced() override;
27 29
28 void ApplyConfiguration(); 30 void ApplyConfiguration();
@@ -57,6 +59,8 @@ private:
57 59
58 std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; 60 std::unique_ptr<Ui::ConfigureMouseAdvanced> ui;
59 61
62 InputCommon::InputSubsystem* input_subsystem;
63
60 /// This will be the the setting function when an input is awaiting configuration. 64 /// This will be the the setting function when an input is awaiting configuration.
61 std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; 65 std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
62 66
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index cd7e78eb4..cab9d680a 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -94,6 +94,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
94#include "core/perf_stats.h" 94#include "core/perf_stats.h"
95#include "core/settings.h" 95#include "core/settings.h"
96#include "core/telemetry_session.h" 96#include "core/telemetry_session.h"
97#include "input_common/main.h"
97#include "video_core/gpu.h" 98#include "video_core/gpu.h"
98#include "video_core/shader_notify.h" 99#include "video_core/shader_notify.h"
99#include "yuzu/about_dialog.h" 100#include "yuzu/about_dialog.h"
@@ -186,9 +187,9 @@ static void InitializeLogging() {
186} 187}
187 188
188GMainWindow::GMainWindow() 189GMainWindow::GMainWindow()
189 : config(new Config()), emu_thread(nullptr), 190 : input_subsystem{std::make_unique<InputCommon::InputSubsystem>()},
190 vfs(std::make_shared<FileSys::RealVfsFilesystem>()), 191 config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
191 provider(std::make_unique<FileSys::ManualContentProvider>()) { 192 provider{std::make_unique<FileSys::ManualContentProvider>()} {
192 InitializeLogging(); 193 InitializeLogging();
193 194
194 LoadTranslation(); 195 LoadTranslation();
@@ -473,7 +474,7 @@ void GMainWindow::InitializeWidgets() {
473#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING 474#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
474 ui.action_Report_Compatibility->setVisible(true); 475 ui.action_Report_Compatibility->setVisible(true);
475#endif 476#endif
476 render_window = new GRenderWindow(this, emu_thread.get()); 477 render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem.get());
477 render_window->hide(); 478 render_window->hide();
478 479
479 game_list = new GameList(vfs, provider.get(), this); 480 game_list = new GameList(vfs, provider.get(), this);
@@ -2213,7 +2214,7 @@ void GMainWindow::OnConfigure() {
2213 const auto old_theme = UISettings::values.theme; 2214 const auto old_theme = UISettings::values.theme;
2214 const bool old_discord_presence = UISettings::values.enable_discord_presence; 2215 const bool old_discord_presence = UISettings::values.enable_discord_presence;
2215 2216
2216 ConfigureDialog configure_dialog(this, hotkey_registry); 2217 ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get());
2217 connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, 2218 connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
2218 &GMainWindow::OnLanguageChanged); 2219 &GMainWindow::OnLanguageChanged);
2219 2220
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 01f9131e5..957f20fa8 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -40,12 +40,20 @@ namespace Core::Frontend {
40struct SoftwareKeyboardParameters; 40struct SoftwareKeyboardParameters;
41} // namespace Core::Frontend 41} // namespace Core::Frontend
42 42
43namespace DiscordRPC {
44class DiscordInterface;
45}
46
43namespace FileSys { 47namespace FileSys {
44class ContentProvider; 48class ContentProvider;
45class ManualContentProvider; 49class ManualContentProvider;
46class VfsFilesystem; 50class VfsFilesystem;
47} // namespace FileSys 51} // namespace FileSys
48 52
53namespace InputCommon {
54class InputSubsystem;
55}
56
49enum class EmulatedDirectoryTarget { 57enum class EmulatedDirectoryTarget {
50 NAND, 58 NAND,
51 SDMC, 59 SDMC,
@@ -62,10 +70,6 @@ enum class ReinitializeKeyBehavior {
62 Warning, 70 Warning,
63}; 71};
64 72
65namespace DiscordRPC {
66class DiscordInterface;
67}
68
69class GMainWindow : public QMainWindow { 73class GMainWindow : public QMainWindow {
70 Q_OBJECT 74 Q_OBJECT
71 75
@@ -86,8 +90,6 @@ public:
86 GMainWindow(); 90 GMainWindow();
87 ~GMainWindow() override; 91 ~GMainWindow() override;
88 92
89 std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc;
90
91 bool DropAction(QDropEvent* event); 93 bool DropAction(QDropEvent* event);
92 void AcceptDropEvent(QDropEvent* event); 94 void AcceptDropEvent(QDropEvent* event);
93 95
@@ -255,6 +257,9 @@ private:
255 257
256 Ui::MainWindow ui; 258 Ui::MainWindow ui;
257 259
260 std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc;
261 std::unique_ptr<InputCommon::InputSubsystem> input_subsystem;
262
258 GRenderWindow* render_window; 263 GRenderWindow* render_window;
259 GameList* game_list; 264 GameList* game_list;
260 LoadingScreen* loading_screen; 265 LoadingScreen* loading_screen;
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index e5e684206..a804d5185 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -13,23 +13,25 @@
13#include "input_common/sdl/sdl.h" 13#include "input_common/sdl/sdl.h"
14#include "yuzu_cmd/emu_window/emu_window_sdl2.h" 14#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
15 15
16EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen) : system{system} { 16EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen,
17 InputCommon::InputSubsystem* input_subsystem_)
18 : system{system}, input_subsystem{input_subsystem_} {
17 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { 19 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
18 LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); 20 LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
19 exit(1); 21 exit(1);
20 } 22 }
21 InputCommon::Init(); 23 input_subsystem->Initialize();
22 SDL_SetMainReady(); 24 SDL_SetMainReady();
23} 25}
24 26
25EmuWindow_SDL2::~EmuWindow_SDL2() { 27EmuWindow_SDL2::~EmuWindow_SDL2() {
26 InputCommon::Shutdown(); 28 input_subsystem->Shutdown();
27 SDL_Quit(); 29 SDL_Quit();
28} 30}
29 31
30void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { 32void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
31 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); 33 TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
32 InputCommon::GetMotionEmu()->Tilt(x, y); 34 input_subsystem->GetMotionEmu()->Tilt(x, y);
33} 35}
34 36
35void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { 37void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
@@ -41,9 +43,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
41 } 43 }
42 } else if (button == SDL_BUTTON_RIGHT) { 44 } else if (button == SDL_BUTTON_RIGHT) {
43 if (state == SDL_PRESSED) { 45 if (state == SDL_PRESSED) {
44 InputCommon::GetMotionEmu()->BeginTilt(x, y); 46 input_subsystem->GetMotionEmu()->BeginTilt(x, y);
45 } else { 47 } else {
46 InputCommon::GetMotionEmu()->EndTilt(); 48 input_subsystem->GetMotionEmu()->EndTilt();
47 } 49 }
48 } 50 }
49} 51}
@@ -79,9 +81,9 @@ void EmuWindow_SDL2::OnFingerUp() {
79 81
80void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { 82void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
81 if (state == SDL_PRESSED) { 83 if (state == SDL_PRESSED) {
82 InputCommon::GetKeyboard()->PressKey(key); 84 input_subsystem->GetKeyboard()->PressKey(key);
83 } else if (state == SDL_RELEASED) { 85 } else if (state == SDL_RELEASED) {
84 InputCommon::GetKeyboard()->ReleaseKey(key); 86 input_subsystem->GetKeyboard()->ReleaseKey(key);
85 } 87 }
86} 88}
87 89
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index fffac4252..82750ffec 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -14,9 +14,14 @@ namespace Core {
14class System; 14class System;
15} 15}
16 16
17namespace InputCommon {
18class InputSubsystem;
19}
20
17class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { 21class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
18public: 22public:
19 explicit EmuWindow_SDL2(Core::System& system, bool fullscreen); 23 explicit EmuWindow_SDL2(Core::System& system, bool fullscreen,
24 InputCommon::InputSubsystem* input_subsystem);
20 ~EmuWindow_SDL2(); 25 ~EmuWindow_SDL2();
21 26
22 /// Polls window events 27 /// Polls window events
@@ -76,4 +81,7 @@ protected:
76 81
77 /// Keeps track of how often to update the title bar during gameplay 82 /// Keeps track of how often to update the title bar during gameplay
78 u32 last_time = 0; 83 u32 last_time = 0;
84
85 /// Input subsystem to use with this window.
86 InputCommon::InputSubsystem* input_subsystem;
79}; 87};
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index e78025737..881b67a76 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -87,8 +87,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
87 return unsupported_ext.empty(); 87 return unsupported_ext.empty();
88} 88}
89 89
90EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen) 90EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen,
91 : EmuWindow_SDL2{system, fullscreen} { 91 InputCommon::InputSubsystem* input_subsystem)
92 : EmuWindow_SDL2{system, fullscreen, input_subsystem} {
92 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 93 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
93 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 94 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
94 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); 95 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
index 48bb41683..732a64edd 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
@@ -8,9 +8,14 @@
8#include "core/frontend/emu_window.h" 8#include "core/frontend/emu_window.h"
9#include "yuzu_cmd/emu_window/emu_window_sdl2.h" 9#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
10 10
11namespace InputCommon {
12class InputSubsystem;
13}
14
11class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { 15class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 {
12public: 16public:
13 explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen); 17 explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen,
18 InputCommon::InputSubsystem* input_subsystem);
14 ~EmuWindow_SDL2_GL(); 19 ~EmuWindow_SDL2_GL();
15 20
16 void Present() override; 21 void Present() override;
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index cb8e68a39..53491f86e 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -19,8 +19,9 @@
19#include <SDL.h> 19#include <SDL.h>
20#include <SDL_syswm.h> 20#include <SDL_syswm.h>
21 21
22EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen) 22EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen,
23 : EmuWindow_SDL2{system, fullscreen} { 23 InputCommon::InputSubsystem* input_subsystem)
24 : EmuWindow_SDL2{system, fullscreen, input_subsystem} {
24 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, 25 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name,
25 Common::g_scm_branch, Common::g_scm_desc); 26 Common::g_scm_branch, Common::g_scm_desc);
26 render_window = 27 render_window =
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
index 77a6ca72b..f99704d4c 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
@@ -13,9 +13,14 @@ namespace Core {
13class System; 13class System;
14} 14}
15 15
16namespace InputCommon {
17class InputSubsystem;
18}
19
16class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { 20class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 {
17public: 21public:
18 explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen); 22 explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen,
23 InputCommon::InputSubsystem* input_subsystem);
19 ~EmuWindow_SDL2_VK(); 24 ~EmuWindow_SDL2_VK();
20 25
21 void Present() override; 26 void Present() override;
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 8efe49390..4f00c804d 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -23,12 +23,14 @@
23#include "common/telemetry.h" 23#include "common/telemetry.h"
24#include "core/core.h" 24#include "core/core.h"
25#include "core/crypto/key_manager.h" 25#include "core/crypto/key_manager.h"
26#include "core/file_sys/registered_cache.h"
26#include "core/file_sys/vfs_real.h" 27#include "core/file_sys/vfs_real.h"
27#include "core/gdbstub/gdbstub.h" 28#include "core/gdbstub/gdbstub.h"
28#include "core/hle/service/filesystem/filesystem.h" 29#include "core/hle/service/filesystem/filesystem.h"
29#include "core/loader/loader.h" 30#include "core/loader/loader.h"
30#include "core/settings.h" 31#include "core/settings.h"
31#include "core/telemetry_session.h" 32#include "core/telemetry_session.h"
33#include "input_common/main.h"
32#include "video_core/renderer_base.h" 34#include "video_core/renderer_base.h"
33#include "yuzu_cmd/config.h" 35#include "yuzu_cmd/config.h"
34#include "yuzu_cmd/emu_window/emu_window_sdl2.h" 36#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
@@ -37,8 +39,6 @@
37#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" 39#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h"
38#endif 40#endif
39 41
40#include "core/file_sys/registered_cache.h"
41
42#ifdef _WIN32 42#ifdef _WIN32
43// windows.h needs to be included before shellapi.h 43// windows.h needs to be included before shellapi.h
44#include <windows.h> 44#include <windows.h>
@@ -179,15 +179,16 @@ int main(int argc, char** argv) {
179 Settings::Apply(); 179 Settings::Apply();
180 180
181 Core::System& system{Core::System::GetInstance()}; 181 Core::System& system{Core::System::GetInstance()};
182 InputCommon::InputSubsystem input_subsystem;
182 183
183 std::unique_ptr<EmuWindow_SDL2> emu_window; 184 std::unique_ptr<EmuWindow_SDL2> emu_window;
184 switch (Settings::values.renderer_backend.GetValue()) { 185 switch (Settings::values.renderer_backend.GetValue()) {
185 case Settings::RendererBackend::OpenGL: 186 case Settings::RendererBackend::OpenGL:
186 emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen); 187 emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, &input_subsystem);
187 break; 188 break;
188 case Settings::RendererBackend::Vulkan: 189 case Settings::RendererBackend::Vulkan:
189#ifdef HAS_VULKAN 190#ifdef HAS_VULKAN
190 emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen); 191 emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen, &input_subsystem);
191 break; 192 break;
192#else 193#else
193 LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!"); 194 LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!");
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
index 8584f6671..78f75fb38 100644
--- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
+++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp
@@ -13,7 +13,6 @@
13 13
14#include <glad/glad.h> 14#include <glad/glad.h>
15 15
16#include "common/assert.h"
17#include "common/logging/log.h" 16#include "common/logging/log.h"
18#include "common/scm_rev.h" 17#include "common/scm_rev.h"
19#include "core/settings.h" 18#include "core/settings.h"
@@ -53,7 +52,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() {
53 exit(1); 52 exit(1);
54 } 53 }
55 54
56 InputCommon::Init(); 55 input_subsystem->Initialize();
57 56
58 SDL_SetMainReady(); 57 SDL_SetMainReady();
59 58
@@ -105,7 +104,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() {
105} 104}
106 105
107EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { 106EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
108 InputCommon::Shutdown(); 107 input_subsystem->Shutdown();
109 SDL_GL_DeleteContext(gl_context); 108 SDL_GL_DeleteContext(gl_context);
110 SDL_Quit(); 109 SDL_Quit();
111} 110}
diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
index c13a82df2..a553b4b95 100644
--- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
+++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h
@@ -8,6 +8,10 @@
8 8
9struct SDL_Window; 9struct SDL_Window;
10 10
11namespace InputCommon {
12class InputSubsystem;
13}
14
11class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow { 15class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow {
12public: 16public:
13 explicit EmuWindow_SDL2_Hide(); 17 explicit EmuWindow_SDL2_Hide();
@@ -25,6 +29,8 @@ private:
25 /// Whether the GPU and driver supports the OpenGL extension required 29 /// Whether the GPU and driver supports the OpenGL extension required
26 bool SupportsRequiredGLExtensions(); 30 bool SupportsRequiredGLExtensions();
27 31
32 std::unique_ptr<InputCommon::InputSubsystem> input_subsystem;
33
28 /// Internal SDL2 render window 34 /// Internal SDL2 render window
29 SDL_Window* render_window; 35 SDL_Window* render_window;
30 36