Skip to content

Commit

Permalink
ControllerInterface/DolphinQt: Make mapping "all devices" way less ha…
Browse files Browse the repository at this point in the history
…cky.
  • Loading branch information
jordan-woyak committed Mar 4, 2019
1 parent 48b69ca commit c389d68
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 232 deletions.
41 changes: 14 additions & 27 deletions Source/Core/DolphinQt/Config/Mapping/IOWindow.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ void IOWindow::ConnectWidgets()
connect(m_or_button, &QPushButton::clicked, [this] { AppendSelectedOption(" | "); }); connect(m_or_button, &QPushButton::clicked, [this] { AppendSelectedOption(" | "); });
connect(m_not_button, &QPushButton::clicked, [this] { AppendSelectedOption("!"); }); connect(m_not_button, &QPushButton::clicked, [this] { AppendSelectedOption("!"); });


connect(m_type == IOWindow::Type::Input ? m_detect_button : m_test_button, &QPushButton::clicked, connect(m_detect_button, &QPushButton::clicked, this, &IOWindow::OnDetectButtonPressed);
this, &IOWindow::OnDetectButtonPressed); connect(m_test_button, &QPushButton::clicked, this, &IOWindow::OnTestButtonPressed);


connect(m_button_box, &QDialogButtonBox::clicked, this, &IOWindow::OnDialogButtonPressed); connect(m_button_box, &QDialogButtonBox::clicked, this, &IOWindow::OnDialogButtonPressed);
connect(m_devices_combo, &QComboBox::currentTextChanged, this, &IOWindow::OnDeviceChanged); connect(m_devices_combo, &QComboBox::currentTextChanged, this, &IOWindow::OnDeviceChanged);
Expand Down Expand Up @@ -180,35 +180,22 @@ void IOWindow::OnDialogButtonPressed(QAbstractButton* button)


void IOWindow::OnDetectButtonPressed() void IOWindow::OnDetectButtonPressed()
{ {
installEventFilter(BlockUserInputFilter::Instance()); const auto expression =
grabKeyboard(); MappingCommon::DetectExpression(m_detect_button, g_controller_interface, {m_devq.ToString()},
grabMouse(); m_devq, MappingCommon::Quote::Off);


std::thread([this] { if (expression.isEmpty())
auto* btn = m_type == IOWindow::Type::Input ? m_detect_button : m_test_button; return;
const auto old_label = btn->text();

btn->setText(QStringLiteral("..."));

const auto expr = MappingCommon::DetectExpression(
m_reference, g_controller_interface.FindDevice(m_devq).get(), m_devq,
MappingCommon::Quote::Off);

btn->setText(old_label);


if (!expr.isEmpty()) const auto list = m_option_list->findItems(expression, Qt::MatchFixedString);
{
const auto list = m_option_list->findItems(expr, Qt::MatchFixedString);


if (!list.empty()) if (!list.empty())
m_option_list->setCurrentItem(list[0]); m_option_list->setCurrentItem(list[0]);
} }


releaseMouse(); void IOWindow::OnTestButtonPressed()
releaseKeyboard(); {
removeEventFilter(BlockUserInputFilter::Instance()); MappingCommon::TestOutput(m_test_button, static_cast<OutputReference*>(m_reference));
})
.detach();
} }


void IOWindow::OnRangeChanged(int value) void IOWindow::OnRangeChanged(int value)
Expand Down
1 change: 1 addition & 0 deletions Source/Core/DolphinQt/Config/Mapping/IOWindow.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class IOWindow final : public QDialog
void OnDialogButtonPressed(QAbstractButton* button); void OnDialogButtonPressed(QAbstractButton* button);
void OnDeviceChanged(const QString& device); void OnDeviceChanged(const QString& device);
void OnDetectButtonPressed(); void OnDetectButtonPressed();
void OnTestButtonPressed();
void OnRangeChanged(int range); void OnRangeChanged(int range);


void AppendSelectedOption(const std::string& prefix); void AppendSelectedOption(const std::string& prefix);
Expand Down
112 changes: 23 additions & 89 deletions Source/Core/DolphinQt/Config/Mapping/MappingButton.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// Licensed under GPLv2+ // Licensed under GPLv2+
// Refer to the license.txt file included. // Refer to the license.txt file included.


#include <future> #include "DolphinQt/Config/Mapping/MappingButton.h"
#include <utility>


