From 6b25b5069614249c3b58717600ad59778026b2c8 Mon Sep 17 00:00:00 2001
From: zty199 <46324746+zty199@users.noreply.github.com>
Date: Sun, 20 Nov 2022 23:55:52 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=90=AF=E5=8A=A8?=
 =?UTF-8?q?=E6=97=B6=E8=AF=86=E5=88=AB=20DTK=20=E4=B8=BB=E9=A2=98=E9=A2=9C?=
 =?UTF-8?q?=E8=89=B2=EF=BC=8C=E5=88=A4=E6=96=AD=E7=BD=91=E9=A1=B5=E6=98=AF?=
 =?UTF-8?q?=E5=90=A6=E9=9C=80=E8=A6=81=E6=98=BE=E7=A4=BA=E4=B8=BA=E6=B7=B1?=
 =?UTF-8?q?=E8=89=B2=E6=A8=A1=E5=BC=8F=EF=BC=88=E5=88=87=E6=8D=A2=20DTK=20?=
 =?UTF-8?q?=E4=B8=BB=E9=A2=98=E5=90=8E=E9=87=8D=E5=90=AF=E7=94=9F=E6=95=88?=
 =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E6=94=AF=E6=8C=81=E5=AE=9E=E6=97=B6=E7=94=9F?=
 =?UTF-8?q?=E6=95=88=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

https://github.com/qutebrowser/qutebrowser/issues/4840
启动时判断 DTK 主题颜色,QTWEBENGINE_CHROMIUM_FLAGS 环境变量添加 --blink-settings=preferredColorScheme=0 启用深色模式(或 --force-dark-mode)(Qt >= 5.14,当前仅 Deepin 支持)

Log: 支持启动时识别 DTK 主题颜色,判断网页是否需要显示为深色模式
---
 spark-webapp-runtime/main.cpp          |  12 ++-
 spark-webapp-runtime/webengineview.cpp |  39 +++++++++-
 spark-webapp-runtime/webengineview.h   |   2 +
 spark-webapp-runtime/widget.cpp        | 100 +++++++++++++++++--------
 spark-webapp-runtime/widget.h          |   9 +++
 5 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/spark-webapp-runtime/main.cpp b/spark-webapp-runtime/main.cpp
index 4eba78b..8f9ca87 100644
--- a/spark-webapp-runtime/main.cpp
+++ b/spark-webapp-runtime/main.cpp
@@ -4,10 +4,11 @@
  */
 #include "application.h"
 #include "mainwindow.h"
-#include "globaldefine.h"
+#include "webengineview.h"
 #include "httpd.h"
 
 #include <DSysInfo>
+#include <DApplicationSettings>
 
 #include <QCommandLineParser>
 #include <QCommandLineOption>
@@ -50,6 +51,9 @@ int main(int argc, char *argv[])
     }
     Application a(fakeArgc, fakeArgv.data());
 
+    // 保存 DTK 主题
+    DApplicationSettings settings;
+
     // 解析命令行启动参数
     QCommandLineParser parser;
 
@@ -255,12 +259,14 @@ int main(int argc, char *argv[])
         toUseGPU = parser.value(useGPU).toUInt();
     }
     if (toUseGPU == true) {
-        qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --blink-settings=darkMode=4,darkModeImagePolicy=2");
+        qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode");
 #ifdef __sw_64__
-        qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --blink-settings=darkMode=4,darkModeImagePolicy=2 --no-sandbox");
+        qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --no-sandbox");
 #endif
         qDebug() << "Setting GPU to True.";
     }
