summaryrefslogtreecommitdiff
path: root/src/yuzu/main.cpp
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2020-12-21 23:47:10 -0800
committerGitHub <noreply@github.com>2020-12-21 23:47:10 -0800
commit29ccc7673fc10dee39880fd7bad0ff264765dd56 (patch)
tree234c2a3fca543e580480ed72e37c1ee9f201aa93 /src/yuzu/main.cpp
parent1279c7ce7afd3d1bf2b4e33aa922158acf2cd060 (diff)
parent82fa9f8d56bc285e7bb58fc81b495a55be9ea82c (diff)
Merge pull request #5042 from Morph1984/project-aether
Project Aether: Reimplementation of the Web Browser Applet
Diffstat (limited to 'src/yuzu/main.cpp')
-rw-r--r--src/yuzu/main.cpp238
1 files changed, 123 insertions, 115 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 3461fa675..620e80cdc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -28,8 +28,6 @@
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
-#include "core/hle/service/hid/controllers/npad.h"
-#include "core/hle/service/hid/hid.h"
// These are wrappers to avoid the calls to CreateDirectory and CreateFile because of the Windows
// defines.
@@ -125,14 +123,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "yuzu/discord_impl.h"
#endif
-#ifdef YUZU_USE_QT_WEB_ENGINE
-#include <QWebEngineProfile>
-#include <QWebEngineScript>
-#include <QWebEngineScriptCollection>
-#include <QWebEngineSettings>
-#include <QWebEngineView>
-#endif
-
#ifdef QT_STATICPLUGIN
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
#endif
@@ -190,6 +180,30 @@ static void InitializeLogging() {
#endif
}
+static void RemoveCachedContents() {
+ const auto offline_fonts = Common::FS::SanitizePath(
+ fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)),
+ Common::FS::DirectorySeparator::PlatformDefault);
+
+ const auto offline_manual = Common::FS::SanitizePath(
+ fmt::format("{}/offline_web_applet_manual",
+ Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)),
+ Common::FS::DirectorySeparator::PlatformDefault);
+ const auto offline_legal_information = Common::FS::SanitizePath(
+ fmt::format("{}/offline_web_applet_legal_information",
+ Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)),
+ Common::FS::DirectorySeparator::PlatformDefault);
+ const auto offline_system_data = Common::FS::SanitizePath(
+ fmt::format("{}/offline_web_applet_system_data",
+ Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)),
+ Common::FS::DirectorySeparator::PlatformDefault);
+
+ Common::FS::DeleteDirRecursively(offline_fonts);
+ Common::FS::DeleteDirRecursively(offline_manual);
+ Common::FS::DeleteDirRecursively(offline_legal_information);
+ Common::FS::DeleteDirRecursively(offline_system_data);
+}
+
GMainWindow::GMainWindow()
: input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
@@ -258,6 +272,9 @@ GMainWindow::GMainWindow()
FileSys::ContentProviderUnionSlot::FrontendManual, provider.get());
Core::System::GetInstance().GetFileSystemController().CreateFactories(*vfs);
+ // Remove cached contents generated during the previous session
+ RemoveCachedContents();
+
// Gen keys if necessary
OnReinitializeKeys(ReinitializeKeyBehavior::NoWarning);
@@ -349,150 +366,141 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message
emit SoftwareKeyboardFinishedCheckDialog();
}
+void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
+ bool is_local) {
#ifdef YUZU_USE_QT_WEB_ENGINE
-void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) {
- NXInputWebEngineView web_browser_view(this);
+ if (disable_web_applet) {
+ emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed,
+ "http://localhost/");
+ return;
+ }
+
+ QtNXWebEngineView web_browser_view(this, Core::System::GetInstance(), input_subsystem.get());
- // Scope to contain the QProgressDialog for initialization
- {
- QProgressDialog progress(this);
- progress.setMinimumDuration(200);
- progress.setLabelText(tr("Loading Web Applet..."));
- progress.setRange(0, 4);
- progress.setValue(0);
- progress.show();
+ ui.action_Pause->setEnabled(false);
+ ui.action_Restart->setEnabled(false);
+ ui.action_Stop->setEnabled(false);
- auto future = QtConcurrent::run([this] { emit WebBrowserUnpackRomFS(); });
+ {
+ QProgressDialog loading_progress(this);
+ loading_progress.setLabelText(tr("Loading Web Applet..."));
+ loading_progress.setRange(0, 3);
+ loading_progress.setValue(0);
- while (!future.isFinished())
- QApplication::processEvents();
+ if (is_local && !Common::FS::Exists(std::string(main_url))) {
+ loading_progress.show();
- progress.setValue(1);
+ auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); });
- // Load the special shim script to handle input and exit.
- QWebEngineScript nx_shim;
- nx_shim.setSourceCode(GetNXShimInjectionScript());
- nx_shim.setWorldId(QWebEngineScript::MainWorld);
- nx_shim.setName(QStringLiteral("nx_inject.js"));
- nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation);
- nx_shim.setRunsOnSubFrames(true);
- web_browser_view.page()->profile()->scripts()->insert(nx_shim);
+ while (!future.isFinished()) {
+ QCoreApplication::processEvents();
+ }
+ }
- web_browser_view.load(
- QUrl(QUrl::fromLocalFile(QString::fromStdString(std::string(filename))).toString() +
- QString::fromStdString(std::string(additional_args))));
+ loading_progress.setValue(1);
- progress.setValue(2);
+ if (is_local) {
+ web_browser_view.LoadLocalWebPage(main_url, additional_args);
+ } else {
+ web_browser_view.LoadExternalWebPage(main_url, additional_args);
+ }
- render_window->hide();
- web_browser_view.setFocus();
+ if (render_window->IsLoadingComplete()) {
+ render_window->hide();
+ }
const auto& layout = render_window->GetFramebufferLayout();
web_browser_view.resize(layout.screen.GetWidth(), layout.screen.GetHeight());
web_browser_view.move(layout.screen.left, layout.screen.top + menuBar()->height());
web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth()) /
- Layout::ScreenUndocked::Width);
- web_browser_view.settings()->setAttribute(
- QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
+ static_cast<qreal>(Layout::ScreenUndocked::Width));
+ web_browser_view.setFocus();
web_browser_view.show();
- progress.setValue(3);
+ loading_progress.setValue(2);
- QApplication::processEvents();
+ QCoreApplication::processEvents();
- progress.setValue(4);
+ loading_progress.setValue(3);
}
- bool finished = false;
- QAction* exit_action = new QAction(tr("Exit Web Applet"), this);
- connect(exit_action, &QAction::triggered, this, [&finished] { finished = true; });
- ui.menubar->addAction(exit_action);
+ bool exit_check = false;
- auto& npad =
- Core::System::GetInstance()
- .ServiceManager()
- .GetService<Service::HID::Hid>("hid")
- ->GetAppletResource()
- ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
-
- const auto fire_js_keypress = [&web_browser_view](u32 key_code) {
- web_browser_view.page()->runJavaScript(
- QStringLiteral("document.dispatchEvent(new KeyboardEvent('keydown', {'key': %1}));")
- .arg(key_code));
- };
+ // TODO (Morph): Remove this
+ QAction* exit_action = new QAction(tr("Disable Web Applet"), this);
+ connect(exit_action, &QAction::triggered, this, [this, &web_browser_view] {
+ const auto result = QMessageBox::warning(
+ this, tr("Disable Web Applet"),
+ tr("Disabling the web applet will cause it to not be shown again for the rest of the "
+ "emulated session. This can lead to undefined behavior and should only be used with "
+ "Super Mario 3D All-Stars. Are you sure you want to disable the web applet?"),
+ QMessageBox::Yes | QMessageBox::No);
+ if (result == QMessageBox::Yes) {
+ disable_web_applet = true;
+ web_browser_view.SetFinished(true);
+ }
+ });
+ ui.menubar->addAction(exit_action);
- QMessageBox::information(
- this, tr("Exit"),
- tr("To exit the web application, use the game provided controls to select exit, select the "
- "'Exit Web Applet' option in the menu bar, or press the 'Enter' key."));
-
- bool running_exit_check = false;
- while (!finished) {
- QApplication::processEvents();
-
- if (!running_exit_check) {
- web_browser_view.page()->runJavaScript(QStringLiteral("applet_done;"),
- [&](const QVariant& res) {
- running_exit_check = false;
- if (res.toBool())
- finished = true;
- });
- running_exit_check = true;
+ while (!web_browser_view.IsFinished()) {
+ QCoreApplication::processEvents();
+
+ if (!exit_check) {
+ web_browser_view.page()->runJavaScript(
+ QStringLiteral("end_applet;"), [&](const QVariant& variant) {
+ exit_check = false;
+ if (variant.toBool()) {
+ web_browser_view.SetFinished(true);
+ web_browser_view.SetExitReason(
+ Service::AM::Applets::WebExitReason::EndButtonPressed);
+ }
+ });
+
+ exit_check = true;
}
- const auto input = npad.GetAndResetPressState();
- for (std::size_t i = 0; i < Settings::NativeButton::NumButtons; ++i) {
- if ((input & (1 << i)) != 0) {
- LOG_DEBUG(Frontend, "firing input for button id={:02X}", i);
- web_browser_view.page()->runJavaScript(
- QStringLiteral("yuzu_key_callbacks[%1]();").arg(i));
+ 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);
}
+
+ web_browser_view.SetLastURL(web_browser_view.GetCurrentURL().toStdString());
}
- if (input & 0x00888000) // RStick Down | LStick Down | DPad Down
- fire_js_keypress(40); // Down Arrow Key
- else if (input & 0x00444000) // RStick Right | LStick Right | DPad Right
- fire_js_keypress(39); // Right Arrow Key
- else if (input & 0x00222000) // RStick Up | LStick Up | DPad Up
- fire_js_keypress(38); // Up Arrow Key
- else if (input & 0x00111000) // RStick Left | LStick Left | DPad Left
- fire_js_keypress(37); // Left Arrow Key
- else if (input & 0x00000001) // A Button
- fire_js_keypress(13); // Enter Key
+ 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();
+
web_browser_view.hide();
- render_window->show();
+
render_window->setFocus();
- ui.menubar->removeAction(exit_action);
- // Needed to update render window focus/show and remove menubar action
- QApplication::processEvents();
- emit WebBrowserFinishedBrowsing();
-}
+ if (render_window->IsLoadingComplete()) {
+ render_window->show();
+ }
-#else
+ ui.action_Pause->setEnabled(true);
+ ui.action_Restart->setEnabled(true);
+ ui.action_Stop->setEnabled(true);
-void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) {
-#ifndef __linux__
- QMessageBox::warning(
- this, tr("Web Applet"),
- tr("This version of yuzu was built without QtWebEngine support, meaning that yuzu cannot "
- "properly display the game manual or web page requested."),
- QMessageBox::Ok, QMessageBox::Ok);
-#endif
+ ui.menubar->removeAction(exit_action);
- LOG_INFO(Frontend,
- "(STUBBED) called - Missing QtWebEngine dependency needed to open website page at "
- "'{}' with arguments '{}'!",
- filename, additional_args);
+ QCoreApplication::processEvents();
- emit WebBrowserFinishedBrowsing();
-}
+ emit WebBrowserClosed(exit_reason, last_url);
+
+#else
+
+ // Utilize the same fallback as the default web browser applet.
+ emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
#endif
+}
void GMainWindow::InitializeWidgets() {
#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
@@ -993,7 +1001,6 @@ bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) {
system.SetAppletFrontendSet({
std::make_unique<QtControllerSelector>(*this), // Controller Selector
- nullptr, // E-Commerce
std::make_unique<QtErrorDisplay>(*this), // Error Display
nullptr, // Parental Controls
nullptr, // Photo Viewer
@@ -2102,6 +2109,7 @@ void GMainWindow::OnStartGame() {
qRegisterMetaType<std::string>("std::string");
qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>");
qRegisterMetaType<std::string_view>("std::string_view");
+ qRegisterMetaType<Service::AM::Applets::WebExitReason>("Service::AM::Applets::WebExitReason");
connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);