summaryrefslogtreecommitdiff
path: root/archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:51:45 +0300
commitd3261e64152397db2dca4d691a990c6bc2a6f4dd (patch)
treefac2f7be638651181a72453d714f0f96675c2b8b /archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp
parent31b9a8949ed0a288143e23bf739f2eb64fdc63be (diff)
downloadProject-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.tar.gz
Project-Tick-d3261e64152397db2dca4d691a990c6bc2a6f4dd.zip
NOISSUE add archived projects
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp')
-rw-r--r--archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp b/archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp
new file mode 100644
index 0000000000..65b2b72589
--- /dev/null
+++ b/archived/projt-launcher/launcher/ui/widgets/WebView2Widget.cpp
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "WebView2Widget.h"
+
+#include <QDir>
+#include <QResizeEvent>
+#include <QShowEvent>
+#include <QStandardPaths>
+#include <QTimer>
+
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+#include <windows.h>
+#include <wrl.h>
+#include <WebView2.h>
+#if __has_include(<WebView2Loader.h>)
+#include <WebView2Loader.h>
+#define PROJT_HAVE_WEBVIEW2_LOADER 1
+#else
+#define PROJT_HAVE_WEBVIEW2_LOADER 0
+extern "C" HRESULT STDAPICALLTYPE CreateCoreWebView2EnvironmentWithOptions(
+ PCWSTR browserExecutableFolder,
+ PCWSTR userDataFolder,
+ ICoreWebView2EnvironmentOptions* environmentOptions,
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* environmentCreatedHandler);
+#endif
+
+using Microsoft::WRL::Callback;
+using Microsoft::WRL::ComPtr;
+
+struct WebView2Widget::Impl
+{
+ ComPtr<ICoreWebView2Environment> env;
+ ComPtr<ICoreWebView2Controller> controller;
+ ComPtr<ICoreWebView2> webview;
+};
+#endif
+
+WebView2Widget::WebView2Widget(QWidget* parent) : HubViewBase(parent)
+{
+ setAttribute(Qt::WA_NativeWindow);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ m_impl = new Impl();
+ QTimer::singleShot(0, this, &WebView2Widget::initialize);
+#endif
+}
+
+WebView2Widget::~WebView2Widget()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ delete m_impl;
+#endif
+}
+
+void WebView2Widget::setUrl(const QUrl& url)
+{
+ m_url = url;
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (m_impl && m_impl->webview)
+ {
+ const auto wide = url.toString().toStdWString();
+ m_impl->webview->Navigate(wide.c_str());
+ return;
+ }
+#endif
+}
+
+QUrl WebView2Widget::url() const
+{
+ return m_url;
+}
+
+bool WebView2Widget::canGoBack() const
+{
+ return m_canGoBack;
+}
+
+bool WebView2Widget::canGoForward() const
+{
+ return m_canGoForward;
+}
+
+void WebView2Widget::back()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (m_impl && m_impl->webview && m_canGoBack)
+ {
+ m_impl->webview->GoBack();
+ }
+#endif
+}
+
+void WebView2Widget::forward()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (m_impl && m_impl->webview && m_canGoForward)
+ {
+ m_impl->webview->GoForward();
+ }
+#endif
+}
+
+void WebView2Widget::reload()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (m_impl && m_impl->webview)
+ {
+ m_impl->webview->Reload();
+ }
+#endif
+}
+
+void WebView2Widget::resizeEvent(QResizeEvent* event)
+{
+ QWidget::resizeEvent(event);
+ updateBounds();
+}
+
+void WebView2Widget::showEvent(QShowEvent* event)
+{
+ QWidget::showEvent(event);
+ updateBounds();
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (m_impl && m_impl->webview && m_url.isValid())
+ {
+ const auto wide = m_url.toString().toStdWString();
+ m_impl->webview->Navigate(wide.c_str());
+ }
+#endif
+}
+
+void WebView2Widget::initialize()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (m_initialized || !m_impl)
+ return;
+
+ m_initialized = true;
+ const QString dataPath =
+ QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/webview2");
+ QDir().mkpath(dataPath);
+
+ const auto dataPathWide = dataPath.toStdWString();
+ const auto hwnd = reinterpret_cast<HWND>(winId());
+ HRESULT comInitResult = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+ Q_UNUSED(comInitResult);
+
+ CreateCoreWebView2EnvironmentWithOptions(
+ nullptr,
+ dataPathWide.c_str(),
+ nullptr,
+ Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
+ [this, hwnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT
+ {
+ if (FAILED(result) || !env)
+ {
+ emit loadFinished(false);
+ return S_OK;
+ }
+
+ m_impl->env = env;
+ env->CreateCoreWebView2Controller(
+ hwnd,
+ Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
+ [this](HRESULT controllerResult, ICoreWebView2Controller* controller) -> HRESULT
+ {
+ if (FAILED(controllerResult) || !controller)
+ {
+ emit loadFinished(false);
+ return S_OK;
+ }
+
+ m_impl->controller = controller;
+ m_impl->controller->get_CoreWebView2(&m_impl->webview);
+
+ if (!m_impl->webview)
+ {
+ emit loadFinished(false);
+ return S_OK;
+ }
+
+ updateBounds();
+
+ EventRegistrationToken token{};
+ m_impl->webview->add_DocumentTitleChanged(
+ Callback<ICoreWebView2DocumentTitleChangedEventHandler>(
+ [this](ICoreWebView2*, IUnknown*) -> HRESULT
+ {
+ LPWSTR title = nullptr;
+ if (SUCCEEDED(m_impl->webview->get_DocumentTitle(&title)) && title)
+ {
+ emit titleChanged(QString::fromWCharArray(title));
+ CoTaskMemFree(title);
+ }
+ return S_OK;
+ })
+ .Get(),
+ &token);
+
+ m_impl->webview->add_SourceChanged(
+ Callback<ICoreWebView2SourceChangedEventHandler>(
+ [this](ICoreWebView2*, ICoreWebView2SourceChangedEventArgs*) -> HRESULT
+ {
+ LPWSTR uri = nullptr;
+ if (SUCCEEDED(m_impl->webview->get_Source(&uri)) && uri)
+ {
+ m_url = QUrl(QString::fromWCharArray(uri));
+ emit urlChanged(m_url);
+ CoTaskMemFree(uri);
+ }
+ updateNavigationState();
+ return S_OK;
+ })
+ .Get(),
+ &token);
+
+ m_impl->webview->add_NavigationCompleted(
+ Callback<ICoreWebView2NavigationCompletedEventHandler>(
+ [this](ICoreWebView2*, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT
+ {
+ BOOL success = FALSE;
+ if (args)
+ {
+ args->get_IsSuccess(&success);
+ }
+ updateNavigationState();
+ emit loadFinished(success == TRUE);
+ return S_OK;
+ })
+ .Get(),
+ &token);
+
+ m_impl->webview->add_HistoryChanged(Callback<ICoreWebView2HistoryChangedEventHandler>(
+ [this](ICoreWebView2*, IUnknown*) -> HRESULT
+ {
+ updateNavigationState();
+ return S_OK;
+ })
+ .Get(),
+ &token);
+
+ if (m_url.isValid())
+ {
+ const auto wideUrl = m_url.toString().toStdWString();
+ m_impl->webview->Navigate(wideUrl.c_str());
+ }
+
+ return S_OK;
+ })
+ .Get());
+
+ return S_OK;
+ })
+ .Get());
+#else
+ emit loadFinished(false);
+#endif
+}
+
+void WebView2Widget::updateBounds()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (!m_impl || !m_impl->controller)
+ return;
+
+ RECT bounds{};
+ bounds.left = 0;
+ bounds.top = 0;
+ bounds.right = width();
+ bounds.bottom = height();
+ m_impl->controller->put_Bounds(bounds);
+#endif
+}
+
+void WebView2Widget::updateNavigationState()
+{
+#if defined(PROJT_USE_WEBVIEW2) && defined(_WIN32)
+ if (!m_impl || !m_impl->webview)
+ return;
+
+ BOOL canBack = FALSE;
+ BOOL canForward = FALSE;
+ m_impl->webview->get_CanGoBack(&canBack);
+ m_impl->webview->get_CanGoForward(&canForward);
+
+ const bool newCanBack = (canBack == TRUE);
+ const bool newCanForward = (canForward == TRUE);
+ if (newCanBack != m_canGoBack || newCanForward != m_canGoForward)
+ {
+ m_canGoBack = newCanBack;
+ m_canGoForward = newCanForward;
+ emit navigationStateChanged();
+ }
+#endif
+}