Merge pull request #9505 from liamwhite/request-exit

applets: implement RequestExit
This commit is contained in:
liamwhite
2023-03-29 09:11:34 -04:00
committed by GitHub
48 changed files with 312 additions and 61 deletions

View File

@ -245,12 +245,19 @@ void QtAmiiboSettingsDialog::SetSettingsDescription() {
QtAmiiboSettings::QtAmiiboSettings(GMainWindow& parent) {
connect(this, &QtAmiiboSettings::MainWindowShowAmiiboSettings, &parent,
&GMainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection);
connect(this, &QtAmiiboSettings::MainWindowRequestExit, &parent,
&GMainWindow::AmiiboSettingsRequestExit, Qt::QueuedConnection);
connect(&parent, &GMainWindow::AmiiboSettingsFinished, this,
&QtAmiiboSettings::MainWindowFinished, Qt::QueuedConnection);
}
QtAmiiboSettings::~QtAmiiboSettings() = default;
void QtAmiiboSettings::Close() const {
callback = {};
emit MainWindowRequestExit();
}
void QtAmiiboSettings::ShowCabinetApplet(
const Core::Frontend::CabinetCallback& callback_,
const Core::Frontend::CabinetParameters& parameters,
@ -260,5 +267,7 @@ void QtAmiiboSettings::ShowCabinetApplet(
}
void QtAmiiboSettings::MainWindowFinished(bool is_success, const std::string& name) {
callback(is_success, name);
if (callback) {
callback(is_success, name);
}
}

View File

@ -68,6 +68,7 @@ public:
explicit QtAmiiboSettings(GMainWindow& parent);
~QtAmiiboSettings() override;
void Close() const override;
void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_,
const Core::Frontend::CabinetParameters& parameters,
std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override;
@ -75,6 +76,7 @@ public:
signals:
void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters,
std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const;
void MainWindowRequestExit() const;
private:
void MainWindowFinished(bool is_success, const std::string& name);

View File

@ -678,12 +678,19 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
QtControllerSelector::QtControllerSelector(GMainWindow& parent) {
connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent,
&GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection);
connect(this, &QtControllerSelector::MainWindowRequestExit, &parent,
&GMainWindow::ControllerSelectorRequestExit, Qt::QueuedConnection);
connect(&parent, &GMainWindow::ControllerSelectorReconfigureFinished, this,
&QtControllerSelector::MainWindowReconfigureFinished, Qt::QueuedConnection);
}
QtControllerSelector::~QtControllerSelector() = default;
void QtControllerSelector::Close() const {
callback = {};
emit MainWindowRequestExit();
}
void QtControllerSelector::ReconfigureControllers(
ReconfigureCallback callback_, const Core::Frontend::ControllerParameters& parameters) const {
callback = std::move(callback_);
@ -691,5 +698,7 @@ void QtControllerSelector::ReconfigureControllers(
}
void QtControllerSelector::MainWindowReconfigureFinished() {
callback();
if (callback) {
callback();
}
}

View File

@ -156,6 +156,7 @@ public:
explicit QtControllerSelector(GMainWindow& parent);
~QtControllerSelector() override;
void Close() const override;
void ReconfigureControllers(
ReconfigureCallback callback_,
const Core::Frontend::ControllerParameters& parameters) const override;
@ -163,6 +164,7 @@ public:
signals:
void MainWindowReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters) const;
void MainWindowRequestExit() const;
private:
void MainWindowReconfigureFinished();

View File

@ -8,12 +8,19 @@
QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent,
&GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection);
connect(this, &QtErrorDisplay::MainWindowRequestExit, &parent,
&GMainWindow::ErrorDisplayRequestExit, Qt::QueuedConnection);
connect(&parent, &GMainWindow::ErrorDisplayFinished, this,
&QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection);
}
QtErrorDisplay::~QtErrorDisplay() = default;
void QtErrorDisplay::Close() const {
callback = {};
emit MainWindowRequestExit();
}
void QtErrorDisplay::ShowError(Result error, FinishedCallback finished) const {
callback = std::move(finished);
emit MainWindowDisplayError(
@ -55,5 +62,7 @@ void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text,
}
void QtErrorDisplay::MainWindowFinishedError() {
callback();
if (callback) {
callback();
}
}

View File

@ -16,6 +16,7 @@ public:
explicit QtErrorDisplay(GMainWindow& parent);
~QtErrorDisplay() override;
void Close() const override;
void ShowError(Result error, FinishedCallback finished) const override;
void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
FinishedCallback finished) const override;
@ -24,6 +25,7 @@ public:
signals:
void MainWindowDisplayError(QString error_code, QString error_text) const;
void MainWindowRequestExit() const;
private:
void MainWindowFinishedError();

