qt: continue event loop during game close

This commit is contained in:
Liam 2022-12-18 23:09:44 -05:00
parent 1b11e0f0d3
commit 053ad04d3f
4 changed files with 64 additions and 14 deletions

View File

@ -1550,8 +1550,9 @@ void GMainWindow::AllowOSSleep() {
bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) { bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) {
// Shutdown previous session if the emu thread is still active... // Shutdown previous session if the emu thread is still active...
if (emu_thread != nullptr) if (emu_thread != nullptr) {
ShutdownGame(); ShutdownGame();
}
if (!render_window->InitRenderTarget()) { if (!render_window->InitRenderTarget()) {
return false; return false;
@ -1779,7 +1780,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
OnStartGame(); OnStartGame();
} }
void GMainWindow::ShutdownGame() { void GMainWindow::OnShutdownBegin() {
if (!emulation_running) { if (!emulation_running) {
return; return;
} }
@ -1802,13 +1803,41 @@ void GMainWindow::ShutdownGame() {
emit EmulationStopping(); emit EmulationStopping();
// Wait for emulation thread to complete and delete it shutdown_timer.setSingleShot(true);
if (system->DebuggerEnabled() || !emu_thread->wait(5000)) { shutdown_timer.start(system->DebuggerEnabled() ? 0 : 5000);
connect(&shutdown_timer, &QTimer::timeout, this, &GMainWindow::OnEmulationStopTimeExpired);
connect(emu_thread.get(), &QThread::finished, this, &GMainWindow::OnEmulationStopped);
// Disable everything to prevent anything from being triggered here
ui->action_Pause->setEnabled(false);
ui->action_Restart->setEnabled(false);
ui->action_Stop->setEnabled(false);
}
void GMainWindow::OnShutdownBeginDialog() {
shutdown_dialog =
new OverlayDialog(render_window, *system, QString{}, tr("Closing software..."), QString{},
QString{}, Qt::AlignHCenter | Qt::AlignVCenter);
shutdown_dialog->open();
}
void GMainWindow::OnEmulationStopTimeExpired() {
if (emu_thread) {
emu_thread->ForceStop(); emu_thread->ForceStop();
emu_thread->wait();
} }
}
void GMainWindow::OnEmulationStopped() {
shutdown_timer.stop();
emu_thread->disconnect();
emu_thread->wait();
emu_thread = nullptr; emu_thread = nullptr;
if (shutdown_dialog) {
shutdown_dialog->deleteLater();
shutdown_dialog = nullptr;
}
emulation_running = false; emulation_running = false;
discord_rpc->Update(); discord_rpc->Update();
@ -1854,6 +1883,20 @@ void GMainWindow::ShutdownGame() {
// When closing the game, destroy the GLWindow to clear the context after the game is closed // When closing the game, destroy the GLWindow to clear the context after the game is closed
render_window->ReleaseRenderTarget(); render_window->ReleaseRenderTarget();
Settings::RestoreGlobalState(system->IsPoweredOn());
system->HIDCore().ReloadInputDevices();
UpdateStatusButtons();
}
void GMainWindow::ShutdownGame() {
if (!emulation_running) {
return;
}
OnShutdownBegin();
OnEmulationStopTimeExpired();
OnEmulationStopped();
} }
void GMainWindow::StoreRecentFile(const QString& filename) { void GMainWindow::StoreRecentFile(const QString& filename) {
@ -2956,11 +2999,8 @@ void GMainWindow::OnStopGame() {
return; return;
} }
ShutdownGame(); OnShutdownBegin();
OnShutdownBeginDialog();
Settings::RestoreGlobalState(system->IsPoweredOn());
system->HIDCore().ReloadInputDevices();
UpdateStatusButtons();
} }
void GMainWindow::OnLoadComplete() { void GMainWindow::OnLoadComplete() {
@ -4047,10 +4087,6 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
// Shutdown session if the emu thread is active... // Shutdown session if the emu thread is active...
if (emu_thread != nullptr) { if (emu_thread != nullptr) {
ShutdownGame(); ShutdownGame();
Settings::RestoreGlobalState(system->IsPoweredOn());
system->HIDCore().ReloadInputDevices();
UpdateStatusButtons();
} }
render_window->close(); render_window->close();

View File

@ -29,6 +29,7 @@ class GImageInfo;
class GRenderWindow; class GRenderWindow;
class LoadingScreen; class LoadingScreen;
class MicroProfileDialog; class MicroProfileDialog;
class OverlayDialog;
class ProfilerWidget; class ProfilerWidget;
class ControllerDialog; class ControllerDialog;
class QLabel; class QLabel;
@ -335,6 +336,10 @@ private slots:
void OnReinitializeKeys(ReinitializeKeyBehavior behavior); void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
void OnLanguageChanged(const QString& locale); void OnLanguageChanged(const QString& locale);
void OnMouseActivity(); void OnMouseActivity();
void OnShutdownBegin();
void OnShutdownBeginDialog();
void OnEmulationStopped();
void OnEmulationStopTimeExpired();
private: private:
QString GetGameListErrorRemoving(InstalledEntryType type) const; QString GetGameListErrorRemoving(InstalledEntryType type) const;
@ -384,6 +389,8 @@ private:
GRenderWindow* render_window; GRenderWindow* render_window;
GameList* game_list; GameList* game_list;
LoadingScreen* loading_screen; LoadingScreen* loading_screen;
QTimer shutdown_timer;
OverlayDialog* shutdown_dialog;
GameListPlaceholder* game_list_placeholder; GameListPlaceholder* game_list_placeholder;

View File

@ -259,3 +259,9 @@ void OverlayDialog::InputThread() {
std::this_thread::sleep_for(std::chrono::milliseconds(50)); std::this_thread::sleep_for(std::chrono::milliseconds(50));
} }
} }
void OverlayDialog::keyPressEvent(QKeyEvent* e) {
if (!ui->buttonsDialog->isHidden() || e->key() != Qt::Key_Escape) {
QDialog::keyPressEvent(e);
}
}

View File

@ -94,6 +94,7 @@ private:
/// The thread where input is being polled and processed. /// The thread where input is being polled and processed.
void InputThread(); void InputThread();
void keyPressEvent(QKeyEvent* e) override;
std::unique_ptr<Ui::OverlayDialog> ui; std::unique_ptr<Ui::OverlayDialog> ui;