#include <QApplication> #include <QApplication>
#include <QFontMetrics> #include <QFontMetrics>
Expand All @@ -12,8 +11,6 @@
#include <QString> #include <QString>
#include <QTimer> #include <QTimer>


#include "DolphinQt/Config/Mapping/MappingButton.h"

#include "Common/Thread.h" #include "Common/Thread.h"
#include "Core/Core.h" #include "Core/Core.h"


Expand Down Expand Up @@ -103,96 +100,33 @@ void MappingButton::Detect()
if (m_parent->GetDevice() == nullptr || !m_reference->IsInput()) if (m_parent->GetDevice() == nullptr || !m_reference->IsInput())
return; return;


installEventFilter(BlockUserInputFilter::Instance()); const auto default_device_qualifier = m_parent->GetController()->GetDefaultDevice();
grabKeyboard();

// Make sure that we don't block event handling
QueueOnObject(this, [this] {
setText(QStringLiteral("..."));

// The button text won't be updated if we don't process events here
QApplication::processEvents();

// Avoid that the button press itself is registered as an event
Common::SleepCurrentThread(100);

std::vector<std::future<std::pair<QString, QString>>> futures;
QString expr;


if (m_parent->GetParent()->IsMappingAllDevices()) QString expression;
{
for (const std::string& device_str : g_controller_interface.GetAllDeviceStrings())
{
ciface::Core::DeviceQualifier devq;
devq.FromString(device_str);

auto dev = g_controller_interface.FindDevice(devq);

auto future = std::async(std::launch::async, [this, devq, dev, device_str] {
return std::make_pair(
QString::fromStdString(device_str),
MappingCommon::DetectExpression(m_reference, dev.get(),
m_parent->GetController()->GetDefaultDevice()));
});

futures.push_back(std::move(future));
}

bool done = false;

while (!done)
{
for (auto& future : futures)
{
const auto status = future.wait_for(std::chrono::milliseconds(10));
if (status == std::future_status::ready)
{
const auto pair = future.get();

done = true;

if (pair.second.isEmpty())
break;

expr = QStringLiteral("`%1:%2`")
.arg(pair.first)
.arg(pair.second.startsWith(QLatin1Char('`')) ? pair.second.mid(1) :
pair.second);
break;
}
}
}
}
else
{
const auto dev = m_parent->GetDevice();
expr = MappingCommon::DetectExpression(m_reference, dev.get(),
m_parent->GetController()->GetDefaultDevice());
}


releaseKeyboard(); if (m_parent->GetParent()->IsMappingAllDevices())
removeEventFilter(BlockUserInputFilter::Instance()); {
expression = MappingCommon::DetectExpression(this, g_controller_interface,
g_controller_interface.GetAllDeviceStrings(),
default_device_qualifier);
}
else
{
expression = MappingCommon::DetectExpression(this, g_controller_interface,
{default_device_qualifier.ToString()},
default_device_qualifier);
}


if (!expr.isEmpty()) if (expression.isEmpty())
{ return;
m_reference->SetExpression(expr.toStdString());
m_parent->SaveSettings();
Update();
m_parent->GetController()->UpdateReferences(g_controller_interface);


if (m_parent->IsIterativeInput()) m_reference->SetExpression(expression.toStdString());
m_parent->NextButton(this); m_parent->SaveSettings();
} Update();
else m_parent->GetController()->UpdateReferences(g_controller_interface);
{
OnButtonTimeout();
}
});
}


void MappingButton::OnButtonTimeout() if (m_parent->IsIterativeInput())
{ m_parent->NextButton(this);
setText(ToDisplayString(QString::fromStdString(m_reference->GetExpression())));
} }


void MappingButton::Clear() void MappingButton::Clear()
Expand Down
1 change: 0 additions & 1 deletion Source/Core/DolphinQt/Config/Mapping/MappingButton.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class MappingButton : public ElidedButton
private: private:
void mouseReleaseEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override;


void OnButtonTimeout();
void Connect(); void Connect();


MappingWidget* m_parent; MappingWidget* m_parent;
Expand Down
65 changes: 55 additions & 10 deletions Source/Core/DolphinQt/Config/Mapping/MappingCommon.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@


#include "DolphinQt/Config/Mapping/MappingCommon.h" #include "DolphinQt/Config/Mapping/MappingCommon.h"


#include <tuple>

#include <QApplication>
#include <QPushButton>
#include <QRegExp> #include <QRegExp>
#include <QString> #include <QString>


