|
|
@ -51,59 +51,32 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system, |
|
|
InputCommon::InputSubsystem* input_subsystem_) |
|
|
InputCommon::InputSubsystem* input_subsystem_) |
|
|
: QWebEngineView(parent), input_subsystem{input_subsystem_}, |
|
|
: QWebEngineView(parent), input_subsystem{input_subsystem_}, |
|
|
url_interceptor(std::make_unique<UrlRequestInterceptor>()), |
|
|
url_interceptor(std::make_unique<UrlRequestInterceptor>()), |
|
|
input_interpreter(std::make_unique<InputInterpreter>(system)) { |
|
|
|
|
|
QWebEngineScript nx_font_css; |
|
|
|
|
|
QWebEngineScript load_nx_font; |
|
|
|
|
|
|
|
|
input_interpreter(std::make_unique<InputInterpreter>(system)), |
|
|
|
|
|
default_profile{QWebEngineProfile::defaultProfile()}, |
|
|
|
|
|
global_settings{QWebEngineSettings::globalSettings()} { |
|
|
QWebEngineScript gamepad; |
|
|
QWebEngineScript gamepad; |
|
|
QWebEngineScript window_nx; |
|
|
QWebEngineScript window_nx; |
|
|
|
|
|
|
|
|
const QString fonts_dir = QString::fromStdString(Common::FS::SanitizePath( |
|
|
|
|
|
fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)))); |
|
|
|
|
|
|
|
|
|
|
|
nx_font_css.setName(QStringLiteral("nx_font_css.js")); |
|
|
|
|
|
load_nx_font.setName(QStringLiteral("load_nx_font.js")); |
|
|
|
|
|
gamepad.setName(QStringLiteral("gamepad_script.js")); |
|
|
gamepad.setName(QStringLiteral("gamepad_script.js")); |
|
|
window_nx.setName(QStringLiteral("window_nx_script.js")); |
|
|
window_nx.setName(QStringLiteral("window_nx_script.js")); |
|
|
|
|
|
|
|
|
nx_font_css.setSourceCode( |
|
|
|
|
|
QString::fromStdString(NX_FONT_CSS) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontStandard.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontChineseSimplified.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontExtendedChineseSimplified.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontChineseTraditional.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontKorean.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontNintendoExtended.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontNintendoExtended2.ttf"))); |
|
|
|
|
|
load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT)); |
|
|
|
|
|
gamepad.setSourceCode(QString::fromStdString(GAMEPAD_SCRIPT)); |
|
|
gamepad.setSourceCode(QString::fromStdString(GAMEPAD_SCRIPT)); |
|
|
window_nx.setSourceCode(QString::fromStdString(WINDOW_NX_SCRIPT)); |
|
|
window_nx.setSourceCode(QString::fromStdString(WINDOW_NX_SCRIPT)); |
|
|
|
|
|
|
|
|
nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady); |
|
|
|
|
|
load_nx_font.setInjectionPoint(QWebEngineScript::Deferred); |
|
|
|
|
|
gamepad.setInjectionPoint(QWebEngineScript::DocumentCreation); |
|
|
gamepad.setInjectionPoint(QWebEngineScript::DocumentCreation); |
|
|
window_nx.setInjectionPoint(QWebEngineScript::DocumentCreation); |
|
|
window_nx.setInjectionPoint(QWebEngineScript::DocumentCreation); |
|
|
|
|
|
|
|
|
nx_font_css.setWorldId(QWebEngineScript::MainWorld); |
|
|
|
|
|
load_nx_font.setWorldId(QWebEngineScript::MainWorld); |
|
|
|
|
|
gamepad.setWorldId(QWebEngineScript::MainWorld); |
|
|
gamepad.setWorldId(QWebEngineScript::MainWorld); |
|
|
window_nx.setWorldId(QWebEngineScript::MainWorld); |
|
|
window_nx.setWorldId(QWebEngineScript::MainWorld); |
|
|
|
|
|
|
|
|
nx_font_css.setRunsOnSubFrames(true); |
|
|
|
|
|
load_nx_font.setRunsOnSubFrames(true); |
|
|
|
|
|
gamepad.setRunsOnSubFrames(true); |
|
|
gamepad.setRunsOnSubFrames(true); |
|
|
window_nx.setRunsOnSubFrames(true); |
|
|
window_nx.setRunsOnSubFrames(true); |
|
|
|
|
|
|
|
|
auto* default_profile = QWebEngineProfile::defaultProfile(); |
|
|
|
|
|
|
|
|
|
|
|
default_profile->scripts()->insert(nx_font_css); |
|
|
|
|
|
default_profile->scripts()->insert(load_nx_font); |
|
|
|
|
|
default_profile->scripts()->insert(gamepad); |
|
|
default_profile->scripts()->insert(gamepad); |
|
|
default_profile->scripts()->insert(window_nx); |
|
|
default_profile->scripts()->insert(window_nx); |
|
|
|
|
|
|
|
|
default_profile->setRequestInterceptor(url_interceptor.get()); |
|
|
default_profile->setRequestInterceptor(url_interceptor.get()); |
|
|
|
|
|
|
|
|
auto* global_settings = QWebEngineSettings::globalSettings(); |
|
|
|
|
|
|
|
|
|
|
|
global_settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); |
|
|
@ -111,13 +84,7 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system, |
|
|
global_settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, true); |
|
|
global_settings->setAttribute(QWebEngineSettings::ShowScrollBars, false); |
|
|
global_settings->setAttribute(QWebEngineSettings::ShowScrollBars, false); |
|
|
|
|
|
|
|
|
connect( |
|
|
|
|
|
url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(), |
|
|
|
|
|
[this] { |
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50)); |
|
|
|
|
|
page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT)); |
|
|
|
|
|
}, |
|
|
|
|
|
Qt::QueuedConnection); |
|
|
|
|
|
|
|
|
global_settings->setFontFamily(QWebEngineSettings::StandardFont, QStringLiteral("Roboto")); |
|
|
|
|
|
|
|
|
connect( |
|
|
connect( |
|
|
page(), &QWebEnginePage::windowCloseRequested, page(), |
|
|
page(), &QWebEnginePage::windowCloseRequested, page(), |
|
|
@ -137,6 +104,9 @@ QtNXWebEngineView::~QtNXWebEngineView() { |
|
|
|
|
|
|
|
|
void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url, |
|
|
void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url, |
|
|
std::string_view additional_args) { |
|
|
std::string_view additional_args) { |
|
|
|
|
|
is_local = true; |
|
|
|
|
|
|
|
|
|
|
|
LoadExtractedFonts(); |
|
|
SetUserAgent(UserAgent::WebApplet); |
|
|
SetUserAgent(UserAgent::WebApplet); |
|
|
SetFinished(false); |
|
|
SetFinished(false); |
|
|
SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); |
|
|
SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); |
|
|
@ -147,6 +117,20 @@ void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url, |
|
|
QString::fromStdString(std::string(additional_args)))); |
|
|
QString::fromStdString(std::string(additional_args)))); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url, |
|
|
|
|
|
std::string_view additional_args) { |
|
|
|
|
|
is_local = false; |
|
|
|
|
|
|
|
|
|
|
|
SetUserAgent(UserAgent::WebApplet); |
|
|
|
|
|
SetFinished(false); |
|
|
|
|
|
SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); |
|
|
|
|
|
SetLastURL("http://localhost/"); |
|
|
|
|
|
StartInputThread(); |
|
|
|
|
|
|
|
|
|
|
|
load(QUrl(QString::fromStdString(std::string(main_url)) + |
|
|
|
|
|
QString::fromStdString(std::string(additional_args)))); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) { |
|
|
void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) { |
|
|
const QString user_agent_str = [user_agent] { |
|
|
const QString user_agent_str = [user_agent] { |
|
|
switch (user_agent) { |
|
|
switch (user_agent) { |
|
|
@ -208,12 +192,16 @@ void QtNXWebEngineView::hide() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void QtNXWebEngineView::keyPressEvent(QKeyEvent* event) { |
|
|
void QtNXWebEngineView::keyPressEvent(QKeyEvent* event) { |
|
|
|
|
|
if (is_local) { |
|
|
input_subsystem->GetKeyboard()->PressKey(event->key()); |
|
|
input_subsystem->GetKeyboard()->PressKey(event->key()); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) { |
|
|
void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) { |
|
|
|
|
|
if (is_local) { |
|
|
input_subsystem->GetKeyboard()->ReleaseKey(event->key()); |
|
|
input_subsystem->GetKeyboard()->ReleaseKey(event->key()); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
template <HIDButton... T> |
|
|
template <HIDButton... T> |
|
|
void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() { |
|
|
void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() { |
|
|
@ -294,7 +282,10 @@ void QtNXWebEngineView::StartInputThread() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void QtNXWebEngineView::StopInputThread() { |
|
|
void QtNXWebEngineView::StopInputThread() { |
|
|
|
|
|
if (is_local) { |
|
|
QWidget::releaseKeyboard(); |
|
|
QWidget::releaseKeyboard(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
input_thread_running = false; |
|
|
input_thread_running = false; |
|
|
if (input_thread.joinable()) { |
|
|
if (input_thread.joinable()) { |
|
|
input_thread.join(); |
|
|
input_thread.join(); |
|
|
@ -305,7 +296,9 @@ void QtNXWebEngineView::InputThread() { |
|
|
// Wait for 1 second before allowing any inputs to be processed.
|
|
|
// Wait for 1 second before allowing any inputs to be processed.
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(1)); |
|
|
std::this_thread::sleep_for(std::chrono::seconds(1)); |
|
|
|
|
|
|
|
|
|
|
|
if (is_local) { |
|
|
QWidget::grabKeyboard(); |
|
|
QWidget::grabKeyboard(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
while (input_thread_running) { |
|
|
while (input_thread_running) { |
|
|
input_interpreter->PollInput(); |
|
|
input_interpreter->PollInput(); |
|
|
@ -326,11 +319,53 @@ void QtNXWebEngineView::InputThread() { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QtNXWebEngineView::LoadExtractedFonts() { |
|
|
|
|
|
QWebEngineScript nx_font_css; |
|
|
|
|
|
QWebEngineScript load_nx_font; |
|
|
|
|
|
|
|
|
|
|
|
const QString fonts_dir = QString::fromStdString(Common::FS::SanitizePath( |
|
|
|
|
|
fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)))); |
|
|
|
|
|
|
|
|
|
|
|
nx_font_css.setName(QStringLiteral("nx_font_css.js")); |
|
|
|
|
|
load_nx_font.setName(QStringLiteral("load_nx_font.js")); |
|
|
|
|
|
|
|
|
|
|
|
nx_font_css.setSourceCode( |
|
|
|
|
|
QString::fromStdString(NX_FONT_CSS) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontStandard.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontChineseSimplified.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontExtendedChineseSimplified.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontChineseTraditional.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontKorean.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontNintendoExtended.ttf")) |
|
|
|
|
|
.arg(fonts_dir + QStringLiteral("/FontNintendoExtended2.ttf"))); |
|
|
|
|
|
load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT)); |
|
|
|
|
|
|
|
|
|
|
|
nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady); |
|
|
|
|
|
load_nx_font.setInjectionPoint(QWebEngineScript::Deferred); |
|
|
|
|
|
|
|
|
|
|
|
nx_font_css.setWorldId(QWebEngineScript::MainWorld); |
|
|
|
|
|
load_nx_font.setWorldId(QWebEngineScript::MainWorld); |
|
|
|
|
|
|
|
|
|
|
|
nx_font_css.setRunsOnSubFrames(true); |
|
|
|
|
|
load_nx_font.setRunsOnSubFrames(true); |
|
|
|
|
|
|
|
|
|
|
|
default_profile->scripts()->insert(nx_font_css); |
|
|
|
|
|
default_profile->scripts()->insert(load_nx_font); |
|
|
|
|
|
|
|
|
|
|
|
connect( |
|
|
|
|
|
url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(), |
|
|
|
|
|
[this] { |
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50)); |
|
|
|
|
|
page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT)); |
|
|
|
|
|
}, |
|
|
|
|
|
Qt::QueuedConnection); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
|
|
|
QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { |
|
|
QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { |
|
|
connect(this, &QtWebBrowser::MainWindowOpenLocalWebPage, &main_window, |
|
|
|
|
|
&GMainWindow::WebBrowserOpenLocalWebPage, Qt::QueuedConnection); |
|
|
|
|
|
|
|
|
connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window, |
|
|
|
|
|
&GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection); |
|
|
connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this, |
|
|
connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this, |
|
|
&QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection); |
|
|
&QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection); |
|
|
connect(&main_window, &GMainWindow::WebBrowserClosed, this, |
|
|
connect(&main_window, &GMainWindow::WebBrowserClosed, this, |
|
|
@ -340,17 +375,32 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { |
|
|
QtWebBrowser::~QtWebBrowser() = default; |
|
|
QtWebBrowser::~QtWebBrowser() = default; |
|
|
|
|
|
|
|
|
void QtWebBrowser::OpenLocalWebPage( |
|
|
void QtWebBrowser::OpenLocalWebPage( |
|
|
std::string_view local_url, std::function<void()> extract_romfs_callback, |
|
|
|
|
|
std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { |
|
|
|
|
|
this->extract_romfs_callback = std::move(extract_romfs_callback); |
|
|
|
|
|
this->callback = std::move(callback); |
|
|
|
|
|
|
|
|
std::string_view local_url, std::function<void()> extract_romfs_callback_, |
|
|
|
|
|
std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { |
|
|
|
|
|
extract_romfs_callback = std::move(extract_romfs_callback_); |
|
|
|
|
|
callback = std::move(callback_); |
|
|
|
|
|
|
|
|
const auto index = local_url.find('?'); |
|
|
const auto index = local_url.find('?'); |
|
|
|
|
|
|
|
|
if (index == std::string::npos) { |
|
|
if (index == std::string::npos) { |
|
|
emit MainWindowOpenLocalWebPage(local_url, ""); |
|
|
|
|
|
|
|
|
emit MainWindowOpenWebPage(local_url, "", true); |
|
|
|
|
|
} else { |
|
|
|
|
|
emit MainWindowOpenWebPage(local_url.substr(0, index), local_url.substr(index), true); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QtWebBrowser::OpenExternalWebPage( |
|
|
|
|
|
std::string_view external_url, |
|
|
|
|
|
std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { |
|
|
|
|
|
callback = std::move(callback_); |
|
|
|
|
|
|
|
|
|
|
|
const auto index = external_url.find('?'); |
|
|
|
|
|
|
|
|
|
|
|
if (index == std::string::npos) { |
|
|
|
|
|
emit MainWindowOpenWebPage(external_url, "", false); |
|
|
} else { |
|
|
} else { |
|
|
emit MainWindowOpenLocalWebPage(local_url.substr(0, index), local_url.substr(index)); |
|
|
|
|
|
|
|
|
emit MainWindowOpenWebPage(external_url.substr(0, index), external_url.substr(index), |
|
|
|
|
|
false); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|