Merge pull request #4544 from lioncash/input-sub

input_common: Eliminate most global state
This commit is contained in:
bunnei 2020-08-28 09:57:50 -04:00 committed by GitHub
commit 45b73ba840
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 397 additions and 243 deletions

View file

@ -18,66 +18,166 @@
namespace InputCommon { namespace InputCommon {
static std::shared_ptr<Keyboard> keyboard; struct InputSubsystem::Impl {
static std::shared_ptr<MotionEmu> motion_emu; void Initialize() {
#ifdef HAVE_SDL2 auto gcadapter = std::make_shared<GCAdapter::Adapter>();
static std::unique_ptr<SDL::State> sdl; gcbuttons = std::make_shared<GCButtonFactory>(gcadapter);
#endif Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
static std::unique_ptr<CemuhookUDP::State> udp; gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
static std::shared_ptr<GCButtonFactory> gcbuttons; Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
static std::shared_ptr<GCAnalogFactory> gcanalog;
void Init() { keyboard = std::make_shared<Keyboard>();
auto gcadapter = std::make_shared<GCAdapter::Adapter>(); Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
gcbuttons = std::make_shared<GCButtonFactory>(gcadapter); Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); std::make_shared<AnalogFromButton>());
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); motion_emu = std::make_shared<MotionEmu>();
Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
keyboard = std::make_shared<Keyboard>();
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
std::make_shared<AnalogFromButton>());
motion_emu = std::make_shared<MotionEmu>();
Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
sdl = SDL::Init(); sdl = SDL::Init();
#endif #endif
udp = CemuhookUDP::Init();
}
void Shutdown() { udp = CemuhookUDP::Init();
Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); }
keyboard.reset();
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); void Shutdown() {
Input::UnregisterFactory<Input::MotionDevice>("motion_emu"); Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
motion_emu.reset(); keyboard.reset();
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
motion_emu.reset();
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
sdl.reset(); sdl.reset();
#endif #endif
udp.reset(); udp.reset();
Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
gcbuttons.reset(); gcbuttons.reset();
gcanalog.reset(); gcanalog.reset();
}
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
std::vector<Common::ParamPackage> devices = {
Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
};
#ifdef HAVE_SDL2
auto sdl_devices = sdl->GetInputDevices();
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
#endif
auto udp_devices = udp->GetInputDevices();
devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
return devices;
}
[[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
const Common::ParamPackage& params) const {
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
#ifdef HAVE_SDL2
if (params.Get("class", "") == "sdl") {
return sdl->GetAnalogMappingForDevice(params);
}
#endif
return {};
}
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(
const Common::ParamPackage& params) const {
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
#ifdef HAVE_SDL2
if (params.Get("class", "") == "sdl") {
return sdl->GetButtonMappingForDevice(params);
}
#endif
return {};
}
std::shared_ptr<Keyboard> keyboard;
std::shared_ptr<MotionEmu> motion_emu;
#ifdef HAVE_SDL2
std::unique_ptr<SDL::State> sdl;
#endif
std::unique_ptr<CemuhookUDP::State> udp;
std::shared_ptr<GCButtonFactory> gcbuttons;
std::shared_ptr<GCAnalogFactory> gcanalog;
};
InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
InputSubsystem::~InputSubsystem() = default;
void InputSubsystem::Initialize() {
impl->Initialize();
} }
Keyboard* GetKeyboard() { void InputSubsystem::Shutdown() {
return keyboard.get(); impl->Shutdown();
} }
MotionEmu* GetMotionEmu() { Keyboard* InputSubsystem::GetKeyboard() {
return motion_emu.get(); return impl->keyboard.get();
} }
GCButtonFactory* GetGCButtons() { const Keyboard* InputSubsystem::GetKeyboard() const {
return gcbuttons.get(); return impl->keyboard.get();
} }
GCAnalogFactory* GetGCAnalogs() { MotionEmu* InputSubsystem::GetMotionEmu() {
return gcanalog.get(); return impl->motion_emu.get();
}
const MotionEmu* InputSubsystem::GetMotionEmu() const {
return impl->motion_emu.get();
}
std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
return impl->GetInputDevices();
}
AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const {
return impl->GetAnalogMappingForDevice(device);
}
ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const {
return impl->GetButtonMappingForDevice(device);
}
GCAnalogFactory* InputSubsystem::GetGCAnalogs() {
return impl->gcanalog.get();
}
const GCAnalogFactory* InputSubsystem::GetGCAnalogs() const {
return impl->gcanalog.get();
}
GCButtonFactory* InputSubsystem::GetGCButtons() {
return impl->gcbuttons.get();
}
const GCButtonFactory* InputSubsystem::GetGCButtons() const {
return impl->gcbuttons.get();
}
std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers(
Polling::DeviceType type) const {
#ifdef HAVE_SDL2
return impl->sdl->GetPollers(type);
#else
return {};
#endif
} }
std::string GenerateKeyboardParam(int key_code) { std::string GenerateKeyboardParam(int key_code) {
@ -101,68 +201,4 @@ std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left,
}; };
return circle_pad_param.Serialize(); return circle_pad_param.Serialize();
} }
std::vector<Common::ParamPackage> GetInputDevices() {
std::vector<Common::ParamPackage> devices = {
Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
};
#ifdef HAVE_SDL2
auto sdl_devices = sdl->GetInputDevices();
devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
#endif
auto udp_devices = udp->GetInputDevices();
devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
return devices;
}
std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> GetButtonMappingForDevice(
const Common::ParamPackage& params) {
std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage> mappings;
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
#ifdef HAVE_SDL2
if (params.Get("class", "") == "sdl") {
return sdl->GetButtonMappingForDevice(params);
}
#endif
return {};
}
std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> GetAnalogMappingForDevice(
const Common::ParamPackage& params) {
std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage> mappings;
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
#ifdef HAVE_SDL2
if (params.Get("class", "") == "sdl") {
return sdl->GetAnalogMappingForDevice(params);
}
#endif
return {};
}
namespace Polling {
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type) {
std::vector<std::unique_ptr<DevicePoller>> pollers;
#ifdef HAVE_SDL2
pollers = sdl->GetPollers(type);
#endif
return pollers;
}
} // namespace Polling
} // namespace InputCommon } // namespace InputCommon

