mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 01:49:33 -06:00
WiimoteControllersWidget: Fix UI hang on opening
Fix the UI hanging for several seconds when opening the Controllers window. Move the scan for Bluetooth adapters onto a separate thread so the Host thread doesn't have to wait for it. Only automatically scan for adapters once, when opening the Controllers window for the first time. Add a Refresh button to let the user refresh the adapter list afterward.
This commit is contained in:
@ -27,7 +27,6 @@ void ControllersWindow::showEvent(QShowEvent* event)
|
|||||||
{
|
{
|
||||||
QDialog::showEvent(event);
|
QDialog::showEvent(event);
|
||||||
m_wiimote_controllers->UpdateBluetoothAvailableStatus();
|
m_wiimote_controllers->UpdateBluetoothAvailableStatus();
|
||||||
m_wiimote_controllers->RefreshBluetoothAdapters();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllersWindow::CreateMainLayout()
|
void ControllersWindow::CreateMainLayout()
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "Common/Config/Config.h"
|
#include "Common/Config/Config.h"
|
||||||
|
#include "Common/WorkQueueThread.h"
|
||||||
|
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/Config/WiimoteSettings.h"
|
#include "Core/Config/WiimoteSettings.h"
|
||||||
@ -35,6 +36,7 @@
|
|||||||
#include "DolphinQt/Config/Mapping/MappingWindow.h"
|
#include "DolphinQt/Config/Mapping/MappingWindow.h"
|
||||||
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
||||||
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
||||||
|
#include "DolphinQt/QtUtils/QueueOnObject.h"
|
||||||
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
|
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
|
||||||
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
||||||
#include "DolphinQt/Settings.h"
|
#include "DolphinQt/Settings.h"
|
||||||
@ -51,6 +53,14 @@ WiimoteControllersWidget::WiimoteControllersWidget(QWidget* parent) : QWidget(pa
|
|||||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||||
[this](Core::State state) { LoadSettings(state); });
|
[this](Core::State state) { LoadSettings(state); });
|
||||||
LoadSettings(Core::GetState(Core::System::GetInstance()));
|
LoadSettings(Core::GetState(Core::System::GetInstance()));
|
||||||
|
|
||||||
|
m_bluetooth_adapter_refresh_thread.Reset("Bluetooth Adapter Refresh Thread");
|
||||||
|
StartBluetoothAdapterRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
WiimoteControllersWidget::~WiimoteControllersWidget()
|
||||||
|
{
|
||||||
|
m_bluetooth_adapter_refresh_thread.WaitForCompletion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiimoteControllersWidget::UpdateBluetoothAvailableStatus()
|
void WiimoteControllersWidget::UpdateBluetoothAvailableStatus()
|
||||||
@ -58,17 +68,46 @@ void WiimoteControllersWidget::UpdateBluetoothAvailableStatus()
|
|||||||
m_bluetooth_unavailable->setHidden(WiimoteReal::IsScannerReady());
|
m_bluetooth_unavailable->setHidden(WiimoteReal::IsScannerReady());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiimoteControllersWidget::RefreshBluetoothAdapters()
|
void WiimoteControllersWidget::StartBluetoothAdapterRefresh()
|
||||||
{
|
{
|
||||||
m_bluetooth_adapters->clear();
|
if (m_bluetooth_adapter_scan_in_progress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_bluetooth_adapters->clear();
|
||||||
|
m_bluetooth_adapters->setDisabled(true);
|
||||||
|
m_bluetooth_adapters->addItem(tr("Scanning for adapters..."));
|
||||||
|
|
||||||
|
m_bluetooth_adapter_scan_in_progress = true;
|
||||||
|
|
||||||
|
const auto scan_func = [this]() {
|
||||||
|
INFO_LOG_FMT(COMMON, "Refreshing Bluetooth adapter list...");
|
||||||
|
auto device_list = IOS::HLE::BluetoothRealDevice::ListDevices();
|
||||||
|
INFO_LOG_FMT(COMMON, "{} Bluetooth adapters available.", device_list.size());
|
||||||
|
const auto refresh_complete_func = [this, devices = std::move(device_list)]() {
|
||||||
|
OnBluetoothAdapterRefreshComplete(devices);
|
||||||
|
};
|
||||||
|
QueueOnObject(this, refresh_complete_func);
|
||||||
|
};
|
||||||
|
|
||||||
|
m_bluetooth_adapter_refresh_thread.Push(scan_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiimoteControllersWidget::OnBluetoothAdapterRefreshComplete(
|
||||||
|
const std::vector<IOS::HLE::BluetoothRealDevice::BluetoothDeviceInfo>& devices)
|
||||||
|
{
|
||||||
const int configured_vid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_VID);
|
const int configured_vid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_VID);
|
||||||
const int configured_pid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_PID);
|
const int configured_pid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_PID);
|
||||||
bool found_configured_device = configured_vid == -1 || configured_pid == -1;
|
bool found_configured_device = configured_vid == -1 || configured_pid == -1;
|
||||||
|
|
||||||
|
m_bluetooth_adapters->clear();
|
||||||
|
m_bluetooth_adapter_scan_in_progress = false;
|
||||||
|
|
||||||
|
const auto state = Core::GetState(Core::System::GetInstance());
|
||||||
|
UpdateBluetoothAdapterWidgetsEnabled(state);
|
||||||
|
|
||||||
m_bluetooth_adapters->addItem(tr("Automatic"));
|
m_bluetooth_adapters->addItem(tr("Automatic"));
|
||||||
|
|
||||||
for (auto& device : IOS::HLE::BluetoothRealDevice::ListDevices())
|
for (auto& device : devices)
|
||||||
{
|
{
|
||||||
std::string name = device.name.empty() ? tr("Unknown Device").toStdString() : device.name;
|
std::string name = device.name.empty() ? tr("Unknown Device").toStdString() : device.name;
|
||||||
QString device_info =
|
QString device_info =
|
||||||
@ -149,8 +188,9 @@ void WiimoteControllersWidget::CreateLayout()
|
|||||||
m_wiimote_box->setLayout(m_wiimote_layout);
|
m_wiimote_box->setLayout(m_wiimote_layout);
|
||||||
|
|
||||||
m_wiimote_passthrough = new QRadioButton(tr("Passthrough a Bluetooth adapter"));
|
m_wiimote_passthrough = new QRadioButton(tr("Passthrough a Bluetooth adapter"));
|
||||||
m_bluetooth_adapters_label = new QLabel(tr("Bluetooth adapter"));
|
m_bluetooth_adapters_label = new QLabel(tr("Adapter"));
|
||||||
m_bluetooth_adapters = new QComboBox();
|
m_bluetooth_adapters = new QComboBox();
|
||||||
|
m_bluetooth_adapters_refresh = new NonDefaultQPushButton(tr("Refresh"));
|
||||||
m_wiimote_sync = new NonDefaultQPushButton(tr("Sync"));
|
m_wiimote_sync = new NonDefaultQPushButton(tr("Sync"));
|
||||||
m_wiimote_reset = new NonDefaultQPushButton(tr("Reset"));
|
m_wiimote_reset = new NonDefaultQPushButton(tr("Reset"));
|
||||||
m_wiimote_refresh = new NonDefaultQPushButton(tr("Refresh"));
|
m_wiimote_refresh = new NonDefaultQPushButton(tr("Refresh"));
|
||||||
@ -172,7 +212,8 @@ void WiimoteControllersWidget::CreateLayout()
|
|||||||
|
|
||||||
int adapter_row = m_wiimote_layout->rowCount();
|
int adapter_row = m_wiimote_layout->rowCount();
|
||||||
m_wiimote_layout->addWidget(m_bluetooth_adapters_label, adapter_row, 1, 1, 1);
|
m_wiimote_layout->addWidget(m_bluetooth_adapters_label, adapter_row, 1, 1, 1);
|
||||||
m_wiimote_layout->addWidget(m_bluetooth_adapters, adapter_row, 2, 1, 2);
|
m_wiimote_layout->addWidget(m_bluetooth_adapters, adapter_row, 2, 1, 1);
|
||||||
|
m_wiimote_layout->addWidget(m_bluetooth_adapters_refresh, adapter_row, 3, 1, 1);
|
||||||
|
|
||||||
int sync_row = m_wiimote_layout->rowCount();
|
int sync_row = m_wiimote_layout->rowCount();
|
||||||
m_wiimote_layout->addWidget(m_wiimote_pt_labels[0], sync_row, 1, 1, 2);
|
m_wiimote_layout->addWidget(m_wiimote_pt_labels[0], sync_row, 1, 1, 2);
|
||||||
@ -242,6 +283,8 @@ void WiimoteControllersWidget::ConnectWidgets()
|
|||||||
&WiimoteControllersWidget::SaveSettings);
|
&WiimoteControllersWidget::SaveSettings);
|
||||||
connect(m_bluetooth_adapters, &QComboBox::activated, this,
|
connect(m_bluetooth_adapters, &QComboBox::activated, this,
|
||||||
&WiimoteControllersWidget::OnBluetoothPassthroughDeviceChanged);
|
&WiimoteControllersWidget::OnBluetoothPassthroughDeviceChanged);
|
||||||
|
connect(m_bluetooth_adapters_refresh, &QPushButton::clicked, this,
|
||||||
|
&WiimoteControllersWidget::StartBluetoothAdapterRefresh);
|
||||||
connect(m_wiimote_sync, &QPushButton::clicked, this,
|
connect(m_wiimote_sync, &QPushButton::clicked, this,
|
||||||
&WiimoteControllersWidget::OnBluetoothPassthroughSyncPressed);
|
&WiimoteControllersWidget::OnBluetoothPassthroughSyncPressed);
|
||||||
connect(m_wiimote_reset, &QPushButton::clicked, this,
|
connect(m_wiimote_reset, &QPushButton::clicked, this,
|
||||||
@ -339,6 +382,19 @@ void WiimoteControllersWidget::OnWiimoteConfigure(size_t index)
|
|||||||
window->show();
|
window->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WiimoteControllersWidget::UpdateBluetoothAdapterWidgetsEnabled(const Core::State state)
|
||||||
|
{
|
||||||
|
const bool running = state != Core::State::Uninitialized;
|
||||||
|
const bool running_wii = running && Core::System::GetInstance().IsWii();
|
||||||
|
const bool enable_adapter_refresh = m_wiimote_passthrough->isChecked() && !running_wii;
|
||||||
|
const bool enable_adapter_selection =
|
||||||
|
enable_adapter_refresh && !m_bluetooth_adapter_scan_in_progress;
|
||||||
|
|
||||||
|
m_bluetooth_adapters_label->setEnabled(enable_adapter_selection);
|
||||||
|
m_bluetooth_adapters->setEnabled(enable_adapter_selection);
|
||||||
|
m_bluetooth_adapters_refresh->setEnabled(enable_adapter_refresh);
|
||||||
|
}
|
||||||
|
|
||||||
void WiimoteControllersWidget::LoadSettings(Core::State state)
|
void WiimoteControllersWidget::LoadSettings(Core::State state)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||||
@ -369,15 +425,13 @@ void WiimoteControllersWidget::LoadSettings(Core::State state)
|
|||||||
m_wiimote_passthrough->setEnabled(!running);
|
m_wiimote_passthrough->setEnabled(!running);
|
||||||
|
|
||||||
const bool running_gc = running && !Core::System::GetInstance().IsWii();
|
const bool running_gc = running && !Core::System::GetInstance().IsWii();
|
||||||
const bool running_wii = running && Core::System::GetInstance().IsWii();
|
|
||||||
const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc;
|
const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc;
|
||||||
const bool enable_adapter_selection = m_wiimote_passthrough->isChecked() && !running_wii;
|
|
||||||
const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc;
|
const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc;
|
||||||
const bool is_netplay = NetPlay::IsNetPlayRunning();
|
const bool is_netplay = NetPlay::IsNetPlayRunning();
|
||||||
const bool running_netplay = running && is_netplay;
|
const bool running_netplay = running && is_netplay;
|
||||||
|
|
||||||
m_bluetooth_adapters_label->setEnabled(enable_adapter_selection);
|
UpdateBluetoothAdapterWidgetsEnabled(state);
|
||||||
m_bluetooth_adapters->setEnabled(enable_adapter_selection);
|
|
||||||
m_wiimote_sync->setEnabled(enable_passthrough);
|
m_wiimote_sync->setEnabled(enable_passthrough);
|
||||||
m_wiimote_reset->setEnabled(enable_passthrough);
|
m_wiimote_reset->setEnabled(enable_passthrough);
|
||||||
|
|
||||||
|
@ -3,9 +3,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include <array>
|
#include "Common/WorkQueueThread.h"
|
||||||
|
#include "Core/IOS/USB/Bluetooth/BTReal.h"
|
||||||
|
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
@ -26,17 +29,21 @@ class WiimoteControllersWidget final : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit WiimoteControllersWidget(QWidget* parent);
|
explicit WiimoteControllersWidget(QWidget* parent);
|
||||||
|
~WiimoteControllersWidget();
|
||||||
|
|
||||||
void UpdateBluetoothAvailableStatus();
|
void UpdateBluetoothAvailableStatus();
|
||||||
void RefreshBluetoothAdapters();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SaveSettings();
|
void SaveSettings();
|
||||||
void OnBluetoothPassthroughDeviceChanged(int index);
|
void OnBluetoothPassthroughDeviceChanged(int index);
|
||||||
void OnBluetoothPassthroughSyncPressed();
|
void OnBluetoothPassthroughSyncPressed();
|
||||||
void OnBluetoothPassthroughResetPressed();
|
void OnBluetoothPassthroughResetPressed();
|
||||||
|
void OnBluetoothAdapterRefreshComplete(
|
||||||
|
const std::vector<IOS::HLE::BluetoothRealDevice::BluetoothDeviceInfo>& devices);
|
||||||
void OnWiimoteRefreshPressed();
|
void OnWiimoteRefreshPressed();
|
||||||
void OnWiimoteConfigure(size_t index);
|
void OnWiimoteConfigure(size_t index);
|
||||||
|
void StartBluetoothAdapterRefresh();
|
||||||
|
void UpdateBluetoothAdapterWidgetsEnabled(Core::State state);
|
||||||
|
|
||||||
void CreateLayout();
|
void CreateLayout();
|
||||||
void ConnectWidgets();
|
void ConnectWidgets();
|
||||||
@ -50,10 +57,14 @@ private:
|
|||||||
std::array<QHBoxLayout*, 4> m_wiimote_groups;
|
std::array<QHBoxLayout*, 4> m_wiimote_groups;
|
||||||
std::array<QLabel*, 2> m_wiimote_pt_labels;
|
std::array<QLabel*, 2> m_wiimote_pt_labels;
|
||||||
|
|
||||||
|
Common::AsyncWorkThreadSP m_bluetooth_adapter_refresh_thread;
|
||||||
|
bool m_bluetooth_adapter_scan_in_progress = false;
|
||||||
|
|
||||||
QRadioButton* m_wiimote_emu;
|
QRadioButton* m_wiimote_emu;
|
||||||
QRadioButton* m_wiimote_passthrough;
|
QRadioButton* m_wiimote_passthrough;
|
||||||
QLabel* m_bluetooth_adapters_label;
|
QLabel* m_bluetooth_adapters_label;
|
||||||
QComboBox* m_bluetooth_adapters;
|
QComboBox* m_bluetooth_adapters;
|
||||||
|
QPushButton* m_bluetooth_adapters_refresh;
|
||||||
QPushButton* m_wiimote_sync;
|
QPushButton* m_wiimote_sync;
|
||||||
QPushButton* m_wiimote_reset;
|
QPushButton* m_wiimote_reset;
|
||||||
QCheckBox* m_wiimote_continuous_scanning;
|
QCheckBox* m_wiimote_continuous_scanning;
|
||||||
|
Reference in New Issue
Block a user