diff options
| author | 2018-12-24 16:23:31 -0500 | |
|---|---|---|
| committer | 2018-12-28 15:32:39 -0500 | |
| commit | 45da3be40edd71195b7aac633187fc81956e3150 (patch) | |
| tree | 52e297ec9e0d34e99300f3eb944534c4f9f187e3 /src | |
| parent | qt: Implement Qt frontend to web browser (diff) | |
| download | yuzu-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.txt | 7 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 151 | ||||
| -rw-r--r-- | src/yuzu/main.h | 10 |
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) |
| 155 | endif() | 157 | endif() |
| 156 | 158 | ||
| 159 | if (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) | ||
| 162 | endif () | ||
| 163 | |||
| 157 | if(UNIX AND NOT APPLE) | 164 | if(UNIX AND NOT APPLE) |
| 158 | install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") | 165 | install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") |
| 159 | endif() | 166 | endif() |
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 |
| 100 | Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); | 111 | Q_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 | |||
| 268 | void 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 | |||
| 387 | void 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 | |||
| 255 | void GMainWindow::InitializeWidgets() { | 404 | void 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; | |||
| 26 | class GRenderWindow; | 26 | class GRenderWindow; |
| 27 | class MicroProfileDialog; | 27 | class MicroProfileDialog; |
| 28 | class ProfilerWidget; | 28 | class ProfilerWidget; |
| 29 | class QLabel; | ||
| 29 | class WaitTreeWidget; | 30 | class WaitTreeWidget; |
| 30 | enum class GameListOpenTarget; | 31 | enum class GameListOpenTarget; |
| 31 | 32 | ||
| @@ -38,6 +39,10 @@ class RegisteredCacheUnion; | |||
| 38 | class VfsFilesystem; | 39 | class VfsFilesystem; |
| 39 | } // namespace FileSys | 40 | } // namespace FileSys |
| 40 | 41 | ||
| 42 | namespace Service::Account { | ||
| 43 | struct UUID; | ||
| 44 | } // namespace Service::Account | ||
| 45 | |||
| 41 | namespace Tegra { | 46 | namespace Tegra { |
| 42 | class DebugContext; | 47 | class 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 | |||
| 106 | public slots: | 114 | public 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 | |||
| 111 | private: | 121 | private: |
| 112 | void InitializeWidgets(); | 122 | void InitializeWidgets(); |
| 113 | void InitializeDebugWidgets(); | 123 | void InitializeDebugWidgets(); |