+    // 初始化 QtWebEngine 深色模式环境变量
+    WebEngineView::handleChromiumFlags();
 
 #if SSL_SERVER
     if (parser.isSet(optSSLPort)) {
diff --git a/spark-webapp-runtime/webengineview.cpp b/spark-webapp-runtime/webengineview.cpp
index dc25354..6fa3ed8 100644
--- a/spark-webapp-runtime/webengineview.cpp
+++ b/spark-webapp-runtime/webengineview.cpp
@@ -1,20 +1,53 @@
 #include "webengineview.h"
 //#include "webengineurlrequestinterceptor.h"
 
+#include <DGuiApplicationHelper>
+
 #include <QWebEngineSettings>
 #include <QWebEngineProfile>
 #include <QLocale>
 
+DGUI_USE_NAMESPACE
+
 WebEngineView::WebEngineView(QWidget *parent)
     : QWebEngineView(parent)
 //    , interceptor(new WebEngineUrlRequestInterceptor(this))
 {
-    //    page()->profile()->setHttpUserAgent(page()->profile()->httpUserAgent() + " MediaFeature/prefers-color-scheme:dark");
-
     connect(this, &WebEngineView::urlChanged, this, [=]() {
         //        page()->setUrlRequestInterceptor(interceptor);
         //        page()->settings()->setAttribute(QWebEngineSettings::WebAttribute::LocalContentCanAccessRemoteUrls, true);
         page()->profile()->setHttpAcceptLanguage(QLocale::system().name());
-        //        qInfo() << "User Agent:" << page()->profile()->httpUserAgent();
     });
 }
+
+void WebEngineView::handleChromiumFlags()
+{
+    DGuiApplicationHelper::ColorType themeType = DGuiApplicationHelper::instance()->themeType();
+
+    QString env = qgetenv("QTWEBENGINE_CHROMIUM_FLAGS");
+    QStringList flags = env.split(" ", QString::SkipEmptyParts);
+
+    /**
+     * --blink-settings=preferredColorScheme=0 强制 prefers-color-scheme=dark (>= 5.14)
+     * --blink-settings=darkModeEnabled=true,darkModeInversionAlgorithm=4 强制反转网页颜色 (>= 5.14 && < 5.15)
+     * --blink-settings=forceDarkModeEnabled=true,darkModeInversionAlgorithm=4 强制反转网页颜色 (>= 5.15)
+     * --force-dark-mode 强制 prefers-color-scheme=dark (>= 5.14)
+     */
+    foreach (const QString &flag, flags) {
+        if (flag == "--force-dark-mode") {
+            flags.removeAll(flag);
+        }
+        if (flag.startsWith("--blink-settings")) {
+            flags.removeAll(flag);
+        }
+    }
+
+    if (themeType == DGuiApplicationHelper::DarkType) {
+        flags.append("--blink-settings=preferredColorScheme=0");
+    } else {
+        flags.append("--blink-settings=preferredColorScheme=1");
+    }
+    qputenv("QTWEBENGINE_CHROMIUM_FLAGS", flags.join(" ").toUtf8());
+
+    qDebug() << Q_FUNC_INFO << "QTWEBENGINE_CHROMIUM_FLAGS=" + qgetenv("QTWEBENGINE_CHROMIUM_FLAGS");
+}
diff --git a/spark-webapp-runtime/webengineview.h b/spark-webapp-runtime/webengineview.h
index 4ca48b2..b688fd6 100644
--- a/spark-webapp-runtime/webengineview.h
+++ b/spark-webapp-runtime/webengineview.h
@@ -11,6 +11,8 @@ class WebEngineView : public QWebEngineView
 public:
     explicit WebEngineView(QWidget *parent = nullptr);
 
+    static void handleChromiumFlags();
+
 private:
     //    WebEngineUrlRequestInterceptor *interceptor = nullptr;
 };
diff --git a/spark-webapp-runtime/widget.cpp b/spark-webapp-runtime/widget.cpp
index 482d457..afff924 100644
--- a/spark-webapp-runtime/widget.cpp
+++ b/spark-webapp-runtime/widget.cpp
@@ -13,37 +13,8 @@ Widget::Widget(QString szUrl, QWidget *parent)
     , mainLayout(new QStackedLayout(this))
     , m_szUrl(szUrl)
 {
-    m_spinner->setFixedSize(96, 96);
-
-    m_webEngineView->setObjectName(QStringLiteral("webEngineView"));
-    m_webEngineView->setEnabled(true);
-    m_webEngineView->setAutoFillBackground(false);
-
-    DApplication *dApp = qobject_cast<DApplication *>(qApp);
-    m_webEngineView->setZoomFactor(dApp->devicePixelRatio());
-
-    WebEnginePage *page = new WebEnginePage(m_webEngineView);
-    m_webEngineView->setPage(page);
-
-    page->setUrl(QUrl());
-    if (!m_szUrl.isEmpty()) {
-        page->setUrl(QUrl(m_szUrl));
-    }
-
-    QWidget *spinnerWidget = new QWidget(this);
-    QHBoxLayout *spinnerLayout = new QHBoxLayout(spinnerWidget);
-    spinnerLayout->setMargin(0);
-    spinnerLayout->setSpacing(0);
-    spinnerLayout->setAlignment(Qt::AlignCenter);
-    spinnerLayout->addStretch();
-    spinnerLayout->addWidget(m_spinner);
-    spinnerLayout->addStretch();
-
-    mainLayout->addWidget(spinnerWidget);
-    mainLayout->addWidget(m_webEngineView);
-
-    connect(m_webEngineView, &QWebEngineView::loadStarted, this, &Widget::on_loadStarted);
-    connect(m_webEngineView, &QWebEngineView::loadFinished, this, &Widget::on_loadFinished);
+    initUI();
+    initConnections();
 }
 
 Widget::~Widget()