View file

@ -16,52 +16,6 @@ class ParamPackage;
} }
namespace InputCommon { namespace InputCommon {
/// Initializes and registers all built-in input device factories.
void Init();
/// Deregisters all built-in input device factories and shuts them down.
void Shutdown();
class Keyboard;
/// Gets the keyboard button device factory.
Keyboard* GetKeyboard();
class MotionEmu;
/// Gets the motion emulation factory.
MotionEmu* GetMotionEmu();
GCButtonFactory* GetGCButtons();
GCAnalogFactory* GetGCAnalogs();
/// Generates a serialized param package for creating a keyboard button device
std::string GenerateKeyboardParam(int key_code);
/// Generates a serialized param package for creating an analog device taking input from keyboard
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
int key_modifier, float modifier_scale);
/**
* Return a list of available input devices that this Factory can create a new device with.
* Each returned Parampackage should have a `display` field used for display, a class field for
* backends to determine if this backend is meant to service the request and any other information
* needed to identify this in the backend later.
*/
std::vector<Common::ParamPackage> GetInputDevices();
/**
* Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
* mapping for the device. This is currently only implemented for the sdl backend devices.
*/
using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage&);
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&);
namespace Polling { namespace Polling {
enum class DeviceType { Button, AnalogPreferred }; enum class DeviceType { Button, AnalogPreferred };
@ -90,4 +44,88 @@ public:
// Get all DevicePoller from all backends for a specific device type // Get all DevicePoller from all backends for a specific device type
std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type); std::vector<std::unique_ptr<DevicePoller>> GetPollers(DeviceType type);
} // namespace Polling } // namespace Polling
class GCAnalogFactory;
class GCButtonFactory;
class Keyboard;
class MotionEmu;
/**
* Given a ParamPackage for a Device returned from `GetInputDevices`, attempt to get the default
* mapping for the device. This is currently only implemented for the SDL backend devices.
*/
using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
class InputSubsystem {
public:
explicit InputSubsystem();
~InputSubsystem();
InputSubsystem(const InputSubsystem&) = delete;
InputSubsystem& operator=(const InputSubsystem&) = delete;
InputSubsystem(InputSubsystem&&) = delete;
InputSubsystem& operator=(InputSubsystem&&) = delete;
/// Initializes and registers all built-in input device factories.
void Initialize();
/// Unregisters all built-in input device factories and shuts them down.
void Shutdown();
/// Retrieves the underlying keyboard device.
[[nodiscard]] Keyboard* GetKeyboard();
/// Retrieves the underlying keyboard device.
[[nodiscard]] const Keyboard* GetKeyboard() const;
/// Retrieves the underlying motion emulation factory.
[[nodiscard]] MotionEmu* GetMotionEmu();
/// Retrieves the underlying motion emulation factory.
[[nodiscard]] const MotionEmu* GetMotionEmu() const;
/**
* Returns all available input devices that this Factory can create a new device with.
* Each returned ParamPackage should have a `display` field used for display, a class field for
* backends to determine if this backend is meant to service the request and any other
* information needed to identify this in the backend later.
*/
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const;
/// Retrieves the analog mappings for the given device.
[[nodiscard]] AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& device) const;
/// Retrieves the button mappings for the given device.
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& device) const;
/// Retrieves the underlying GameCube analog handler.
[[nodiscard]] GCAnalogFactory* GetGCAnalogs();
/// Retrieves the underlying GameCube analog handler.
[[nodiscard]] const GCAnalogFactory* GetGCAnalogs() const;
/// Retrieves the underlying GameCube button handler.
[[nodiscard]] GCButtonFactory* GetGCButtons();
/// Retrieves the underlying GameCube button handler.
[[nodiscard]] const GCButtonFactory* GetGCButtons() const;
/// Get all DevicePoller from all backends for a specific device type
[[nodiscard]] std::vector<std::unique_ptr<Polling::DevicePoller>> GetPollers(
Polling::DeviceType type) const;
private:
struct Impl;
std::unique_ptr<Impl> impl;
};
/// Generates a serialized param package for creating a keyboard button device
std::string GenerateKeyboardParam(int key_code);
/// Generates a serialized param package for creating an analog device taking input from keyboard
std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
int key_modifier, float modifier_scale);
} // namespace InputCommon } // namespace InputCommon

