PowerManager: add dim display feature

pull/21/head
reionwong 4 years ago
parent 04697c1c3f
commit bc6c46a02f

@ -12,7 +12,7 @@ sudo pacman -S extra-cmake-modules pkgconf qt5-base qt5-quickcontrols2 qt5-x11ex
For Ubuntu:
```shell
sudo apt install libpolkit-agent-1-dev libpolkit-qt5-1-dev libpulse-dev libsm-dev libxtst-dev\
libxcb-randr0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb-composite0-dev libxcb-damage0-dev libxcb-image0-dev libxcb-util0-dev
libxcb-randr0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxcb-composite0-dev libxcb-damage0-dev libxcb-image0-dev libxcb-util0-dev libkf5idletime-dev
```
(Yes it's annoying that so many xcb's packages here is needed to install. Isn't there a way to install one package and these `libxcb`s all get ready?)

1
debian/control vendored

@ -34,6 +34,7 @@ Build-Depends: cmake,
libkf5windowsystem-dev,
libkf5globalaccel-dev,
libkf5coreaddons-dev,
libkf5idletime-dev,
libqt5x11extras5-dev,
qtbase5-dev,
qtdeclarative5-dev,

@ -1,10 +1,15 @@
project(cutefish-powerman)
set(TARGET cutefish-powerman)
find_package(KF5IdleTime)
set(SOURCES
main.cpp
application.cpp
lidwatcher.cpp
action.cpp
idlemanager.cpp
dimdisplayaction.cpp
cpu/cpuitem.cpp
cpu/cpumanagement.cpp
)
@ -12,6 +17,10 @@ set(SOURCES
qt5_add_dbus_adaptor(DBUS_SOURCES
cpu/com.cutefish.CPUManagement.xml
cpu/cpumanagement.h CPUManagement)
qt5_add_dbus_adaptor(DBUS_SOURCES
com.cutefish.PowerManager.xml
application.h Application)
qt_add_dbus_interface(DBUS_SOURCES org.freedesktop.ScreenSaver.xml screenlocker_interface)
set_source_files_properties(${DBUS_SOURCES} PROPERTIES SKIP_AUTOGEN ON)
add_executable(${TARGET} ${SOURCES} ${DBUS_SOURCES})
@ -22,6 +31,8 @@ target_link_libraries(${TARGET}
Qt5::Quick
Qt5::DBus
Qt5::X11Extras
KF5::IdleTime
)
install(TARGETS ${TARGET} DESTINATION ${CMAKE_INSTALL_BINDIR})

@ -0,0 +1,60 @@
/***************************************************************************
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#include "action.h"
#include "idlemanager.h"
#include <QDebug>
class Action::Private
{
public:
Private() {}
~Private() {}
QVector< int > registeredIdleTimeouts;
};
Action::Action(QObject* parent)
: QObject(parent)
, d(new Private)
{
}
Action::~Action()
{
delete d;
}
void Action::registerIdleTimeout(int msec)
{
d->registeredIdleTimeouts.append(msec);
IdleManager::self()->registerActionTimeout(this, msec);
}
bool Action::isSupported()
{
return true;
}
void Action::setTimeout(int timeout)
{
Q_UNUSED(timeout)
}

@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#ifndef POWERDEVIL_POWERDEVILACTION_H
#define POWERDEVIL_POWERDEVILACTION_H
#include <QObject>
#include <QVariantMap>
class IDleManager;
class Q_DECL_EXPORT Action : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Action)
public:
/**
* Default constructor
*/
explicit Action(QObject *parent);
/**
* Default destructor
*/
~Action() override;
/**
* This function is meant to find out if this action is available on this system. Actions
* CAN reimplement this function if they are dependent on specific hardware/software requirements.
* By default, this function will always return true.
*
* Should this function return false, the core will delete and ignore the action right after creation.
*
* @returns Whether this action is supported or not by the current system
*/
virtual bool isSupported();
virtual void setTimeout(int timeout);
protected:
/**
* Registers an idle timeout for this action. Call this function and not KIdleTime directly to take advantage
* of Action's automated handling of idle timeouts. Also, please reimplement onIdleTimeout instead of listening
* to KIdleTime's signals to catch idle timeout events.
*
* @param msec The idle timeout to be registered in milliseconds.
*/
void registerIdleTimeout(int msec);
public Q_SLOTS:
/**
* This slot is triggered whenever an idle timeout registered with registerIdleTimeout is reached.
*
* @param msec The idle timeout reached in milliseconds
*/
virtual void onIdleTimeout(int msec) = 0;
/**
* This slot is triggered whenever the PC wakes up from an Idle state. It is @b always called after a registered
* idle timeout has been reached.
*/
virtual void onWakeupFromIdle() = 0;
Q_SIGNALS:
void actionTriggered(bool result, const QString &error = QString());
private:
class Private;
Private * const d;
friend class IDleManager;
};
#endif // POWERDEVIL_POWERDEVILACTION_H

@ -18,12 +18,29 @@
*/
#include "application.h"
#include "powermanageradaptor.h"
#include <QDBusConnection>
#include <QDebug>
Application::Application(QObject *parent)
: QObject(parent)
, m_lidWatcher(new LidWatcher)
, m_cpuManagement(new CPUManagement)
, m_settings("cutefishos", "power")
, m_dimDisplayAction(new DimDisplayAction)
{
m_closeScreenTimeout = m_settings.value("CloseScreenTimeout", 600).toInt();
m_dimDisplayAction->setTimeout(m_closeScreenTimeout);
QDBusConnection::sessionBus().registerService(QStringLiteral("com.cutefish.PowerManager"));
QDBusConnection::sessionBus().registerObject(QStringLiteral("/PowerManager"), this);
new PowerManagerAdaptor(this);
}
void Application::setDimDisplayTimeout(int timeout)
{
m_closeScreenTimeout = timeout;
m_dimDisplayAction->setTimeout(timeout);
}

@ -21,7 +21,14 @@
#define APPLICATION_H
#include <QObject>
#include <QSettings>
#include <QAction>
#include <QSet>
#include "lidwatcher.h"
#include "idlemanager.h"
#include "dimdisplayaction.h"
#include "cpu/cpumanagement.h"
class Application : public QObject
@ -31,9 +38,16 @@ class Application : public QObject
public:
explicit Application(QObject *parent = nullptr);
void setDimDisplayTimeout(int timeout);
private:
LidWatcher *m_lidWatcher;
CPUManagement *m_cpuManagement;
QSettings m_settings;
int m_closeScreenTimeout;
DimDisplayAction *m_dimDisplayAction;
};
#endif // APPLICATION_H

