File indexing completed on 2024-05-19 05:39:20

0001 /*  This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
0003     SPDX-FileCopyrightText: 2008-2010 Dario Freddi <drf@kde.org>
0004     SPDX-FileCopyrightText: 2010 Alejandro Fiestas <alex@eyeos.org>
0005     SPDX-FileCopyrightText: 2010-2013 Lukáš Tinkl <ltinkl@redhat.com>
0006     SPDX-FileCopyrightText: 2015 Kai Uwe Broulik <kde@privat.broulik.de>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-only
0009 
0010 */
0011 
0012 #include "screenbrightnesscontroller.h"
0013 
0014 #include <brightnessosdwidget.h>
0015 #include <powerdevil_debug.h>
0016 
0017 #include <QDebug>
0018 #include <QPropertyAnimation>
0019 
0020 #include "backlightbrightness.h"
0021 #include "ddcutilbrightness.h"
0022 
0023 ScreenBrightnessController::ScreenBrightnessController()
0024     : QObject()
0025     , m_backlightBrightnessControl(new BacklightBrightness(this))
0026     , m_ddcBrightnessControl(new DDCutilBrightness(this))
0027 {
0028     connect(m_backlightBrightnessControl, &BacklightBrightness::detectionFinished, this, &ScreenBrightnessController::onBacklightDetectionFinished);
0029     connect(m_backlightBrightnessControl, &BacklightBrightness::brightnessChanged, this, &ScreenBrightnessController::onScreenBrightnessChanged);
0030 
0031     qCDebug(POWERDEVIL) << "Trying to detect internal display backlight for brightness control...";
0032     m_backlightBrightnessControl->detect();
0033 }
0034 
0035 void ScreenBrightnessController::onBacklightDetectionFinished(bool isSupported)
0036 {
0037     disconnect(m_backlightBrightnessControl, &BacklightBrightness::detectionFinished, this, &ScreenBrightnessController::onBacklightDetectionFinished);
0038 
0039     if (isSupported) {
0040         m_screenBrightnessAvailable = true;
0041         m_cachedBrightness = m_backlightBrightnessControl->brightness();
0042     } else {
0043         qCDebug(POWERDEVIL) << "No internal dislay backlight detected. Trying DDC for brightness controls...";
0044         m_ddcBrightnessControl->detect();
0045         if (m_ddcBrightnessControl->isSupported()) {
0046             qCDebug(POWERDEVIL) << "Using DDCutillib";
0047             m_cachedBrightness = screenBrightness();
0048             if (m_brightnessAnimationDurationMsec > 0 && screenBrightnessMax() >= m_brightnessAnimationThreshold) {
0049                 m_brightnessAnimation = new QPropertyAnimation(this);
0050                 m_brightnessAnimation->setTargetObject(this);
0051                 m_brightnessAnimation->setDuration(m_brightnessAnimationDurationMsec);
0052                 connect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &ScreenBrightnessController::animationValueChanged);
0053                 connect(m_brightnessAnimation, &QPropertyAnimation::finished, this, &ScreenBrightnessController::ddcScreenBrightnessChanged);
0054             }
0055             m_screenBrightnessAvailable = true;
0056         }
0057     }
0058     // Brightness Controls available
0059     if (m_screenBrightnessAvailable) {
0060         qCDebug(POWERDEVIL) << "initial screen brightness value:" << m_cachedBrightness;
0061     }
0062     Q_EMIT detectionFinished();
0063 }
0064 
0065 int ScreenBrightnessController::screenBrightnessSteps()
0066 {
0067     m_screenBrightnessLogic.setValueMax(screenBrightnessMax());
0068     return m_screenBrightnessLogic.steps();
0069 }
0070 
0071 int ScreenBrightnessController::calculateNextScreenBrightnessStep(int value, int valueMax, PowerDevil::BrightnessLogic::BrightnessKeyType keyType)
0072 {
0073     m_screenBrightnessLogic.setValueMax(valueMax);
0074     m_screenBrightnessLogic.setValue(value);
0075 
0076     return m_screenBrightnessLogic.action(keyType);
0077 }
0078 
0079 int ScreenBrightnessController::screenBrightnessKeyPressed(PowerDevil::BrightnessLogic::BrightnessKeyType type)
0080 {
0081     if (!m_screenBrightnessAvailable) {
0082         return -1; // ignore as we are not able to determine the brightness level
0083     }
0084 
0085     int currentBrightness = screenBrightness();
0086     // m_cachedBrightness is not being updated during animation, thus checking the m_cachedBrightness
0087     // value here doesn't make much sense, use the endValue from brightness() anyway.
0088     // This prevents brightness key being ignored during the animation.
0089     if (!(m_brightnessAnimation && m_brightnessAnimation->state() == QPropertyAnimation::Running) && currentBrightness != m_cachedBrightness) {
0090         m_cachedBrightness = currentBrightness;
0091         return currentBrightness;
0092     }
0093 
0094     int maxBrightness = screenBrightnessMax();
0095     int newBrightness = calculateNextScreenBrightnessStep(currentBrightness, maxBrightness, type);
0096 
0097     if (newBrightness < 0) {
0098         return -1;
0099     }
0100 
0101     setScreenBrightness(newBrightness);
0102     return newBrightness;
0103 }
0104 
0105 int ScreenBrightnessController::screenBrightness() const
0106 {
0107     int result = 0;
0108 
0109     if (m_ddcBrightnessControl->isSupported()) {
0110         if (m_brightnessAnimation && m_brightnessAnimation->state() == QPropertyAnimation::Running) {
0111             result = m_brightnessAnimation->endValue().toInt();
0112         } else {
0113             result = m_ddcBrightnessControl->brightness(m_ddcBrightnessControl->displayIds().constFirst());
0114         }
0115     } else {
0116         result = m_cachedBrightness;
0117     }
0118     qCDebug(POWERDEVIL) << "Screen brightness value:" << result;
0119     return result;
0120 }
0121 
0122 int ScreenBrightnessController::screenBrightnessMax() const
0123 {
0124     int result = 0;
0125 
0126     if (m_ddcBrightnessControl->isSupported()) {
0127         result = m_ddcBrightnessControl->maxBrightness(m_ddcBrightnessControl->displayIds().constFirst());
0128     } else if (m_backlightBrightnessControl->isSupported()) {
0129         result = m_backlightBrightnessControl->maxBrightness();
0130     }
0131     qCDebug(POWERDEVIL) << "Screen brightness value max:" << result;
0132 
0133     return result;
0134 }
0135 
0136 void ScreenBrightnessController::setScreenBrightness(int value)
0137 {
0138     qCDebug(POWERDEVIL) << "set screen brightness value:" << value;
0139     if (m_ddcBrightnessControl->isSupported()) {
0140         if (m_brightnessAnimation) {
0141             m_brightnessAnimation->stop();
0142             disconnect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &ScreenBrightnessController::animationValueChanged);
0143             m_brightnessAnimation->setStartValue(screenBrightness());
0144             m_brightnessAnimation->setEndValue(value);
0145             m_brightnessAnimation->setEasingCurve(screenBrightness() < value ? QEasingCurve::OutQuad : QEasingCurve::InQuad);
0146             connect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &ScreenBrightnessController::animationValueChanged);
0147             m_brightnessAnimation->start();
0148         } else {
0149             for (const QString &displayId : m_ddcBrightnessControl->displayIds()) {
0150                 m_ddcBrightnessControl->setBrightness(displayId, value);
0151             }
0152         }
0153     } else if (m_backlightBrightnessControl->isSupported()) {
0154         m_backlightBrightnessControl->setBrightness(value, m_brightnessAnimationDurationMsec);
0155     }
0156 }
0157 
0158 bool ScreenBrightnessController::screenBrightnessAvailable() const
0159 {
0160     return m_screenBrightnessAvailable;
0161 }
0162 
0163 void ScreenBrightnessController::ddcScreenBrightnessChanged()
0164 {
0165     if (m_brightnessAnimation && m_brightnessAnimation->state() != QPropertyAnimation::Stopped) {
0166         return;
0167     }
0168 
0169     if (int currentBrightness = screenBrightness(); currentBrightness != m_cachedBrightness) {
0170         onScreenBrightnessChanged(currentBrightness, screenBrightnessMax());
0171     }
0172 }
0173 
0174 void ScreenBrightnessController::animationValueChanged(const QVariant &value)
0175 {
0176     if (m_ddcBrightnessControl->isSupported()) {
0177         for (const QString &displayId : m_ddcBrightnessControl->displayIds()) {
0178             m_ddcBrightnessControl->setBrightness(displayId, value.toInt());
0179         }
0180     } else {
0181         qCInfo(POWERDEVIL) << "ScreenBrightnessController::animationValueChanged: brightness control not supported";
0182     }
0183 }
0184 
0185 void ScreenBrightnessController::onScreenBrightnessChanged(int value, int valueMax)
0186 {
0187     m_cachedBrightness = value;
0188 
0189     m_screenBrightnessLogic.setValueMax(valueMax);
0190     m_screenBrightnessLogic.setValue(value);
0191 
0192     Q_EMIT screenBrightnessChanged(m_screenBrightnessLogic.info());
0193 }
0194 
0195 #include "moc_screenbrightnesscontroller.cpp"