Merge pull request #7093 from Morph1984/exit
core: Properly shutdown and exit the running application when ISelfController::Exit is called
This commit is contained in:
commit
ae3e51c795
|
@ -421,6 +421,7 @@ struct System::Impl {
|
||||||
bool is_async_gpu{};
|
bool is_async_gpu{};
|
||||||
|
|
||||||
ExecuteProgramCallback execute_program_callback;
|
ExecuteProgramCallback execute_program_callback;
|
||||||
|
ExitCallback exit_callback;
|
||||||
|
|
||||||
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
||||||
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
|
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
|
||||||
|
@ -798,6 +799,18 @@ void System::ExecuteProgram(std::size_t program_index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void System::RegisterExitCallback(ExitCallback&& callback) {
|
||||||
|
impl->exit_callback = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::Exit() {
|
||||||
|
if (impl->exit_callback) {
|
||||||
|
impl->exit_callback();
|
||||||
|
} else {
|
||||||
|
LOG_CRITICAL(Core, "exit_callback must be initialized by the frontend");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void System::ApplySettings() {
|
void System::ApplySettings() {
|
||||||
if (IsPoweredOn()) {
|
if (IsPoweredOn()) {
|
||||||
Renderer().RefreshBaseSettings();
|
Renderer().RefreshBaseSettings();
|
||||||
|
|
|
@ -387,6 +387,18 @@ public:
|
||||||
*/
|
*/
|
||||||
void ExecuteProgram(std::size_t program_index);
|
void ExecuteProgram(std::size_t program_index);
|
||||||
|
|
||||||
|
/// Type used for the frontend to designate a callback for System to exit the application.
|
||||||
|
using ExitCallback = std::function<void()>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a callback from the frontend for System to exit the application.
|
||||||
|
* @param callback Callback from the frontend to exit the application.
|
||||||
|
*/
|
||||||
|
void RegisterExitCallback(ExitCallback&& callback);
|
||||||
|
|
||||||
|
/// Instructs the frontend to exit the application.
|
||||||
|
void Exit();
|
||||||
|
|
||||||
/// Applies any changes to settings to this core instance.
|
/// Applies any changes to settings to this core instance.
|
||||||
void ApplySettings();
|
void ApplySettings();
|
||||||
|
|
||||||
|
|
|
@ -332,10 +332,10 @@ ISelfController::~ISelfController() = default;
|
||||||
void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
|
void ISelfController::Exit(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
system.Shutdown();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
system.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
|
void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
|
@ -302,12 +302,17 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||||
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
|
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
|
||||||
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
|
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
connect(this, &GRenderWindow::ExitSignal, parent, &GMainWindow::OnExit, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
|
void GRenderWindow::ExecuteProgram(std::size_t program_index) {
|
||||||
emit ExecuteProgramSignal(program_index);
|
emit ExecuteProgramSignal(program_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GRenderWindow::Exit() {
|
||||||
|
emit ExitSignal();
|
||||||
|
}
|
||||||
|
|
||||||
GRenderWindow::~GRenderWindow() {
|
GRenderWindow::~GRenderWindow() {
|
||||||
input_subsystem->Shutdown();
|
input_subsystem->Shutdown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void ExecuteProgram(std::size_t program_index);
|
void ExecuteProgram(std::size_t program_index);
|
||||||
|
|
||||||
|
/// Instructs the window to exit the application.
|
||||||
|
void Exit();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnEmulationStarting(EmuThread* emu_thread);
|
void OnEmulationStarting(EmuThread* emu_thread);
|
||||||
void OnEmulationStopping();
|
void OnEmulationStopping();
|
||||||
|
@ -191,6 +194,7 @@ signals:
|
||||||
void Closed();
|
void Closed();
|
||||||
void FirstFrameDisplayed();
|
void FirstFrameDisplayed();
|
||||||
void ExecuteProgramSignal(std::size_t program_index);
|
void ExecuteProgramSignal(std::size_t program_index);
|
||||||
|
void ExitSignal();
|
||||||
void MouseActivity();
|
void MouseActivity();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1384,6 +1384,9 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
||||||
system.RegisterExecuteProgramCallback(
|
system.RegisterExecuteProgramCallback(
|
||||||
[this](std::size_t program_index) { render_window->ExecuteProgram(program_index); });
|
[this](std::size_t program_index) { render_window->ExecuteProgram(program_index); });
|
||||||
|
|
||||||
|
// Register an Exit callback such that Core can exit the currently running application.
|
||||||
|
system.RegisterExitCallback([this]() { render_window->Exit(); });
|
||||||
|
|
||||||
connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
|
connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
|
||||||
connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity);
|
connect(render_window, &GRenderWindow::MouseActivity, this, &GMainWindow::OnMouseActivity);
|
||||||
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
|
// BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
|
||||||
|
@ -2469,6 +2472,10 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
|
||||||
BootGame(last_filename_booted, 0, program_index);
|
BootGame(last_filename_booted, 0, program_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnExit() {
|
||||||
|
OnStopGame();
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
|
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
|
||||||
OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text,
|
OverlayDialog dialog(render_window, Core::System::GetInstance(), error_code, error_text,
|
||||||
QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
|
QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
|
|
@ -153,6 +153,7 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
void OnLoadComplete();
|
void OnLoadComplete();
|
||||||
void OnExecuteProgram(std::size_t program_index);
|
void OnExecuteProgram(std::size_t program_index);
|
||||||
|
void OnExit();
|
||||||
void ControllerSelectorReconfigureControllers(
|
void ControllerSelectorReconfigureControllers(
|
||||||
const Core::Frontend::ControllerParameters& parameters);
|
const Core::Frontend::ControllerParameters& parameters);
|
||||||
void SoftwareKeyboardInitialize(
|
void SoftwareKeyboardInitialize(
|
||||||
|
|
Reference in New Issue