Qt: Fix multiple emulation shutdown bugs

This commit is contained in:
spycrab 2017-07-03 16:04:24 +02:00
parent 0f9ae6d361
commit ebe169a218
2 changed files with 42 additions and 16 deletions

View File

@ -166,7 +166,7 @@ void MainWindow::ConnectMenuBar()
// Emulation // Emulation
connect(m_menu_bar, &MenuBar::Pause, this, &MainWindow::Pause); connect(m_menu_bar, &MenuBar::Pause, this, &MainWindow::Pause);
connect(m_menu_bar, &MenuBar::Play, this, &MainWindow::Play); connect(m_menu_bar, &MenuBar::Play, this, &MainWindow::Play);
connect(m_menu_bar, &MenuBar::Stop, this, &MainWindow::Stop); connect(m_menu_bar, &MenuBar::Stop, this, &MainWindow::RequestStop);
connect(m_menu_bar, &MenuBar::Reset, this, &MainWindow::Reset); connect(m_menu_bar, &MenuBar::Reset, this, &MainWindow::Reset);
connect(m_menu_bar, &MenuBar::Fullscreen, this, &MainWindow::FullScreen); connect(m_menu_bar, &MenuBar::Fullscreen, this, &MainWindow::FullScreen);
connect(m_menu_bar, &MenuBar::FrameAdvance, this, &MainWindow::FrameAdvance); connect(m_menu_bar, &MenuBar::FrameAdvance, this, &MainWindow::FrameAdvance);
@ -209,7 +209,7 @@ void MainWindow::ConnectHotkeys()
{ {
connect(m_hotkey_scheduler, &HotkeyScheduler::ExitHotkey, this, &MainWindow::close); connect(m_hotkey_scheduler, &HotkeyScheduler::ExitHotkey, this, &MainWindow::close);
connect(m_hotkey_scheduler, &HotkeyScheduler::PauseHotkey, this, &MainWindow::Pause); connect(m_hotkey_scheduler, &HotkeyScheduler::PauseHotkey, this, &MainWindow::Pause);
connect(m_hotkey_scheduler, &HotkeyScheduler::StopHotkey, this, &MainWindow::Stop); connect(m_hotkey_scheduler, &HotkeyScheduler::StopHotkey, this, &MainWindow::RequestStop);
connect(m_hotkey_scheduler, &HotkeyScheduler::ScreenShotHotkey, this, &MainWindow::ScreenShot); connect(m_hotkey_scheduler, &HotkeyScheduler::ScreenShotHotkey, this, &MainWindow::ScreenShot);
connect(m_hotkey_scheduler, &HotkeyScheduler::FullScreenHotkey, this, &MainWindow::FullScreen); connect(m_hotkey_scheduler, &HotkeyScheduler::FullScreenHotkey, this, &MainWindow::FullScreen);
@ -227,7 +227,7 @@ void MainWindow::ConnectToolBar()
connect(m_tool_bar, &ToolBar::OpenPressed, this, &MainWindow::Open); connect(m_tool_bar, &ToolBar::OpenPressed, this, &MainWindow::Open);
connect(m_tool_bar, &ToolBar::PlayPressed, this, &MainWindow::Play); connect(m_tool_bar, &ToolBar::PlayPressed, this, &MainWindow::Play);
connect(m_tool_bar, &ToolBar::PausePressed, this, &MainWindow::Pause); connect(m_tool_bar, &ToolBar::PausePressed, this, &MainWindow::Pause);
connect(m_tool_bar, &ToolBar::StopPressed, this, &MainWindow::Stop); connect(m_tool_bar, &ToolBar::StopPressed, this, &MainWindow::RequestStop);
connect(m_tool_bar, &ToolBar::FullScreenPressed, this, &MainWindow::FullScreen); connect(m_tool_bar, &ToolBar::FullScreenPressed, this, &MainWindow::FullScreen);
connect(m_tool_bar, &ToolBar::ScreenShotPressed, this, &MainWindow::ScreenShot); connect(m_tool_bar, &ToolBar::ScreenShotPressed, this, &MainWindow::ScreenShot);
connect(m_tool_bar, &ToolBar::SettingsPressed, this, &MainWindow::ShowSettingsWindow); connect(m_tool_bar, &ToolBar::SettingsPressed, this, &MainWindow::ShowSettingsWindow);
@ -238,10 +238,7 @@ void MainWindow::ConnectToolBar()
connect(this, &MainWindow::EmulationPaused, m_tool_bar, &ToolBar::EmulationPaused); connect(this, &MainWindow::EmulationPaused, m_tool_bar, &ToolBar::EmulationPaused);
connect(this, &MainWindow::EmulationStopped, m_tool_bar, &ToolBar::EmulationStopped); connect(this, &MainWindow::EmulationStopped, m_tool_bar, &ToolBar::EmulationStopped);
connect(this, &MainWindow::EmulationStopped, [this] { connect(this, &MainWindow::EmulationStopped, this, &MainWindow::OnStopComplete);
m_stop_requested = false;
m_render_widget->hide();
});
} }
void MainWindow::ConnectGameList() void MainWindow::ConnectGameList()
@ -253,7 +250,7 @@ void MainWindow::ConnectRenderWidget()
{ {
m_rendering_to_main = false; m_rendering_to_main = false;
m_render_widget->hide(); m_render_widget->hide();
connect(m_render_widget, &RenderWidget::EscapePressed, this, &MainWindow::Stop); connect(m_render_widget, &RenderWidget::EscapePressed, this, &MainWindow::RequestStop);
connect(m_render_widget, &RenderWidget::Closed, this, &MainWindow::ForceStop); connect(m_render_widget, &RenderWidget::Closed, this, &MainWindow::ForceStop);
} }
@ -314,15 +311,34 @@ void MainWindow::Pause()
emit EmulationPaused(); emit EmulationPaused();
} }
bool MainWindow::Stop() void MainWindow::OnStopComplete()
{
m_stop_requested = false;
m_render_widget->hide();
if (m_exit_requested)
QGuiApplication::instance()->quit();
// If the current emulation prevented the booting of another, do that now
if (!m_pending_boot.isEmpty())
{
StartGame(m_pending_boot);
m_pending_boot.clear();
}
}
bool MainWindow::RequestStop()
{ {
if (!Core::IsRunning()) if (!Core::IsRunning())
{
Core::QueueHostJob([this] { OnStopComplete(); }, true);
return true; return true;
}
if (Settings::Instance().GetConfirmStop()) if (Settings::Instance().GetConfirmStop())
{ {
const Core::State state = Core::GetState(); const Core::State state = Core::GetState();
// Set to false when Netplay is running as a CPU thread // TODO: Set to false when Netplay is running as a CPU thread
bool pause = true; bool pause = true;
if (pause) if (pause)
@ -335,6 +351,7 @@ bool MainWindow::Stop()
"may be lost if you stop the current emulation " "may be lost if you stop the current emulation "
"before it completes. Force stop?") : "before it completes. Force stop?") :
tr("Do you want to stop the current emulation?")); tr("Do you want to stop the current emulation?"));
if (pause) if (pause)
Core::SetState(state); Core::SetState(state);
@ -350,15 +367,14 @@ bool MainWindow::Stop()
m_stop_requested = true; m_stop_requested = true;
// Unpause because gracefully shutting down needs the game to actually request a shutdown. // Unpause because gracefully shutting down needs the game to actually request a shutdown.
// Do not unpause in debug mode to allow debugging until the complete shutdown. // TODO: Do not unpause in debug mode to allow debugging until the complete shutdown.
if (Core::GetState() == Core::State::Paused) if (Core::GetState() == Core::State::Paused)
Core::SetState(Core::State::Running); Core::SetState(Core::State::Running);
return false; return true;
} }
ForceStop(); ForceStop();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Allow windows to idle or turn off display again // Allow windows to idle or turn off display again
SetThreadExecutionState(ES_CONTINUOUS); SetThreadExecutionState(ES_CONTINUOUS);
@ -408,8 +424,12 @@ void MainWindow::StartGame(const QString& path)
// If we're running, only start a new game once we've stopped the last. // If we're running, only start a new game once we've stopped the last.
if (Core::GetState() != Core::State::Uninitialized) if (Core::GetState() != Core::State::Uninitialized)
{ {
if (!Stop()) if (!RequestStop())
return; return;
// As long as the shutdown isn't complete, we can't boot, so let's boot later
m_pending_boot = path;
return;
} }
// Boot up, show an error if it fails to load the game. // Boot up, show an error if it fails to load the game.
if (!BootManager::BootCore(BootParameters::GenerateFromFile(path.toStdString()))) if (!BootManager::BootCore(BootParameters::GenerateFromFile(path.toStdString())))
@ -570,8 +590,11 @@ void MainWindow::PerformOnlineUpdate(const std::string& region)
bool MainWindow::eventFilter(QObject* object, QEvent* event) bool MainWindow::eventFilter(QObject* object, QEvent* event)
{ {
if (event->type() == QEvent::Close && !Stop()) if (event->type() == QEvent::Close)
{ {
if (RequestStop() && object == this)
m_exit_requested = true;
static_cast<QCloseEvent*>(event)->ignore(); static_cast<QCloseEvent*>(event)->ignore();
return true; return true;
} }

View File

@ -42,7 +42,7 @@ private slots:
void Pause(); void Pause();
// May ask for confirmation. Returns whether or not it actually stopped. // May ask for confirmation. Returns whether or not it actually stopped.
bool Stop(); bool RequestStop();
void ForceStop(); void ForceStop();
void Reset(); void Reset();
void FrameAdvance(); void FrameAdvance();
@ -87,6 +87,7 @@ private:
void ShowAboutDialog(); void ShowAboutDialog();
void ShowHotkeyDialog(); void ShowHotkeyDialog();
void OnStopComplete();
void dragEnterEvent(QDragEnterEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent* event) override; void dropEvent(QDropEvent* event) override;
@ -97,7 +98,9 @@ private:
RenderWidget* m_render_widget; RenderWidget* m_render_widget;
bool m_rendering_to_main; bool m_rendering_to_main;
bool m_stop_requested = false; bool m_stop_requested = false;
bool m_exit_requested = false;
int m_state_slot = 1; int m_state_slot = 1;
QString m_pending_boot;
HotkeyScheduler* m_hotkey_scheduler; HotkeyScheduler* m_hotkey_scheduler;
ControllersWindow* m_controllers_window; ControllersWindow* m_controllers_window;