diff --git a/panels/notification/osd/brightness/CMakeLists.txt b/panels/notification/osd/brightness/CMakeLists.txt index 3aa6ccdd0..9a1e2b0b8 100644 --- a/panels/notification/osd/brightness/CMakeLists.txt +++ b/panels/notification/osd/brightness/CMakeLists.txt @@ -1,15 +1,30 @@ -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: GPL-3.0-or-later +find_package(TreelandProtocols REQUIRED) +find_package(PkgConfig REQUIRED) +pkg_check_modules(WaylandClient REQUIRED IMPORTED_TARGET wayland-client) + add_library(osd-brightness SHARED brightnessapplet.cpp brightnessapplet.h + treelandbrightness.cpp + treelandbrightness.h +) + +qt_generate_wayland_protocol_client_sources(osd-brightness + NO_INCLUDE_CORE_ONLY + FILES + ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-output-manager-v1.xml ) target_link_libraries(osd-brightness PRIVATE dde-shell-frame Qt${QT_MAJOR_VERSION}::DBus + Qt${QT_MAJOR_VERSION}::Gui + Qt${QT_MAJOR_VERSION}::WaylandClient + PkgConfig::WaylandClient ) ds_install_package(PACKAGE org.deepin.ds.osd.brightness TARGET osd-brightness) diff --git a/panels/notification/osd/brightness/brightnessapplet.cpp b/panels/notification/osd/brightness/brightnessapplet.cpp index d05ec9d10..422583302 100644 --- a/panels/notification/osd/brightness/brightnessapplet.cpp +++ b/panels/notification/osd/brightness/brightnessapplet.cpp @@ -1,15 +1,20 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later #include "brightnessapplet.h" +#include "treelandbrightness.h" #include "pluginfactory.h" #include #include +#include #include +#include + +DGUI_USE_NAMESPACE namespace osd { @@ -26,6 +31,30 @@ BrightnessApplet::BrightnessApplet(QObject *parent) } +bool BrightnessApplet::load() +{ + m_isWayland = DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform); + if (!m_isWayland) { + return DApplet::load(); + } + + // Display1 is unavailable on Wayland, so brightness is read from the + // Treeland output-manager protocol. The provider caches the value the + // compositor reports and updates it reactively; it never commits changes. + m_treelandBrightness = new TreelandBrightness(this); + connect(m_treelandBrightness, &TreelandBrightness::brightnessChanged, this, [this](double value) { + setBrightness(value / 100.0); + setIconName(fetchIconName()); + }); + connect(qApp, &QGuiApplication::primaryScreenChanged, m_treelandBrightness, [this]() { + if (m_treelandBrightness) { + m_treelandBrightness->refresh(); + } + }); + m_treelandBrightness->refresh(); + return DApplet::load(); +} + QString BrightnessApplet::iconName() const { return m_iconName; @@ -33,11 +62,14 @@ QString BrightnessApplet::iconName() const void BrightnessApplet::sync() { - auto brightness = fetchBrightness(); - - setBrightness(brightness); - auto icon = fetchIconName(); - setIconName(icon); + if (m_isWayland) { + if (m_treelandBrightness) { + setBrightness(m_treelandBrightness->brightness() / 100.0); + } + } else { + setBrightness(fetchBrightness()); + } + setIconName(fetchIconName()); } void BrightnessApplet::setIconName(const QString &newIconName) diff --git a/panels/notification/osd/brightness/brightnessapplet.h b/panels/notification/osd/brightness/brightnessapplet.h index 9c5773996..99d4285f1 100644 --- a/panels/notification/osd/brightness/brightnessapplet.h +++ b/panels/notification/osd/brightness/brightnessapplet.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -6,8 +6,12 @@ #include "applet.h" +#include + namespace osd { +class TreelandBrightness; + class BrightnessApplet : public DS_NAMESPACE::DApplet { Q_OBJECT @@ -16,6 +20,8 @@ class BrightnessApplet : public DS_NAMESPACE::DApplet public: explicit BrightnessApplet(QObject *parent = nullptr); + bool load() override; + double brightness() const; QString iconName() const; @@ -32,8 +38,10 @@ class BrightnessApplet : public DS_NAMESPACE::DApplet QString fetchIconName() const; double fetchBrightness() const; private: - double m_brightness; + double m_brightness = 0.0; QString m_iconName; + bool m_isWayland = false; + QPointer m_treelandBrightness; }; } diff --git a/panels/notification/osd/brightness/treelandbrightness.cpp b/panels/notification/osd/brightness/treelandbrightness.cpp new file mode 100644 index 000000000..dd6b99983 --- /dev/null +++ b/panels/notification/osd/brightness/treelandbrightness.cpp @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "treelandbrightness.h" + +#include "wayland-treeland-output-manager-v1-client-protocol.h" + +#include +#include + +#include + +namespace osd { + +TreelandColorControl::TreelandColorControl(struct ::treeland_output_color_control_v1 *object, QObject *parent) + : QObject(parent) + , QtWayland::treeland_output_color_control_v1(object) +{ +} + +TreelandColorControl::~TreelandColorControl() +{ + if (isInitialized()) { + destroy(); + } +} + +double TreelandColorControl::brightness() const +{ + return m_brightness; +} + +void TreelandColorControl::treeland_output_color_control_v1_brightness(wl_fixed_t brightness) +{ + m_brightness = wl_fixed_to_double(brightness); + Q_EMIT brightnessChanged(m_brightness); +} + +TreelandBrightness::TreelandBrightness(QObject *parent) + : QWaylandClientExtensionTemplate(treeland_output_manager_v1_interface.version) +{ + setParent(parent); + connect(this, &TreelandBrightness::activeChanged, this, &TreelandBrightness::refresh); +} + +TreelandBrightness::~TreelandBrightness() +{ + delete m_control; + m_control = nullptr; + m_output = nullptr; + if (isInitialized()) { + destroy(); + } +} + +void TreelandBrightness::refresh() +{ + if (!isActive()) { + delete m_control; + m_control = nullptr; + m_output = nullptr; + return; + } + + struct wl_output *output = primaryWlOutput(); + if (m_control && m_output == output && output) { + return; + } + + delete m_control; + m_control = nullptr; + m_output = output; + + if (!output) { + return; + } + + auto *raw = get_color_control(output); + if (!raw) { + return; + } + + m_control = new TreelandColorControl(raw, this); + connect(m_control, &TreelandColorControl::brightnessChanged, + this, &TreelandBrightness::brightnessChanged); +} + +double TreelandBrightness::brightness() const +{ + return m_control ? m_control->brightness() : 0.0; +} + +struct wl_output *TreelandBrightness::primaryWlOutput() const +{ + auto *screen = qApp->primaryScreen(); + if (!screen) { + return nullptr; + } + + auto *waylandScreen = screen->nativeInterface(); + return waylandScreen ? waylandScreen->output() : nullptr; +} + +} // namespace osd diff --git a/panels/notification/osd/brightness/treelandbrightness.h b/panels/notification/osd/brightness/treelandbrightness.h new file mode 100644 index 000000000..ea87d8a92 --- /dev/null +++ b/panels/notification/osd/brightness/treelandbrightness.h @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "qwayland-treeland-output-manager-v1.h" + +#include +#include +#include + +struct wl_output; +struct treeland_output_color_control_v1; + +namespace osd { + +class TreelandColorControl : public QObject, public QtWayland::treeland_output_color_control_v1 +{ + Q_OBJECT + +public: + explicit TreelandColorControl(struct ::treeland_output_color_control_v1 *object, QObject *parent = nullptr); + ~TreelandColorControl() override; + + double brightness() const; + +Q_SIGNALS: + void brightnessChanged(double brightness); + +protected: + void treeland_output_color_control_v1_brightness(wl_fixed_t brightness) override; + +private: + double m_brightness = 0.0; +}; + +// Read-only Treeland brightness provider for the OSD. It binds a single +// treeland_output_color_control_v1 to the primary wl_output and caches the +// brightness reported by the compositor. It never commits brightness changes; +// dde-shortcut-tool is responsible for adjusting brightness, and this provider +// only reflects the resulting value. +class TreelandBrightness : public QWaylandClientExtensionTemplate, public QtWayland::treeland_output_manager_v1 +{ + Q_OBJECT + +public: + explicit TreelandBrightness(QObject *parent = nullptr); + ~TreelandBrightness() override; + + void refresh(); + + double brightness() const; + +Q_SIGNALS: + void brightnessChanged(double brightness); + +private: + struct wl_output *primaryWlOutput() const; + + QPointer m_control; + struct wl_output *m_output = nullptr; +}; + +} // namespace osd