summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-12-24 16:23:31 -0500
committerGravatar Zach Hilman2018-12-28 15:32:39 -0500
commit45da3be40edd71195b7aac633187fc81956e3150 (patch)
tree52e297ec9e0d34e99300f3eb944534c4f9f187e3 /src
parentqt: Implement Qt frontend to web browser (diff)
downloadyuzu-45da3be40edd71195b7aac633187fc81956e3150.tar.gz
yuzu-45da3be40edd71195b7aac633187fc81956e3150.tar.xz
yuzu-45da3be40edd71195b7aac633187fc81956e3150.zip
main: Add main window integrations for QtWebBrowserApplet
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/CMakeLists.txt7
-rw-r--r--src/yuzu/main.cpp151
-rw-r--r--src/yuzu/main.h10
3 files changed, 168 insertions, 0 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 17ecaafde..c6378bce9 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -11,6 +11,8 @@ add_executable(yuzu
11 applets/profile_select.h 11 applets/profile_select.h
12 applets/software_keyboard.cpp 12 applets/software_keyboard.cpp
13 applets/software_keyboard.h 13 applets/software_keyboard.h
14 applets/web_browser.cpp
15 applets/web_browser.h
14 bootmanager.cpp 16 bootmanager.cpp
15 bootmanager.h 17 bootmanager.h
16 compatibility_list.cpp 18 compatibility_list.cpp
@@ -154,6 +156,11 @@ if (USE_DISCORD_PRESENCE)
154 target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) 156 target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE)
155endif() 157endif()
156 158
159if (YUZU_USE_QT_WEB_ENGINE)
160 target_link_libraries(yuzu PRIVATE Qt5::WebEngineCore Qt5::WebEngineWidgets)
161 target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE)
162endif ()
163
157if(UNIX AND NOT APPLE) 164if(UNIX AND NOT APPLE)
158 install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") 165 install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
159endif() 166endif()
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 01a0f94ab..18dc93c95 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -10,11 +10,14 @@
10// VFS includes must be before glad as they will conflict with Windows file api, which uses defines. 10// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
11#include "applets/profile_select.h" 11#include "applets/profile_select.h"
12#include "applets/software_keyboard.h" 12#include "applets/software_keyboard.h"
13#include "applets/web_browser.h"
13#include "configuration/configure_per_general.h" 14#include "configuration/configure_per_general.h"
14#include "core/file_sys/vfs.h" 15#include "core/file_sys/vfs.h"
15#include "core/file_sys/vfs_real.h" 16#include "core/file_sys/vfs_real.h"
16#include "core/hle/service/acc/profile_manager.h" 17#include "core/hle/service/acc/profile_manager.h"
17#include "core/hle/service/am/applets/applets.h" 18#include "core/hle/service/am/applets/applets.h"
19#include "core/hle/service/hid/controllers/npad.h"
20#include "core/hle/service/hid/hid.h"
18 21
19// These are wrappers to avoid the calls to CreateDirectory and CreateFile because of the Windows 22// These are wrappers to avoid the calls to CreateDirectory and CreateFile because of the Windows
20// defines. 23// defines.
@@ -96,6 +99,14 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
96#include "yuzu/discord_impl.h" 99#include "yuzu/discord_impl.h"
97#endif 100#endif
98 101
102#ifdef YUZU_USE_QT_WEB_ENGINE
103#include <QWebEngineProfile>
104#include <QWebEngineScript>
105#include <QWebEngineScriptCollection>
106#include <QWebEngineSettings>
107#include <QWebEngineView>
108#endif
109
99#ifdef QT_STATICPLUGIN 110#ifdef QT_STATICPLUGIN
100Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); 111Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
101#endif 112#endif
@@ -252,6 +263,144 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message
252 emit SoftwareKeyboardFinishedCheckDialog(); 263 emit SoftwareKeyboardFinishedCheckDialog();
253} 264}
254 265
266#ifdef YUZU_USE_QT_WEB_ENGINE
267
268void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) {
269 NXInputWebEngineView web_browser_view(this);
270
271 // Scope to contain the QProgressDialog for initalization
272 {
273 QProgressDialog progress(this);
274 progress.setMinimumDuration(200);
275 progress.setLabelText(tr("Loading Web Applet..."));
276 progress.setRange(0, 4);
277 progress.setValue(0);
278 progress.show();
279
280 auto future = QtConcurrent::run([this] { emit WebBrowserUnpackRomFS(); });
281
282 while (!future.isFinished())
283 QApplication::processEvents();
284
285 progress.setValue(1);
286
287 // Load the special shim script to handle input and exit.
288 QWebEngineScript nx_shim;
289 nx_shim.setSourceCode(GetNXShimInjectionScript());
290 nx_shim.setWorldId(QWebEngineScript::MainWorld);
291 nx_shim.setName("nx_inject.js");
292 nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation);
293 nx_shim.setRunsOnSubFrames(true);
294 web_browser_view.page()->profile()->scripts()->insert(nx_shim);
295
296 web_browser_view.load(
297 QUrl(QUrl::fromLocalFile(QString::fromStdString(std::string(filename))).toString() +
298 QString::fromStdString(std::string(additional_args))));
299
300 progress.setValue(2);
301
302 render_window->hide();
303 web_browser_view.setFocus();
304
305 const auto& layout = render_window->GetFramebufferLayout();
306 web_browser_view.resize(layout.screen.GetWidth(), layout.screen.GetHeight());
307 web_browser_view.move(layout.screen.left, layout.screen.top + menuBar()->height());
308 web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth()) /
309 Layout::ScreenUndocked::Width);
310 web_browser_view.settings()->setAttribute(
311 QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
312
313 web_browser_view.show();
314
315 progress.setValue(3);
316
317 QApplication::processEvents();
318
319 progress.setValue(4);
320 }
321
322 bool finished = false;
323 QAction* exit_action = new QAction(tr("Exit Web Applet"), this);
324 connect(exit_action, &QAction::triggered, this, [&finished] { finished = true; });
325 ui.menubar->addAction(exit_action);
326
327 auto& npad =
328 Core::System::GetInstance()
329 .ServiceManager()
330 .GetService<Service::HID::Hid>("hid")
331 ->GetAppletResource()
332 ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
333
334 const auto fire_js_keypress = [&web_browser_view](u32 key_code) {
335 web_browser_view.page()->runJavaScript(
336 QStringLiteral("document.dispatchEvent(new KeyboardEvent('keydown', {'key': %1}));")
337 .arg(QString::fromStdString(std::to_string(key_code))));
338 };
339
340 bool running_exit_check = false;
341 while (!finished) {
342 QApplication::processEvents();
343
344 if (!running_exit_check) {
345 web_browser_view.page()->runJavaScript(QStringLiteral("applet_done;"),
346 [&](const QVariant& res) {
347 running_exit_check = false;
348 if (res.toBool())
349 finished = true;
350 });
351 running_exit_check = true;
352 }
353
354 const auto input = npad.GetPressState();
355 for (std::size_t i = 0; i < Settings::NativeButton::NumButtons; ++i) {
356 if ((input & (1 << i)) != 0) {
357 LOG_DEBUG(Frontend, "firing input for button id={:02X}", i);
358 web_browser_view.page()->runJavaScript(
359 QStringLiteral("yuzu_key_callbacks[%1]();").arg(i));
360 }
361 }
362
363 if (input & 0x00888000) // RStick Down | LStick Down | DPad Down
364 fire_js_keypress(40); // Down Arrow Key
365 else if (input & 0x00444000) // RStick Right | LStick Right | DPad Right
366 fire_js_keypress(39); // Right Arrow Key
367 else if (input & 0x00222000) // RStick Up | LStick Up | DPad Up
368 fire_js_keypress(38); // Up Arrow Key
369 else if (input & 0x00111000) // RStick Left | LStick Left | DPad Left
370 fire_js_keypress(37); // Left Arrow Key
371 else if (input & 0x00000001) // A Button
372 fire_js_keypress(13); // Enter Key
373 }
374
375 web_browser_view.hide();
376 render_window->show();
377 render_window->setFocus();
378 ui.menubar->removeAction(exit_action);
379
380 // Needed to update render window focus/show and remove menubar action
381 QApplication::processEvents();
382 emit WebBrowserFinishedBrowsing();
383}
384
385#else
386
387void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) {
388 QMessageBox::warning(
389 this, tr("Web Applet"),
390 tr("This version of yuzu was built without QtWebEngine support, meaning that yuzu cannot "
391 "properly display the game manual or web page requested."),
392 QMessageBox::Ok, QMessageBox::Ok);
393
394 LOG_INFO(Frontend,
395 "(STUBBED) called - Missing QtWebEngine dependency needed to open website page at "
396 "'{}' with arguments '{}'!",
397 filename, additional_args);
398
399 emit WebBrowserFinishedBrowsing();
400}
401
402#endif
403
255void GMainWindow::InitializeWidgets() { 404void GMainWindow::InitializeWidgets() {
256#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING 405#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
257 ui.action_Report_Compatibility->setVisible(true); 406 ui.action_Report_Compatibility->setVisible(true);
@@ -612,6 +761,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
612 761
613 system.SetProfileSelector(std::make_unique<QtProfileSelector>(*this)); 762 system.SetProfileSelector(std::make_unique<QtProfileSelector>(*this));
614 system.SetSoftwareKeyboard(std::make_unique<QtSoftwareKeyboard>(*this)); 763 system.SetSoftwareKeyboard(std::make_unique<QtSoftwareKeyboard>(*this));
764 system.SetWebBrowser(std::make_unique<QtWebBrowser>(*this));
615 765
616 const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; 766 const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
617 767
@@ -1315,6 +1465,7 @@ void GMainWindow::OnStartGame() {
1315 qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); 1465 qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
1316 qRegisterMetaType<std::string>("std::string"); 1466 qRegisterMetaType<std::string>("std::string");
1317 qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>"); 1467 qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>");
1468 qRegisterMetaType<std::string_view>("std::string_view");
1318 1469
1319 connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); 1470 connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
1320 1471
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 4e37f6a2d..3af5fa1f3 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -26,6 +26,7 @@ class GraphicsSurfaceWidget;
26class GRenderWindow; 26class GRenderWindow;
27class MicroProfileDialog; 27class MicroProfileDialog;
28class ProfilerWidget; 28class ProfilerWidget;
29class QLabel;
29class WaitTreeWidget; 30class WaitTreeWidget;
30enum class GameListOpenTarget; 31enum class GameListOpenTarget;
31 32
@@ -38,6 +39,10 @@ class RegisteredCacheUnion;
38class VfsFilesystem; 39class VfsFilesystem;
39} // namespace FileSys 40} // namespace FileSys
40 41
42namespace Service::Account {
43struct UUID;
44} // namespace Service::Account
45
41namespace Tegra { 46namespace Tegra {
42class DebugContext; 47class DebugContext;
43} 48}
@@ -103,11 +108,16 @@ signals:
103 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); 108 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
104 void SoftwareKeyboardFinishedCheckDialog(); 109 void SoftwareKeyboardFinishedCheckDialog();
105 110
111 void WebBrowserUnpackRomFS();
112 void WebBrowserFinishedBrowsing();
113
106public slots: 114public slots:
107 void ProfileSelectorSelectProfile(); 115 void ProfileSelectorSelectProfile();
108 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); 116 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
109 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); 117 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
110 118
119 void WebBrowserOpenPage(std::string_view filename, std::string_view arguments);
120
111private: 121private:
112 void InitializeWidgets(); 122 void InitializeWidgets();
113 void InitializeDebugWidgets(); 123 void InitializeDebugWidgets();