Merge pull request #8456 from jordan-woyak/input-gate-race-fix
InputCommon: Make the "input gate" not racy.
This commit is contained in:
commit
913cb08066
|
@ -124,11 +124,6 @@ void Host_RequestRenderWindowSize(int width, int height)
|
|||
jnicall.join();
|
||||
}
|
||||
|
||||
bool Host_UINeedsControllerState()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Host_RendererHasFocus()
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#include "Core/MemoryWatcher.h"
|
||||
#endif
|
||||
|
||||
#include "InputCommon/ControlReference/ControlReference.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
|
||||
|
@ -1045,4 +1046,11 @@ void DoFrameStep()
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateInputGate()
|
||||
{
|
||||
ControlReference::SetInputGate(
|
||||
(SConfig::GetInstance().m_BackgroundInput || Host_RendererHasFocus()) &&
|
||||
!Host_UIBlocksControllerState());
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -111,4 +111,6 @@ void HostDispatchJobs();
|
|||
|
||||
void DoFrameStep();
|
||||
|
||||
void UpdateInputGate();
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -820,6 +820,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();
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ enum class HostMessageID
|
|||
WMUserJobDispatch,
|
||||
};
|
||||
|
||||
bool Host_UINeedsControllerState();
|
||||
bool Host_UIBlocksControllerState();
|
||||
bool Host_RendererHasFocus();
|
||||
bool Host_RendererIsFullscreen();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -82,11 +82,6 @@ void Host_RequestRenderWindowSize(int width, int height)
|
|||
{
|
||||
}
|
||||
|
||||
bool Host_UINeedsControllerState()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Host_RendererHasFocus()
|
||||
{
|
||||
return s_platform->IsWindowFocused();
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "DolphinQt/Config/Mapping/MappingWidget.h"
|
||||
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -589,9 +588,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:
|
||||
|
@ -610,8 +606,6 @@ void MappingIndicator::paintEvent(QPaintEvent*)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Settings::Instance().SetControllerStateNeeded(false);
|
||||
}
|
||||
|
||||
ShakeMappingIndicator::ShakeMappingIndicator(ControllerEmu::Shake* group)
|
||||
|
@ -621,9 +615,7 @@ ShakeMappingIndicator::ShakeMappingIndicator(ControllerEmu::Shake* group)
|
|||
|
||||
void ShakeMappingIndicator::paintEvent(QPaintEvent*)
|
||||
{
|
||||
Settings::Instance().SetControllerStateNeeded(true);
|
||||
DrawShake();
|
||||
Settings::Instance().SetControllerStateNeeded(false);
|
||||
}
|
||||
|
||||
void ShakeMappingIndicator::DrawShake()
|
||||
|
|
|
@ -13,7 +13,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"
|
||||
|
@ -30,11 +29,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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -393,16 +393,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)
|
||||
|
|
|
@ -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);
|
||||
|
@ -181,7 +179,6 @@ signals:
|
|||
|
||||
private:
|
||||
bool m_batch = false;
|
||||
bool m_controller_state_needed = false;
|
||||
std::shared_ptr<NetPlay::NetPlayClient> m_client;
|
||||
std::shared_ptr<NetPlay::NetPlayServer> m_server;
|
||||
Settings();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -34,10 +34,6 @@ void Host_UpdateMainFrame()
|
|||
void Host_RequestRenderWindowSize(int, int)
|
||||
{
|
||||
}
|
||||
bool Host_UINeedsControllerState()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool Host_RendererHasFocus()
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -31,10 +31,6 @@ void Host_UpdateMainFrame()
|
|||
void Host_RequestRenderWindowSize(int, int)
|
||||
{
|
||||
}
|
||||
bool Host_UINeedsControllerState()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool Host_UIBlocksControllerState()
|
||||
{
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue