diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe3d9cfa8..776e9ce34 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -373,6 +373,8 @@ add_subdirectory(treeland-screensaver) set(BIN_NAME treeland) qt_add_executable(${BIN_NAME} + deepintheme.cpp + deepintheme.h main.cpp ) diff --git a/src/deepintheme.cpp b/src/deepintheme.cpp new file mode 100644 index 000000000..152925c75 --- /dev/null +++ b/src/deepintheme.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "deepintheme.h" + +#include "seat/helper.h" +#include "seatuserconfig.hpp" +#include "treelanduserconfig.hpp" + +#include + +#include +#include +#include +#include + +DCORE_USE_NAMESPACE; +DGUI_USE_NAMESPACE; + +QDeepinTheme::QDeepinTheme() = default; + +QDeepinTheme::~QDeepinTheme() +{ + disconnectConfig(); + disconnectSeatConfig(); +} + +const QPalette *QDeepinTheme::palette(QPlatformTheme::Palette type) const +{ + if (type != QPlatformTheme::SystemPalette) { + return QGenericUnixTheme::palette(type); + } + static QPalette palette; + palette = DGuiApplicationHelper::instance()->applicationPalette(); + return &palette; +} + +QVariant QDeepinTheme::themeHint(ThemeHint hint) const +{ + if (!m_config) + return QGenericUnixTheme::themeHint(hint); + + switch (hint) { + case CursorFlashTime: + return m_config->cursorBlink() ? m_config->cursorBlinkTime() : 0; + case MouseDoubleClickInterval: + return m_config->doubleClickTime(); + case MouseDoubleClickDistance: + return m_config->doubleClickDistance(); + case StartDragDistance: + return m_config->dndDragThreshold(); + case MouseCursorTheme: + return m_config->cursorThemeName(); + case MouseCursorSize: + return QSizeF(m_config->cursorSize(), m_config->cursorSize()); + case KeyboardAutoRepeatRate: + return m_seatConfig ? m_seatConfig->keyboardRate() : QGenericUnixTheme::themeHint(hint); + case KeyboardInputInterval: + return m_seatConfig ? m_seatConfig->keyboardDelay() : QGenericUnixTheme::themeHint(hint); + default: + break; + } + return QGenericUnixTheme::themeHint(hint); +} + +const QFont *QDeepinTheme::font(Font type) const +{ + if (!m_config) + return QGenericUnixTheme::font(type); + + switch (type) { + case SystemFont: { + static QFont f; + f.setFamily(m_config->font()); + f.setPointSize(m_config->fontSize() / 10.0); + return &f; + } + case FixedFont: { + static QFont f; + f.setFamily(m_config->monoFont()); + f.setPointSize(m_config->fontSize() / 10.0); + return &f; + } + default: + break; + } + return QGenericUnixTheme::font(type); +} + +void QDeepinTheme::bindConfig(TreelandUserConfig *config) +{ + if (m_config == config) + return; + + disconnectConfig(); + m_config = config; + if (!m_config) + return; + + auto addConnection = [this](const QMetaObject::Connection &conn) { + m_connections.push_back(conn); + }; + + addConnection(QObject::connect(m_config, &TreelandUserConfig::cursorBlinkChanged, m_config, [this]() { applyCursorSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::cursorBlinkTimeChanged, m_config, [this]() { applyCursorSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::doubleClickTimeChanged, m_config, [this]() { applyStyleHintSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::doubleClickDistanceChanged, m_config, [this]() { applyThemeSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::dndDragThresholdChanged, m_config, [this]() { applyStyleHintSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::fontChanged, m_config, [this]() { applyFontSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::monoFontChanged, m_config, [this]() { applyFontSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::fontSizeChanged, m_config, [this]() { applyFontSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::iconThemeNameChanged, m_config, [this]() { applyThemeSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::themeNameChanged, m_config, [this]() { applyThemeSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::preferDarkChanged, m_config, [this]() { applyStyleHintSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::cursorThemeNameChanged, m_config, [this]() { applyThemeSettings(); })); + addConnection(QObject::connect(m_config, &TreelandUserConfig::cursorSizeChanged, m_config, [this]() { applyThemeSettings(); })); + + applyAllSettings(); +} + +void QDeepinTheme::applyAllSettings() +{ + applyCursorSettings(); + applyStyleHintSettings(); + applyFontSettings(); + applyThemeSettings(); + applyKeyboardSettings(); +} + +void QDeepinTheme::applyCursorSettings() +{ + if (!m_config) + return; + + int flashTime = m_config->cursorBlink() ? m_config->cursorBlinkTime() : 0; + QGuiApplication::styleHints()->setCursorFlashTime(flashTime); +} + +void QDeepinTheme::applyFontSettings() +{ + if (!m_config) + return; + + QFont systemFont; + systemFont.setFamily(m_config->font()); + systemFont.setPointSize(m_config->fontSize() / 10.0); + QGuiApplication::setFont(systemFont); +} + +void QDeepinTheme::applyThemeSettings() +{ + if (!m_config) + return; + + QCoreApplication::postEvent(qGuiApp, new QEvent(QEvent::ThemeChange)); +} + +void QDeepinTheme::applyStyleHintSettings() +{ + if (!m_config) + return; + + auto *hints = QGuiApplication::styleHints(); + hints->setMouseDoubleClickInterval(m_config->doubleClickTime()); + hints->setStartDragDistance(m_config->dndDragThreshold()); + + if (m_config->preferDark()) { + hints->setColorScheme(Qt::ColorScheme::Dark); + } else { + hints->setColorScheme(Qt::ColorScheme::Light); + } +} + +void QDeepinTheme::disconnectConfig() +{ + for (const auto &conn : std::as_const(m_connections)) { + QObject::disconnect(conn); + } + m_connections.clear(); + m_config = nullptr; +} + +void QDeepinTheme::bindSeatConfig(SeatUserDConfig *config) +{ + if (m_seatConfig == config) + return; + + disconnectSeatConfig(); + m_seatConfig = config; + if (!m_seatConfig) + return; + + auto addConnection = [this](const QMetaObject::Connection &conn) { + m_seatConnections.push_back(conn); + }; + + addConnection(QObject::connect(m_seatConfig, &SeatUserDConfig::keyboardRateChanged, + m_seatConfig, [this]() { applyKeyboardSettings(); })); + addConnection(QObject::connect(m_seatConfig, &SeatUserDConfig::keyboardDelayChanged, + m_seatConfig, [this]() { applyKeyboardSettings(); })); + + applyKeyboardSettings(); +} + +void QDeepinTheme::applyKeyboardSettings() +{ + if (!m_seatConfig) + return; + + auto *hints = QGuiApplication::styleHints(); + hints->setKeyboardAutoRepeatRate(m_seatConfig->keyboardRate()); + hints->setKeyboardInputInterval(m_seatConfig->keyboardDelay()); +} + +void QDeepinTheme::disconnectSeatConfig() +{ + for (const auto &conn : std::as_const(m_seatConnections)) { + QObject::disconnect(conn); + } + m_seatConnections.clear(); + m_seatConfig = nullptr; +} diff --git a/src/deepintheme.h b/src/deepintheme.h new file mode 100644 index 000000000..99f41c3ed --- /dev/null +++ b/src/deepintheme.h @@ -0,0 +1,49 @@ +// Copyright (C) 2026 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#pragma once + +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0) +# include +#else +# include +#endif + +#include + +class SeatUserDConfig; +class TreelandUserConfig; + +class QDeepinTheme : public QGenericUnixTheme +{ +public: + QDeepinTheme(); + ~QDeepinTheme() override; + + const QPalette *palette(QPlatformTheme::Palette type) const override; + QVariant themeHint(ThemeHint hint) const override; + const QFont *font(Font type) const override; + + void bindConfig(TreelandUserConfig *config); + void bindSeatConfig(SeatUserDConfig *config); + +private: + void applyAllSettings(); + void applyCursorSettings(); + void applyFontSettings(); + void applyThemeSettings(); + void applyStyleHintSettings(); + void applyKeyboardSettings(); + + void disconnectConfig(); + void disconnectSeatConfig(); + + QPointer m_config; + QPointer m_seatConfig; + std::vector m_connections; + std::vector m_seatConnections; +}; diff --git a/src/input/inputmanager.cpp b/src/input/inputmanager.cpp index 2859b7807..18d42bd3b 100644 --- a/src/input/inputmanager.cpp +++ b/src/input/inputmanager.cpp @@ -41,6 +41,8 @@ void InputManager::setupSeatUserConfig(const QString &userName) "org.deepin.dde.treeland", "/" + userName); + Q_EMIT seatConfigChanged(m_seatDConfig); + #if SEATUSERDCONFIG_DCONFIG_FILE_VERSION_MINOR > 0 if (m_seatDConfig->isInitializeSucceeded()) { #else diff --git a/src/input/inputmanager.h b/src/input/inputmanager.h index 96796a4e7..6fc325cfb 100644 --- a/src/input/inputmanager.h +++ b/src/input/inputmanager.h @@ -33,6 +33,9 @@ public Q_SLOTS: void onMousePointerConfigCreated(PointerDeviceConfigurationV1 *config); void onTouchpadPointerConfigCreated(PointerDeviceConfigurationV1 *config); +Q_SIGNALS: + void seatConfigChanged(SeatUserDConfig *config); + private Q_SLOTS: void handleMousePointerConfigApplied(PointerDeviceConfigurationV1::ChangeFlags changes); void handleTouchpadPointerConfigApplied(PointerDeviceConfigurationV1::ChangeFlags changes); diff --git a/src/main.cpp b/src/main.cpp index 9d3909978..2eb086243 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "core/treeland.h" +#include "deepintheme.h" +#include "input/inputmanager.h" +#include "seat/helper.h" #include "utils/cmdline.h" #include @@ -14,13 +17,6 @@ #include #include -#include - -#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0) -# include -#else -# include -#endif #include @@ -29,19 +25,16 @@ WAYLIB_SERVER_USE_NAMESPACE DCORE_USE_NAMESPACE; -class QDeepinTheme : public QGenericUnixTheme +static QDeepinTheme *g_theme = nullptr; + +static void bindThemeConfig() { -public: - const QPalette *palette(QPlatformTheme::Palette type) const override - { - if (type != QPlatformTheme::SystemPalette) { - return QGenericUnixTheme::palette(type); - } - static QPalette palette; - palette = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette(); - return &palette; - } -}; + auto *helper = Helper::instance(); + if (!helper || !g_theme) + return; + + g_theme->bindConfig(helper->config()); +} int main(int argc, char *argv[]) { @@ -50,9 +43,9 @@ int main(int argc, char *argv[]) DTK_GUI_NAMESPACE::DGuiApplicationHelper::DontSaveApplicationTheme, true); WServer::initializeQPA({}, [](const QString &) { - return static_cast(new QDeepinTheme()); + g_theme = new QDeepinTheme(); + return static_cast(g_theme); }); - // QQuickStyle::setStyle("Material"); QGuiApplication::setAttribute(Qt::AA_UseOpenGLES); QGuiApplication::setHighDpiScaleFactorRoundingPolicy( @@ -86,6 +79,11 @@ int main(int argc, char *argv[]) { Treeland::Treeland treeland; + bindThemeConfig(); + QObject::connect(Helper::instance(), &Helper::configChanged, &bindThemeConfig); + QObject::connect(Helper::instance()->inputManager(), &InputManager::seatConfigChanged, + [](SeatUserDConfig *config) { g_theme->bindSeatConfig(config); }); + quitCode = app.exec(); } diff --git a/src/seat/helper.h b/src/seat/helper.h index d2eb4b071..f20fb7d6d 100644 --- a/src/seat/helper.h +++ b/src/seat/helper.h @@ -267,6 +267,7 @@ class Helper : public WSeatEventFilter RootSurfaceContainer *rootContainer() const { return m_rootSurfaceContainer; } inline WBackend *backend() const { return m_backend; } + InputManager *inputManager() const { return m_inputManager; } public Q_SLOTS: void activateSurface(SurfaceWrapper *wrapper, Qt::FocusReason reason = Qt::OtherFocusReason); void forceActivateSurface(SurfaceWrapper *wrapper,