View file

@ -304,8 +304,9 @@ static Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow*
return wsi; return wsi;
} }
GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_) GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
: QWidget(parent_), emu_thread(emu_thread_) { InputCommon::InputSubsystem* input_subsystem_)
: QWidget(parent), emu_thread(emu_thread_), input_subsystem{input_subsystem_} {
setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") setWindowTitle(QStringLiteral("yuzu %1 | %2-%3")
.arg(QString::fromUtf8(Common::g_build_name), .arg(QString::fromUtf8(Common::g_build_name),
QString::fromUtf8(Common::g_scm_branch), QString::fromUtf8(Common::g_scm_branch),
@ -314,15 +315,15 @@ GRenderWindow::GRenderWindow(GMainWindow* parent_, EmuThread* emu_thread_)
auto layout = new QHBoxLayout(this); auto layout = new QHBoxLayout(this);
layout->setMargin(0); layout->setMargin(0);
setLayout(layout); setLayout(layout);
InputCommon::Init(); input_subsystem->Initialize();
this->setMouseTracking(true); this->setMouseTracking(true);
connect(this, &GRenderWindow::FirstFrameDisplayed, parent_, &GMainWindow::OnLoadComplete); connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
} }
GRenderWindow::~GRenderWindow() { GRenderWindow::~GRenderWindow() {
InputCommon::Shutdown(); input_subsystem->Shutdown();
} }
void GRenderWindow::PollEvents() { void GRenderWindow::PollEvents() {
@ -391,11 +392,11 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
} }
void GRenderWindow::keyPressEvent(QKeyEvent* event) { void GRenderWindow::keyPressEvent(QKeyEvent* event) {
InputCommon::GetKeyboard()->PressKey(event->key()); input_subsystem->GetKeyboard()->PressKey(event->key());
} }
void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
InputCommon::GetKeyboard()->ReleaseKey(event->key()); input_subsystem->GetKeyboard()->ReleaseKey(event->key());
} }
void GRenderWindow::mousePressEvent(QMouseEvent* event) { void GRenderWindow::mousePressEvent(QMouseEvent* event) {
@ -409,7 +410,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
const auto [x, y] = ScaleTouch(pos); const auto [x, y] = ScaleTouch(pos);
this->TouchPressed(x, y); this->TouchPressed(x, y);
} else if (event->button() == Qt::RightButton) { } else if (event->button() == Qt::RightButton) {
InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y()); input_subsystem->GetMotionEmu()->BeginTilt(pos.x(), pos.y());
} }
QWidget::mousePressEvent(event); QWidget::mousePressEvent(event);
} }
@ -423,7 +424,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
auto pos = event->pos(); auto pos = event->pos();
const auto [x, y] = ScaleTouch(pos); const auto [x, y] = ScaleTouch(pos);
this->TouchMoved(x, y); this->TouchMoved(x, y);
InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y()); input_subsystem->GetMotionEmu()->Tilt(pos.x(), pos.y());
QWidget::mouseMoveEvent(event); QWidget::mouseMoveEvent(event);
} }
@ -436,7 +437,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
this->TouchReleased(); this->TouchReleased();
} else if (event->button() == Qt::RightButton) { } else if (event->button() == Qt::RightButton) {
InputCommon::GetMotionEmu()->EndTilt(); input_subsystem->GetMotionEmu()->EndTilt();
} }
} }
@ -485,7 +486,7 @@ bool GRenderWindow::event(QEvent* event) {
void GRenderWindow::focusOutEvent(QFocusEvent* event) { void GRenderWindow::focusOutEvent(QFocusEvent* event) {
QWidget::focusOutEvent(event); QWidget::focusOutEvent(event);
InputCommon::GetKeyboard()->ReleaseAllKeys(); input_subsystem->GetKeyboard()->ReleaseAllKeys();
} }
void GRenderWindow::resizeEvent(QResizeEvent* event) { void GRenderWindow::resizeEvent(QResizeEvent* event) {

View file

@ -23,6 +23,10 @@ class QKeyEvent;
class QTouchEvent; class QTouchEvent;
class QStringList; class QStringList;
namespace InputCommon {
class InputSubsystem;
}
namespace VideoCore { namespace VideoCore {
enum class LoadCallbackStage; enum class LoadCallbackStage;
} }
@ -121,7 +125,8 @@ class GRenderWindow : public QWidget, public Core::Frontend::EmuWindow {
Q_OBJECT Q_OBJECT
public: public:
GRenderWindow(GMainWindow* parent, EmuThread* emu_thread); explicit GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
InputCommon::InputSubsystem* input_subsystem_);
~GRenderWindow() override; ~GRenderWindow() override;
// EmuWindow implementation. // EmuWindow implementation.
@ -183,6 +188,7 @@ private:
QStringList GetUnsupportedGLExtensions() const; QStringList GetUnsupportedGLExtensions() const;
EmuThread* emu_thread; EmuThread* emu_thread;
InputCommon::InputSubsystem* input_subsystem;
// Main context that will be shared with all other contexts that are requested. // Main context that will be shared with all other contexts that are requested.
// If this is used in a shared context setting, then this should not be used directly, but // If this is used in a shared context setting, then this should not be used directly, but

View file

@ -5,9 +5,10 @@
#include "ui_configure_debug_controller.h" #include "ui_configure_debug_controller.h"
#include "yuzu/configuration/configure_debug_controller.h" #include "yuzu/configuration/configure_debug_controller.h"
ConfigureDebugController::ConfigureDebugController(QWidget* parent) ConfigureDebugController::ConfigureDebugController(QWidget* parent,
InputCommon::InputSubsystem* input_subsystem)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
debug_controller(new ConfigureInputPlayer(this, 9, nullptr, true)) { debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) {
ui->setupUi(this); ui->setupUi(this);
ui->controllerLayout->addWidget(debug_controller); ui->controllerLayout->addWidget(debug_controller);

View file

@ -10,6 +10,10 @@
class QPushButton; class QPushButton;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui { namespace Ui {
class ConfigureDebugController; class ConfigureDebugController;
} }
@ -18,7 +22,8 @@ class ConfigureDebugController : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureDebugController(QWidget* parent); explicit ConfigureDebugController(QWidget* parent,
InputCommon::InputSubsystem* input_subsystem);
~ConfigureDebugController() override; ~ConfigureDebugController() override;
void ApplyConfiguration(); void ApplyConfiguration();

View file

@ -12,7 +12,8 @@
#include "yuzu/configuration/configure_input_player.h" #include "yuzu/configuration/configure_input_player.h"
#include "yuzu/hotkeys.h" #include "yuzu/hotkeys.h"
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
InputCommon::InputSubsystem* input_subsystem)
: QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) {
Settings::configuring_global = true; Settings::configuring_global = true;
@ -20,6 +21,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
ui->hotkeysTab->Populate(registry); ui->hotkeysTab->Populate(registry);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
ui->inputTab->Initialize(input_subsystem);
SetConfiguration(); SetConfiguration();
PopulateSelectionList(); PopulateSelectionList();

View file

@ -9,6 +9,10 @@
class HotkeyRegistry; class HotkeyRegistry;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui { namespace Ui {
class ConfigureDialog; class ConfigureDialog;
} }
@ -17,7 +21,8 @@ class ConfigureDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
InputCommon::InputSubsystem* input_subsystem);
~ConfigureDialog() override; ~ConfigureDialog() override;
void ApplyConfiguration(); void ApplyConfiguration();

View file

@ -65,16 +65,20 @@ void OnDockedModeChanged(bool last_state, bool new_state) {
ConfigureInput::ConfigureInput(QWidget* parent) ConfigureInput::ConfigureInput(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
ui->setupUi(this); ui->setupUi(this);
}
ConfigureInput::~ConfigureInput() = default;
void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem) {
player_controllers = { player_controllers = {
new ConfigureInputPlayer(this, 0, ui->consoleInputSettings), new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 1, ui->consoleInputSettings), new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 2, ui->consoleInputSettings), new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 3, ui->consoleInputSettings), new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 4, ui->consoleInputSettings), new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 5, ui->consoleInputSettings), new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 6, ui->consoleInputSettings), new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 7, ui->consoleInputSettings), new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem),
}; };
player_tabs = { player_tabs = {
@ -115,10 +119,12 @@ ConfigureInput::ConfigureInput(QWidget* parent)
advanced = new ConfigureInputAdvanced(this); advanced = new ConfigureInputAdvanced(this);
ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
ui->tabAdvanced->layout()->addWidget(advanced); ui->tabAdvanced->layout()->addWidget(advanced);
connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] {
[this] { CallConfigureDialog<ConfigureDebugController>(*this); }); CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem);
connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, });
[this] { CallConfigureDialog<ConfigureMouseAdvanced>(*this); }); connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
});
connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog, connect(advanced, &ConfigureInputAdvanced::CallTouchscreenConfigDialog,
[this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); });
@ -129,8 +135,6 @@ ConfigureInput::ConfigureInput(QWidget* parent)
LoadConfiguration(); LoadConfiguration();
} }
ConfigureInput::~ConfigureInput() = default;
QList<QWidget*> ConfigureInput::GetSubTabs() const { QList<QWidget*> ConfigureInput::GetSubTabs() const {
return { return {
ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5, ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5,

View file

@ -7,8 +7,8 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <QDialog>
#include <QKeyEvent> #include <QKeyEvent>
#include <QWidget>
#include "yuzu/configuration/configure_input_advanced.h" #include "yuzu/configuration/configure_input_advanced.h"
#include "yuzu/configuration/configure_input_player.h" #include "yuzu/configuration/configure_input_player.h"
@ -19,6 +19,10 @@ class QCheckBox;
class QString; class QString;
class QTimer; class QTimer;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui { namespace Ui {
class ConfigureInput; class ConfigureInput;
} }
@ -32,6 +36,9 @@ public:
explicit ConfigureInput(QWidget* parent = nullptr); explicit ConfigureInput(QWidget* parent = nullptr);
~ConfigureInput() override; ~ConfigureInput() override;
/// Initializes the input dialog with the given input subsystem.
void Initialize(InputCommon::InputSubsystem* input_subsystem_);
/// Save all button configurations to settings file. /// Save all button configurations to settings file.
void ApplyConfiguration(); void ApplyConfiguration();

View file

@ -11,12 +11,12 @@
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include <QTimer> #include <QTimer>
#include "common/assert.h"
#include "common/param_package.h" #include "common/param_package.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/hid/controllers/npad.h" #include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/hid.h" #include "core/hle/service/hid/hid.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#include "input_common/gcadapter/gc_poller.h"
#include "input_common/main.h" #include "input_common/main.h"
#include "ui_configure_input_player.h" #include "ui_configure_input_player.h"
#include "yuzu/configuration/config.h" #include "yuzu/configuration/config.h"
@ -229,9 +229,11 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
} // namespace } // namespace
ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
QWidget* bottom_row, bool debug) QWidget* bottom_row,
InputCommon::InputSubsystem* input_subsystem_,
bool debug)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index),
debug(debug), timeout_timer(std::make_unique<QTimer>()), debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()),
poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) {
ui->setupUi(this); ui->setupUi(this);
@ -287,7 +289,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
params.Set("direction", "+"); params.Set("direction", "+");
params.Set("threshold", "0.5"); params.Set("threshold", "0.5");
} }
(*param) = std::move(params); *param = std::move(params);
}, },
InputCommon::Polling::DeviceType::Button); InputCommon::Polling::DeviceType::Button);
}); });
@ -401,15 +403,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
connect(poll_timer.get(), &QTimer::timeout, [this] { connect(poll_timer.get(), &QTimer::timeout, [this] {
Common::ParamPackage params; Common::ParamPackage params;
if (InputCommon::GetGCButtons()->IsPolling()) { if (input_subsystem->GetGCButtons()->IsPolling()) {
params = InputCommon::GetGCButtons()->GetNextInput(); params = input_subsystem->GetGCButtons()->GetNextInput();
if (params.Has("engine")) { if (params.Has("engine")) {
SetPollingResult(params, false); SetPollingResult(params, false);
return; return;
} }
} }
if (InputCommon::GetGCAnalogs()->IsPolling()) { if (input_subsystem->GetGCAnalogs()->IsPolling()) {
params = InputCommon::GetGCAnalogs()->GetNextInput(); params = input_subsystem->GetGCAnalogs()->GetNextInput();
if (params.Has("engine")) { if (params.Has("engine")) {
SetPollingResult(params, false); SetPollingResult(params, false);
return; return;
@ -514,7 +516,7 @@ void ConfigureInputPlayer::LoadConfiguration() {
} }
void ConfigureInputPlayer::UpdateInputDevices() { void ConfigureInputPlayer::UpdateInputDevices() {
input_devices = InputCommon::GetInputDevices(); input_devices = input_subsystem->GetInputDevices();
ui->comboDevices->clear(); ui->comboDevices->clear();
for (auto device : input_devices) { for (auto device : input_devices) {
ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
@ -642,8 +644,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
return; return;
} }
const auto& device = input_devices[ui->comboDevices->currentIndex()]; const auto& device = input_devices[ui->comboDevices->currentIndex()];
auto button_mapping = InputCommon::GetButtonMappingForDevice(device); auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
auto analog_mapping = InputCommon::GetAnalogMappingForDevice(device); auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
for (int i = 0; i < buttons_param.size(); ++i) { for (int i = 0; i < buttons_param.size(); ++i) {
buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
} }
@ -666,7 +668,7 @@ void ConfigureInputPlayer::HandleClick(
input_setter = new_input_setter; input_setter = new_input_setter;
device_pollers = InputCommon::Polling::GetPollers(type); device_pollers = input_subsystem->GetPollers(type);
for (auto& poller : device_pollers) { for (auto& poller : device_pollers) {
poller->Start(); poller->Start();
@ -676,9 +678,9 @@ void ConfigureInputPlayer::HandleClick(
QWidget::grabKeyboard(); QWidget::grabKeyboard();
if (type == InputCommon::Polling::DeviceType::Button) { if (type == InputCommon::Polling::DeviceType::Button) {
InputCommon::GetGCButtons()->BeginConfiguration(); input_subsystem->GetGCButtons()->BeginConfiguration();
} else { } else {
InputCommon::GetGCAnalogs()->BeginConfiguration(); input_subsystem->GetGCAnalogs()->BeginConfiguration();
} }
timeout_timer->start(2500); // Cancel after 2.5 seconds timeout_timer->start(2500); // Cancel after 2.5 seconds
@ -695,8 +697,8 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
QWidget::releaseMouse(); QWidget::releaseMouse();
QWidget::releaseKeyboard(); QWidget::releaseKeyboard();
InputCommon::GetGCButtons()->EndConfiguration(); input_subsystem->GetGCButtons()->EndConfiguration();
InputCommon::GetGCAnalogs()->EndConfiguration(); input_subsystem->GetGCAnalogs()->EndConfiguration();
if (!abort) { if (!abort) {
(*input_setter)(params); (*input_setter)(params);

View file

@ -10,12 +10,11 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <QDialog> #include <QWidget>
#include "common/param_package.h" #include "common/param_package.h"
#include "core/settings.h" #include "core/settings.h"
#include "ui_configure_input.h" #include "ui_configure_input.h"
#include "yuzu/uisettings.h"
class QCheckBox; class QCheckBox;
class QKeyEvent; class QKeyEvent;
@ -27,6 +26,10 @@ class QString;
class QTimer; class QTimer;
class QWidget; class QWidget;
namespace InputCommon {
class InputSubsystem;
}
namespace InputCommon::Polling { namespace InputCommon::Polling {
class DevicePoller; class DevicePoller;
enum class DeviceType; enum class DeviceType;
@ -41,6 +44,7 @@ class ConfigureInputPlayer : public QWidget {
public: public:
explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row,
InputCommon::InputSubsystem* input_subsystem_,
bool debug = false); bool debug = false);
~ConfigureInputPlayer() override; ~ConfigureInputPlayer() override;
@ -111,6 +115,8 @@ private:
std::size_t player_index; std::size_t player_index;
bool debug; bool debug;
InputCommon::InputSubsystem* input_subsystem;
std::unique_ptr<QTimer> timeout_timer; std::unique_ptr<QTimer> timeout_timer;
std::unique_ptr<QTimer> poll_timer; std::unique_ptr<QTimer> poll_timer;

View file

@ -76,8 +76,10 @@ static QString ButtonToText(const Common::ParamPackage& param) {
return QObject::tr("[unknown]"); return QObject::tr("[unknown]");
} }
ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent,
: QDialog(parent), ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), InputCommon::InputSubsystem* input_subsystem_)
: QDialog(parent),
ui(std::make_unique<Ui::ConfigureMouseAdvanced>()), input_subsystem{input_subsystem_},
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
ui->setupUi(this); ui->setupUi(this);
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
@ -209,7 +211,7 @@ void ConfigureMouseAdvanced::HandleClick(
input_setter = new_input_setter; input_setter = new_input_setter;
device_pollers = InputCommon::Polling::GetPollers(type); device_pollers = input_subsystem->GetPollers(type);
for (auto& poller : device_pollers) { for (auto& poller : device_pollers) {
poller->Start(); poller->Start();

View file

@ -8,12 +8,14 @@
#include <optional> #include <optional>
#include <QDialog> #include <QDialog>
#include "core/settings.h"
class QCheckBox; class QCheckBox;
class QPushButton; class QPushButton;
class QTimer; class QTimer;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui { namespace Ui {
class ConfigureMouseAdvanced; class ConfigureMouseAdvanced;
} }
@ -22,7 +24,7 @@ class ConfigureMouseAdvanced : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureMouseAdvanced(QWidget* parent); explicit ConfigureMouseAdvanced(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_);
~ConfigureMouseAdvanced() override; ~ConfigureMouseAdvanced() override;
void ApplyConfiguration(); void ApplyConfiguration();
@ -57,6 +59,8 @@ private:
std::unique_ptr<Ui::ConfigureMouseAdvanced> ui; std::unique_ptr<Ui::ConfigureMouseAdvanced> ui;
InputCommon::InputSubsystem* input_subsystem;
/// This will be the the setting function when an input is awaiting configuration. /// This will be the the setting function when an input is awaiting configuration.
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;

View file

@ -94,6 +94,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "core/perf_stats.h" #include "core/perf_stats.h"
#include "core/settings.h" #include "core/settings.h"
#include "core/telemetry_session.h" #include "core/telemetry_session.h"
#include "input_common/main.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/shader_notify.h" #include "video_core/shader_notify.h"
#include "yuzu/about_dialog.h" #include "yuzu/about_dialog.h"
@ -186,9 +187,9 @@ static void InitializeLogging() {
} }
GMainWindow::GMainWindow() GMainWindow::GMainWindow()
: config(new Config()), emu_thread(nullptr), : input_subsystem{std::make_unique<InputCommon::InputSubsystem>()},
vfs(std::make_shared<FileSys::RealVfsFilesystem>()), config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
provider(std::make_unique<FileSys::ManualContentProvider>()) { provider{std::make_unique<FileSys::ManualContentProvider>()} {
InitializeLogging(); InitializeLogging();
LoadTranslation(); LoadTranslation();
@ -473,7 +474,7 @@ void GMainWindow::InitializeWidgets() {
#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
ui.action_Report_Compatibility->setVisible(true); ui.action_Report_Compatibility->setVisible(true);
#endif #endif
render_window = new GRenderWindow(this, emu_thread.get()); render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem.get());
render_window->hide(); render_window->hide();
game_list = new GameList(vfs, provider.get(), this); game_list = new GameList(vfs, provider.get(), this);
@ -2213,7 +2214,7 @@ void GMainWindow::OnConfigure() {
const auto old_theme = UISettings::values.theme; const auto old_theme = UISettings::values.theme;
const bool old_discord_presence = UISettings::values.enable_discord_presence; const bool old_discord_presence = UISettings::values.enable_discord_presence;
ConfigureDialog configure_dialog(this, hotkey_registry); ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get());
connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
&GMainWindow::OnLanguageChanged); &GMainWindow::OnLanguageChanged);

View file

@ -40,12 +40,20 @@ namespace Core::Frontend {
struct SoftwareKeyboardParameters; struct SoftwareKeyboardParameters;
} // namespace Core::Frontend } // namespace Core::Frontend
namespace DiscordRPC {
class DiscordInterface;
}
namespace FileSys { namespace FileSys {
class ContentProvider; class ContentProvider;
class ManualContentProvider; class ManualContentProvider;
class VfsFilesystem; class VfsFilesystem;
} // namespace FileSys } // namespace FileSys
namespace InputCommon {
class InputSubsystem;
}
enum class EmulatedDirectoryTarget { enum class EmulatedDirectoryTarget {
NAND, NAND,
SDMC, SDMC,
@ -62,10 +70,6 @@ enum class ReinitializeKeyBehavior {
Warning, Warning,
}; };
namespace DiscordRPC {
class DiscordInterface;
}
class GMainWindow : public QMainWindow { class GMainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
@ -86,8 +90,6 @@ public:
GMainWindow(); GMainWindow();
~GMainWindow() override; ~GMainWindow() override;
std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc;
bool DropAction(QDropEvent* event); bool DropAction(QDropEvent* event);
void AcceptDropEvent(QDropEvent* event); void AcceptDropEvent(QDropEvent* event);
@ -255,6 +257,9 @@ private:
Ui::MainWindow ui; Ui::MainWindow ui;
std::unique_ptr<DiscordRPC::DiscordInterface> discord_rpc;
std::unique_ptr<InputCommon::InputSubsystem> input_subsystem;
GRenderWindow* render_window; GRenderWindow* render_window;
GameList* game_list; GameList* game_list;
LoadingScreen* loading_screen; LoadingScreen* loading_screen;

View file

@ -13,23 +13,25 @@
#include "input_common/sdl/sdl.h" #include "input_common/sdl/sdl.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h" #include "yuzu_cmd/emu_window/emu_window_sdl2.h"
EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen) : system{system} { EmuWindow_SDL2::EmuWindow_SDL2(Core::System& system, bool fullscreen,
InputCommon::InputSubsystem* input_subsystem_)
: system{system}, input_subsystem{input_subsystem_} {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
exit(1); exit(1);
} }
InputCommon::Init(); input_subsystem->Initialize();
SDL_SetMainReady(); SDL_SetMainReady();
} }
EmuWindow_SDL2::~EmuWindow_SDL2() { EmuWindow_SDL2::~EmuWindow_SDL2() {
InputCommon::Shutdown(); input_subsystem->Shutdown();
SDL_Quit(); SDL_Quit();
} }
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
InputCommon::GetMotionEmu()->Tilt(x, y); input_subsystem->GetMotionEmu()->Tilt(x, y);
} }
void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { void 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) {
} }
} else if (button == SDL_BUTTON_RIGHT) { } else if (button == SDL_BUTTON_RIGHT) {
if (state == SDL_PRESSED) { if (state == SDL_PRESSED) {
InputCommon::GetMotionEmu()->BeginTilt(x, y); input_subsystem->GetMotionEmu()->BeginTilt(x, y);
} else { } else {
InputCommon::GetMotionEmu()->EndTilt(); input_subsystem->GetMotionEmu()->EndTilt();
} }
} }
} }
@ -79,9 +81,9 @@ void EmuWindow_SDL2::OnFingerUp() {
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
if (state == SDL_PRESSED) { if (state == SDL_PRESSED) {
InputCommon::GetKeyboard()->PressKey(key); input_subsystem->GetKeyboard()->PressKey(key);
} else if (state == SDL_RELEASED) { } else if (state == SDL_RELEASED) {
InputCommon::GetKeyboard()->ReleaseKey(key); input_subsystem->GetKeyboard()->ReleaseKey(key);
} }
} }

View file

@ -14,9 +14,14 @@ namespace Core {
class System; class System;
} }
namespace InputCommon {
class InputSubsystem;
}
class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
public: public:
explicit EmuWindow_SDL2(Core::System& system, bool fullscreen); explicit EmuWindow_SDL2(Core::System& system, bool fullscreen,
InputCommon::InputSubsystem* input_subsystem);
~EmuWindow_SDL2(); ~EmuWindow_SDL2();
/// Polls window events /// Polls window events
@ -76,4 +81,7 @@ protected:
/// Keeps track of how often to update the title bar during gameplay /// Keeps track of how often to update the title bar during gameplay
u32 last_time = 0; u32 last_time = 0;
/// Input subsystem to use with this window.
InputCommon::InputSubsystem* input_subsystem;
}; };

View file

@ -87,8 +87,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
return unsupported_ext.empty(); return unsupported_ext.empty();
} }
EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen) EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(Core::System& system, bool fullscreen,
: EmuWindow_SDL2{system, fullscreen} { InputCommon::InputSubsystem* input_subsystem)
: EmuWindow_SDL2{system, fullscreen, input_subsystem} {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);

View file

@ -8,9 +8,14 @@
#include "core/frontend/emu_window.h" #include "core/frontend/emu_window.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h" #include "yuzu_cmd/emu_window/emu_window_sdl2.h"
namespace InputCommon {
class InputSubsystem;
}
class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 {
public: public:
explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen); explicit EmuWindow_SDL2_GL(Core::System& system, bool fullscreen,
InputCommon::InputSubsystem* input_subsystem);
~EmuWindow_SDL2_GL(); ~EmuWindow_SDL2_GL();
void Present() override; void Present() override;

View file

@ -19,8 +19,9 @@
#include <SDL.h> #include <SDL.h>
#include <SDL_syswm.h> #include <SDL_syswm.h>
EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen) EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(Core::System& system, bool fullscreen,
: EmuWindow_SDL2{system, fullscreen} { InputCommon::InputSubsystem* input_subsystem)
: EmuWindow_SDL2{system, fullscreen, input_subsystem} {
const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name,
Common::g_scm_branch, Common::g_scm_desc); Common::g_scm_branch, Common::g_scm_desc);
render_window = render_window =

View file

@ -13,9 +13,14 @@ namespace Core {
class System; class System;
} }
namespace InputCommon {
class InputSubsystem;
}
class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 {
public: public:
explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen); explicit EmuWindow_SDL2_VK(Core::System& system, bool fullscreen,
InputCommon::InputSubsystem* input_subsystem);
~EmuWindow_SDL2_VK(); ~EmuWindow_SDL2_VK();
void Present() override; void Present() override;