View File

@ -157,17 +157,26 @@ void QtProfileSelectionDialog::SelectUser(const QModelIndex& index) {
QtProfileSelector::QtProfileSelector(GMainWindow& parent) {
connect(this, &QtProfileSelector::MainWindowSelectProfile, &parent,
&GMainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection);
connect(this, &QtProfileSelector::MainWindowRequestExit, &parent,
&GMainWindow::ProfileSelectorRequestExit, Qt::QueuedConnection);
connect(&parent, &GMainWindow::ProfileSelectorFinishedSelection, this,
&QtProfileSelector::MainWindowFinishedSelection, Qt::DirectConnection);
}
QtProfileSelector::~QtProfileSelector() = default;
void QtProfileSelector::Close() const {
callback = {};
emit MainWindowRequestExit();
}
void QtProfileSelector::SelectProfile(SelectProfileCallback callback_) const {
callback = std::move(callback_);
emit MainWindowSelectProfile();
}
void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) {
callback(uuid);
if (callback) {
callback(uuid);
}
}

View File

@ -65,10 +65,12 @@ public:
explicit QtProfileSelector(GMainWindow& parent);
~QtProfileSelector() override;
void Close() const override;
void SelectProfile(SelectProfileCallback callback_) const override;
signals:
void MainWindowSelectProfile() const;
void MainWindowRequestExit() const;
private:
void MainWindowFinishedSelection(std::optional<Common::UUID> uuid);

View File