@@ -70,6 +41,63 @@ void Widget::refresh()
     m_webEngineView->reload();
 }
 
+void Widget::initUI()
+{
+    m_spinner->setFixedSize(96, 96);
+
+    DApplication *dApp = qobject_cast<DApplication *>(qApp);
+    m_webEngineView->setZoomFactor(dApp->devicePixelRatio());
+
+    WebEnginePage *page = new WebEnginePage(m_webEngineView);
+    m_webEngineView->setPage(page);
+
+    page->setUrl(QUrl());
+    if (!m_szUrl.isEmpty()) {
+        page->setUrl(QUrl(m_szUrl));
+    }
+
+    QWidget *spinnerWidget = new QWidget(this);
+    QHBoxLayout *spinnerLayout = new QHBoxLayout(spinnerWidget);
+    spinnerLayout->setMargin(0);
+    spinnerLayout->setSpacing(0);
+    spinnerLayout->setAlignment(Qt::AlignCenter);
+    spinnerLayout->addStretch();
+    spinnerLayout->addWidget(m_spinner);
+    spinnerLayout->addStretch();
+
+    mainLayout->addWidget(spinnerWidget);
+    mainLayout->addWidget(m_webEngineView);
+}
+
+void Widget::initConnections()
+{
+    connect(m_webEngineView, &QWebEngineView::loadStarted, this, &Widget::on_loadStarted, Qt::UniqueConnection);
+    connect(m_webEngineView, &QWebEngineView::loadFinished, this, &Widget::on_loadFinished, Qt::UniqueConnection);
+
+    // FIXME: DTK 主题切换时,动态修改 QtWebEngine prefers-color-scheme
+    //    connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::paletteTypeChanged, this, &Widget::slotPaletteTypeChanged, Qt::UniqueConnection);
+}
+
+void Widget::updateLayout()
+{
+    on_loadStarted();
+
+    mainLayout->removeWidget(m_webEngineView);
+    QUrl url = m_webEngineView->url();
+    m_webEngineView->deleteLater();
+
+    m_webEngineView = new WebEngineView(this);
+    mainLayout->addWidget(m_webEngineView);
+    initConnections();
+
+    DApplication *dApp = qobject_cast<DApplication *>(qApp);
+    m_webEngineView->setZoomFactor(dApp->devicePixelRatio());
+
+    WebEnginePage *page = new WebEnginePage(m_webEngineView);
+    m_webEngineView->setPage(page);
+    page->setUrl(url);
+}
+
 void Widget::on_loadStarted()
 {
     mainLayout->setCurrentIndex(0);
@@ -81,3 +109,13 @@ void Widget::on_loadFinished()
     m_spinner->stop();
     mainLayout->setCurrentIndex(1);
 }
+
+void Widget::slotPaletteTypeChanged(DGuiApplicationHelper::ColorType paletteType)
+{
+    Q_UNUSED(paletteType)
+
+    WebEngineView::handleChromiumFlags();
+    if (m_webEngineView) {
+        updateLayout();
+    }
+}
diff --git a/spark-webapp-runtime/widget.h b/spark-webapp-runtime/widget.h
index c128dbc..2ed7ee2 100644
--- a/spark-webapp-runtime/widget.h
+++ b/spark-webapp-runtime/widget.h
@@ -2,12 +2,14 @@
 #define WIDGET_H
 
 #include <DSpinner>
+#include <DGuiApplicationHelper>
 
 #include <QWidget>
 #include <QWebEnginePage>
 #include <QStackedLayout>
 
 DWIDGET_USE_NAMESPACE
+DGUI_USE_NAMESPACE
 
 class WebEngineView;
 class Widget : public QWidget
@@ -23,10 +25,17 @@ public:
     void goForward();
     void refresh();
 
+private:
+    void initUI();
+    void initConnections();
+    void updateLayout();
+
 private slots:
     void on_loadStarted();
     void on_loadFinished();
 
+    void slotPaletteTypeChanged(DGuiApplicationHelper::ColorType paletteType);
+
 private:
     WebEngineView *m_webEngineView = nullptr;
     DSpinner *m_spinner = nullptr;