Skip to content
Permalink
Browse files

Merge pull request #8456 from jordan-woyak/input-gate-race-fix

InputCommon: Make the "input gate" not racy.
  • Loading branch information
stenzek committed Nov 11, 2019
2 parents 066012b + 85ceb37 commit 913cb080667302760e42e3a6e2346b6e7c5cb1b6
@@ -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 @@ class Settings final : public QObject
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 @@ class Settings final : public QObject

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)
{
tls_input_gate = enable;
}

bool ControlReference::GetInputGate()
{
return (SConfig::GetInstance().m_BackgroundInput || Host_RendererHasFocus() ||
Host_UINeedsControllerState()) &&
!Host_UIBlocksControllerState();
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;

0 comments on commit 913cb08

Please sign in to comment.
You can’t perform that action at this time.