mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	main: Add main window integrations for QtWebBrowserApplet
This commit is contained in:
		
							parent
							
								
									e00e1fc755
								
							
						
					
					
						commit
						45da3be40e
					
				| @ -11,6 +11,8 @@ add_executable(yuzu | ||||
|     applets/profile_select.h | ||||
|     applets/software_keyboard.cpp | ||||
|     applets/software_keyboard.h | ||||
|     applets/web_browser.cpp | ||||
|     applets/web_browser.h | ||||
|     bootmanager.cpp | ||||
|     bootmanager.h | ||||
|     compatibility_list.cpp | ||||
| @ -154,6 +156,11 @@ if (USE_DISCORD_PRESENCE) | ||||
|     target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) | ||||
| endif() | ||||
| 
 | ||||
| if (YUZU_USE_QT_WEB_ENGINE) | ||||
|     target_link_libraries(yuzu PRIVATE Qt5::WebEngineCore Qt5::WebEngineWidgets) | ||||
|     target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE) | ||||
| endif () | ||||
| 
 | ||||
| if(UNIX AND NOT APPLE) | ||||
|     install(TARGETS yuzu RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") | ||||
| endif() | ||||
|  | ||||
| @ -10,11 +10,14 @@ | ||||
| // VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
 | ||||
| #include "applets/profile_select.h" | ||||
| #include "applets/software_keyboard.h" | ||||
| #include "applets/web_browser.h" | ||||
| #include "configuration/configure_per_general.h" | ||||
| #include "core/file_sys/vfs.h" | ||||
| #include "core/file_sys/vfs_real.h" | ||||
| #include "core/hle/service/acc/profile_manager.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.
 | ||||
| @ -96,6 +99,14 @@ 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 | ||||
| @ -252,6 +263,144 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message | ||||
|     emit SoftwareKeyboardFinishedCheckDialog(); | ||||
| } | ||||
| 
 | ||||
| #ifdef YUZU_USE_QT_WEB_ENGINE | ||||
| 
 | ||||
| void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) { | ||||
|     NXInputWebEngineView web_browser_view(this); | ||||
| 
 | ||||
|     // Scope to contain the QProgressDialog for initalization
 | ||||
|     { | ||||
|         QProgressDialog progress(this); | ||||
|         progress.setMinimumDuration(200); | ||||
|         progress.setLabelText(tr("Loading Web Applet...")); | ||||
|         progress.setRange(0, 4); | ||||
|         progress.setValue(0); | ||||
|         progress.show(); | ||||
| 
 | ||||
|         auto future = QtConcurrent::run([this] { emit WebBrowserUnpackRomFS(); }); | ||||
| 
 | ||||
|         while (!future.isFinished()) | ||||
|             QApplication::processEvents(); | ||||
| 
 | ||||
|         progress.setValue(1); | ||||
| 
 | ||||
|         // 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("nx_inject.js"); | ||||
|         nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation); | ||||
|         nx_shim.setRunsOnSubFrames(true); | ||||
|         web_browser_view.page()->profile()->scripts()->insert(nx_shim); | ||||
| 
 | ||||
|         web_browser_view.load( | ||||
|             QUrl(QUrl::fromLocalFile(QString::fromStdString(std::string(filename))).toString() + | ||||
|                  QString::fromStdString(std::string(additional_args)))); | ||||
| 
 | ||||
|         progress.setValue(2); | ||||
| 
 | ||||
|         render_window->hide(); | ||||
|         web_browser_view.setFocus(); | ||||
| 
 | ||||
|         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); | ||||
| 
 | ||||
|         web_browser_view.show(); | ||||
| 
 | ||||
|         progress.setValue(3); | ||||
| 
 | ||||
|         QApplication::processEvents(); | ||||
| 
 | ||||
|         progress.setValue(4); | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     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(QString::fromStdString(std::to_string(key_code)))); | ||||
|     }; | ||||
| 
 | ||||
|     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; | ||||
|         } | ||||
| 
 | ||||
|         const auto input = npad.GetPressState(); | ||||
|         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 (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
 | ||||
|     } | ||||
| 
 | ||||
|     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(); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) { | ||||
|     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); | ||||
| 
 | ||||
|     LOG_INFO(Frontend, | ||||
|              "(STUBBED) called - Missing QtWebEngine dependency needed to open website page at " | ||||
|              "'{}' with arguments '{}'!", | ||||
|              filename, additional_args); | ||||
| 
 | ||||
|     emit WebBrowserFinishedBrowsing(); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| void GMainWindow::InitializeWidgets() { | ||||
| #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING | ||||
|     ui.action_Report_Compatibility->setVisible(true); | ||||
| @ -612,6 +761,7 @@ bool GMainWindow::LoadROM(const QString& filename) { | ||||
| 
 | ||||
|     system.SetProfileSelector(std::make_unique<QtProfileSelector>(*this)); | ||||
|     system.SetSoftwareKeyboard(std::make_unique<QtSoftwareKeyboard>(*this)); | ||||
|     system.SetWebBrowser(std::make_unique<QtWebBrowser>(*this)); | ||||
| 
 | ||||
|     const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; | ||||
| 
 | ||||
| @ -1315,6 +1465,7 @@ void GMainWindow::OnStartGame() { | ||||
|     qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); | ||||
|     qRegisterMetaType<std::string>("std::string"); | ||||
|     qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>"); | ||||
|     qRegisterMetaType<std::string_view>("std::string_view"); | ||||
| 
 | ||||
|     connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); | ||||
| 
 | ||||
|  | ||||
| @ -26,6 +26,7 @@ class GraphicsSurfaceWidget; | ||||
| class GRenderWindow; | ||||
| class MicroProfileDialog; | ||||
| class ProfilerWidget; | ||||
| class QLabel; | ||||
| class WaitTreeWidget; | ||||
| enum class GameListOpenTarget; | ||||
| 
 | ||||
| @ -38,6 +39,10 @@ class RegisteredCacheUnion; | ||||
| class VfsFilesystem; | ||||
| } // namespace FileSys
 | ||||
| 
 | ||||
| namespace Service::Account { | ||||
| struct UUID; | ||||
| } // namespace Service::Account
 | ||||
| 
 | ||||
| namespace Tegra { | ||||
| class DebugContext; | ||||
| } | ||||
| @ -103,11 +108,16 @@ signals: | ||||
|     void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); | ||||
|     void SoftwareKeyboardFinishedCheckDialog(); | ||||
| 
 | ||||
|     void WebBrowserUnpackRomFS(); | ||||
|     void WebBrowserFinishedBrowsing(); | ||||
| 
 | ||||
| public slots: | ||||
|     void ProfileSelectorSelectProfile(); | ||||
|     void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); | ||||
|     void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); | ||||
| 
 | ||||
|     void WebBrowserOpenPage(std::string_view filename, std::string_view arguments); | ||||
| 
 | ||||
| private: | ||||
|     void InitializeWidgets(); | ||||
|     void InitializeDebugWidgets(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user