From 2f3c0cdbc594cdcb76644e1e77aa185a1e50a244 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 27 Apr 2021 23:43:04 +0200 Subject: [PATCH 1/2] Split out controller initialization to UICommon --- Source/Core/DolphinQt/HotkeyScheduler.cpp | 2 -- Source/Core/DolphinQt/MainWindow.cpp | 26 +++----------- Source/Core/UICommon/UICommon.cpp | 41 +++++++++++++++++++++++ Source/Core/UICommon/UICommon.h | 5 +++ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp index c3d2aadcb7..52fd1ac00a 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp @@ -48,8 +48,6 @@ constexpr const char* DUBOIS_ALGORITHM_SHADER = "dubois"; HotkeyScheduler::HotkeyScheduler() : m_stop_requested(false) { - HotkeyManagerEmu::Initialize(); - HotkeyManagerEmu::LoadConfig(); HotkeyManagerEmu::Enable(true); } diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index dab8f45c24..281bbc78a8 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -321,24 +321,12 @@ void MainWindow::InitControllers() if (g_controller_interface.IsInit()) return; - g_controller_interface.Initialize(GetWindowSystemInfo(windowHandle())); - if (!g_controller_interface.HasDefaultDevice()) - { - // Note that the CI default device could be still temporarily removed at any time - WARN_LOG_FMT(CONTROLLERINTERFACE, - "No default device has been added in time. EmulatedController(s) defaulting adds" - " input mappings made for a specific default device depending on the platform"); - } - GCAdapter::Init(); - Pad::Initialize(); - Pad::InitializeGBA(); - Keyboard::Initialize(); - Wiimote::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); - FreeLook::Initialize(); + UICommon::InitControllers(GetWindowSystemInfo(windowHandle())); + m_hotkey_scheduler = new HotkeyScheduler(); m_hotkey_scheduler->Start(); - // Defaults won't work reliabily without loading and saving the config first + // Defaults won't work reliably without loading and saving the config first Wiimote::LoadConfig(); Wiimote::GetConfig()->SaveConfig(); @@ -362,13 +350,7 @@ void MainWindow::ShutdownControllers() Settings::Instance().UnregisterDevicesChangedCallback(); - Pad::Shutdown(); - Pad::ShutdownGBA(); - Keyboard::Shutdown(); - Wiimote::Shutdown(); - HotkeyManagerEmu::Shutdown(); - FreeLook::Shutdown(); - g_controller_interface.Shutdown(); + UICommon::ShutdownControllers(); m_hotkey_scheduler->deleteLater(); } diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 469c9b2c67..8d9dc2abb8 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -28,12 +28,18 @@ #include "Core/ConfigLoaders/BaseConfigLoader.h" #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/FreeLookManager.h" +#include "Core/HW/GBAPad.h" +#include "Core/HW/GCKeyboard.h" +#include "Core/HW/GCPad.h" #include "Core/HW/ProcessorInterface.h" #include "Core/HW/Wiimote.h" +#include "Core/HotkeyManager.h" #include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" #include "Core/WiiRoot.h" +#include "InputCommon/ControllerInterface/ControllerInterface.h" #include "InputCommon/GCAdapter.h" #include "UICommon/DiscordPresence.h" @@ -128,6 +134,41 @@ void Shutdown() Config::Shutdown(); } +void InitControllers(const WindowSystemInfo& wsi) +{ + if (g_controller_interface.IsInit()) + return; + + g_controller_interface.Initialize(wsi); + + if (!g_controller_interface.HasDefaultDevice()) + { + // Note that the CI default device could be still temporarily removed at any time + WARN_LOG_FMT(CONTROLLERINTERFACE, "No default device has been added in time. Premade control " + "mappings intended for the default device may not work."); + } + + GCAdapter::Init(); + Pad::Initialize(); + Pad::InitializeGBA(); + Keyboard::Initialize(); + Wiimote::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); + HotkeyManagerEmu::Initialize(); + FreeLook::Initialize(); +} + +void ShutdownControllers() +{ + Pad::Shutdown(); + Pad::ShutdownGBA(); + Keyboard::Shutdown(); + Wiimote::Shutdown(); + HotkeyManagerEmu::Shutdown(); + FreeLook::Shutdown(); + + g_controller_interface.Shutdown(); +} + void SetLocale(std::string locale_name) { auto set_locale = [](const std::string& locale) { diff --git a/Source/Core/UICommon/UICommon.h b/Source/Core/UICommon/UICommon.h index 6bdb11f541..f57518cf14 100644 --- a/Source/Core/UICommon/UICommon.h +++ b/Source/Core/UICommon/UICommon.h @@ -7,11 +7,16 @@ #include "Common/CommonTypes.h" +struct WindowSystemInfo; + namespace UICommon { void Init(); void Shutdown(); +void InitControllers(const WindowSystemInfo& wsi); +void ShutdownControllers(); + #ifdef HAVE_X11 void InhibitScreenSaver(unsigned long win, bool enable); #else From dabad822193f23bd01c13c4d0798f0a507e910eb Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 25 Jun 2022 17:31:31 +0200 Subject: [PATCH 2/2] Require frontend to initialize controllers We currently have two different code paths for initializing controllers: Either the frontend (DolphinQt) can do it, or if the frontend doesn't do it, the core will do it automatically when booting. Having these two paths has caused problems in the past due to only one frontend being tested (see de7ef47548). I would like to get rid of the latter path to avoid further problems like this. --- Source/Android/jni/MainAndroid.cpp | 5 +- Source/Core/Core/Core.cpp | 72 +++++--------------------- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 19 ++++--- 3 files changed, 27 insertions(+), 69 deletions(-) diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 77c373a481..d41ebe4cc9 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include #include #include #include @@ -56,13 +55,13 @@ #include "InputCommon/ControllerInterface/Touch/ButtonManager.h" #include "InputCommon/GCAdapter.h" +#include "UICommon/GameFile.h" #include "UICommon/UICommon.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VideoBackendBase.h" -#include "../../Core/Common/WindowSystemInfo.h" #include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/IDCache.h" @@ -521,7 +520,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Initialize(J Common::AndroidSetReportHandler(&ReportSend); DolphinAnalytics::AndroidSetGetValFunc(&GetAnalyticValue); UICommon::Init(); - GCAdapter::Init(); + UICommon::InitControllers(WindowSystemInfo(WindowSystemType::Android, nullptr, nullptr, nullptr)); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ReportStartToAnalytics(JNIEnv*, diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index f2a9ec334d..e445749d8d 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -20,6 +20,7 @@ #include "AudioCommon/AudioCommon.h" +#include "Common/Assert.h" #include "Common/CPUDetect.h" #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" @@ -470,26 +471,14 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi DeclareAsCPUThread(); s_frame_step = false; - // The frontend will likely have initialized the controller interface, as it needs - // it to provide the configuration dialogs. In this case, instead of re-initializing - // entirely, we switch the window used for inputs to the render window. This way, the - // cursor position is relative to the render window, instead of the main window. - bool init_controllers = false; - if (!g_controller_interface.IsInit()) - { - g_controller_interface.Initialize(wsi); - Pad::Initialize(); - Pad::InitializeGBA(); - Keyboard::Initialize(); - init_controllers = true; - } - else - { - g_controller_interface.ChangeWindow(wsi.render_window); - Pad::LoadConfig(); - Pad::LoadGBAConfig(); - Keyboard::LoadConfig(); - } + // Switch the window used for inputs to the render window. This way, the cursor position + // is relative to the render window, instead of the main window. + ASSERT(g_controller_interface.IsInit()); + g_controller_interface.ChangeWindow(wsi.render_window); + + Pad::LoadConfig(); + Pad::LoadGBAConfig(); + Keyboard::LoadConfig(); BootSessionData boot_session_data = std::move(boot->boot_session_data); const std::optional& savestate_path = boot_session_data.GetSavestatePath(); @@ -506,53 +495,16 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi Common::SyncSDImageToSDFolder(); }}; - // Load and Init Wiimotes - only if we are booting in Wii mode - bool init_wiimotes = false; + // Load Wiimotes - only if we are booting in Wii mode if (core_parameter.bWii && !Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED)) { - if (init_controllers) - { - Wiimote::Initialize(savestate_path ? Wiimote::InitializeMode::DO_WAIT_FOR_WIIMOTES : - Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); - init_wiimotes = true; - } - else - { - Wiimote::LoadConfig(); - } + Wiimote::LoadConfig(); if (NetPlay::IsNetPlayRunning()) NetPlay::SetupWiimotes(); } - if (init_controllers) - { - FreeLook::Initialize(); - } - else - { - FreeLook::LoadInputConfig(); - } - - Common::ScopeGuard controller_guard{[init_controllers, init_wiimotes] { - if (!init_controllers) - return; - - if (init_wiimotes) - { - Wiimote::ResetAllWiimotes(); - Wiimote::Shutdown(); - } - - FreeLook::Shutdown(); - - ResetRumble(); - - Keyboard::Shutdown(); - Pad::Shutdown(); - Pad::ShutdownGBA(); - g_controller_interface.Shutdown(); - }}; + FreeLook::LoadInputConfig(); Movie::Init(*boot); Common::ScopeGuard movie_guard{&Movie::Shutdown}; diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index cec4788f1c..03ea30ec17 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -17,6 +17,7 @@ #include #endif +#include "Common/ScopeGuard.h" #include "Common/StringUtil.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" @@ -226,10 +227,6 @@ int main(int argc, char* argv[]) if (options.is_set("user")) user_directory = static_cast(options.get("user")); - UICommon::SetUserDirectory(user_directory); - UICommon::Init(); - GCAdapter::Init(); - s_platform = GetPlatform(options); if (!s_platform || !s_platform->Init()) { @@ -237,6 +234,17 @@ int main(int argc, char* argv[]) return 1; } + const WindowSystemInfo wsi = s_platform->GetWindowSystemInfo(); + + UICommon::SetUserDirectory(user_directory); + UICommon::Init(); + UICommon::InitControllers(wsi); + + Common::ScopeGuard ui_common_guard([] { + UICommon::ShutdownControllers(); + UICommon::Shutdown(); + }); + if (save_state_path && !game_specified) { fprintf(stderr, "A save state cannot be loaded without specifying a game to launch.\n"); @@ -263,7 +271,7 @@ int main(int argc, char* argv[]) DolphinAnalytics::Instance().ReportDolphinStart("nogui"); - if (!BootManager::BootCore(std::move(boot), s_platform->GetWindowSystemInfo())) + if (!BootManager::BootCore(std::move(boot), wsi)) { fprintf(stderr, "Could not boot the specified file\n"); return 1; @@ -278,7 +286,6 @@ int main(int argc, char* argv[]) Core::Shutdown(); s_platform.reset(); - UICommon::Shutdown(); return 0; }