@ -0,0 +1,8 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.cutefish.PowerManager">
<method name="setDimDisplayTimeout">
<arg name="value" type="i" direction="in"/>
</method>
</interface>
</node>

@ -0,0 +1,79 @@
/***************************************************************************
* Copyright (C) 2021 by Reion Wong <reion@cutefishos.com> *
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#include "dimdisplayaction.h"
#include <QSettings>
#include <QTimer>
#include <QDBusPendingCall>
#include <QDebug>
DimDisplayAction::DimDisplayAction(QObject *parent)
: Action(parent)
, m_iface("com.cutefish.Settings",
"/Brightness",
"com.cutefish.Brightness", QDBusConnection::sessionBus())
{
}
void DimDisplayAction::onWakeupFromIdle()
{
if (!m_dimmed) {
return;
}
// 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));
});
m_dimmed = false;
}
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));
} 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)) {
m_oldScreenBrightness = m_iface.property("brightness").toInt();
const int newBrightness = qRound(m_oldScreenBrightness / 2.0);
m_iface.asyncCall("setValue", QVariant::fromValue(newBrightness));
}
m_dimmed = true;
}
void DimDisplayAction::setTimeout(int timeout)
{
m_dimOnIdleTime = timeout;
registerIdleTimeout(m_dimOnIdleTime * 3 / 4);
registerIdleTimeout(m_dimOnIdleTime / 2);
registerIdleTimeout(m_dimOnIdleTime);
}

@ -0,0 +1,45 @@
/***************************************************************************
* Copyright (C) 2021 by Reion Wong <reion@cutefishos.com> *
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#ifndef DIMDISPLAYACTION_H
#define DIMDISPLAYACTION_H
#include "action.h"
#include <QDBusInterface>
class DimDisplayAction : public Action
{
Q_OBJECT
public:
explicit DimDisplayAction(QObject *parent = nullptr);
void onWakeupFromIdle() override;
void onIdleTimeout(int msec) override;
void setTimeout(int timeout) override;
private:
QDBusInterface m_iface;
int m_dimOnIdleTime = 0;
int m_oldScreenBrightness = 0;
bool m_dimmed = false;
};
#endif // DIMDISPLAYACTION_H

@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (C) 2021 by Reion Wong <reion@cutefishos.com> *
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#include "idlemanager.h"
#include <KIdleTime>
IdleManager *IdleManager::self()
{
static IdleManager mgr;
return &mgr;
}
IdleManager::IdleManager(QObject *parent)
: QObject(parent)
{
connect(KIdleTime::instance(), SIGNAL(timeoutReached(int,int)),
this, SLOT(onKIdleTimeoutReached(int,int)));
connect(KIdleTime::instance(), &KIdleTime::resumingFromIdle,
this, &IdleManager::onResumingFromIdle);
}
void IdleManager::registerActionTimeout(Action *action, int secs)
{
int identifier = KIdleTime::instance()->addIdleTimeout(secs * 1000);
QList<int> timeouts = m_registeredActionTimeouts[action];
timeouts.append(identifier);
m_registeredActionTimeouts[action] = timeouts;
}
void IdleManager::unregisterActionTimeouts(Action *action)
{
// Clear all timeouts from the action
const QList< int > timeoutsToClean = m_registeredActionTimeouts[action];
for (int id : timeoutsToClean) {
KIdleTime::instance()->removeIdleTimeout(id);
}
m_registeredActionTimeouts.remove(action);
}
void IdleManager::onKIdleTimeoutReached(int identifier, int timeout)
{
for (auto i = m_registeredActionTimeouts.constBegin(), end = m_registeredActionTimeouts.constEnd(); i != end; ++i) {
if (i.value().contains(identifier)) {
i.key()->onIdleTimeout(timeout);
// And it will need to be awaken
m_pendingResumeFromIdleActions.insert(i.key());
break;
}
}
// Catch the next resume event if some actions require it
if (!m_pendingResumeFromIdleActions.isEmpty()) {
KIdleTime::instance()->catchNextResumeEvent();
}
}
void IdleManager::onResumingFromIdle()
{
KIdleTime::instance()->simulateUserActivity();
// Wake up the actions in which an idle action was triggered
std::for_each(m_pendingResumeFromIdleActions.cbegin(), m_pendingResumeFromIdleActions.cend(),
std::mem_fn(&Action::onWakeupFromIdle));
m_pendingResumeFromIdleActions.clear();
}

@ -0,0 +1,52 @@
/***************************************************************************
* Copyright (C) 2021 by Reion Wong <reion@cutefishos.com> *
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#ifndef IDLEMANAGER_H
#define IDLEMANAGER_H
#include <QObject>
#include <QHash>
#include <QSet>
#include "action.h"
class IdleManager : public QObject
{
Q_OBJECT
public:
static IdleManager *self();
explicit IdleManager(QObject *parent = nullptr);
void registerActionTimeout(Action *action, int secs);
void unregisterActionTimeouts(Action *action);
private slots:
void onKIdleTimeoutReached(int, int);
void onResumingFromIdle();
private:
friend class Action;
QHash<Action *, QList<int>> m_registeredActionTimeouts;
QSet<Action *> m_pendingResumeFromIdleActions;
};
#endif // IDLEMANAGER_H

@ -0,0 +1,41 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.ScreenSaver">
<signal name="ActiveChanged">
<arg type="b"/>
</signal>
<method name="Lock">
</method>
<method name="SimulateUserActivity">
</method>
<method name="GetActive">
<arg type="b" direction="out"/>
</method>
<method name="GetActiveTime">
<arg name="seconds" type="u" direction="out"/>
</method>
<method name="GetSessionIdleTime">
<arg name="seconds" type="u" direction="out"/>
</method>
<method name="SetActive">
<arg type="b" direction="out"/>
<arg name="e" type="b" direction="in"/>
</method>
<method name="Inhibit">
<arg name="application_name" type="s" direction="in"/>
<arg name="reason_for_inhibit" type="s" direction="in"/>
<arg name="cookie" type="u" direction="out"/>
</method>
<method name="UnInhibit">
<arg name="cookie" type="u" direction="in"/>
</method>
<method name="Throttle">
<arg name="application_name" type="s" direction="in"/>
<arg name="reason_for_inhibit" type="s" direction="in"/>
<arg name="cookie" type="u" direction="out"/>
</method>
<method name="UnThrottle">
<arg name="cookie" type="u" direction="in"/>
</method>
</interface>
</node>

@ -20,7 +20,8 @@
#include "brightnesshelper.h"
BrightnessHelper::BrightnessHelper(QObject *parent) : QObject(parent)
BrightnessHelper::BrightnessHelper(QObject *parent)
: QObject(parent)
{
init();
anime.setEasingCurve(QEasingCurve::Linear);
@ -30,12 +31,13 @@ BrightnessHelper::BrightnessHelper(QObject *parent) : QObject(parent)
writeBrightness(value.toInt());
}
});
connect(&anime, &QVariantAnimation::finished, this, [this](){
connect(&anime, &QVariantAnimation::finished, this, [this]() {
qApp->quit();
});
}
BrightnessHelper::~BrightnessHelper(){
BrightnessHelper::~BrightnessHelper()
{
}
void BrightnessHelper::init()
@ -86,9 +88,10 @@ void BrightnessHelper::init()
maxValue = readFile(QDir(name).filePath(kMaxFile)).toInt();
}
void BrightnessHelper::setBrightness(int value){
if (value <= 0)
value = 1;
void BrightnessHelper::setBrightness(int value)
{
if (value < 0)
value = 0;
if (value > 100)
value = 100;
anime.setDuration(85);
@ -98,21 +101,24 @@ void BrightnessHelper::setBrightness(int value){
anime.start();
}
void BrightnessHelper::increaseBrightness() {
void BrightnessHelper::increaseBrightness()
{
int value = static_cast<int>(actual / (double)maxValue * 100);
setBrightness(value + 20);
}
void BrightnessHelper::decreaseBrightness() {
void BrightnessHelper::decreaseBrightness()
{
int value = static_cast<int>(actual / (double)maxValue * 100);
setBrightness(value - 20);
}
void BrightnessHelper::writeBrightness(int brightness) {
void BrightnessHelper::writeBrightness(int brightness)
{
if (brightness < 0)
brightness = 0;
if (brightness > maxValue)
brightness = maxValue;
QString dbg_s = QDir(name).filePath("brightness");
writeFile(QDir(name).filePath("brightness"), QString::number(brightness));
}
}

@ -157,9 +157,9 @@ void ProcessManager::startDaemonProcess()
{
QList<QPair<QString, QStringList>> list;
list << qMakePair(QString("cutefish-settings-daemon"), QStringList());
list << qMakePair(QString("cutefish-powerman"), QStringList());
list << qMakePair(QString("cutefish-xembedsniproxy"), QStringList());
list << qMakePair(QString("cutefish-gmenuproxy"), QStringList());
list << qMakePair(QString("cutefish-powerman"), QStringList());
list << qMakePair(QString("chotkeys"), QStringList());
for (QPair<QString, QStringList> pair : list) {

Loading…
Cancel
Save