From 7328739e34c29dd2f867a54963bec8ce85278d7d Mon Sep 17 00:00:00 2001 From: Smit Shivcharan Patil Date: Sat, 9 Apr 2022 15:47:35 +0530 Subject: [PATCH 1/2] Allow setting gamma ramp of colordevice --- src/CMakeLists.txt | 2 + src/colors/colordevice.cpp | 65 +++++++++++++++++++++++++++++++++ src/colors/colordevice.h | 10 +++++ src/colors/colormanager.cpp | 20 ++++++++++ src/colors/colormanager.h | 5 +++ src/dbusinterface.cpp | 73 +++++++++++++++++++++++++++++++++++++ src/dbusinterface.h | 32 ++++++++++++++++ src/org.kde.KWin.Gamma.xml | 33 +++++++++++++++++ src/workspace.cpp | 2 + 9 files changed, 242 insertions(+) create mode 100644 src/org.kde.KWin.Gamma.xml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 290f399a7c..3c7bbf6502 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -236,6 +236,7 @@ qt_add_dbus_adaptor(kwin_dbus_SRCS ${kwin_effects_dbus_xml} effects.h KWin::Effe qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Session.xml sm.h KWin::SessionManager) qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Plugins.xml dbusinterface.h KWin::PluginManagerDBusInterface) +qt_add_dbus_adaptor(kwin_dbus_SRCS org.kde.KWin.Gamma.xml dbusinterface.h KWin::GammaDBusInterface) if (KWIN_BUILD_SCREENLOCKER) qt_add_dbus_interface(kwin_dbus_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/kf5_org.freedesktop.ScreenSaver.xml screenlocker_interface) @@ -346,6 +347,7 @@ install( org.kde.kwin.Compositing.xml org.kde.kwin.Effects.xml org.kde.KWin.Plugins.xml + org.kde.KWin.Gamma.xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kwin.VirtualKeyboard.xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KWin.TabletModeManager.xml DESTINATION diff --git a/src/colors/colordevice.cpp b/src/colors/colordevice.cpp index 80eef239cd..a54c9d5039 100644 --- a/src/colors/colordevice.cpp +++ b/src/colors/colordevice.cpp @@ -14,6 +14,9 @@ #include +#include +#include + #include namespace KWin @@ -43,6 +46,7 @@ public: DirtyTemperatureToneCurve = 0x1, DirtyBrightnessToneCurve = 0x2, DirtyCalibrationToneCurve = 0x4, + DirtyCustomGammaToneCurve = 0x8, }; Q_DECLARE_FLAGS(DirtyToneCurves, DirtyToneCurveBit) @@ -51,6 +55,7 @@ public: void updateTemperatureToneCurves(); void updateBrightnessToneCurves(); void updateCalibrationToneCurves(); + void updateCustomGammaToneCurves(); Output *output; DirtyToneCurves dirtyCurves; @@ -59,9 +64,16 @@ public: uint brightness = 100; uint temperature = 6500; + struct _gamma { + double red = 1; + double green = 1; + double blue = 1; + } gamma; + std::unique_ptr temperatureStage; std::unique_ptr brightnessStage; std::unique_ptr calibrationStage; + std::unique_ptr customGammaStage; std::shared_ptr transformation; }; @@ -71,6 +83,9 @@ void ColorDevicePrivate::rebuildPipeline() if (dirtyCurves & DirtyCalibrationToneCurve) { updateCalibrationToneCurves(); } + if (dirtyCurves & DirtyCustomGammaToneCurve) { + updateCustomGammaToneCurves(); + } if (dirtyCurves & DirtyBrightnessToneCurve) { updateBrightnessToneCurves(); } @@ -101,6 +116,13 @@ void ColorDevicePrivate::rebuildPipeline() return; } } + if (customGammaStage) { + if (auto s = customGammaStage->dup()) { + stages.push_back(std::move(s)); + } else { + return; + } + } const auto tmp = std::make_shared(std::move(stages)); if (tmp->valid()) { @@ -240,6 +262,17 @@ ColorDevice::ColorDevice(Output *output, QObject *parent) connect(d->updateTimer, &QTimer::timeout, this, &ColorDevice::update); d->output = output; + + // load gamma values + auto config = KSharedConfig::openConfig(); + auto group = config->group(QStringLiteral("Gamma/") + output->name()); + + double red = group.readEntry("red", 1.0); + auto green = group.readEntry("green", 1.0); + auto blue = group.readEntry("blue", 1.0); + + setGamma(red, green, blue); + scheduleUpdate(); } @@ -314,9 +347,41 @@ void ColorDevice::update() d->output->setColorTransformation(d->transformation); } + void ColorDevice::scheduleUpdate() { d->updateTimer->start(); } +void ColorDevice::setGamma(double r, double g, double b) +{ + d->gamma.red = r; + d->gamma.blue = b; + d->gamma.green = g; + + d->dirtyCurves |= ColorDevicePrivate::DirtyCustomGammaToneCurve; + scheduleUpdate(); +} + +void ColorDevicePrivate::updateCustomGammaToneCurves() +{ + customGammaStage.reset(); + + cmsToneCurve *toneCurves[] = { + cmsBuildGamma(nullptr, 1 / gamma.red), + cmsBuildGamma(nullptr, 1 / gamma.green), + cmsBuildGamma(nullptr, 1 / gamma.blue), + }; + + customGammaStage.reset(cmsStageAllocToneCurves(nullptr, 3, toneCurves)); + if (!customGammaStage) { + qCWarning(KWIN_CORE) << "Failed to create the cutsom gamma pipeline stage"; + } +} + +QVector ColorDevice::getGamma() const +{ + return { d->gamma.red, d->gamma.green, d->gamma.blue }; +} + } // namespace KWin diff --git a/src/colors/colordevice.h b/src/colors/colordevice.h index 49370c38d9..75f37c4368 100644 --- a/src/colors/colordevice.h +++ b/src/colors/colordevice.h @@ -62,6 +62,16 @@ public: */ void setProfile(const QString &profile); + /** + * Sets the gamma values + */ + void setGamma(double red, double green, double blue); + + /** + * Returns the gamma values + */ + QVector getGamma() const; + public Q_SLOTS: void update(); void scheduleUpdate(); diff --git a/src/colors/colormanager.cpp b/src/colors/colormanager.cpp index ca36b7781d..33fc2c075d 100644 --- a/src/colors/colormanager.cpp +++ b/src/colors/colormanager.cpp @@ -21,6 +21,7 @@ class ColorManagerPrivate { public: QVector devices; + QHash deviceMap; }; ColorManager::ColorManager(QObject *parent) @@ -65,6 +66,7 @@ void ColorManager::handleOutputEnabled(Output *output) { ColorDevice *device = new ColorDevice(output, this); d->devices.append(device); + d->deviceMap.insert(output->name() , device); Q_EMIT deviceAdded(device); } @@ -79,6 +81,7 @@ void ColorManager::handleOutputDisabled(Output *output) } ColorDevice *device = *it; d->devices.erase(it); + d->deviceMap.remove(output->name()); Q_EMIT deviceRemoved(device); delete device; } @@ -93,4 +96,21 @@ void ColorManager::handleSessionActiveChanged(bool active) } } +void ColorManager::syncGamma() +{ + auto config = KSharedConfig::openConfig(); + const auto devs = devices(); + + for (const auto dev : devs) { + auto group = config->group(QStringLiteral("Gamma/") + dev->output()->name()); + auto gamma = dev->getGamma(); + if (gamma.size() == 3) { + group.writeEntry("red", gamma[0]); + group.writeEntry("green", gamma[1]); + group.writeEntry("blue", gamma[2]); + } + } + config->sync(); +} + } // namespace KWin diff --git a/src/colors/colormanager.h b/src/colors/colormanager.h index 746010da6c..e9d5a4ff1c 100644 --- a/src/colors/colormanager.h +++ b/src/colors/colormanager.h @@ -38,6 +38,11 @@ public: */ QVector devices() const; + /** + * saves gamma of all color devices + */ + void syncGamma(); + Q_SIGNALS: /** * This signal is emitted when a new color device @a device has been added. diff --git a/src/dbusinterface.cpp b/src/dbusinterface.cpp index 76011ffe8e..00043584b8 100644 --- a/src/dbusinterface.cpp +++ b/src/dbusinterface.cpp @@ -10,9 +10,14 @@ // own #include "dbusinterface.h" #include "compositingadaptor.h" +#include "gammaadaptor.h" #include "pluginsadaptor.h" #include "virtualdesktopmanageradaptor.h" +#include "abstract_output.h" +#include "colordevice.h" +#include "colormanager.h" + // kwin #include "atoms.h" #include "composite.h" @@ -543,4 +548,72 @@ void PluginManagerDBusInterface::UnloadPlugin(const QString &name) m_manager->unloadPlugin(name); } +GammaDBusInterface::GammaDBusInterface(QObject *parent) + : QObject(parent) +{ + new GammaAdaptor(this); + + QDBusConnection::sessionBus().registerObject(QStringLiteral("/Gamma"), + QStringLiteral("org.kde.KWin.Gamma"), + this); + + activeDevice = ColorManager::self()->devices()[0]; + + connect(ColorManager::self(), &ColorManager::deviceAdded, [this](ColorDevice *device) { + Q_EMIT deviceAdded(device->output()->name()); + }); + + connect(ColorManager::self(), &ColorManager::deviceRemoved, [this](ColorDevice *device) { + Q_EMIT deviceRemoved(device->output()->name()); + + if (activeDevice == device) + activeDevice = ColorManager::self()->devices()[0]; + }); +} + +QString GammaDBusInterface::getActiveDevice() const +{ + return activeDevice->output()->name(); +} + +void GammaDBusInterface::setActiveDevice(QString device) +{ + const auto devs = ColorManager::self()->devices(); + for (const auto dev : devs) { + if (dev->output()->name() == device) { + activeDevice = dev; + return; + } + } +} + +QStringList GammaDBusInterface::devices() const +{ + QStringList ls; + const auto devs = ColorManager::self()->devices(); + for (const auto d : devs) { + ls.push_back(d->output()->name()); + } + return ls; +} + +void GammaDBusInterface::set(double r, double g, double b) +{ + activeDevice->setGamma(r, g, b); +} + +QVector GammaDBusInterface::get() const +{ + const auto gamma = activeDevice->getGamma(); + if (gamma.size() != 3) { + return {1, 1, 1}; + } + return gamma; +} + +void GammaDBusInterface::save() +{ + ColorManager::self()->syncGamma(); +} + } // namespace diff --git a/src/dbusinterface.h b/src/dbusinterface.h index a50ece8686..a87ef41af3 100644 --- a/src/dbusinterface.h +++ b/src/dbusinterface.h @@ -296,6 +296,38 @@ private: PluginManager *m_manager; }; +class ColorDevice; + +class GammaDBusInterface : public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.Gamma") + +public: + Q_PROPERTY(QString activeDevice READ getActiveDevice WRITE setActiveDevice); + + explicit GammaDBusInterface(QObject *parent); + +public Q_SLOTS: + + QStringList devices() const; + + QVector get() const; + void set(double r, double g, double b); + + QString getActiveDevice() const; + void setActiveDevice(QString device); + + void save(); + +Q_SIGNALS: + void deviceAdded(QString device); + void deviceRemoved(QString device); + +private: + ColorDevice *activeDevice; +}; + } // namespace #endif // KWIN_DBUS_INTERFACE_H diff --git a/src/org.kde.KWin.Gamma.xml b/src/org.kde.KWin.Gamma.xml new file mode 100644 index 0000000000..6bbc0f4550 --- /dev/null +++ b/src/org.kde.KWin.Gamma.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/workspace.cpp b/src/workspace.cpp index c0d3e1a83c..d238dfdc96 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -181,6 +181,8 @@ Workspace::Workspace() decorationBridge->init(); connect(this, &Workspace::configChanged, decorationBridge, &Decoration::DecorationBridge::reconfigure); + new GammaDBusInterface(this); + new DBusInterface(this); Outline::create(this); -- GitLab From bc8e14e58ed26cb4e91bc549b06cf77b1fe3a159 Mon Sep 17 00:00:00 2001 From: Smit Shivcharan Patil Date: Sun, 12 Jun 2022 21:27:31 +0530 Subject: [PATCH 2/2] fix compilation --- src/colors/colordevice.cpp | 4 ++-- src/dbusinterface.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/colors/colordevice.cpp b/src/colors/colordevice.cpp index a54c9d5039..0119d0c9f5 100644 --- a/src/colors/colordevice.cpp +++ b/src/colors/colordevice.cpp @@ -373,9 +373,9 @@ void ColorDevicePrivate::updateCustomGammaToneCurves() cmsBuildGamma(nullptr, 1 / gamma.blue), }; - customGammaStage.reset(cmsStageAllocToneCurves(nullptr, 3, toneCurves)); + customGammaStage = std::make_unique(cmsStageAllocToneCurves(nullptr, 3, toneCurves)); if (!customGammaStage) { - qCWarning(KWIN_CORE) << "Failed to create the cutsom gamma pipeline stage"; + qCWarning(KWIN_CORE) << "Failed to create the custom gamma pipeline stage"; } } diff --git a/src/dbusinterface.cpp b/src/dbusinterface.cpp index 00043584b8..758c2da486 100644 --- a/src/dbusinterface.cpp +++ b/src/dbusinterface.cpp @@ -14,9 +14,9 @@ #include "pluginsadaptor.h" #include "virtualdesktopmanageradaptor.h" -#include "abstract_output.h" #include "colordevice.h" #include "colormanager.h" +#include "output.h" // kwin #include "atoms.h" -- GitLab