#include "DolphinQt/QtUtils/BlockUserInputFilter.h"
#include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerInterface/Device.h" #include "InputCommon/ControllerInterface/Device.h"


#include "Common/Thread.h"

namespace MappingCommon namespace MappingCommon
{ {
constexpr int INPUT_DETECT_TIME = 3000; constexpr int INPUT_DETECT_TIME = 3000;
constexpr int OUTPUT_DETECT_TIME = 2000; constexpr int OUTPUT_TEST_TIME = 2000;


QString GetExpressionForControl(const QString& control_name, QString GetExpressionForControl(const QString& control_name,
const ciface::Core::DeviceQualifier& control_device, const ciface::Core::DeviceQualifier& control_device,
Expand Down Expand Up @@ -41,18 +48,56 @@ QString GetExpressionForControl(const QString& control_name,
return expr; return expr;
} }


QString DetectExpression(ControlReference* reference, ciface::Core::Device* device, QString DetectExpression(QPushButton* button, ciface::Core::DeviceContainer& device_container,
const std::vector<std::string>& device_strings,
const ciface::Core::DeviceQualifier& default_device, Quote quote) const ciface::Core::DeviceQualifier& default_device, Quote quote)
{ {
const int ms = reference->IsInput() ? INPUT_DETECT_TIME : OUTPUT_DETECT_TIME; button->installEventFilter(BlockUserInputFilter::Instance());
button->grabKeyboard();
button->grabMouse();


ciface::Core::Device::Control* const ctrl = reference->Detect(ms, device); const auto old_text = button->text();
button->setText(QStringLiteral("..."));


if (ctrl) // The button text won't be updated if we don't process events here
{ QApplication::processEvents();
return MappingCommon::GetExpressionForControl(QString::fromStdString(ctrl->GetName()),
default_device, default_device, quote); // Avoid that the button press itself is registered as an event
} Common::SleepCurrentThread(100);
return QStringLiteral("");
std::shared_ptr<ciface::Core::Device> device;
ciface::Core::Device::Input* input;
std::tie(device, input) = device_container.DetectInput(INPUT_DETECT_TIME, device_strings);

button->releaseMouse();
button->releaseKeyboard();
button->removeEventFilter(BlockUserInputFilter::Instance());

button->setText(old_text);

if (!input)
return {};

ciface::Core::DeviceQualifier device_qualifier;
device_qualifier.FromDevice(device.get());

return MappingCommon::GetExpressionForControl(QString::fromStdString(input->GetName()),
device_qualifier, default_device, quote);
} }

void TestOutput(QPushButton* button, OutputReference* reference)
{
const auto old_text = button->text();
button->setText(QStringLiteral("..."));

// The button text won't be updated if we don't process events here
QApplication::processEvents();

reference->State(1.0);
Common::SleepCurrentThread(OUTPUT_TEST_TIME);
reference->State(0.0);

button->setText(old_text);
}

} // namespace MappingCommon } // namespace MappingCommon
19 changes: 14 additions & 5 deletions Source/Core/DolphinQt/Config/Mapping/MappingCommon.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@


#pragma once #pragma once


#include <string>
#include <vector>

class QString; class QString;
class ControlReference; class OutputReference;
class QPushButton;


namespace ciface namespace ciface
{ {
namespace Core namespace Core
{ {
class Device; class DeviceContainer;
class DeviceQualifier; class DeviceQualifier;
} } // namespace Core
} } // namespace ciface


namespace MappingCommon namespace MappingCommon
{ {
Expand All @@ -28,7 +32,12 @@ QString GetExpressionForControl(const QString& control_name,
const ciface::Core::DeviceQualifier& control_device, const ciface::Core::DeviceQualifier& control_device,
const ciface::Core::DeviceQualifier& default_device, const ciface::Core::DeviceQualifier& default_device,
Quote quote = Quote::On); Quote quote = Quote::On);
QString DetectExpression(ControlReference* reference, ciface::Core::Device* device,
QString DetectExpression(QPushButton* button, ciface::Core::DeviceContainer& device_container,
const std::vector<std::string>& device_strings,
const ciface::Core::DeviceQualifier& default_device, const ciface::Core::DeviceQualifier& default_device,
Quote quote = Quote::On); Quote quote = Quote::On);

void TestOutput(QPushButton* button, OutputReference* reference);

} // namespace MappingCommon } // namespace MappingCommon
Loading

0 comments on commit c389d68

Please sign in to comment.