feat(power): use KWin Wayland DPMS for screen timeout

main
Reion Wong 3 weeks ago
parent 5ce731d54f
commit f06f7b795d

1
debian/control vendored

@ -10,6 +10,7 @@ Build-Depends: cmake,
libpolkit-agent-1-dev,
libkf6coreaddons-dev,
libkf6idletime-dev,
kwayland-dev,
qt6-base-dev,
qt6-declarative-dev,
qt6-tools-dev,

@ -2,6 +2,7 @@ project(cutefish-powerman)
set(TARGET cutefish-powerman)
find_package(KF6IdleTime)
find_package(KWayland REQUIRED)
set(SOURCES
main.cpp
application.cpp
@ -31,6 +32,7 @@ target_link_libraries(${TARGET}
Qt6::DBus
KF6::IdleTime
Plasma::KWaylandClient
)
install(TARGETS ${TARGET} DESTINATION ${CMAKE_INSTALL_BINDIR})

@ -21,17 +21,113 @@
#include "dimdisplayaction.h"
#include "screenlocker_interface.h"
#include <QGuiApplication>
#include <QSettings>
#include <QTimer>
#include <QDBusPendingCall>
#include <QDebug>
#include <utility>
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/dpms.h>
#include <KWayland/Client/output.h>
#include <KWayland/Client/registry.h>
DimDisplayAction::DimDisplayAction(QObject *parent)
: Action(parent)
, m_iface("com.cutefish.Settings",
"/Brightness",
"com.cutefish.Brightness", QDBusConnection::sessionBus())
{
setupWaylandDpms();
}
void DimDisplayAction::setupWaylandDpms()
{
if (!QGuiApplication::platformName().startsWith(QStringLiteral("wayland")))
return;
m_waylandConnection = KWayland::Client::ConnectionThread::fromApplication(this);
if (!m_waylandConnection)
return;
m_waylandRegistry = new KWayland::Client::Registry(this);
m_waylandRegistry->create(m_waylandConnection);
connect(m_waylandRegistry, &KWayland::Client::Registry::outputAnnounced,
this, &DimDisplayAction::setupWaylandOutput);
connect(m_waylandRegistry, &KWayland::Client::Registry::dpmsAnnounced,
this, &DimDisplayAction::setupWaylandDpmsManager);
m_waylandRegistry->setup();
m_waylandConnection->roundtrip();
// DPMS support is announced after the output objects are created.
m_waylandConnection->roundtrip();
}
void DimDisplayAction::setupWaylandOutput(quint32 name, quint32 version)
{
auto *output = m_waylandRegistry->createOutput(name, version, this);
if (!output || !output->isValid())
return;
m_waylandOutputs.append(output);
addWaylandDpms(output);
}
void DimDisplayAction::setupWaylandDpmsManager(quint32 name, quint32 version)
{
if (m_waylandDpmsManager)
return;
m_waylandDpmsManager = m_waylandRegistry->createDpmsManager(name, version, this);
if (!m_waylandDpmsManager || !m_waylandDpmsManager->isValid()) {
m_waylandDpmsManager = nullptr;
return;
}
for (const auto &output : std::as_const(m_waylandOutputs)) {
if (output)
addWaylandDpms(output);
}
}
void DimDisplayAction::addWaylandDpms(KWayland::Client::Output *output)
{
if (!m_waylandDpmsManager || !output)
return;
auto *dpms = m_waylandDpmsManager->getDpms(output, this);
if (dpms && dpms->isValid())
m_waylandDpmsOutputs.append(dpms);
}
bool DimDisplayAction::hasSupportedWaylandDpms() const
{
for (const auto &dpms : std::as_const(m_waylandDpmsOutputs)) {
if (dpms && dpms->isSupported())
return true;
}
return false;
}
bool DimDisplayAction::setDisplayPower(bool on)
{
bool requested = false;
const auto mode = on ? KWayland::Client::Dpms::Mode::On
: KWayland::Client::Dpms::Mode::Off;
for (const auto &dpms : std::as_const(m_waylandDpmsOutputs)) {
if (!dpms || !dpms->isSupported())
continue;
dpms->requestMode(mode);
requested = true;
}
return requested;
}
void DimDisplayAction::onWakeupFromIdle()
@ -40,15 +136,19 @@ void DimDisplayAction::onWakeupFromIdle()
return;
}
if (m_oldScreenBrightness < 0)
m_oldScreenBrightness = 1;
// An active inhibition may not let us restore the brightness.
// We should wait a bit screen to wake-up from sleep
QTimer::singleShot(0, this, [this]() {
m_iface.asyncCall("setValue", QVariant::fromValue(m_oldScreenBrightness));
if (m_displayPoweredOff) {
setDisplayPower(true);
m_displayPoweredOff = false;
}
if (m_oldScreenBrightness >= 0)
m_iface.asyncCall("setValue", QVariant::fromValue(m_oldScreenBrightness));
});
m_oldScreenBrightness = -1;
m_dimmed = false;
}
@ -56,11 +156,11 @@ void DimDisplayAction::onIdleTimeout(int msec)
{
int sec = msec / 1000;
if (m_iface.property("brightness").toInt() == 0)
return;
if (sec == m_dimOnIdleTime) {
m_iface.asyncCall("setValue", QVariant::fromValue(0));
m_displayPoweredOff = setDisplayPower(false);
if (!m_displayPoweredOff && m_iface.property("brightness").toInt() > 0)
m_iface.asyncCall("setValue", QVariant::fromValue(0));
// Sleep
if (m_sleep) {
@ -81,15 +181,18 @@ void DimDisplayAction::onIdleTimeout(int msec)
screenSaver.Lock();
}
} else if (sec == (m_dimOnIdleTime * 3 / 4)) {
const int newBrightness = qRound(m_oldScreenBrightness / 8.0);
m_iface.asyncCall("setValue", QVariant::fromValue(newBrightness));
} else if (sec == (m_dimOnIdleTime * 1 / 2)) {
} else if (!hasSupportedWaylandDpms() && sec == (m_dimOnIdleTime * 3 / 4)) {
if (m_oldScreenBrightness > 0) {
const int newBrightness = qRound(m_oldScreenBrightness / 8.0);
m_iface.asyncCall("setValue", QVariant::fromValue(newBrightness));
}
} else if (!hasSupportedWaylandDpms() && sec == (m_dimOnIdleTime * 1 / 2)) {
m_oldScreenBrightness = m_iface.property("brightness").toInt();
const int newBrightness = qRound(m_oldScreenBrightness / 2.0);
m_iface.asyncCall("setValue", QVariant::fromValue(newBrightness));
if (m_oldScreenBrightness > 0) {
const int newBrightness = qRound(m_oldScreenBrightness / 2.0);
m_iface.asyncCall("setValue", QVariant::fromValue(newBrightness));
}
}
m_dimmed = true;

@ -22,7 +22,21 @@
#define DIMDISPLAYACTION_H
#include "action.h"
#include <QList>
#include <QDBusInterface>
#include <QPointer>
namespace KWayland
{
namespace Client
{
class ConnectionThread;
class Dpms;
class DpmsManager;
class Output;
class Registry;
}
}
class DimDisplayAction : public Action
{
@ -38,12 +52,26 @@ public:
void setLock(bool lock);
private:
void setupWaylandDpms();
void setupWaylandOutput(quint32 name, quint32 version);
void setupWaylandDpmsManager(quint32 name, quint32 version);
void addWaylandDpms(KWayland::Client::Output *output);
bool hasSupportedWaylandDpms() const;
bool setDisplayPower(bool on);
QDBusInterface m_iface;
int m_dimOnIdleTime = 0;
int m_oldScreenBrightness = 0;
int m_oldScreenBrightness = -1;
bool m_dimmed = false;
bool m_sleep = false;
bool m_lock = false;
bool m_displayPoweredOff = false;
KWayland::Client::ConnectionThread *m_waylandConnection = nullptr;
KWayland::Client::Registry *m_waylandRegistry = nullptr;
KWayland::Client::DpmsManager *m_waylandDpmsManager = nullptr;
QList<QPointer<KWayland::Client::Output>> m_waylandOutputs;
QList<QPointer<KWayland::Client::Dpms>> m_waylandDpmsOutputs;
};
#endif // DIMDISPLAYACTION_H

@ -158,7 +158,6 @@ void BrightnessManager::initUsingWhitelist()
void BrightnessManager::initUsingBacklightType()
{
QString m_dirname;
QDir dir(PREFIX);
dir.setFilter(QDir::AllDirs | QDir::NoDot | QDir::NoDotDot | QDir::NoDotAndDotDot | QDir::Readable);
dir.setSorting(QDir::Name | QDir::Reversed);// Reverse is needed to priorize acpi_video1 over 0

Loading…
Cancel
Save