diff --git a/colorcorrection/colorcorrectdbusinterface.h b/colorcorrection/colorcorrectdbusinterface.h --- a/colorcorrection/colorcorrectdbusinterface.h +++ b/colorcorrection/colorcorrectdbusinterface.h @@ -37,12 +37,24 @@ Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.ColorCorrect") Q_PROPERTY(bool inhibited READ isInhibited) + Q_PROPERTY(bool enabled READ isEnabled) + Q_PROPERTY(bool running READ isRunning) + Q_PROPERTY(bool available READ isAvailable) + Q_PROPERTY(int currentTemperature READ currentTemperature) + Q_PROPERTY(int targetTemperature READ targetTemperature) + Q_PROPERTY(int mode READ mode) public: explicit ColorCorrectDBusInterface(Manager *parent); ~ColorCorrectDBusInterface() override = default; bool isInhibited() const; + bool isEnabled() const; + bool isRunning() const; + bool isAvailable() const; + int currentTemperature() const; + int targetTemperature() const; + int mode() const; public Q_SLOTS: /** diff --git a/colorcorrection/colorcorrectdbusinterface.cpp b/colorcorrection/colorcorrectdbusinterface.cpp --- a/colorcorrection/colorcorrectdbusinterface.cpp +++ b/colorcorrection/colorcorrectdbusinterface.cpp @@ -38,7 +38,6 @@ connect(m_inhibitorWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &ColorCorrectDBusInterface::removeInhibitorService); - // Argh, all this code is just to send one innocent signal... connect(m_manager, &Manager::inhibitedChanged, this, [this] { QVariantMap changedProperties; changedProperties.insert(QStringLiteral("inhibited"), m_manager->isInhibited()); @@ -58,6 +57,101 @@ QDBusConnection::sessionBus().send(message); }); + connect(m_manager, &Manager::enabledChanged, this, [this] { + QVariantMap changedProperties; + changedProperties.insert(QStringLiteral("enabled"), m_manager->isEnabled()); + + QDBusMessage message = QDBusMessage::createSignal( + QStringLiteral("/ColorCorrect"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("PropertiesChanged") + ); + + message.setArguments({ + QStringLiteral("org.kde.kwin.ColorCorrect"), + changedProperties, + QStringList(), // invalidated_properties + }); + + QDBusConnection::sessionBus().send(message); + }); + + connect(m_manager, &Manager::runningChanged, this, [this] { + QVariantMap changedProperties; + changedProperties.insert(QStringLiteral("running"), m_manager->isRunning()); + + QDBusMessage message = QDBusMessage::createSignal( + QStringLiteral("/ColorCorrect"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("PropertiesChanged") + ); + + message.setArguments({ + QStringLiteral("org.kde.kwin.ColorCorrect"), + changedProperties, + QStringList(), // invalidated_properties + }); + + QDBusConnection::sessionBus().send(message); + }); + + connect(m_manager, &Manager::currentTemperatureChanged, this, [this] { + QVariantMap changedProperties; + changedProperties.insert(QStringLiteral("currentTemperature"), m_manager->currentTemperature()); + + QDBusMessage message = QDBusMessage::createSignal( + QStringLiteral("/ColorCorrect"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("PropertiesChanged") + ); + + message.setArguments({ + QStringLiteral("org.kde.kwin.ColorCorrect"), + changedProperties, + QStringList(), // invalidated_properties + }); + + QDBusConnection::sessionBus().send(message); + }); + + connect(m_manager, &Manager::targetTemperatureChanged, this, [this] { + QVariantMap changedProperties; + changedProperties.insert(QStringLiteral("targetTemperature"), m_manager->targetTemperature()); + + QDBusMessage message = QDBusMessage::createSignal( + QStringLiteral("/ColorCorrect"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("PropertiesChanged") + ); + + message.setArguments({ + QStringLiteral("org.kde.kwin.ColorCorrect"), + changedProperties, + QStringList(), // invalidated_properties + }); + + QDBusConnection::sessionBus().send(message); + }); + + connect(m_manager, &Manager::modeChanged, this, [this] { + QVariantMap changedProperties; + changedProperties.insert(QStringLiteral("mode"), uint(m_manager->mode())); + + QDBusMessage message = QDBusMessage::createSignal( + QStringLiteral("/ColorCorrect"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("PropertiesChanged") + ); + + message.setArguments({ + QStringLiteral("org.kde.kwin.ColorCorrect"), + changedProperties, + QStringList(), // invalidated_properties + }); + + QDBusConnection::sessionBus().send(message); + }); + connect(m_manager, &Manager::configChange, this, &ColorCorrectDBusInterface::nightColorConfigChanged); new ColorCorrectAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/ColorCorrect"), this); @@ -68,6 +162,36 @@ return m_manager->isInhibited(); } +bool ColorCorrectDBusInterface::isEnabled() const +{ + return m_manager->isEnabled(); +} + +bool ColorCorrectDBusInterface::isRunning() const +{ + return m_manager->isRunning(); +} + +bool ColorCorrectDBusInterface::isAvailable() const +{ + return m_manager->isAvailable(); +} + +int ColorCorrectDBusInterface::currentTemperature() const +{ + return m_manager->currentTemperature(); +} + +int ColorCorrectDBusInterface::targetTemperature() const +{ + return m_manager->targetTemperature(); +} + +int ColorCorrectDBusInterface::mode() const +{ + return m_manager->mode(); +} + QHash ColorCorrectDBusInterface::nightColorInfo() { return m_manager->info(); diff --git a/colorcorrection/manager.h b/colorcorrection/manager.h --- a/colorcorrection/manager.h +++ b/colorcorrection/manager.h @@ -144,6 +144,36 @@ */ void uninhibit(); + /** + * Returns @c true if Night Color is enabled; otherwise @c false. + */ + bool isEnabled() const; + + /** + * Returns @c true if Night Color is currently running; otherwise @c false. + */ + bool isRunning() const; + + /** + * Returns @c true if Night Color is supported by platform; otherwise @c false. + */ + bool isAvailable() const; + + /** + * Returns the current screen color temperature. + */ + int currentTemperature() const; + + /** + * Returns the target screen color temperature. + */ + int targetTemperature() const; + + /** + * Returns the mode in which Night Color is operating. + */ + NightColorMode mode() const; + // for auto tests void reparseConfigAndReset(); @@ -159,6 +189,31 @@ */ void inhibitedChanged(); + /** + * Emitted whenever the night color manager is enabled or disabled. + */ + void enabledChanged(); + + /** + * Emitted whenever the night color manager starts or stops running. + */ + void runningChanged(); + + /** + * Emitted whenever the current screen color temperature has changed. + */ + void currentTemperatureChanged(); + + /** + * Emitted whenever the target screen color temperature has changed. + */ + void targetTemperatureChanged(); + + /** + * Emitted whenver the operation mode has changed. + */ + void modeChanged(); + private: void initShortcuts(); void readConfig(); @@ -176,13 +231,19 @@ */ void resetSlowUpdateTimer(); + void updateTargetTemperature(); void updateSunTimings(bool force); DateTimes getSunTimings(const QDateTime &dateTime, double latitude, double longitude, bool morning) const; bool checkAutomaticSunTimings() const; bool daylight() const; void commitGammaRamps(int temperature); + void setEnabled(bool enabled); + void setRunning(bool running); + void setCurrentTemperature(int temperature); + void setMode(NightColorMode mode); + ColorCorrectDBusInterface *m_iface; // Specifies whether Night Color is enabled. @@ -217,6 +278,7 @@ QTimer *m_quickAdjustTimer = nullptr; int m_currentTemp = NEUTRAL_TEMPERATURE; + int m_targetTemperature = NEUTRAL_TEMPERATURE; int m_dayTargetTemp = NEUTRAL_TEMPERATURE; int m_nightTargetTemp = DEFAULT_NIGHT_TEMPERATURE; diff --git a/colorcorrection/manager.cpp b/colorcorrection/manager.cpp --- a/colorcorrection/manager.cpp +++ b/colorcorrection/manager.cpp @@ -90,7 +90,7 @@ // we may always read in the current config readConfig(); - if (!kwinApp()->platform()->supportsGammaControl()) { + if (!isAvailable()) { return; } @@ -165,9 +165,10 @@ if (m_mode != NightColorMode::Constant) { updateSunTimings(true); } + updateTargetTemperature(); - if (kwinApp()->platform()->supportsGammaControl() && m_active && !isInhibited()) { - m_running = true; + if (isAvailable() && isEnabled() && !isInhibited()) { + setRunning(true); commitGammaRamps(currentTargetTemp()); } resetAllTimers(); @@ -211,6 +212,36 @@ } } +bool Manager::isEnabled() const +{ + return m_active; +} + +bool Manager::isRunning() const +{ + return m_running; +} + +bool Manager::isAvailable() const +{ + return kwinApp()->platform()->supportsGammaControl(); +} + +int Manager::currentTemperature() const +{ + return m_currentTemp; +} + +int Manager::targetTemperature() const +{ + return m_targetTemperature; +} + +NightColorMode Manager::mode() const +{ + return m_mode; +} + void Manager::initShortcuts() { QAction *toggleAction = new QAction(this); @@ -226,19 +257,19 @@ Settings *s = Settings::self(); s->load(); - m_active = s->active(); + setEnabled(s->active()); const NightColorMode mode = s->mode(); switch (s->mode()) { case NightColorMode::Automatic: case NightColorMode::Location: case NightColorMode::Timings: case NightColorMode::Constant: - m_mode = mode; + setMode(mode); break; default: // Fallback for invalid setting values. - m_mode = NightColorMode::Automatic; + setMode(NightColorMode::Automatic); break; } @@ -293,12 +324,12 @@ void Manager::resetAllTimers() { cancelAllTimers(); - if (kwinApp()->platform()->supportsGammaControl()) { - m_running = m_active && !isInhibited(); + if (isAvailable()) { + setRunning(isEnabled() && !isInhibited()); // we do this also for active being false in order to reset the temperature back to the day value resetQuickAdjustTimer(); } else { - m_running = false; + setRunning(false); } } @@ -319,6 +350,7 @@ if (m_mode != NightColorMode::Constant) { updateSunTimings(false); } + updateTargetTemperature(); int tempDiff = qAbs(currentTargetTemp() - m_currentTemp); // allow tolerance of one TEMPERATURE_STEP to compensate if a slow update is coincidental @@ -384,6 +416,8 @@ connect(m_slowUpdateStartTimer, &QTimer::timeout, this, &Manager::resetSlowUpdateStartTimer); updateSunTimings(false); + updateTargetTemperature(); + const int diff = QDateTime::currentDateTime().msecsTo(m_next.first); if (diff <= 0) { qCCritical(KWIN_COLORCORRECTION) << "Error in time calculation. Deactivating Night Color."; @@ -448,6 +482,19 @@ } } +void Manager::updateTargetTemperature() +{ + const int targetTemperature = mode() != NightColorMode::Constant && daylight() ? m_dayTargetTemp : m_nightTargetTemp; + + if (m_targetTemperature == targetTemperature) { + return; + } + + m_targetTemperature = targetTemperature; + + emit targetTemperatureChanged(); +} + void Manager::updateSunTimings(bool force) { const QDateTime todayNow = QDateTime::currentDateTime(); @@ -624,7 +671,7 @@ } if (o->setGammaRamp(ramp)) { - m_currentTemp = temperature; + setCurrentTemperature(temperature); m_failedCommitAttempts = 0; } else { m_failedCommitAttempts++; @@ -635,7 +682,7 @@ // TODO: On multi monitor setups we could try to rollback earlier changes for already committed outputs qCWarning(KWIN_COLORCORRECTION) << "Gamma Ramp commit failed too often. Deactivating color correction for now."; m_failedCommitAttempts = 0; // reset so we can try again later (i.e. after suspend phase or config change) - m_running = false; + setRunning(false); cancelAllTimers(); } } @@ -645,7 +692,7 @@ QHash Manager::info() const { return QHash { - { QStringLiteral("Available"), kwinApp()->platform()->supportsGammaControl() }, + { QStringLiteral("Available"), isAvailable() }, { QStringLiteral("ActiveEnabled"), true}, { QStringLiteral("Active"), m_active}, @@ -798,12 +845,12 @@ Settings *s = Settings::self(); if (activeUpdate) { - m_active = active; + setEnabled(active); s->setActive(active); } if (modeUpdate) { - m_mode = mode; + setMode(mode); s->setMode(mode); } @@ -861,5 +908,41 @@ emit configChange(info()); } +void Manager::setEnabled(bool enabled) +{ + if (m_active == enabled) { + return; + } + m_active = enabled; + emit enabledChanged(); +} + +void Manager::setRunning(bool running) +{ + if (m_running == running) { + return; + } + m_running = running; + emit runningChanged(); +} + +void Manager::setCurrentTemperature(int temperature) +{ + if (m_currentTemp == temperature) { + return; + } + m_currentTemp = temperature; + emit currentTemperatureChanged(); +} + +void Manager::setMode(NightColorMode mode) +{ + if (m_mode == mode) { + return; + } + m_mode = mode; + emit modeChanged(); +} + } } diff --git a/org.kde.kwin.ColorCorrect.xml b/org.kde.kwin.ColorCorrect.xml --- a/org.kde.kwin.ColorCorrect.xml +++ b/org.kde.kwin.ColorCorrect.xml @@ -52,5 +52,37 @@ This property holds a value to indicate whether Night Color is inhibited. --> + + + + + + + + + + + + + + + + + +