@ -233,6 +233,10 @@ public:
explicit QtSoftwareKeyboard(GMainWindow& parent);
~QtSoftwareKeyboard() override;
void Close() const override {
ExitKeyboard();
}
void InitializeKeyboard(bool is_inline,
Core::Frontend::KeyboardInitializeParameters initialize_parameters,
SubmitNormalCallback submit_normal_callback_,

View File

@ -393,6 +393,8 @@ void QtNXWebEngineView::FocusFirstLinkElement() {
QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window,
&GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection);
connect(this, &QtWebBrowser::MainWindowRequestExit, &main_window,
&GMainWindow::WebBrowserRequestExit, Qt::QueuedConnection);
connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this,
&QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection);
connect(&main_window, &GMainWindow::WebBrowserClosed, this,
@ -401,6 +403,11 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
QtWebBrowser::~QtWebBrowser() = default;
void QtWebBrowser::Close() const {
callback = {};
emit MainWindowRequestExit();
}
void QtWebBrowser::OpenLocalWebPage(const std::string& local_url,
ExtractROMFSCallback extract_romfs_callback_,
OpenWebPageCallback callback_) const {
@ -436,5 +443,7 @@ void QtWebBrowser::MainWindowExtractOfflineRomFS() {
void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason,
std::string last_url) {
callback(exit_reason, last_url);
if (callback) {
callback(exit_reason, last_url);
}
}

View File

@ -196,6 +196,7 @@ public:
explicit QtWebBrowser(GMainWindow& parent);
~QtWebBrowser() override;
void Close() const override;
void OpenLocalWebPage(const std::string& local_url,
ExtractROMFSCallback extract_romfs_callback_,
OpenWebPageCallback callback_) const override;
@ -206,6 +207,7 @@ public:
signals:
void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args,
bool is_local) const;
void MainWindowRequestExit() const;
private:
void MainWindowExtractOfflineRomFS();

View File

@ -596,27 +596,45 @@ void GMainWindow::RegisterMetaTypes() {
void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
std::shared_ptr<Service::NFP::NfpDevice> nfp_device) {
QtAmiiboSettingsDialog dialog(this, parameters, input_subsystem.get(), nfp_device);
cabinet_applet =
new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device);
SCOPE_EXIT({
cabinet_applet->deleteLater();
cabinet_applet = nullptr;
});
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
dialog.setWindowModality(Qt::WindowModal);
if (dialog.exec() == QDialog::Rejected) {
cabinet_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
cabinet_applet->setWindowModality(Qt::WindowModal);
if (cabinet_applet->exec() == QDialog::Rejected) {
emit AmiiboSettingsFinished(false, {});
return;
}
emit AmiiboSettingsFinished(true, dialog.GetName());
emit AmiiboSettingsFinished(true, cabinet_applet->GetName());
}
void GMainWindow::AmiiboSettingsRequestExit() {
if (cabinet_applet) {
cabinet_applet->reject();
}
}
void GMainWindow::ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters) {
QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get(), *system);
controller_applet =
new QtControllerSelectorDialog(this, parameters, input_subsystem.get(), *system);
SCOPE_EXIT({
controller_applet->deleteLater();
controller_applet = nullptr;
});
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
dialog.setWindowModality(Qt::WindowModal);
dialog.exec();
controller_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint |
Qt::WindowStaysOnTopHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint);
controller_applet->setWindowModality(Qt::WindowModal);
controller_applet->exec();
emit ControllerSelectorReconfigureFinished();
@ -627,19 +645,30 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
UpdateStatusButtons();
}
void GMainWindow::ControllerSelectorRequestExit() {
if (controller_applet) {
controller_applet->reject();
}
}
void GMainWindow::ProfileSelectorSelectProfile() {
QtProfileSelectionDialog dialog(system->HIDCore(), this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
if (dialog.exec() == QDialog::Rejected) {
profile_select_applet = new QtProfileSelectionDialog(system->HIDCore(), this);
SCOPE_EXIT({
profile_select_applet->deleteLater();
profile_select_applet = nullptr;
});
profile_select_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint |
Qt::WindowStaysOnTopHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
profile_select_applet->setWindowModality(Qt::WindowModal);
if (profile_select_applet->exec() == QDialog::Rejected) {
emit ProfileSelectorFinishedSelection(std::nullopt);
return;
}
const Service::Account::ProfileManager manager;
const auto uuid = manager.GetUser(static_cast<std::size_t>(dialog.GetIndex()));
const auto uuid = manager.GetUser(static_cast<std::size_t>(profile_select_applet->GetIndex()));
if (!uuid.has_value()) {
emit ProfileSelectorFinishedSelection(std::nullopt);
return;
@ -648,6 +677,12 @@ void GMainWindow::ProfileSelectorSelectProfile() {
emit ProfileSelectorFinishedSelection(uuid);
}
void GMainWindow::ProfileSelectorRequestExit() {
if (profile_select_applet) {
profile_select_applet->reject();
}
}
void GMainWindow::SoftwareKeyboardInitialize(
bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
if (software_keyboard) {
@ -772,7 +807,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
return;
}
QtNXWebEngineView web_browser_view(this, *system, input_subsystem.get());
web_applet = new QtNXWebEngineView(this, *system, input_subsystem.get());
ui->action_Pause->setEnabled(false);
ui->action_Restart->setEnabled(false);
@ -799,9 +834,9 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
loading_progress.setValue(1);
if (is_local) {
web_browser_view.LoadLocalWebPage(main_url, additional_args);
web_applet->LoadLocalWebPage(main_url, additional_args);
} else {
web_browser_view.LoadExternalWebPage(main_url, additional_args);
web_applet->LoadExternalWebPage(main_url, additional_args);
}
if (render_window->IsLoadingComplete()) {
@ -810,15 +845,15 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
const auto& layout = render_window->GetFramebufferLayout();
const auto scale_ratio = devicePixelRatioF();
web_browser_view.resize(layout.screen.GetWidth() / scale_ratio,
layout.screen.GetHeight() / scale_ratio);
web_browser_view.move(layout.screen.left / scale_ratio,
(layout.screen.top / scale_ratio) + menuBar()->height());
web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth() / scale_ratio) /
static_cast<qreal>(Layout::ScreenUndocked::Width));
web_applet->resize(layout.screen.GetWidth() / scale_ratio,
layout.screen.GetHeight() / scale_ratio);
web_applet->move(layout.screen.left / scale_ratio,
(layout.screen.top / scale_ratio) + menuBar()->height());
web_applet->setZoomFactor(static_cast<qreal>(layout.screen.GetWidth() / scale_ratio) /
static_cast<qreal>(Layout::ScreenUndocked::Width));
web_browser_view.setFocus();
web_browser_view.show();
web_applet->setFocus();
web_applet->show();
loading_progress.setValue(2);
@ -831,7 +866,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
// TODO (Morph): Remove this
QAction* exit_action = new QAction(tr("Disable Web Applet"), this);
connect(exit_action, &QAction::triggered, this, [this, &web_browser_view] {
connect(exit_action, &QAction::triggered, this, [this] {
const auto result = QMessageBox::warning(
this, tr("Disable Web Applet"),
tr("Disabling the web applet can lead to undefined behavior and should only be used "
@ -840,21 +875,21 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::Yes) {
UISettings::values.disable_web_applet = true;
web_browser_view.SetFinished(true);
web_applet->SetFinished(true);
}
});
ui->menubar->addAction(exit_action);
while (!web_browser_view.IsFinished()) {
while (!web_applet->IsFinished()) {
QCoreApplication::processEvents();
if (!exit_check) {
web_browser_view.page()->runJavaScript(
web_applet->page()->runJavaScript(
QStringLiteral("end_applet;"), [&](const QVariant& variant) {
exit_check = false;
if (variant.toBool()) {
web_browser_view.SetFinished(true);
web_browser_view.SetExitReason(
web_applet->SetFinished(true);
web_applet->SetExitReason(
Service::AM::Applets::WebExitReason::EndButtonPressed);
}
});
@ -862,22 +897,22 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
exit_check = true;
}
if (web_browser_view.GetCurrentURL().contains(QStringLiteral("localhost"))) {
if (!web_browser_view.IsFinished()) {
web_browser_view.SetFinished(true);
web_browser_view.SetExitReason(Service::AM::Applets::WebExitReason::CallbackURL);
if (web_applet->GetCurrentURL().contains(QStringLiteral("localhost"))) {
if (!web_applet->IsFinished()) {
web_applet->SetFinished(true);
web_applet->SetExitReason(Service::AM::Applets::WebExitReason::CallbackURL);
}
web_browser_view.SetLastURL(web_browser_view.GetCurrentURL().toStdString());
web_applet->SetLastURL(web_applet->GetCurrentURL().toStdString());
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
const auto exit_reason = web_browser_view.GetExitReason();
const auto last_url = web_browser_view.GetLastURL();
const auto exit_reason = web_applet->GetExitReason();
const auto last_url = web_applet->GetLastURL();
web_browser_view.hide();
web_applet->hide();
render_window->setFocus();
@ -903,6 +938,15 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
#endif
}
void GMainWindow::WebBrowserRequestExit() {
#ifdef YUZU_USE_QT_WEB_ENGINE
if (web_applet) {
web_applet->SetExitReason(Service::AM::Applets::WebExitReason::ExitRequested);
web_applet->SetFinished(true);
}
#endif
}
void GMainWindow::InitializeWidgets() {
#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
ui->action_Report_Compatibility->setVisible(true);
@ -3089,13 +3133,23 @@ void GMainWindow::OnSaveConfig() {
}
void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
OverlayDialog dialog(render_window, *system, error_code, error_text, QString{}, tr("OK"),
Qt::AlignLeft | Qt::AlignVCenter);
dialog.exec();
error_applet = new OverlayDialog(render_window, *system, error_code, error_text, QString{},
tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
SCOPE_EXIT({
error_applet->deleteLater();
error_applet = nullptr;
});
error_applet->exec();
emit ErrorDisplayFinished();
}
void GMainWindow::ErrorDisplayRequestExit() {
if (error_applet) {
error_applet->reject();
}
}
void GMainWindow::OnMenuReportCompatibility() {
#if defined(ARCHITECTURE_x86_64) && !defined(__APPLE__)
const auto& caps = Common::GetCPUCaps();

View File

@ -47,7 +47,11 @@ enum class DumpRomFSTarget;
enum class InstalledEntryType;
class GameListPlaceholder;
class QtAmiiboSettingsDialog;
class QtControllerSelectorDialog;
class QtProfileSelectionDialog;
class QtSoftwareKeyboardDialog;
class QtNXWebEngineView;
enum class StartGameType {
Normal, // Can use custom configuration
@ -184,8 +188,10 @@ public slots:
void OnSaveConfig();
void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
std::shared_ptr<Service::NFP::NfpDevice> nfp_device);
void AmiiboSettingsRequestExit();
void ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters);
void ControllerSelectorRequestExit();
void SoftwareKeyboardInitialize(
bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters);
void SoftwareKeyboardShowNormal();
@ -196,9 +202,12 @@ public slots:
void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
void SoftwareKeyboardExit();
void ErrorDisplayDisplayError(QString error_code, QString error_text);
void ErrorDisplayRequestExit();
void ProfileSelectorSelectProfile();
void ProfileSelectorRequestExit();
void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
bool is_local);
void WebBrowserRequestExit();
void OnAppFocusStateChanged(Qt::ApplicationState state);
void OnTasStateChanged();
@ -466,7 +475,12 @@ private:
QString last_filename_booted;
// Applets
QtAmiiboSettingsDialog* cabinet_applet = nullptr;
QtControllerSelectorDialog* controller_applet = nullptr;
QtProfileSelectionDialog* profile_select_applet = nullptr;
QDialog* error_applet = nullptr;
QtSoftwareKeyboardDialog* software_keyboard = nullptr;
QtNXWebEngineView* web_applet = nullptr;
// True if amiibo file select is visible
bool is_amiibo_file_select_active{};