Commit c1ba5498 authored by Kai Uwe Broulik's avatar Kai Uwe Broulik 🍇
Browse files

WIP: Implement smooth brightness change for sysfs / backlight helper

Has the helper do QVariantAnimation and has PowerDevil ignore any brightness
change events with a stupid QTimer.
I tried making the Auth action wait until the animation was done with a
QEventLoop but then KAuth would reject any other actions until it was done...
parent 79942e6b
......@@ -23,6 +23,7 @@
#include <QDir>
#include <QDebug>
#include <QVariantAnimation>
#include <KLocalizedString>
......@@ -61,6 +62,11 @@ void BacklightHelper::init()
}
}
m_anim.setEasingCurve(QEasingCurve::InOutQuad);
connect(&m_anim, &QVariantAnimation::valueChanged, this, [this](const QVariant &value) {
writeBrightness(value.toInt());
});
m_isSupported = true;
}
......@@ -181,30 +187,35 @@ void BacklightHelper::initUsingSysctl()
ActionReply BacklightHelper::brightness(const QVariantMap &args)
{
Q_UNUSED(args);
const int brightness = readBrightness();
if (brightness == -1) {
return ActionReply::HelperErrorReply();
}
ActionReply reply;
reply.addData("brightness", brightness);
return reply;
}
int BacklightHelper::readBrightness() const
{
if (!m_isSupported) {
reply = ActionReply::HelperErrorReply();
return reply;
return -1;
}
// current brightness
int brightness;
#ifdef USE_SYSCTL
size_t len = sizeof(int);
if (sysctlbyname(qPrintable(QStringLiteral("hw.acpi.video.%1.brightness").arg(m_sysctlDevice)), &brightness, &len, nullptr, 0) != 0) {
reply = ActionReply::HelperErrorReply();
return reply;
return -1;
}
#else
QFile file(m_dirname + "/brightness");
if (!file.open(QIODevice::ReadOnly)) {
reply = ActionReply(ActionReply::HelperErrorType);
reply.setErrorDescription(i18n("Can't open file"));
qCWarning(POWERDEVIL) << "reading brightness failed with error code " << file.error() << file.errorString();
return reply;
return -1;
}
QTextStream stream(&file);
......@@ -212,26 +223,29 @@ ActionReply BacklightHelper::brightness(const QVariantMap &args)
file.close();
#endif
//qCDebug(POWERDEVIL) << "brightness:" << brightness;
reply.addData("brightness", brightness);
//qCDebug(POWERDEVIL) << "data contains:" << reply.data()["brightness"];
return reply;
return brightness;
}
ActionReply BacklightHelper::setbrightness(const QVariantMap &args)
{
ActionReply reply;
int actual_brightness = args.value(QStringLiteral("brightness")).toInt();
if (!m_isSupported) {
reply = ActionReply::HelperErrorReply();
return reply;
return ActionReply::HelperErrorReply();
}
//qCDebug(POWERDEVIL) << "setting brightness:" << actual_brightness;
const int brightness = args.value(QStringLiteral("brightness")).toInt();
const int animationDuration = args.value(QStringLiteral("animationDuration")).toInt();
m_anim.stop();
m_anim.setDuration(animationDuration);
m_anim.setStartValue(readBrightness());
m_anim.setEndValue(brightness);
m_anim.start();
return ActionReply::SuccessReply();
}
bool BacklightHelper::writeBrightness(int brightness) const
{
#ifdef USE_SYSCTL
int actual_level = -1;
int d1 = 101;
......@@ -252,29 +266,24 @@ ActionReply BacklightHelper::setbrightness(const QVariantMap &args)
d1 = d2;
}
size_t len = sizeof(int);
if (sysctlbyname(qPrintable(QStringLiteral("hw.acpi.video.%1.brightness").arg(m_sysctlDevice)), nullptr, nullptr, &actual_level, len) != 0) {
reply = ActionReply::HelperErrorReply();
return reply;
}
return sysctlbyname(qPrintable(QStringLiteral("hw.acpi.video.%1.brightness").arg(m_sysctlDevice)), nullptr, nullptr, &actual_level, len) == 0;
#else
QFile file(m_dirname + QLatin1String("/brightness"));
if (!file.open(QIODevice::WriteOnly)) {
reply = ActionReply::HelperErrorReply();
// reply.setErrorCode(ActionReply::ActionReply::UserCancelledError);
qCWarning(POWERDEVIL) << "writing brightness failed with error code " << file.error() << file.errorString();
return reply;
return false;
}
int result = file.write(QByteArray::number(actual_brightness));
file.close();
if (result == -1) {
reply = ActionReply::HelperErrorReply();
// reply.setErrorCode(file.error());
const int bytesWritten = file.write(QByteArray::number(brightness));
if (bytesWritten == -1) {
qCWarning(POWERDEVIL) << "writing brightness failed with error code " << file.error() << file.errorString();
return false;
}
return true;
#endif
return reply;
return false;
}
ActionReply BacklightHelper::syspath(const QVariantMap &args)
......
......@@ -21,6 +21,8 @@
#define BACKLIGHTHELPER_H
#include <QObject>
#include <QVariantAnimation>
#include <kauth.h>
using namespace KAuth;
......@@ -40,6 +42,9 @@ public Q_SLOTS:
private:
void init();
int readBrightness() const;
bool writeBrightness(int brightness) const;
/**
* The kernel offer from version 2.6.37 the type of the interface, and based on that
* we can decide which interface is better for us, being the order
......@@ -56,6 +61,8 @@ private:
QString m_dirname;
QString m_sysctlDevice;
QList<int> m_sysctlBrightnessLevels;
QVariantAnimation m_anim;
};
#endif // BACKLIGHTHELPER_H
......@@ -30,11 +30,12 @@
#include <QDBusMessage>
#include <QDebug>
#include <QPropertyAnimation>
#include <QTimer>
#include <kauthexecutejob.h>
#include <KAuthAction>
#include <KAuthExecuteJob>
#include <KPluginFactory>
#include <KSharedConfig>
#include <KAuthAction>
#include "xrandrxcbhelper.h"
#include "xrandrbrightness.h"
......@@ -224,7 +225,7 @@ void PowerDevilUPowerBackend::init()
m_brightnessAnimation = new QPropertyAnimation(this);
m_brightnessAnimation->setTargetObject(this);
m_brightnessAnimation->setDuration(duration);
m_brightnessAnimation->setEasingCurve(QEasingCurve::InOutQuad);
m_brightnessAnimation->setEasingCurve(QEasingCurve::OutQuad);
connect(m_brightnessAnimation, &QPropertyAnimation::valueChanged, this, &PowerDevilUPowerBackend::animationValueChanged);
connect(m_brightnessAnimation, &QPropertyAnimation::finished, this, &PowerDevilUPowerBackend::slotScreenBrightnessChanged);
}
......@@ -363,6 +364,11 @@ void PowerDevilUPowerBackend::initWithBrightness(bool screenBrightnessAvailable)
void PowerDevilUPowerBackend::onDeviceChanged(const UdevQt::Device &device)
{
// If we're currently in the process of changing brightness, ignore any such events
if (m_brightnessAnimationTimer && m_brightnessAnimationTimer->isActive()) {
return;
}
qCDebug(POWERDEVIL) << "Udev device changed" << m_syspath << device.sysfsPath();
if (device.sysfsPath() != m_syspath) {
return;
......@@ -492,16 +498,30 @@ void PowerDevilUPowerBackend::setBrightness(int value, PowerDevil::BackendInterf
}
} else {
//qCDebug(POWERDEVIL) << "Falling back to helper to set brightness";
KAuth::Action action("org.kde.powerdevil.backlighthelper.setbrightness");
action.setHelperId(HELPER_ID);
action.addArgument("brightness", value);
KAuth::ExecuteJob *job = action.execute();
// we don't care about the result since executing the job sync is bad
job->start();
if (m_isLedBrightnessControl) {
action.addArgument("animationDuration", PowerDevilSettings::brightnessAnimationDuration());
auto *job = action.execute();
connect(job, &KAuth::ExecuteJob::result, this, [this, job, value] {
if (job->error()) {
qCWarning(POWERDEVIL) << "Failed to set screen brightness" << job->errorText();
return;
}
// Immediately announce the new brightness to everyone while we still animate to it
m_cachedBrightnessMap[Screen] = value;
slotScreenBrightnessChanged();
}
onBrightnessChanged(Screen, value, brightnessMax(Screen));
// So we ignore any brightness changes during the animation
if (!m_brightnessAnimationTimer) {
m_brightnessAnimationTimer = new QTimer(this);
m_brightnessAnimationTimer->setSingleShot(true);
}
m_brightnessAnimationTimer->start(PowerDevilSettings::brightnessAnimationDuration());
});
job->start();
}
} else if (type == Keyboard) {
qCDebug(POWERDEVIL) << "set kbd backlight value: " << value;
......@@ -515,6 +535,10 @@ void PowerDevilUPowerBackend::slotScreenBrightnessChanged()
return;
}
if (m_brightnessAnimationTimer && m_brightnessAnimationTimer->isActive()) {
return;
}
int value = brightness(Screen);
if (value != m_cachedBrightnessMap[Screen] || m_isLedBrightnessControl) {
m_cachedBrightnessMap[Screen] = value;
......
......@@ -44,6 +44,7 @@
class XRandRXCBHelper;
class XRandrBrightness;
class QPropertyAnimation;
class QTimer;
class DDCutilBrightness;
class Q_DECL_EXPORT PowerDevilUPowerBackend : public PowerDevil::BackendInterface
{
......@@ -109,6 +110,8 @@ private:
QPropertyAnimation *m_brightnessAnimation = nullptr;
QTimer *m_brightnessAnimationTimer = nullptr;
// login1 interface
QPointer<QDBusInterface> m_login1Interface;
bool m_useUPowerSuspend = false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment