Make configure dialog non-blocking
Currently, when the configure dialog is open, it prevents inputs to the main window. This is annoying if you are trying to change your keybinds as you have to constantly reopen the configure dialog to test your keys. To make the window non-blocking, we use .show() instead of .exec() on the configure dialog, and have a slot handle when the confirmation buttons (ok, cancel, x) are pressed. However, entering the configuration dialog disables inputs to prevent sending inputs to the running game while changing inputs. We modify this by preventing inputs from being sent to the game only when focus is not on the main menu. The steps are as follows: - Determine focus in/focus out on main window with QGuiApplication::focusWindowChanged - Send focus in/focus out signal to ConfigureDialog slot - ConfigureDialog slot calls EnableConfiguration/DisableConfiguration for ConfigureInput - ConfigureInput calls EnableConfiguration/DisableConfiguration for ConfigureInputPlayer Added: - Signal FocusIn/FocusOut for GMainWindow - EnableConfiguration()/DisableConfiguration() for ConfigureInputPlayer and ConfigureInput to control whether inputs to the game should be blocked. ConfigureInput::EnableConfiguration/DisableConfiguration simply forwards the call to ConfigureInputPlayer.
This commit is contained in:
parent
e16d1b85f1
commit
75f00f756f
8 changed files with 126 additions and 30 deletions
|
@ -117,6 +117,14 @@ void ConfigureDialog::ApplyConfiguration() {
|
|||
Settings::LogSettings();
|
||||
}
|
||||
|
||||
void ConfigureDialog::MainWindowFocusIn() {
|
||||
input_tab->DisableConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureDialog::MainWindowFocusOut() {
|
||||
input_tab->EnableConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureDialog::changeEvent(QEvent* event) {
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
RetranslateUI();
|
||||
|
|
|
@ -46,6 +46,10 @@ public:
|
|||
|
||||
void ApplyConfiguration();
|
||||
|
||||
public slots:
|
||||
void MainWindowFocusIn();
|
||||
void MainWindowFocusOut();
|
||||
|
||||
private slots:
|
||||
void OnLanguageChanged(const QString& locale);
|
||||
|
||||
|
|
|
@ -181,6 +181,18 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
|
|||
LoadConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureInput::EnableConfiguration() {
|
||||
for (auto controller : player_controllers) {
|
||||
controller->EnableConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInput::DisableConfiguration() {
|
||||
for (auto controller : player_controllers) {
|
||||
controller->DisableConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
QList<QWidget*> ConfigureInput::GetSubTabs() const {
|
||||
return {
|
||||
ui->tabPlayer1, ui->tabPlayer2, ui->tabPlayer3, ui->tabPlayer4, ui->tabPlayer5,
|
||||
|
|
|
@ -43,6 +43,12 @@ public:
|
|||
/// Initializes the input dialog with the given input subsystem.
|
||||
void Initialize(InputCommon::InputSubsystem* input_subsystem_, std::size_t max_players = 8);
|
||||
|
||||
/// Enables configuration on controllers
|
||||
void EnableConfiguration();
|
||||
|
||||
/// Disables configuration on controllers
|
||||
void DisableConfiguration();
|
||||
|
||||
/// Save all button configurations to settings file.
|
||||
void ApplyConfiguration();
|
||||
|
||||
|
|
|
@ -274,26 +274,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_),
|
||||
timeout_timer(std::make_unique<QTimer>()),
|
||||
poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
auto* emulated_controller_handheld =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
emulated_controller_p1->SaveCurrentConfig();
|
||||
emulated_controller_p1->EnableConfiguration();
|
||||
emulated_controller_handheld->SaveCurrentConfig();
|
||||
emulated_controller_handheld->EnableConfiguration();
|
||||
if (emulated_controller_handheld->IsConnected(true)) {
|
||||
emulated_controller_p1->Disconnect();
|
||||
emulated_controller = emulated_controller_handheld;
|
||||
} else {
|
||||
emulated_controller = emulated_controller_p1;
|
||||
}
|
||||
} else {
|
||||
emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index);
|
||||
emulated_controller->SaveCurrentConfig();
|
||||
emulated_controller->EnableConfiguration();
|
||||
}
|
||||
EnableConfiguration();
|
||||
ui->setupUi(this);
|
||||
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
@ -771,6 +752,33 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
|||
}
|
||||
|
||||
ConfigureInputPlayer::~ConfigureInputPlayer() {
|
||||
DisableConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::EnableConfiguration() {
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
auto* emulated_controller_handheld =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
emulated_controller_p1->SaveCurrentConfig();
|
||||
emulated_controller_p1->EnableConfiguration();
|
||||
emulated_controller_handheld->SaveCurrentConfig();
|
||||
emulated_controller_handheld->EnableConfiguration();
|
||||
if (emulated_controller_handheld->IsConnected(true)) {
|
||||
emulated_controller_p1->Disconnect();
|
||||
emulated_controller = emulated_controller_handheld;
|
||||
} else {
|
||||
emulated_controller = emulated_controller_p1;
|
||||
}
|
||||
} else {
|
||||
emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index);
|
||||
emulated_controller->SaveCurrentConfig();
|
||||
emulated_controller->EnableConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureInputPlayer::DisableConfiguration() {
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
|
|
|
@ -56,6 +56,12 @@ public:
|
|||
bool is_powered_on_, bool debug = false);
|
||||
~ConfigureInputPlayer() override;
|
||||
|
||||
/// Enables configuration on controllers
|
||||
void EnableConfiguration();
|
||||
|
||||
/// Disables configuration on controllers
|
||||
void DisableConfiguration();
|
||||
|
||||
/// Save all button configurations to settings file.
|
||||
void ApplyConfiguration();
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
|||
#include <QString>
|
||||
#include <QSysInfo>
|
||||
#include <QUrl>
|
||||
#include <QWindow>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
|
@ -1246,6 +1247,16 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
|
|||
}
|
||||
}
|
||||
|
||||
void GMainWindow::FocusWindowChanged(QWindow* focusWindow) {
|
||||
if (focusWindow && focusWindow->winId() == winId() && !main_window_in_focus) {
|
||||
emit FocusIn();
|
||||
main_window_in_focus = true;
|
||||
} else if (main_window_in_focus) {
|
||||
emit FocusOut();
|
||||
main_window_in_focus = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::ConnectWidgetEvents() {
|
||||
connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGame);
|
||||
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
|
||||
|
@ -3023,16 +3034,33 @@ void GMainWindow::ResetWindowSize1080() {
|
|||
}
|
||||
|
||||
void GMainWindow::OnConfigure() {
|
||||
const auto old_theme = UISettings::values.theme;
|
||||
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
|
||||
old_configure_value = {UISettings::values.theme,
|
||||
UISettings::values.enable_discord_presence.GetValue()};
|
||||
|
||||
Settings::SetConfiguringGlobal(true);
|
||||
ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), *system,
|
||||
!multiplayer_state->IsHostingPublicRoom());
|
||||
connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
|
||||
&GMainWindow::OnLanguageChanged);
|
||||
|
||||
const auto result = configure_dialog.exec();
|
||||
configure_dialog.reset(); // The destructor must run first
|
||||
configure_dialog =
|
||||
std::make_unique<ConfigureDialog>(this, hotkey_registry, input_subsystem.get(), *system,
|
||||
!multiplayer_state->IsHostingPublicRoom());
|
||||
connect(configure_dialog.get(), &ConfigureDialog::LanguageChanged, this,
|
||||
&GMainWindow::OnLanguageChanged);
|
||||
connect(configure_dialog.get(), &ConfigureDialog::finished, this,
|
||||
&GMainWindow::OnConfigureFinished);
|
||||
|
||||
configure_dialog->show();
|
||||
|
||||
connect(this, &GMainWindow::FocusIn, configure_dialog.get(),
|
||||
&ConfigureDialog::MainWindowFocusIn);
|
||||
connect(this, &GMainWindow::FocusOut, configure_dialog.get(),
|
||||
&ConfigureDialog::MainWindowFocusOut);
|
||||
}
|
||||
|
||||
void GMainWindow::OnConfigureFinished(int result) {
|
||||
// Configure dialog needs to be deleted after this function finishes to run the appropriate
|
||||
// destructors
|
||||
std::unique_ptr<ConfigureDialog> config_dialog(std::move(configure_dialog));
|
||||
|
||||
if (result != QDialog::Accepted && !UISettings::values.configuration_applied &&
|
||||
!UISettings::values.reset_to_defaults) {
|
||||
// Runs if the user hit Cancel or closed the window, and did not ever press the Apply button
|
||||
|
@ -3042,7 +3070,7 @@ void GMainWindow::OnConfigure() {
|
|||
// Only apply new changes if user hit Okay
|
||||
// This is here to avoid applying changes if the user hit Apply, made some changes, then hit
|
||||
// Cancel
|
||||
configure_dialog.ApplyConfiguration();
|
||||
config_dialog->ApplyConfiguration();
|
||||
} else if (UISettings::values.reset_to_defaults) {
|
||||
LOG_INFO(Frontend, "Resetting all settings to defaults");
|
||||
if (!Common::FS::RemoveFile(config->GetConfigFilePath())) {
|
||||
|
@ -3079,10 +3107,11 @@ void GMainWindow::OnConfigure() {
|
|||
}
|
||||
InitializeHotkeys();
|
||||
|
||||
if (UISettings::values.theme != old_theme) {
|
||||
if (UISettings::values.theme != old_configure_value.theme) {
|
||||
UpdateUITheme();
|
||||
}
|
||||
if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) {
|
||||
if (UISettings::values.enable_discord_presence.GetValue() !=
|
||||
old_configure_value.discord_presence) {
|
||||
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
|
||||
}
|
||||
|
||||
|
@ -4232,6 +4261,8 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
QObject::connect(&app, &QGuiApplication::applicationStateChanged, &main_window,
|
||||
&GMainWindow::OnAppFocusStateChanged);
|
||||
QObject::connect(&app, &QGuiApplication::focusWindowChanged, &main_window,
|
||||
&GMainWindow::FocusWindowChanged);
|
||||
|
||||
int result = app.exec();
|
||||
detached_tasks.WaitForAllTasks();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
class Config;
|
||||
class ClickableLabel;
|
||||
class ConfigureDialog;
|
||||
class EmuThread;
|
||||
class GameList;
|
||||
class GImageInfo;
|
||||
|
@ -122,6 +123,12 @@ class GMainWindow : public QMainWindow {
|
|||
UI_EMU_STOPPING,
|
||||
};
|
||||
|
||||
// Used to save previous configure values to check for changes
|
||||
struct OldConfigureValue {
|
||||
QString theme;
|
||||
bool discord_presence;
|
||||
};
|
||||
|
||||
public:
|
||||
void filterBarSetChecked(bool state);
|
||||
void UpdateUITheme();
|
||||
|
@ -132,6 +139,11 @@ public:
|
|||
void AcceptDropEvent(QDropEvent* event);
|
||||
|
||||
signals:
|
||||
/// Emitted when this main window receives focus
|
||||
void FocusIn();
|
||||
|
||||
/// Emitted when this main window loses focus
|
||||
void FocusOut();
|
||||
|
||||
/**
|
||||
* Signal that is emitted when a new EmuThread has been created and an emulation session is
|
||||
|
@ -195,6 +207,7 @@ public slots:
|
|||
void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
|
||||
bool is_local);
|
||||
void OnAppFocusStateChanged(Qt::ApplicationState state);
|
||||
void FocusWindowChanged(QWindow* focusWindow);
|
||||
void OnTasStateChanged();
|
||||
|
||||
private:
|
||||
|
@ -303,6 +316,7 @@ private slots:
|
|||
void OnMenuInstallToNAND();
|
||||
void OnMenuRecentFile();
|
||||
void OnConfigure();
|
||||
void OnConfigureFinished(int result);
|
||||
void OnConfigureTas();
|
||||
void OnTasStartStop();
|
||||
void OnTasRecord();
|
||||
|
@ -430,6 +444,11 @@ private:
|
|||
// Install progress dialog
|
||||
QProgressDialog* install_progress;
|
||||
|
||||
// Configuration dialog, use unique_ptr as it is possible for the user to open the configure
|
||||
// menu multiple times, thus we must delete the old menu
|
||||
std::unique_ptr<ConfigureDialog> configure_dialog;
|
||||
OldConfigureValue old_configure_value;
|
||||
|
||||
// Last game booted, used for multi-process apps
|
||||
QString last_filename_booted;
|
||||
|
||||
|
@ -445,6 +464,8 @@ private:
|
|||
// True if TAS recording dialog is visible
|
||||
bool is_tas_recording_dialog_active{};
|
||||
|
||||
bool main_window_in_focus = false;
|
||||
|
||||
#ifdef __unix__
|
||||
QSocketNotifier* sig_interrupt_notifier;
|
||||
static std::array<int, 3> sig_interrupt_fds;
|
||||
|
|
Loading…
Add table
Reference in a new issue