From 85ceb37ccd24acc5ea026583ce3a0f6a4fb26eaa Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 6 Nov 2019 15:59:36 -0600 Subject: [PATCH] InputCommon: Make the "input gate" not racey. --- Source/Android/jni/MainAndroid.cpp | 5 ----- Source/Core/Core/Core.cpp | 8 +++++++ Source/Core/Core/Core.h | 2 ++ Source/Core/Core/HW/VideoInterface.cpp | 1 + Source/Core/Core/Host.h | 1 - Source/Core/Core/IOS/USB/USB_KBD.cpp | 2 +- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 5 ----- .../Config/Mapping/MappingIndicator.cpp | 8 ------- .../Config/Mapping/MappingWidget.cpp | 4 ---- Source/Core/DolphinQt/Host.cpp | 6 ------ Source/Core/DolphinQt/HotkeyScheduler.cpp | 7 +++++++ Source/Core/DolphinQt/Settings.cpp | 10 --------- Source/Core/DolphinQt/Settings.h | 3 --- .../ControlReference/ControlReference.cpp | 21 +++++++++---------- .../ControlReference/ControlReference.h | 4 +++- Source/DSPTool/StubHost.cpp | 4 ---- Source/UnitTests/StubHost.cpp | 4 ---- 17 files changed, 32 insertions(+), 63 deletions(-) diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index e1b19314c3..ec7bbafd2f 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -124,11 +124,6 @@ void Host_RequestRenderWindowSize(int width, int height) jnicall.join(); } -bool Host_UINeedsControllerState() -{ - return true; -} - bool Host_RendererHasFocus() { return true; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 5908cc1347..a2f60badae 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -72,6 +72,7 @@ #include "Core/MemoryWatcher.h" #endif +#include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "InputCommon/GCAdapter.h" @@ -1035,4 +1036,11 @@ void DoFrameStep() } } +void UpdateInputGate() +{ + ControlReference::SetInputGate( + (SConfig::GetInstance().m_BackgroundInput || Host_RendererHasFocus()) && + !Host_UIBlocksControllerState()); +} + } // namespace Core diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 530079b8ab..4145895faf 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -110,4 +110,6 @@ void HostDispatchJobs(); void DoFrameStep(); +void UpdateInputGate(); + } // namespace Core diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp index 9af6f9f46a..7d78e314b9 100644 --- a/Source/Core/Core/HW/VideoInterface.cpp +++ b/Source/Core/Core/HW/VideoInterface.cpp @@ -737,6 +737,7 @@ void Update(u64 ticks) if (s_half_line_of_next_si_poll == s_half_line_count) { + Core::UpdateInputGate(); SerialInterface::UpdateDevices(); s_half_line_of_next_si_poll += 2 * SerialInterface::GetPollXLines(); } diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index 99c0c61708..d3f5ee4b61 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -32,7 +32,6 @@ enum class HostMessageID WMUserJobDispatch, }; -bool Host_UINeedsControllerState(); bool Host_UIBlocksControllerState(); bool Host_RendererHasFocus(); bool Host_RendererIsFullscreen(); diff --git a/Source/Core/Core/IOS/USB/USB_KBD.cpp b/Source/Core/Core/IOS/USB/USB_KBD.cpp index 77deb65948..5f690506cb 100644 --- a/Source/Core/Core/IOS/USB/USB_KBD.cpp +++ b/Source/Core/Core/IOS/USB/USB_KBD.cpp @@ -212,7 +212,7 @@ IPCCommandResult USB_KBD::Write(const ReadWriteRequest& request) IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request) { if (SConfig::GetInstance().m_WiiKeyboard && !Core::WantsDeterminism() && - ControlReference::InputGateOn() && !m_message_queue.empty()) + ControlReference::GetInputGate() && !m_message_queue.empty()) { Memory::CopyToEmu(request.buffer_out, &m_message_queue.front(), sizeof(MessageData)); m_message_queue.pop(); diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 711583f736..178501194a 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -82,11 +82,6 @@ void Host_RequestRenderWindowSize(int width, int height) { } -bool Host_UINeedsControllerState() -{ - return false; -} - bool Host_RendererHasFocus() { return s_platform->IsWindowFocused(); diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp index a1d0eb144c..08a4f1ccb4 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp @@ -25,7 +25,6 @@ #include "DolphinQt/Config/Mapping/MappingWidget.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" -#include "DolphinQt/Settings.h" namespace { @@ -567,9 +566,6 @@ void MappingIndicator::DrawForce(ControllerEmu::Force& force) void MappingIndicator::paintEvent(QPaintEvent*) { - // TODO: The SetControllerStateNeeded interface leaks input into the game. - Settings::Instance().SetControllerStateNeeded(true); - switch (m_group->type) { case ControllerEmu::GroupType::Cursor: @@ -588,8 +584,6 @@ void MappingIndicator::paintEvent(QPaintEvent*) default: break; } - - Settings::Instance().SetControllerStateNeeded(false); } ShakeMappingIndicator::ShakeMappingIndicator(ControllerEmu::Shake* group) @@ -599,9 +593,7 @@ ShakeMappingIndicator::ShakeMappingIndicator(ControllerEmu::Shake* group) void ShakeMappingIndicator::paintEvent(QPaintEvent*) { - Settings::Instance().SetControllerStateNeeded(true); DrawShake(); - Settings::Instance().SetControllerStateNeeded(false); } void ShakeMappingIndicator::DrawShake() diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp index b9149027ea..ec4b055989 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp @@ -14,7 +14,6 @@ #include "DolphinQt/Config/Mapping/MappingIndicator.h" #include "DolphinQt/Config/Mapping/MappingNumeric.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" -#include "DolphinQt/Settings.h" #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerEmu/Control/Control.h" @@ -31,11 +30,8 @@ MappingWidget::MappingWidget(MappingWindow* parent) : m_parent(parent) const auto timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this] { - // TODO: The SetControllerStateNeeded interface leaks input into the game. const auto lock = m_parent->GetController()->GetStateLock(); - Settings::Instance().SetControllerStateNeeded(true); emit Update(); - Settings::Instance().SetControllerStateNeeded(false); }); timer->start(1000 / INDICATOR_UPDATE_FREQ); diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp index ac9c91942f..fc53954195 100644 --- a/Source/Core/DolphinQt/Host.cpp +++ b/Source/Core/DolphinQt/Host.cpp @@ -153,12 +153,6 @@ void Host_RequestRenderWindowSize(int w, int h) emit Host::GetInstance()->RequestRenderSize(w, h); } -bool Host_UINeedsControllerState() -{ - return Settings::Instance().IsControllerStateNeeded() || - (ImGui::GetCurrentContext() && ImGui::GetIO().WantCaptureKeyboard); -} - bool Host_UIBlocksControllerState() { return ImGui::GetCurrentContext() && ImGui::GetIO().WantCaptureKeyboard; diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp index b2f5c86d98..cb67fba6ea 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp @@ -25,6 +25,7 @@ #include "DolphinQt/Settings.h" +#include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "VideoCommon/OnScreenDisplay.h" @@ -142,8 +143,14 @@ void HotkeyScheduler::Run() if (Core::GetState() != Core::State::Stopping) { + // Obey window focus before checking hotkeys. + Core::UpdateInputGate(); + HotkeyManagerEmu::GetStatus(); + // Everything else on the host thread (controller config dialog) should always get input. + ControlReference::SetInputGate(true); + if (!Core::IsRunningAndStarted()) continue; diff --git a/Source/Core/DolphinQt/Settings.cpp b/Source/Core/DolphinQt/Settings.cpp index 99322db7fe..cbc4849793 100644 --- a/Source/Core/DolphinQt/Settings.cpp +++ b/Source/Core/DolphinQt/Settings.cpp @@ -388,16 +388,6 @@ bool Settings::IsBreakpointsVisible() const return GetQSettings().value(QStringLiteral("debugger/showbreakpoints")).toBool(); } -bool Settings::IsControllerStateNeeded() const -{ - return m_controller_state_needed; -} - -void Settings::SetControllerStateNeeded(bool needed) -{ - m_controller_state_needed = needed; -} - void Settings::SetCodeVisible(bool enabled) { if (IsCodeVisible() != enabled) diff --git a/Source/Core/DolphinQt/Settings.h b/Source/Core/DolphinQt/Settings.h index f16ce2a474..c9c5f1a422 100644 --- a/Source/Core/DolphinQt/Settings.h +++ b/Source/Core/DolphinQt/Settings.h @@ -57,8 +57,6 @@ public: void SetLogVisible(bool visible); bool IsLogConfigVisible() const; void SetLogConfigVisible(bool visible); - bool IsControllerStateNeeded() const; - void SetControllerStateNeeded(bool needed); void SetToolBarVisible(bool visible); bool IsToolBarVisible() const; void SetWidgetsLocked(bool visible); @@ -179,7 +177,6 @@ signals: private: bool m_batch = false; - bool m_controller_state_needed = false; std::shared_ptr m_client; std::shared_ptr m_server; Settings(); diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index af7536547c..b1dd5deee3 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -4,19 +4,18 @@ #include "InputCommon/ControlReference/ControlReference.h" -// For InputGateOn() -// This is a bad layering violation, but it's the cleanest -// place I could find to put it. -#include "Core/ConfigManager.h" -#include "Core/Host.h" - using namespace ciface::ExpressionParser; -bool ControlReference::InputGateOn() +static thread_local bool tls_input_gate = true; + +void ControlReference::SetInputGate(bool enable) { - return (SConfig::GetInstance().m_BackgroundInput || Host_RendererHasFocus() || - Host_UINeedsControllerState()) && - !Host_UIBlocksControllerState(); + tls_input_gate = enable; +} + +bool ControlReference::GetInputGate() +{ + return tls_input_gate; } // @@ -90,7 +89,7 @@ bool OutputReference::IsInput() const // ControlState InputReference::State(const ControlState ignore) { - if (m_parsed_expression && InputGateOn()) + if (m_parsed_expression && GetInputGate()) return m_parsed_expression->GetValue() * range; return 0.0; } diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.h b/Source/Core/InputCommon/ControlReference/ControlReference.h index 3f2c205501..539c7f4927 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.h +++ b/Source/Core/InputCommon/ControlReference/ControlReference.h @@ -22,7 +22,9 @@ class ControlReference { public: - static bool InputGateOn(); + // Note: this is per thread. + static void SetInputGate(bool enable); + static bool GetInputGate(); virtual ~ControlReference(); virtual ControlState State(const ControlState state = 0) = 0; diff --git a/Source/DSPTool/StubHost.cpp b/Source/DSPTool/StubHost.cpp index ac6ef92e52..75dd66296d 100644 --- a/Source/DSPTool/StubHost.cpp +++ b/Source/DSPTool/StubHost.cpp @@ -34,10 +34,6 @@ void Host_UpdateMainFrame() void Host_RequestRenderWindowSize(int, int) { } -bool Host_UINeedsControllerState() -{ - return false; -} bool Host_RendererHasFocus() { return false; diff --git a/Source/UnitTests/StubHost.cpp b/Source/UnitTests/StubHost.cpp index 440ecd336a..4fa45ef1c2 100644 --- a/Source/UnitTests/StubHost.cpp +++ b/Source/UnitTests/StubHost.cpp @@ -31,10 +31,6 @@ void Host_UpdateMainFrame() void Host_RequestRenderWindowSize(int, int) { } -bool Host_UINeedsControllerState() -{ - return false; -} bool Host_UIBlocksControllerState() { return false;