File indexing completed on 2024-05-12 05:38:43
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 SPDX-FileCopyrightText: 2023 Jakob Petsovits <jpetso@petsovits.com> 0008 0009 SPDX-License-Identifier: LGPL-2.0-only 0010 */ 0011 0012 #include "backlightbrightness.h" 0013 0014 #include <powerdevil_debug.h> 0015 0016 #include <QDebug> 0017 #include <QFileInfo> 0018 #include <QTimer> 0019 0020 #include <KAuth/Action> 0021 #include <KAuth/ActionReply> 0022 #include <KAuth/ExecuteJob> 0023 #include <KAuth/HelperSupport> 0024 0025 #include "udevqt.h" 0026 0027 #define HELPER_ID "org.kde.powerdevil.backlighthelper" 0028 0029 BacklightBrightness::BacklightBrightness(QObject *parent) 0030 : QObject(parent) 0031 { 0032 } 0033 0034 void BacklightBrightness::detect() 0035 { 0036 KAuth::Action brightnessAction("org.kde.powerdevil.backlighthelper.brightness"); 0037 brightnessAction.setHelperId(HELPER_ID); 0038 KAuth::ExecuteJob *brightnessJob = brightnessAction.execute(); 0039 connect(brightnessJob, &KJob::result, this, [this, brightnessJob] { 0040 if (brightnessJob->error()) { 0041 qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.brightness failed"; 0042 qCDebug(POWERDEVIL) << brightnessJob->errorText(); 0043 Q_EMIT detectionFinished(isSupported()); 0044 return; 0045 } 0046 m_cachedBrightness = brightnessJob->data()["brightness"].toFloat(); 0047 0048 KAuth::Action brightnessMaxAction("org.kde.powerdevil.backlighthelper.brightnessmax"); 0049 brightnessMaxAction.setHelperId(HELPER_ID); 0050 KAuth::ExecuteJob *brightnessMaxJob = brightnessMaxAction.execute(); 0051 connect(brightnessMaxJob, &KJob::result, this, [this, brightnessMaxJob] { 0052 if (brightnessMaxJob->error()) { 0053 qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.brightnessmax failed"; 0054 qCDebug(POWERDEVIL) << brightnessMaxJob->errorText(); 0055 } else { 0056 m_maxBrightness = brightnessMaxJob->data()["brightnessmax"].toInt(); 0057 } 0058 0059 #ifdef Q_OS_FREEBSD 0060 // FreeBSD doesn't have the sysfs interface that the bits below expect; 0061 // the sysfs calls always fail, leading to detectionFinished(false) emission. 0062 // Skip that command and carry on with the information that we do have. 0063 Q_EMIT detectionFinished(isSupported()); 0064 #else 0065 KAuth::Action syspathAction("org.kde.powerdevil.backlighthelper.syspath"); 0066 syspathAction.setHelperId(HELPER_ID); 0067 KAuth::ExecuteJob* syspathJob = syspathAction.execute(); 0068 connect(syspathJob, &KJob::result, this, [this, syspathJob] { 0069 if (syspathJob->error()) { 0070 qCWarning(POWERDEVIL) << "org.kde.powerdevil.backlighthelper.syspath failed"; 0071 qCDebug(POWERDEVIL) << syspathJob->errorText(); 0072 m_maxBrightness = 0; // i.e. isSupported() == false 0073 Q_EMIT detectionFinished(isSupported()); 0074 return; 0075 } 0076 m_syspath = syspathJob->data()["syspath"].toString(); 0077 m_syspath = QFileInfo(m_syspath).symLinkTarget(); 0078 0079 // Kernel doesn't send uevent for leds-class devices, or at least that's what 0080 // commit 26a48f9db claimed (although the monitored subsystem was already hardcoded 0081 // to "backlight" then). That's okay because we emit brightnessChanged() at least 0082 // once when setBrightness() starts successfully. 0083 if (!m_syspath.contains(QLatin1String("/leds/"))) { 0084 UdevQt::Client *client = new UdevQt::Client(QStringList("backlight"), this); 0085 connect(client, &UdevQt::Client::deviceChanged, this, &BacklightBrightness::onDeviceChanged); 0086 } 0087 0088 Q_EMIT detectionFinished(isSupported()); 0089 }); 0090 syspathJob->start(); 0091 #endif 0092 }); 0093 brightnessMaxJob->start(); 0094 }); 0095 brightnessJob->start(); 0096 } 0097 0098 bool BacklightBrightness::isSupported() const 0099 { 0100 return m_maxBrightness > 0; 0101 } 0102 0103 void BacklightBrightness::onDeviceChanged(const UdevQt::Device &device) 0104 { 0105 // If we're currently in the process of changing brightness, ignore any such events 0106 if (m_brightnessAnimationTimer && m_brightnessAnimationTimer->isActive()) { 0107 return; 0108 } 0109 0110 qCDebug(POWERDEVIL) << "Udev device changed" << m_syspath << device.sysfsPath(); 0111 if (device.sysfsPath() != m_syspath) { 0112 return; 0113 } 0114 0115 int maxBrightness = device.sysfsProperty("max_brightness").toInt(); 0116 if (maxBrightness <= 0) { 0117 return; 0118 } 0119 int newBrightness = device.sysfsProperty("brightness").toInt(); 0120 0121 if (newBrightness != m_cachedBrightness) { 0122 m_cachedBrightness = newBrightness; 0123 Q_EMIT brightnessChanged(newBrightness, maxBrightness); 0124 } 0125 } 0126 0127 int BacklightBrightness::maxBrightness() const 0128 { 0129 return m_maxBrightness; 0130 } 0131 0132 int BacklightBrightness::brightness() const 0133 { 0134 return m_cachedBrightness; 0135 } 0136 0137 void BacklightBrightness::setBrightness(int newBrightness, int animationDurationMsec) 0138 { 0139 if (!isSupported()) { 0140 qCWarning(POWERDEVIL) << "backlight not supported, setBrightness() should not be called"; 0141 return; 0142 } 0143 0144 KAuth::Action action("org.kde.powerdevil.backlighthelper.setbrightness"); 0145 action.setHelperId(HELPER_ID); 0146 action.addArgument("brightness", newBrightness); 0147 if (brightness() >= m_brightnessAnimationThreshold) { 0148 action.addArgument("animationDuration", animationDurationMsec); 0149 } 0150 auto *job = action.execute(); 0151 0152 connect(job, &KAuth::ExecuteJob::result, this, [this, job, newBrightness, animationDurationMsec] { 0153 if (job->error()) { 0154 qCWarning(POWERDEVIL) << "Failed to set screen brightness" << job->errorText(); 0155 return; 0156 } 0157 0158 // So we ignore any brightness changes during the animation 0159 if (!m_brightnessAnimationTimer) { 0160 m_brightnessAnimationTimer = new QTimer(this); 0161 m_brightnessAnimationTimer->setSingleShot(true); 0162 } 0163 m_brightnessAnimationTimer->start(animationDurationMsec); 0164 0165 // Immediately announce the new brightness to everyone while we still animate to it 0166 m_cachedBrightness = newBrightness; 0167 Q_EMIT brightnessChanged(newBrightness, maxBrightness()); 0168 }); 0169 job->start(); 0170 } 0171 0172 #include "moc_backlightbrightness.cpp"