View file

@ -23,12 +23,14 @@
#include "common/telemetry.h" #include "common/telemetry.h"
#include "core/core.h" #include "core/core.h"
#include "core/crypto/key_manager.h" #include "core/crypto/key_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/vfs_real.h" #include "core/file_sys/vfs_real.h"
#include "core/gdbstub/gdbstub.h" #include "core/gdbstub/gdbstub.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/settings.h" #include "core/settings.h"
#include "core/telemetry_session.h" #include "core/telemetry_session.h"
#include "input_common/main.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
#include "yuzu_cmd/config.h" #include "yuzu_cmd/config.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h" #include "yuzu_cmd/emu_window/emu_window_sdl2.h"
@ -37,8 +39,6 @@
#include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h"
#endif #endif
#include "core/file_sys/registered_cache.h"
#ifdef _WIN32 #ifdef _WIN32
// windows.h needs to be included before shellapi.h // windows.h needs to be included before shellapi.h
#include <windows.h> #include <windows.h>
@ -179,15 +179,16 @@ int main(int argc, char** argv) {
Settings::Apply(); Settings::Apply();
Core::System& system{Core::System::GetInstance()}; Core::System& system{Core::System::GetInstance()};
InputCommon::InputSubsystem input_subsystem;
std::unique_ptr<EmuWindow_SDL2> emu_window; std::unique_ptr<EmuWindow_SDL2> emu_window;
switch (Settings::values.renderer_backend.GetValue()) { switch (Settings::values.renderer_backend.GetValue()) {
case Settings::RendererBackend::OpenGL: case Settings::RendererBackend::OpenGL:
emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen); emu_window = std::make_unique<EmuWindow_SDL2_GL>(system, fullscreen, &input_subsystem);
break; break;
case Settings::RendererBackend::Vulkan: case Settings::RendererBackend::Vulkan:
#ifdef HAS_VULKAN #ifdef HAS_VULKAN
emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen); emu_window = std::make_unique<EmuWindow_SDL2_VK>(system, fullscreen, &input_subsystem);
break; break;
#else #else
LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!"); LOG_CRITICAL(Frontend, "Vulkan backend has not been compiled!");

View file

@ -13,7 +13,6 @@
#include <glad/glad.h> #include <glad/glad.h>
#include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scm_rev.h" #include "common/scm_rev.h"
#include "core/settings.h" #include "core/settings.h"
@ -53,7 +52,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() {
exit(1); exit(1);
} }
InputCommon::Init(); input_subsystem->Initialize();
SDL_SetMainReady(); SDL_SetMainReady();
@ -105,7 +104,7 @@ EmuWindow_SDL2_Hide::EmuWindow_SDL2_Hide() {
} }
EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() {
InputCommon::Shutdown(); input_subsystem->Shutdown();
SDL_GL_DeleteContext(gl_context); SDL_GL_DeleteContext(gl_context);
SDL_Quit(); SDL_Quit();
} }

View file

@ -8,6 +8,10 @@
struct SDL_Window; struct SDL_Window;
namespace InputCommon {
class InputSubsystem;
}
class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow { class EmuWindow_SDL2_Hide : public Core::Frontend::EmuWindow {
public: public:
explicit EmuWindow_SDL2_Hide(); explicit EmuWindow_SDL2_Hide();
@ -25,6 +29,8 @@ private:
/// Whether the GPU and driver supports the OpenGL extension required /// Whether the GPU and driver supports the OpenGL extension required
bool SupportsRequiredGLExtensions(); bool SupportsRequiredGLExtensions();
std::unique_ptr<InputCommon::InputSubsystem> input_subsystem;
/// Internal SDL2 render window /// Internal SDL2 render window
SDL_Window* render_window; SDL_Window* render_window;