├── docs
├── CNAME
├── _config.yml
├── screenshot.png
├── build.sh
├── README.md
├── powerkit.md
└── powerkit.1
├── .gitignore
├── share
├── powerkit.desktop
├── com.ubuntu.enable-hibernate.pkla
├── org.freedesktop.PowerManagement.Inhibit.xml
├── org.freedesktop.ScreenSaver.xml
└── 90-backlight.rules
├── .github
└── workflows
│ └── c-cpp.yml
├── src
├── powerkit_notify.h
├── powerkit_backlight.h
├── powerkit_theme.h
├── powerkit_client.h
├── powerkit_powermanagement.h
├── powerkit_screensaver.h
├── powerkit_notify.cpp
├── powerkit_device.h
├── powerkit_cpu.h
├── powerkit_common.h
├── powerkit_powermanagement.cpp
├── powerkit_settings.h
├── powerkit.cpp
├── powerkit_settings.cpp
├── powerkit_backlight.cpp
├── powerkit_dialog.h
├── powerkit_manager.h
├── powerkit_device.cpp
├── powerkit_app.h
├── powerkit_theme.cpp
├── powerkit_client.cpp
├── powerkit_screensaver.cpp
├── powerkit_cpu.cpp
├── powerkit_manager.cpp
├── powerkit_app.cpp
└── powerkit_dialog.cpp
├── LICENSE
└── CMakeLists.txt
/docs/CNAME:
--------------------------------------------------------------------------------
1 | powerkit.dracolinux.org
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user*
2 | build*
3 | *~
4 |
5 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-hacker
2 | show_downloads: false
3 |
--------------------------------------------------------------------------------
/docs/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rodlie/powerkit/HEAD/docs/screenshot.png
--------------------------------------------------------------------------------
/share/powerkit.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=PowerKit
3 | Comment=Power Manager
4 | Icon=ac-adapter
5 | Exec=@PROJECT_NAME@ --config
6 | Terminal=false
7 | Type=Application
8 | Categories=Settings;
9 | StartupNotify=false
10 |
--------------------------------------------------------------------------------
/share/com.ubuntu.enable-hibernate.pkla:
--------------------------------------------------------------------------------
1 | [Re-enable hibernate by default in upower]
2 | Identity=unix-user:*
3 | Action=org.freedesktop.upower.hibernate
4 | ResultActive=yes
5 |
6 | [Re-enable hibernate by default in logind]
7 | Identity=unix-user:*
8 | Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
9 | ResultActive=yes
10 |
11 |
--------------------------------------------------------------------------------
/.github/workflows/c-cpp.yml:
--------------------------------------------------------------------------------
1 | name: C/C++ CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ${{ matrix.os }}
9 | strategy:
10 | matrix:
11 | os: [ubuntu-22.04]
12 |
13 | steps:
14 | - uses: actions/checkout@v3
15 | - name: Install Dependencies
16 | run: sudo apt update && sudo apt install cmake qtbase5-dev libxss-dev libxrandr-dev
17 | - name: Build and Package
18 | run: |
19 | mkdir build && cd build
20 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DSERVICE_GROUP=plugdev -DCMAKE_BUILD_TYPE=Release ..
21 | make -j2
22 | cpack -G DEB
23 |
--------------------------------------------------------------------------------
/docs/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | CWD=`pwd`
3 |
4 | if [ ! -f "${CWD}/CMakeLists.txt" ]; then
5 | echo "Run this script from the powerkit root directory"
6 | exit 1
7 | fi
8 |
9 | PANDOC=${PANDOC:-pandoc}
10 | MONTH=`echo $(LANG=en_us_88591; date "+%B")`
11 | YEAR=`echo $(LANG=en_us_88591; date "+%Y")`
12 | VERSION=`cat ${CWD}/CMakeLists.txt | sed '/powerkit VERSION/!d;s/)//' | awk '{print $3}'`
13 | echo "% POWERKIT(1) Version ${VERSION} | PowerKit Documentation" > ${CWD}/tmp.md
14 | echo "% Ole-André Rodlie" >> ${CWD}/tmp.md
15 | echo "% ${MONTH} ${YEAR}" >> ${CWD}/tmp.md
16 | cat ${CWD}/docs/powerkit.md >> ${CWD}/tmp.md
17 | ${PANDOC} ${CWD}/tmp.md -s -t man > ${CWD}/docs/powerkit.1
18 | rm ${CWD}/tmp.md
19 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # powerkit
2 |
3 | Desktop independent power manager for use with alternative X11 desktop environments and window managers on Linux.
4 |
5 | 
6 |
7 | * Implements *``org.freedesktop.ScreenSaver``* service
8 | * Implements *``org.freedesktop.PowerManagement.Inhibit``* service
9 | * Automatic actions on lid, idle and low battery
10 | * Sleep
11 | * Hibernate
12 | * HybridSleep
13 | * Suspend then Hibernate
14 | * Shutdown
15 | * Screen saver support
16 | * Screen lid support
17 | * Screen locking support
18 | * Screen backlight support
19 | * Notification support (can use *``org.freedesktop.Notifications``* if available)
20 |
21 | See [documentation](powerkit.md) (`man powerkit`) for more information.
22 |
--------------------------------------------------------------------------------
/share/org.freedesktop.PowerManagement.Inhibit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/share/org.freedesktop.ScreenSaver.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/share/90-backlight.rules:
--------------------------------------------------------------------------------
1 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="acpi_video0", RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness"
2 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="acpi_video0", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
3 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="intel_backlight", RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness"
4 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="intel_backlight", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
5 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="radeon_bl0", RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness"
6 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="radeon_bl0", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
7 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="amdgpu_bl0", RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness"
8 | ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="amdgpu_bl0", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
9 |
--------------------------------------------------------------------------------
/src/powerkit_notify.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) 2018-2022 Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_NOTIFY_H
10 | #define POWERKIT_NOTIFY_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | class QDBusInterface;
19 |
20 | namespace PowerKit
21 | {
22 | class SystemNotification : public QObject
23 | {
24 | Q_OBJECT
25 |
26 | public:
27 | explicit SystemNotification(QObject* parent = nullptr);
28 | bool valid;
29 |
30 | void sendMessage(const QString& title,
31 | const QString& text,
32 | const bool critical);
33 |
34 | private:
35 | QDBusInterface *dbus;
36 | };
37 | }
38 |
39 | #endif // POWERKIT_NOTIFY_H
40 |
--------------------------------------------------------------------------------
/src/powerkit_backlight.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_BACKLIGHT_H
10 | #define POWERKIT_BACKLIGHT_H
11 |
12 | #include
13 |
14 | namespace PowerKit
15 | {
16 | class Backlight
17 | {
18 | public:
19 | static const QString getDevice();
20 | static bool canAdjustBrightness(const QString &device);
21 | static bool canAdjustBrightness();
22 | static int getMaxBrightness(const QString &device);
23 | static int getMaxBrightness();
24 | static int getCurrentBrightness(const QString &device);
25 | static int getCurrentBrightness();
26 | static bool setCurrentBrightness(const QString &device, int value); // deprecated
27 | static bool setCurrentBrightness(int value); // deprecated
28 | static bool setBrightness(const QString &device, int value);
29 | static bool setBrightness(int value);
30 | };
31 | }
32 |
33 | #endif // POWERKIT_BACKLIGHT_H
34 |
--------------------------------------------------------------------------------
/src/powerkit_theme.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_THEME_H
10 | #define POWERKIT_THEME_H
11 |
12 | #include
13 | #include
14 | #include
15 |
16 | namespace PowerKit
17 | {
18 | class Theme
19 | {
20 | public:
21 | static void setAppTheme(bool darker = false);
22 | static void setIconTheme();
23 | static const QPixmap drawCircleProgress(const int &progress,
24 | const int &dimension,
25 | const int &width,
26 | const int &padding,
27 | const bool dash,
28 | const QString &text,
29 | const QColor &color1 = Qt::red,
30 | const QColor &color2 = Qt::white,
31 | const QColor &color3 = Qt::white);
32 | };
33 | }
34 |
35 | #endif // POWERKIT_THEME_H
36 |
--------------------------------------------------------------------------------
/src/powerkit_client.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_CLIENT_H
10 | #define POWERKIT_CLIENT_H
11 |
12 | #include
13 |
14 | namespace PowerKit
15 | {
16 | class Client
17 | {
18 | public:
19 | static double getBatteryLeft(QDBusInterface *iface);
20 | static bool hasBattery(QDBusInterface *iface);
21 | static bool onBattery(QDBusInterface *iface);
22 | static qlonglong timeToEmpty(QDBusInterface *iface);
23 | static qlonglong timeToFull(QDBusInterface *iface);
24 | static bool canHibernate(QDBusInterface *iface);
25 | static bool canSuspend(QDBusInterface *iface);
26 | static bool canRestart(QDBusInterface *iface);
27 | static bool canPowerOff(QDBusInterface *iface);
28 | static bool lidIsPresent(QDBusInterface *iface);
29 | static bool lockScreen(QDBusInterface *iface);
30 | static bool hibernate(QDBusInterface *iface);
31 | static bool suspend(QDBusInterface *iface);
32 | static bool suspendThenHibernate(QDBusInterface *iface);
33 | static bool restart(QDBusInterface *iface);
34 | static bool poweroff(QDBusInterface *iface);
35 | };
36 | }
37 |
38 | #endif // POWERKIT_CLIENT_H
39 |
--------------------------------------------------------------------------------
/src/powerkit_powermanagement.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_POWERMANAGEMENT_H
10 | #define POWERKIT_POWERMANAGEMENT_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | namespace PowerKit
19 | {
20 | class PowerManagement : public QObject
21 | {
22 | Q_OBJECT
23 |
24 | public:
25 | explicit PowerManagement(QObject *parent = NULL);
26 |
27 | private:
28 | QTimer timer;
29 | QMap clients;
30 |
31 | signals:
32 | void HasInhibitChanged(bool has_inhibit_changed);
33 | void newInhibit(const QString &application,
34 | const QString &reason,
35 | quint32 cookie);
36 | void removedInhibit(quint32 cookie);
37 |
38 | private slots:
39 | quint32 genCookie();
40 | void checkForExpiredClients();
41 | bool canInhibit();
42 | void timeOut();
43 |
44 | public slots:
45 | void SimulateUserActivity();
46 | quint32 Inhibit(const QString &application,
47 | const QString &reason);
48 | void UnInhibit(quint32 cookie);
49 | bool HasInhibit();
50 | };
51 | }
52 |
53 | #endif // POWERKIT_POWERMANAGEMENT_H
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) Ole-André Rodlie
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | * Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | * Neither the name of the copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived from
17 | this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
--------------------------------------------------------------------------------
/src/powerkit_screensaver.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_SCREENSAVER_H
10 | #define POWERKIT_SCREENSAVER_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | namespace PowerKit
19 | {
20 | class ScreenSaver : public QObject
21 | {
22 | Q_OBJECT
23 |
24 | public:
25 | explicit ScreenSaver(QObject *parent = NULL);
26 |
27 | private:
28 | QTimer timer;
29 | QMap clients;
30 | int blank;
31 | QString xlock;
32 |
33 | signals:
34 | void newInhibit(const QString &application_name,
35 | const QString &reason_for_inhibit,
36 | quint32 cookie);
37 | void removedInhibit(quint32 cookie);
38 |
39 | private slots:
40 | quint32 genCookie();
41 | void checkForExpiredClients();
42 | bool canInhibit();
43 | void timeOut();
44 |
45 | public slots:
46 | void Update();
47 | void Lock();
48 | void SimulateUserActivity();
49 | quint32 GetSessionIdleTime();
50 | quint32 Inhibit(const QString &application_name,
51 | const QString &reason_for_inhibit);
52 | void UnInhibit(quint32 cookie);
53 | static const QMap GetDisplays();
54 | static const QString GetInternalDisplay();
55 | static void setDisplaysOff(bool off);
56 | };
57 | }
58 |
59 | #endif // POWERKIT_SCREENSAVER_H
60 |
--------------------------------------------------------------------------------
/src/powerkit_notify.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) 2018-2022 Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_notify.h"
10 | #include "powerkit_common.h"
11 |
12 | #define NOTIFY_SERVICE "org.freedesktop.Notifications"
13 | #define NOTIFY_PATH "/org/freedesktop/Notifications"
14 |
15 | using namespace PowerKit;
16 |
17 | SystemNotification::SystemNotification(QObject* parent)
18 | : QObject(parent)
19 | {
20 | dbus =
21 | new QDBusInterface(NOTIFY_SERVICE,
22 | NOTIFY_PATH,
23 | NOTIFY_SERVICE,
24 | QDBusConnection::sessionBus(),
25 | this);
26 | valid = dbus->isValid();
27 | }
28 |
29 | void SystemNotification::sendMessage(const QString& title,
30 | const QString& text,
31 | const bool critical)
32 | {
33 | QList args;
34 | QVariantMap hintsMap;
35 | int timeout = 5000;
36 |
37 | if (critical) {
38 | hintsMap.insert("urgency", QVariant::fromValue(uchar(2)));
39 | timeout = 0;
40 | }
41 |
42 | args << (qAppName()) // appname
43 | << static_cast(0) // id
44 | << POWERKIT_ICON // icon
45 | << title // summary
46 | << text // body
47 | << QStringList() // actions
48 | << hintsMap // hints
49 | << timeout; // timeout
50 | dbus->callWithArgumentList( QDBus::AutoDetect, QString("Notify"), args);
51 | }
52 |
--------------------------------------------------------------------------------
/src/powerkit_device.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_DEVICE_H
10 | #define POWERKIT_DEVICE_H
11 |
12 | #include
13 | #include
14 |
15 | namespace PowerKit
16 | {
17 | class Device : public QObject
18 | {
19 | Q_OBJECT
20 |
21 | public:
22 | enum DeviceType {
23 | DeviceUnknown,
24 | DeviceLinePower,
25 | DeviceBattery,
26 | DeviceUps,
27 | DeviceMonitor,
28 | DeviceMouse,
29 | DeviceKeyboard,
30 | DevicePda,
31 | DevicePhone
32 | };
33 | explicit Device(const QString block,
34 | QObject *parent = nullptr);
35 | QString name;
36 | QString path;
37 | QString model;
38 | DeviceType type;
39 | bool isRechargable;
40 | bool isPresent;
41 | double percentage;
42 | bool online;
43 | bool hasPowerSupply;
44 | bool isBattery;
45 | bool isAC;
46 | QString vendor;
47 | QString nativePath;
48 | double capacity;
49 | double energy;
50 | double energyFullDesign;
51 | double energyFull;
52 | double energyEmpty;
53 | qlonglong timeToEmpty;
54 | qlonglong timeToFull;
55 |
56 | private:
57 | QDBusInterface *dbus;
58 | QDBusInterface *dbusp;
59 |
60 | signals:
61 | void deviceChanged(const QString &devicePath);
62 |
63 | private slots:
64 | void updateDeviceProperties();
65 |
66 | public slots:
67 | void update();
68 | void updateBattery();
69 | };
70 | }
71 |
72 | #endif // POWERKIT_DEVICE_H
73 |
--------------------------------------------------------------------------------
/src/powerkit_cpu.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_CPU_H
10 | #define POWERKIT_CPU_H
11 |
12 | #include
13 | #include
14 |
15 | namespace PowerKit
16 | {
17 | class Cpu
18 | {
19 | public:
20 | static int getTotal();
21 |
22 | static const QString getGovernor(int cpu);
23 | static const QStringList getGovernors();
24 | static const QStringList getAvailableGovernors();
25 | static bool governorExists(const QString &gov);
26 | static bool setGovernor(const QString &gov, int cpu);
27 | static bool setGovernor(const QString &gov);
28 |
29 | static const QString getFrequency(int cpu);
30 | static const QStringList getFrequencies();
31 | static const QStringList getAvailableFrequency();
32 | static int getMinFrequency();
33 | static int getMaxFrequency();
34 | static int getScalingFrequency(int cpu, int scale);
35 | static bool frequencyExists(const QString &freq);
36 | static bool setFrequency(const QString &freq, int cpu);
37 | static bool setFrequency(const QString &freq);
38 |
39 | static bool hasPState();
40 | static bool hasPStateTurbo();
41 | static bool setPStateTurbo(bool turbo);
42 | static int getPStateMax();
43 | static int getPStateMin();
44 | static bool setPStateMax(int maxState);
45 | static bool setPStateMin(int minState);
46 | static bool setPState(int min, int max);
47 |
48 | static bool hasCoreTemp();
49 | static QPair getCoreTemp();
50 |
51 | static const QPair getCpuFreqLabel();
52 | static const QPair getCpuTempLabel();
53 | };
54 | }
55 |
56 | #endif // POWERKIT_CPU_H
57 |
--------------------------------------------------------------------------------
/src/powerkit_common.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_COMMON_H
10 | #define POWERKIT_COMMON_H
11 |
12 | namespace PowerKit
13 | {
14 | enum randrAction
15 | {
16 | randrAuto,
17 | randrLeftOf,
18 | randrRightOf,
19 | randrAbove,
20 | randrBelow,
21 | randrSameAs
22 | };
23 |
24 | enum suspendAction
25 | {
26 | suspendNone,
27 | suspendSleep,
28 | suspendHibernate,
29 | suspendShutdown,
30 | suspendHybrid,
31 | suspendSleepHibernate
32 | };
33 |
34 | enum lidAction
35 | {
36 | lidNone,
37 | lidLock,
38 | lidSleep,
39 | lidHibernate,
40 | lidShutdown,
41 | lidHybridSleep,
42 | lidSleepHibernate
43 | };
44 |
45 | enum criticalAction
46 | {
47 | criticalNone,
48 | criticalHibernate,
49 | criticalShutdown,
50 | criticalSuspend
51 | };
52 | }
53 |
54 | #define POWERKIT_LID_BATTERY_ACTION PowerKit::lidSleep
55 | #define POWERKIT_LID_AC_ACTION PowerKit::lidLock
56 | #define POWERKIT_CRITICAL_ACTION PowerKit::criticalNone
57 | #define POWERKIT_SUSPEND_BATTERY_ACTION PowerKit::suspendSleep
58 | #define POWERKIT_SUSPEND_AC_ACTION PowerKit::suspendNone
59 | #define POWERKIT_BACKLIGHT_STEP 10 // +/-
60 | #define POWERKIT_LOW_BATTERY 5 // % over critical
61 | #define POWERKIT_CRITICAL_BATTERY 10 // %
62 | #define POWERKIT_AUTO_SLEEP_BATTERY 15 // min
63 | #define POWERKIT_ICON "ac-adapter"
64 | #define POWERKIT_SERVICE "org.freedesktop.PowerKit"
65 | #define POWERKIT_PATH "/PowerKit"
66 | #define POWERKIT_MANAGER "org.freedesktop.PowerKit.Manager"
67 | #define POWERKIT_CONFIG "org.freedesktop.PowerKit.Configuration"
68 | #define POWERKIT_LOGIND_SERVICE "org.freedesktop.login1"
69 | #define POWERKIT_UPOWER_SERVICE "org.freedesktop.UPower"
70 | #define POWERKIT_DBUS_PROPERTIES "org.freedesktop.DBus.Properties"
71 | #define POWERKIT_SCREENSAVER_LOCK_CMD "xsecurelock"
72 | #define POWERKIT_SCREENSAVER_TIMEOUT_BLANK 300
73 |
74 | #endif // POWERKIT_COMMON_H
75 |
--------------------------------------------------------------------------------
/src/powerkit_powermanagement.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_powermanagement.h"
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include "powerkit_common.h"
18 |
19 | #define PM_TIMEOUT 60000
20 | #define PM_MAX_INHIBIT 18000
21 |
22 | using namespace PowerKit;
23 |
24 | PowerManagement::PowerManagement(QObject *parent) : QObject(parent)
25 | {
26 | timer.setInterval(PM_TIMEOUT);
27 | connect(&timer, SIGNAL(timeout()),
28 | this, SLOT(timeOut()));
29 | timer.start();
30 | }
31 |
32 | quint32 PowerManagement::genCookie()
33 | {
34 | quint32 cookie = QRandomGenerator::global()->generate();
35 | while (!clients.contains(cookie)) {
36 | if (!clients.contains(cookie)) { clients[cookie] = QTime::currentTime(); }
37 | else { cookie = QRandomGenerator::global()->generate(); }
38 | }
39 | return cookie;
40 | }
41 |
42 | void PowerManagement::checkForExpiredClients()
43 | {
44 | QMapIterator client(clients);
45 | while (client.hasNext()) {
46 | client.next();
47 | if (client.value()
48 | .secsTo(QTime::currentTime())>=PM_MAX_INHIBIT) {
49 | clients.remove(client.key());
50 | }
51 | }
52 | }
53 |
54 | bool PowerManagement::canInhibit()
55 | {
56 | checkForExpiredClients();
57 | if (clients.size()>0) { return true; }
58 | return false;
59 | }
60 |
61 | void PowerManagement::timeOut()
62 | {
63 | if (canInhibit()) { SimulateUserActivity(); }
64 | }
65 |
66 | void PowerManagement::SimulateUserActivity()
67 | {
68 | qDebug() << "SimulateUserActivity";
69 | emit HasInhibitChanged(true);
70 | }
71 |
72 | quint32 PowerManagement::Inhibit(const QString &application,
73 | const QString &reason)
74 | {
75 | qDebug() << "Inhibit" << application << reason;
76 | quint32 cookie = genCookie();
77 | timeOut();
78 | emit newInhibit(application, reason, cookie);
79 | emit HasInhibitChanged(canInhibit());
80 | return cookie;
81 | }
82 |
83 | void PowerManagement::UnInhibit(quint32 cookie)
84 | {
85 | qDebug() << "UnInhibit" << cookie;
86 | if (clients.contains(cookie)) { clients.remove(cookie); }
87 | timeOut();
88 | emit removedInhibit(cookie);
89 | emit HasInhibitChanged(canInhibit());
90 | }
91 |
92 | bool PowerManagement::HasInhibit()
93 | {
94 | return canInhibit();
95 | }
96 |
--------------------------------------------------------------------------------
/src/powerkit_settings.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_SETTINGS_H
10 | #define POWERKIT_SETTINGS_H
11 |
12 | #include
13 | #include
14 |
15 | #define CONF_DIALOG_GEOMETRY "dialog_geometry"
16 | #define CONF_SUSPEND_BATTERY_TIMEOUT "suspend_battery_timeout"
17 | #define CONF_SUSPEND_BATTERY_ACTION "suspend_battery_action"
18 | #define CONF_SUSPEND_AC_TIMEOUT "suspend_ac_timeout"
19 | #define CONF_SUSPEND_AC_ACTION "suspend_ac_action"
20 | #define CONF_SUSPEND_WAKEUP_HIBERNATE_BATTERY "suspend_wakeup_hibernate_battery"
21 | #define CONF_SUSPEND_WAKEUP_HIBERNATE_AC "suspend_wakeup_hibernate_ac"
22 | #define CONF_CRITICAL_BATTERY_TIMEOUT "critical_battery_timeout"
23 | #define CONF_CRITICAL_BATTERY_ACTION "critical_battery_action"
24 | #define CONF_LID_BATTERY_ACTION "lid_battery_action"
25 | #define CONF_LID_AC_ACTION "lid_ac_action"
26 | #define CONF_LID_DISABLE_IF_EXTERNAL "disable_lid_action_external_monitor"
27 | #define CONF_TRAY_NOTIFY "tray_notify"
28 | #define CONF_TRAY_SHOW "show_tray"
29 | #define CONF_LID_XRANDR "lid_xrandr_action"
30 | #define CONF_BACKLIGHT_BATTERY "backlight_battery_value"
31 | #define CONF_BACKLIGHT_BATTERY_ENABLE "backlight_battery_enable"
32 | #define CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER "backlight_battery_disable_if_lower"
33 | #define CONF_BACKLIGHT_AC "backlight_ac_value"
34 | #define CONF_BACKLIGHT_AC_ENABLE "backlight_ac_enable"
35 | #define CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER "backlight_ac_disable_if_higher"
36 | #define CONF_BACKLIGHT_MOUSE_WHEEL "backlight_mouse_wheel"
37 | #define CONF_DIALOG "dialog_geometry"
38 | #define CONF_WARN_ON_LOW_BATTERY "warn_on_low_battery"
39 | #define CONF_WARN_ON_VERYLOW_BATTERY "warn_on_verylow_battery"
40 | #define CONF_NOTIFY_ON_BATTERY "notify_on_battery"
41 | #define CONF_NOTIFY_ON_AC "notify_on_ac"
42 | #define CONF_NOTIFY_NEW_INHIBITOR "notify_new_inhibitor"
43 | #define CONF_SUSPEND_LOCK_SCREEN "lock_screen_on_suspend"
44 | #define CONF_RESUME_LOCK_SCREEN "lock_screen_on_resume"
45 | #define CONF_ICON_THEME "icon_theme"
46 | #define CONF_NATIVE_THEME "native_theme"
47 | #define CONF_KERNEL_BYPASS "kernel_cmd_bypass"
48 | #define CONF_SCREENSAVER_LOCK_CMD "screensaver_lock_cmd"
49 | #define CONF_SCREENSAVER_TIMEOUT_BLANK "screensaver_blank_timeout"
50 |
51 | namespace PowerKit
52 | {
53 | class Settings
54 | {
55 | public:
56 | static void setValue(const QString &type,
57 | const QVariant &value);
58 | static const QVariant getValue(const QString &type,
59 | const QVariant &fallback = QVariant());
60 | static bool isValid(const QString &type);
61 | static void saveDefault();
62 | static const QString getConf();
63 | static const QString getDir();
64 | };
65 | }
66 |
67 | #endif // POWERKIT_SETTINGS_H
68 |
--------------------------------------------------------------------------------
/src/powerkit.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include
10 |
11 | #include "powerkit_app.h"
12 | #include "powerkit_dialog.h"
13 | #include "powerkit_common.h"
14 | #include "powerkit_backlight.h"
15 | #include "powerkit_client.h"
16 |
17 | #define CMD_OPT_CONFIG "--config"
18 | #define CMD_OPT_BRIGHTNESS_UP "--set-brightness-up"
19 | #define CMD_OPT_BRIGHTNESS_DOWN "--set-brightness-down"
20 | #define CMD_OPT_SLEEP "--sleep"
21 | #define CMD_OPT_HIBERNATE "--hibernate"
22 | #define CMD_OPT_LOCK "--lock"
23 |
24 | int main(int argc, char *argv[])
25 | {
26 | QApplication a(argc, argv);
27 | QCoreApplication::setApplicationName("freedesktop");
28 | QCoreApplication::setOrganizationDomain("org");
29 | QCoreApplication::setApplicationVersion(QString::fromUtf8(POWERKIT_VERSION));
30 |
31 | const auto args = QApplication::arguments();
32 | bool openConfig = args.contains(CMD_OPT_CONFIG);
33 | bool setBrightness = (args.contains(CMD_OPT_BRIGHTNESS_UP) ||
34 | args.contains(CMD_OPT_BRIGHTNESS_DOWN));
35 | bool setSleep = args.contains(CMD_OPT_SLEEP);
36 | bool setHibernate = args.contains(CMD_OPT_HIBERNATE);
37 | bool setLock = args.contains(CMD_OPT_LOCK);
38 |
39 | if (openConfig) {
40 | if (!QDBusConnection::sessionBus().registerService(POWERKIT_CONFIG)) {
41 | qWarning() << QObject::tr("A powerkit config instance is already running");
42 | return 1;
43 | }
44 | PowerKit::Dialog dialog;
45 | dialog.show();
46 | return a.exec();
47 | } else if (setBrightness) {
48 | int val = PowerKit::Backlight::getCurrentBrightness();
49 | if (args.contains(CMD_OPT_BRIGHTNESS_UP)) { val += POWERKIT_BACKLIGHT_STEP; }
50 | else if (args.contains(CMD_OPT_BRIGHTNESS_DOWN)) { val -= POWERKIT_BACKLIGHT_STEP; }
51 | return PowerKit::Backlight::setBrightness(val);
52 | } else if (setSleep || setHibernate || setLock) {
53 | QDBusInterface manager(POWERKIT_SERVICE,
54 | POWERKIT_PATH,
55 | POWERKIT_MANAGER,
56 | QDBusConnection::sessionBus());
57 | if (!manager.isValid()) {
58 | qWarning() << QObject::tr("Unable to connect to the powerkit service");
59 | return 1;
60 | }
61 | if (setSleep && setHibernate) {
62 | return PowerKit::Client::suspendThenHibernate(&manager);
63 | } else if (setSleep) {
64 | return PowerKit::Client::suspend(&manager);
65 | } else if (setHibernate) {
66 | return PowerKit::Client::hibernate(&manager);
67 | } else if (setLock) {
68 | return PowerKit::Client::lockScreen(&manager);
69 | }
70 | return 1;
71 | }
72 |
73 | QDBusInterface session(POWERKIT_SERVICE,
74 | POWERKIT_PATH,
75 | POWERKIT_SERVICE,
76 | QDBusConnection::sessionBus());
77 | if (session.isValid()) {
78 | qWarning() << QObject::tr("A powerkit session is already running");
79 | return 1;
80 | }
81 |
82 | PowerKit::App powerkit(a.parent());
83 | return a.exec();
84 | }
85 |
--------------------------------------------------------------------------------
/src/powerkit_settings.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_settings.h"
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include "powerkit_common.h"
17 |
18 | #define PK "powerkit"
19 |
20 | using namespace PowerKit;
21 |
22 | void Settings::setValue(const QString &type,
23 | const QVariant &value)
24 | {
25 | QSettings settings(PK, PK);
26 | settings.setValue(type, value);
27 | settings.sync();
28 | }
29 |
30 | const QVariant Settings::getValue(const QString &type,
31 | const QVariant &fallback)
32 | {
33 | QSettings settings(PK, PK);
34 | return settings.value(type, fallback);
35 | }
36 |
37 | bool Settings::isValid(const QString &type)
38 | {
39 | QSettings settings(PK, PK);
40 | return settings.value(type).isValid();
41 | }
42 |
43 | void Settings::saveDefault()
44 | {
45 | setValue(CONF_LID_BATTERY_ACTION,
46 | POWERKIT_LID_BATTERY_ACTION);
47 | setValue(CONF_LID_AC_ACTION,
48 | POWERKIT_LID_AC_ACTION);
49 | setValue(CONF_CRITICAL_BATTERY_ACTION,
50 | POWERKIT_CRITICAL_ACTION);
51 | setValue(CONF_CRITICAL_BATTERY_TIMEOUT,
52 | POWERKIT_CRITICAL_BATTERY);
53 | setValue(CONF_SUSPEND_BATTERY_TIMEOUT,
54 | POWERKIT_AUTO_SLEEP_BATTERY);
55 | setValue(CONF_TRAY_NOTIFY,
56 | true);
57 | setValue(CONF_TRAY_SHOW,
58 | true);
59 | setValue(CONF_LID_DISABLE_IF_EXTERNAL,
60 | false);
61 | setValue(CONF_SUSPEND_BATTERY_ACTION,
62 | suspendSleep);
63 | setValue(CONF_SUSPEND_AC_ACTION,
64 | suspendNone);
65 | setValue(CONF_BACKLIGHT_BATTERY_ENABLE,
66 | false);
67 | setValue(CONF_BACKLIGHT_AC_ENABLE,
68 | false);
69 | setValue(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER,
70 | false);
71 | setValue(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER,
72 | false);
73 | setValue(CONF_WARN_ON_LOW_BATTERY,
74 | true);
75 | setValue(CONF_WARN_ON_VERYLOW_BATTERY,
76 | true);
77 | setValue(CONF_NOTIFY_ON_BATTERY,
78 | true);
79 | setValue(CONF_NOTIFY_ON_AC,
80 | true);
81 | setValue(CONF_BACKLIGHT_MOUSE_WHEEL,
82 | true);
83 | setValue(CONF_SUSPEND_LOCK_SCREEN,
84 | true);
85 | setValue(CONF_RESUME_LOCK_SCREEN,
86 | false);
87 | }
88 |
89 | const QString Settings::getConf()
90 | {
91 | QString config = QString("%1/.config/powerkit/powerkit.conf")
92 | .arg(QDir::homePath());
93 | if (!QFile::exists(config)) { saveDefault(); }
94 | return config;
95 | }
96 |
97 | const QString Settings::getDir()
98 | {
99 | QString config = QString("%1/.config/powerkit").arg(QDir::homePath());
100 | if (!QFile::exists(config)) {
101 | QDir dir(config);
102 | dir.mkpath(config);
103 | }
104 | return config;
105 | }
106 |
--------------------------------------------------------------------------------
/src/powerkit_backlight.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_backlight.h"
10 | #include "powerkit_common.h"
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #define LOGIND_SESSION "org.freedesktop.login1.Session"
20 | #define LOGIND_PATH_SESSION "/org/freedesktop/login1/session/self"
21 |
22 | using namespace PowerKit;
23 |
24 | const QString Backlight::getDevice()
25 | {
26 | QString path = "/sys/class/backlight";
27 | QDirIterator it(path, QDirIterator::Subdirectories);
28 | while (it.hasNext()) {
29 | QString foundDir = it.next();
30 | if (foundDir.startsWith(QString("%1/radeon").arg(path))) {
31 | return foundDir;
32 | } else if (foundDir.startsWith(QString("%1/amdgpu").arg(path))) {
33 | return foundDir;
34 | } else if (foundDir.startsWith(QString("%1/intel").arg(path))) {
35 | return foundDir;
36 | } else if (foundDir.startsWith(QString("%1/acpi").arg(path))) {
37 | return foundDir;
38 | }
39 | }
40 | return QString();
41 | }
42 |
43 | bool Backlight::canAdjustBrightness(const QString &device)
44 | {
45 | QFileInfo backlight(QString("%1/brightness").arg(device));
46 | if (backlight.isWritable()) { return true; }
47 | return false;
48 | }
49 |
50 | bool Backlight::canAdjustBrightness()
51 | {
52 | return canAdjustBrightness(getDevice());
53 | }
54 |
55 | int Backlight::getMaxBrightness(const QString &device)
56 | {
57 | int result = 0;
58 | QFile backlight(QString("%1/max_brightness").arg(device));
59 | if (backlight.open(QIODevice::ReadOnly)) {
60 | result = backlight.readAll().trimmed().toInt();
61 | backlight.close();
62 | }
63 | return result;
64 | }
65 |
66 | int Backlight::getMaxBrightness()
67 | {
68 | return getMaxBrightness(getDevice());
69 | }
70 |
71 | int Backlight::getCurrentBrightness(const QString &device)
72 | {
73 | int result = 0;
74 | QFile backlight(QString("%1/brightness").arg(device));
75 | if (backlight.open(QIODevice::ReadOnly)) {
76 | result = backlight.readAll().trimmed().toInt();
77 | backlight.close();
78 | }
79 | return result;
80 | }
81 |
82 | int Backlight::getCurrentBrightness()
83 | {
84 | return getCurrentBrightness(getDevice());
85 | }
86 |
87 | bool Backlight::setCurrentBrightness(const QString &device, int value)
88 | {
89 | if (!canAdjustBrightness(device)) { return false; }
90 | QFile backlight(QString("%1/brightness").arg(device));
91 | if (backlight.open(QIODevice::WriteOnly|QIODevice::Truncate)) {
92 | QTextStream out(&backlight);
93 | if (value<1) { value = 1; }
94 | out << QString::number(value);
95 | backlight.close();
96 | if (value == getCurrentBrightness(device)) { return true;}
97 | }
98 | return false;
99 | }
100 |
101 | bool Backlight::setCurrentBrightness(int value)
102 | {
103 | return setCurrentBrightness(getDevice(), value);
104 | }
105 |
106 | bool Backlight::setBrightness(const QString &device,
107 | int value)
108 | {
109 | QDBusInterface iface(POWERKIT_LOGIND_SERVICE,
110 | LOGIND_PATH_SESSION,
111 | LOGIND_SESSION,
112 | QDBusConnection::systemBus());
113 | if (!iface.isValid()) { return false; }
114 | QDBusMessage reply = iface.call("SetBrightness",
115 | "backlight",
116 | device.split("/").takeLast(),
117 | (quint32)value);
118 | return reply.errorMessage().isEmpty();
119 | }
120 |
121 | bool Backlight::setBrightness(int value)
122 | {
123 | return setBrightness(getDevice(), value);
124 | }
125 |
--------------------------------------------------------------------------------
/src/powerkit_dialog.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_CONFIG_H
10 | #define POWERKIT_CONFIG_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | namespace PowerKit
33 | {
34 | class Dialog : public QDialog
35 | {
36 | Q_OBJECT
37 |
38 | public:
39 | explicit Dialog(QWidget *parent = nullptr,
40 | bool quitOnClose = true);
41 | ~Dialog();
42 |
43 | private:
44 | QTimer *cpuTimer;
45 | QDBusInterface *dbus;
46 | QComboBox *lidActionBattery;
47 | QComboBox *lidActionAC;
48 | QComboBox *criticalActionBattery;
49 | QSpinBox *criticalBattery;
50 | QSpinBox *autoSleepBattery;
51 | QSpinBox *autoSleepAC;
52 | QCheckBox *showNotifications;
53 | QCheckBox *showSystemTray;
54 | QCheckBox *disableLidAction;
55 | QComboBox *autoSleepBatteryAction;
56 | QComboBox *autoSleepACAction;
57 | QString backlightDevice;
58 | QSlider *backlightSliderBattery;
59 | QSlider *backlightSliderAC;
60 | QCheckBox *backlightBatteryCheck;
61 | QCheckBox *backlightACCheck;
62 | QCheckBox *backlightBatteryLowerCheck;
63 | QCheckBox *backlightACHigherCheck;
64 | QCheckBox *warnOnLowBattery;
65 | QCheckBox *warnOnVeryLowBattery;
66 |
67 | QCheckBox *notifyOnBattery;
68 | QCheckBox *notifyOnAC;
69 | QCheckBox *notifyNewInhibitor;
70 | QLabel *lidActionACLabel;
71 | QLabel *lidActionBatteryLabel;
72 | QLabel *batteryBacklightLabel;
73 | QLabel *acBacklightLabel;
74 | QCheckBox *backlightMouseWheel;
75 |
76 | QLabel *batteryStatusLabel;
77 | QLabel *cpuFreqLabel;
78 | QLabel *cpuTempLabel;
79 |
80 | QSpinBox *screensaverBlank;
81 |
82 | bool hasCpuCoreTemp;
83 | bool hasBattery;
84 |
85 | private slots:
86 | void setupWidgets();
87 | void populateWidgets();
88 | void connectWidgets();
89 | void loadSettings();
90 | void saveSettings();
91 |
92 | void setDefaultAction(QComboBox *box, int action);
93 | void setDefaultAction(QSpinBox *box, int action);
94 | void setDefaultAction(QComboBox *box, QString value);
95 |
96 | void drawBattery();
97 | void drawCpu();
98 |
99 | void handleUpdatedDevices();
100 |
101 | void handleLidActionBattery(int index);
102 | void handleLidActionAC(int index);
103 | void handleCriticalAction(int index);
104 | void handleCriticalBattery(int value);
105 | void handleAutoSleepBattery(int value);
106 | void handleAutoSleepAC(int value);
107 | void handleShowNotifications(bool triggered);
108 | void handleShowSystemTray(bool triggered);
109 | void handleDisableLidAction(bool triggered);
110 | void handleAutoSleepBatteryAction(int index);
111 | void handleAutoSleepACAction(int index);
112 | void checkPerms();
113 | void handleBacklightBatteryCheck(bool triggered);
114 | void handleBacklightACCheck(bool triggered);
115 | void handleBacklightBatterySlider(int value);
116 | void handleBacklightACSlider(int value);
117 | void hibernateWarn();
118 | void sleepWarn();
119 | void handleBacklightBatteryCheckLower(bool triggered);
120 | void handleBacklightACCheckHigher(bool triggered);
121 | void enableBacklight(bool enabled);
122 | void handleWarnOnLowBattery(bool triggered);
123 | void handleWarnOnVeryLowBattery(bool triggered);
124 | void handleNotifyBattery(bool triggered);
125 | void handleNotifyAC(bool triggered);
126 | void handleNotifyNewInhibitor(bool triggered);
127 | void enableLid(bool enabled);
128 | void handleBacklightMouseWheel(bool triggered);
129 | void handleScreensaverBlank(int value);
130 | };
131 | }
132 |
133 | #endif // POWERKIT_CONFIG_H
134 |
--------------------------------------------------------------------------------
/src/powerkit_manager.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_MANAGER_H
10 | #define POWERKIT_MANAGER_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "powerkit_device.h"
23 |
24 | namespace PowerKit
25 | {
26 | class Manager : public QObject
27 | {
28 | Q_OBJECT
29 |
30 | public:
31 | explicit Manager(QObject *parent = 0);
32 | ~Manager();
33 | QMap getDevices();
34 |
35 | private:
36 | QMap devices;
37 | QMap ssInhibitors;
38 | QMap pmInhibitors;
39 |
40 | QDBusInterface *upower;
41 | QDBusInterface *logind;
42 |
43 | QTimer timer;
44 |
45 | bool wasDocked;
46 | bool wasLidClosed;
47 | bool wasOnBattery;
48 |
49 | QScopedPointer suspendLock;
50 | QScopedPointer lidLock;
51 |
52 | signals:
53 | void Update();
54 | void UpdatedDevices();
55 | void LidClosed();
56 | void LidOpened();
57 | void SwitchedToBattery();
58 | void SwitchedToAC();
59 | void PrepareForSuspend();
60 | void PrepareForResume();
61 | void DeviceWasRemoved(const QString &path);
62 | void DeviceWasAdded(const QString &path);
63 | void UpdatedInhibitors();
64 | void Error(const QString &message);
65 | void Warning(const QString &message);
66 |
67 | void isDockedChanged(bool isDocked);
68 | void isLidClosedChanged(bool isClosed);
69 | void isOnBatteryChanged(bool onBattery);
70 |
71 |
72 | private slots:
73 | bool canLogind(const QString &method);
74 | const QDBusMessage callLogind(const QString &method);
75 |
76 | QStringList find();
77 | void setup();
78 | void check();
79 | void scan();
80 |
81 | void deviceAdded(const QDBusObjectPath &obj);
82 | void deviceAdded(const QString &path);
83 | void deviceRemoved(const QDBusObjectPath &obj);
84 | void deviceRemoved(const QString &path);
85 | void deviceChanged();
86 | void propertiesChanged();
87 | void handleDeviceChanged(const QString &device);
88 | void handlePrepareForSuspend(bool prepare);
89 | void clearDevices();
90 | void handleNewInhibitScreenSaver(const QString &application,
91 | const QString &reason,
92 | quint32 cookie);
93 | void handleNewInhibitPowerManagement(const QString &application,
94 | const QString &reason,
95 | quint32 cookie);
96 | void handleDelInhibitScreenSaver(quint32 cookie);
97 | void handleDelInhibitPowerManagement(quint32 cookie);
98 |
99 | bool registerSuspendLock();
100 | bool registerLidLock();
101 |
102 | public slots:
103 | bool HasSuspendLock();
104 | bool HasLidLock();
105 |
106 | bool CanRestart();
107 | bool CanPowerOff();
108 | bool CanSuspend();
109 | bool CanHibernate();
110 | bool CanHybridSleep();
111 | bool CanSuspendThenHibernate();
112 |
113 | const QString Restart();
114 | const QString PowerOff();
115 | const QString Suspend();
116 | const QString Hibernate();
117 | const QString HybridSleep();
118 | const QString SuspendThenHibernate();
119 |
120 | bool IsDocked();
121 | bool LidIsPresent();
122 | bool LidIsClosed();
123 | bool OnBattery();
124 | double BatteryLeft();
125 | void LockScreen();
126 | bool HasBattery();
127 | qlonglong TimeToEmpty();
128 | qlonglong TimeToFull();
129 | void UpdateDevices();
130 | void UpdateBattery();
131 | void UpdateConfig();
132 | const QStringList GetScreenSaverInhibitors();
133 | const QStringList GetPowerManagementInhibitors();
134 | QMap GetInhibitors();
135 | void ReleaseSuspendLock();
136 | void ReleaseLidLock();
137 | };
138 | }
139 |
140 | #endif // POWERKIT_MANAGER_H
141 |
--------------------------------------------------------------------------------
/src/powerkit_device.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_device.h"
10 | #include "powerkit_common.h"
11 |
12 | #include
13 | #include
14 |
15 | #define PROP_CHANGED "PropertiesChanged"
16 | #define PROP_DEV_MODEL "Model"
17 | #define PROP_DEV_CAPACITY "Capacity"
18 | #define PROP_DEV_IS_RECHARGE "IsRechargeable"
19 | #define PROP_DEV_PRESENT "IsPresent"
20 | #define PROP_DEV_PERCENT "Percentage"
21 | #define PROP_DEV_ENERGY_FULL_DESIGN "EnergyFullDesign"
22 | #define PROP_DEV_ENERGY_FULL "EnergyFull"
23 | #define PROP_DEV_ENERGY_EMPTY "EnergyEmpty"
24 | #define PROP_DEV_ENERGY "Energy"
25 | #define PROP_DEV_ONLINE "Online"
26 | #define PROP_DEV_POWER_SUPPLY "PowerSupply"
27 | #define PROP_DEV_TIME_TO_EMPTY "TimeToEmpty"
28 | #define PROP_DEV_TIME_TO_FULL "TimeToFull"
29 | #define PROP_DEV_TYPE "Type"
30 | #define PROP_DEV_VENDOR "Vendor"
31 | #define PROP_DEV_NATIVEPATH "NativePath"
32 |
33 | #define DBUS_CHANGED "Changed"
34 | #define DBUS_DEVICE "Device"
35 |
36 | using namespace PowerKit;
37 |
38 | Device::Device(const QString block, QObject *parent)
39 | : QObject(parent)
40 | , path(block)
41 | , isRechargable(false)
42 | , isPresent(false)
43 | , percentage(0)
44 | , online(false)
45 | , hasPowerSupply(false)
46 | , isBattery(false)
47 | , isAC(false)
48 | , capacity(0)
49 | , energy(0)
50 | , energyFullDesign(0)
51 | , energyFull(0)
52 | , energyEmpty(0)
53 | , dbus(nullptr)
54 | , dbusp(nullptr)
55 | {
56 | QDBusConnection system = QDBusConnection::systemBus();
57 | dbus = new QDBusInterface(POWERKIT_UPOWER_SERVICE,
58 | path,
59 | QString("%1.%2").arg(POWERKIT_UPOWER_SERVICE, DBUS_DEVICE),
60 | system,
61 | parent);
62 | system.connect(dbus->service(),
63 | dbus->path(),
64 | QString("%1.%2").arg(POWERKIT_UPOWER_SERVICE, DBUS_DEVICE),
65 | DBUS_CHANGED,
66 | this,
67 | SLOT(updateDeviceProperties()));
68 | dbusp = new QDBusInterface(POWERKIT_UPOWER_SERVICE,
69 | path,
70 | POWERKIT_DBUS_PROPERTIES,
71 | system,
72 | parent);
73 | system.connect(dbusp->service(),
74 | dbusp->path(),
75 | POWERKIT_DBUS_PROPERTIES,
76 | PROP_CHANGED,
77 | this,
78 | SLOT(updateDeviceProperties()));
79 | if (name.isEmpty()) { name = path.split("/").takeLast(); }
80 | updateDeviceProperties();
81 | }
82 |
83 | // get device properties
84 | void Device::updateDeviceProperties()
85 | {
86 | if (!dbus->isValid()) { return; }
87 |
88 | model = dbus->property(PROP_DEV_MODEL).toString();
89 | capacity = dbus->property(PROP_DEV_CAPACITY).toDouble();
90 | isRechargable = dbus->property(PROP_DEV_IS_RECHARGE).toBool();
91 | isPresent = dbus->property(PROP_DEV_PRESENT).toBool();
92 | percentage = dbus->property(PROP_DEV_PERCENT).toDouble();
93 | energyFullDesign = dbus->property(PROP_DEV_ENERGY_FULL_DESIGN).toDouble();
94 | energyFull = dbus->property(PROP_DEV_ENERGY_FULL).toDouble();
95 | energyEmpty = dbus->property(PROP_DEV_ENERGY_EMPTY).toDouble();
96 | energy = dbus->property(PROP_DEV_ENERGY).toDouble();
97 | online = dbus->property(PROP_DEV_ONLINE).toBool();
98 | hasPowerSupply = dbus->property(PROP_DEV_POWER_SUPPLY).toBool();
99 | timeToEmpty = dbus->property(PROP_DEV_TIME_TO_EMPTY).toLongLong();
100 | timeToFull = dbus->property(PROP_DEV_TIME_TO_FULL).toLongLong();
101 | type = (DeviceType)dbus->property(PROP_DEV_TYPE).toUInt();
102 |
103 | if (type == DeviceBattery) { isBattery = true; }
104 | else {
105 | isBattery = false;
106 | if (type == DeviceLinePower) { isAC = true; }
107 | else { isAC = false; }
108 | }
109 |
110 | vendor = dbus->property(PROP_DEV_VENDOR).toString();
111 | nativePath = dbus->property(PROP_DEV_NATIVEPATH).toString();
112 |
113 | emit deviceChanged(path);
114 | }
115 |
116 | void Device::update()
117 | {
118 | updateDeviceProperties();
119 | }
120 |
121 | void Device::updateBattery()
122 | {
123 | percentage = dbus->property(PROP_DEV_PERCENT).toDouble();
124 | timeToEmpty = dbus->property(PROP_DEV_TIME_TO_EMPTY).toLongLong();
125 | timeToFull = dbus->property(PROP_DEV_TIME_TO_FULL).toLongLong();
126 | }
127 |
--------------------------------------------------------------------------------
/src/powerkit_app.h:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #ifndef POWERKIT_APP_H
10 | #define POWERKIT_APP_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "powerkit_powermanagement.h"
21 | #include "powerkit_screensaver.h"
22 | #include "powerkit_manager.h"
23 |
24 | namespace PowerKit
25 | {
26 | class TrayIcon : public QSystemTrayIcon
27 | {
28 | Q_OBJECT
29 | public:
30 | enum WheelAction {
31 | WheelUp,
32 | WheelDown
33 | };
34 | TrayIcon(QObject *parent = 0)
35 | : QSystemTrayIcon(parent), wheel_delta(0) {}
36 | TrayIcon(const QIcon &icon, QObject *parent = 0)
37 | : QSystemTrayIcon(icon, parent), wheel_delta(0) {}
38 | bool event(QEvent *event);
39 | signals:
40 | void wheel(TrayIcon::WheelAction action);
41 | private:
42 | int wheel_delta;
43 | };
44 |
45 | class App : public QObject
46 | {
47 | Q_OBJECT
48 |
49 | public:
50 | explicit App(QObject *parent = NULL);
51 | ~App();
52 |
53 | private:
54 | TrayIcon *tray;
55 | PowerKit::Manager *man;
56 | PowerKit::PowerManagement *pm;
57 | PowerKit::ScreenSaver *ss;
58 | bool wasLowBattery;
59 | bool wasVeryLowBattery;
60 | int lowBatteryValue;
61 | int critBatteryValue;
62 | bool hasService;
63 | int lidActionBattery;
64 | int lidActionAC;
65 | int criticalAction;
66 | int autoSuspendBattery;
67 | int autoSuspendAC;
68 | QTimer *timer;
69 | int timeouts;
70 | bool showNotifications;
71 | bool showTray;
72 | bool disableLidOnExternalMonitors;
73 | int autoSuspendBatteryAction;
74 | int autoSuspendACAction;
75 | QString internalMonitor;
76 | QFileSystemWatcher *watcher;
77 | bool lidXrandr;
78 | bool lidWasClosed;
79 | QString backlightDevice;
80 | bool hasBacklight;
81 | bool backlightOnBattery;
82 | bool backlightOnAC;
83 | int backlightBatteryValue;
84 | int backlightACValue;
85 | bool backlightBatteryDisableIfLower;
86 | bool backlightACDisableIfHigher;
87 | bool warnOnLowBattery;
88 | bool warnOnVeryLowBattery;
89 | bool notifyOnBattery;
90 | bool notifyOnAC;
91 | bool notifyNewInhibitor;
92 | bool backlightMouseWheel;
93 | bool ignoreKernelResume;
94 |
95 | private slots:
96 | void trayActivated(QSystemTrayIcon::ActivationReason reason);
97 | void checkDevices();
98 | void handleClosedLid();
99 | void handleOpenedLid();
100 | void handleOnBattery();
101 | void handleOnAC();
102 | void loadSettings();
103 | void registerService();
104 | void handleHasInhibitChanged(bool has_inhibit);
105 | void handleLow(double left);
106 | void handleVeryLow(double left);
107 | void handleCritical(double left);
108 | void drawBattery(double left);
109 | void updateToolTip();
110 | void updateTrayVisibility();
111 | void timeout();
112 | void resetTimer();
113 | void setInternalMonitor();
114 | bool internalMonitorIsConnected();
115 | bool externalMonitorIsConnected();
116 | void handleNewInhibitScreenSaver(const QString &application,
117 | const QString &reason,
118 | quint32 cookie);
119 | void handleNewInhibitPowerManagement(const QString &application,
120 | const QString &reason,
121 | quint32 cookie);
122 | void handleDelInhibitScreenSaver(quint32 cookie);
123 | void handleDelInhibitPowerManagement(quint32 cookie);
124 | void showMessage(const QString &title,
125 | const QString &msg,
126 | bool critical = false);
127 | void handleConfChanged(const QString &file);
128 | void disableHibernate();
129 | void disableSuspend();
130 | void handlePrepareForSuspend();
131 | void handlePrepareForResume();
132 | void switchInternalMonitor(bool toggle);
133 | void handleTrayWheel(TrayIcon::WheelAction action);
134 | void handleDeviceChanged(const QString &path);
135 | void openSettings();
136 | void handleError(const QString &message);
137 | void handleWarning(const QString &message);
138 | };
139 | }
140 |
141 | #endif // POWERKIT_APP_H
142 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # PowerKit
2 | # Copyright (c) Ole-André Rodlie All rights reserved.
3 | #
4 | # Available under the 3-clause BSD license
5 | # See the LICENSE file for full details
6 |
7 | cmake_minimum_required(VERSION 3.14.3)
8 |
9 | project(powerkit VERSION 2.0.0 LANGUAGES CXX)
10 |
11 | set(PROJECT_HOMEPAGE_URL "https://github.com/rodlie/powerkit")
12 | set(PROJECT_DESCRIPTION "Power manager for alternative X11 desktop environments and window managers")
13 |
14 | set(CMAKE_CXX_STANDARD 11)
15 | set(CMAKE_AUTOMOC ON)
16 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
17 |
18 | # set version
19 | add_definitions(-DPOWERKIT_VERSION="${PROJECT_VERSION}")
20 |
21 | # debug/release
22 | add_compile_options(-Wall -Wextra)
23 | if(CMAKE_BUILD_TYPE MATCHES "^(release|Release|RELEASE)$")
24 | add_definitions(-DQT_NO_DEBUG_OUTPUT)
25 | else()
26 | add_definitions(-DQT_MESSAGELOGCONTEXT)
27 | endif()
28 |
29 | # qt
30 | find_package(QT NAMES Qt5 COMPONENTS Core REQUIRED)
31 | find_package(
32 | Qt${QT_VERSION_MAJOR}
33 | 5.15
34 | COMPONENTS
35 | Gui
36 | Widgets
37 | DBus
38 | REQUIRED
39 | )
40 |
41 | # x11
42 | find_package(X11 REQUIRED)
43 | if(NOT X11_Xrandr_FOUND)
44 | message(FATAL_ERROR "Xrandr library not found")
45 | endif()
46 | if(NOT X11_Xss_FOUND)
47 | message(FATAL_ERROR "Xss library not found")
48 | endif()
49 |
50 | # setup adapters
51 | set(ADAPTERS)
52 |
53 | # org.freedesktop.PowerManagement.Inhibit
54 | qt_add_dbus_adaptor(
55 | ADAPTERS
56 | share/org.freedesktop.PowerManagement.Inhibit.xml
57 | ${PROJECT_NAME}_powermanagement.h
58 | PowerKit::PowerManagement
59 | InhibitAdaptor
60 | )
61 |
62 | # org.freedesktop.ScreenSaver
63 | qt_add_dbus_adaptor(
64 | ADAPTERS
65 | share/org.freedesktop.ScreenSaver.xml
66 | ${PROJECT_NAME}_screensaver.h
67 | PowerKit::ScreenSaver
68 | ScreenSaverAdaptor
69 | )
70 |
71 | # powerkit
72 | set(SOURCES
73 | src/${PROJECT_NAME}.cpp
74 | src/${PROJECT_NAME}_app.cpp
75 | src/${PROJECT_NAME}_backlight.cpp
76 | src/${PROJECT_NAME}_client.cpp
77 | src/${PROJECT_NAME}_cpu.cpp
78 | src/${PROJECT_NAME}_device.cpp
79 | src/${PROJECT_NAME}_dialog.cpp
80 | src/${PROJECT_NAME}_manager.cpp
81 | src/${PROJECT_NAME}_notify.cpp
82 | src/${PROJECT_NAME}_powermanagement.cpp
83 | src/${PROJECT_NAME}_screensaver.cpp
84 | src/${PROJECT_NAME}_settings.cpp
85 | src/${PROJECT_NAME}_theme.cpp
86 | )
87 | set(HEADERS
88 | src/${PROJECT_NAME}_app.h
89 | src/${PROJECT_NAME}_backlight.h
90 | src/${PROJECT_NAME}_client.h
91 | src/${PROJECT_NAME}_common.h
92 | src/${PROJECT_NAME}_cpu.h
93 | src/${PROJECT_NAME}_device.h
94 | src/${PROJECT_NAME}_dialog.h
95 | src/${PROJECT_NAME}_manager.h
96 | src/${PROJECT_NAME}_notify.h
97 | src/${PROJECT_NAME}_powermanagement.h
98 | src/${PROJECT_NAME}_screensaver.h
99 | src/${PROJECT_NAME}_settings.h
100 | src/${PROJECT_NAME}_theme.h
101 | )
102 | add_executable(${PROJECT_NAME}
103 | ${SOURCES}
104 | ${HEADERS}
105 | ${ADAPTERS}
106 | )
107 | target_include_directories(${PROJECT_NAME}
108 | PRIVATE
109 | src
110 | ${X11_X11_INCLUDE_PATH}
111 | ${X11_Xrandr_INCLUDE_PATH}
112 | ${X11_Xss_INCLUDE_PATH})
113 | target_link_libraries(${PROJECT_NAME}
114 | ${X11_LIBRARIES}
115 | ${X11_Xrandr_LIB}
116 | ${X11_Xss_LIB}
117 | Qt${QT_VERSION_MAJOR}::Core
118 | Qt${QT_VERSION_MAJOR}::DBus
119 | Qt${QT_VERSION_MAJOR}::Gui
120 | Qt${QT_VERSION_MAJOR}::Widgets)
121 |
122 | # desktop files
123 | configure_file(share/${PROJECT_NAME}.desktop
124 | ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.desktop
125 | @ONLY)
126 |
127 | # install
128 | include(GNUInstallDirs)
129 | install(TARGETS
130 | ${PROJECT_NAME}
131 | DESTINATION
132 | ${CMAKE_INSTALL_BINDIR})
133 | install(FILES
134 | docs/${PROJECT_NAME}.1
135 | DESTINATION
136 | ${CMAKE_INSTALL_MANDIR}/man1)
137 | install(FILES
138 | ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.desktop
139 | DESTINATION
140 | ${CMAKE_INSTALL_DATAROOTDIR}/applications)
141 | install(FILES
142 | LICENSE
143 | DESTINATION
144 | ${CMAKE_INSTALL_DOCDIR}/${PROJECT_NAME}-${PROJECT_VERSION})
145 |
146 | # package
147 | set(CPACK_SET_DESTDIR ON)
148 | set(CPACK_PACKAGE_CONTACT ${PROJECT_HOMEPAGE_URL})
149 | set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
150 | set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
151 | set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
152 | set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
153 | set(CPACK_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION})
154 | set(CPACK_PACKAGE_VENDOR ${PROJECT_NAME})
155 | set(CPACK_STRIP_FILES TRUE)
156 |
157 | set(CPACK_RPM_SPEC_MORE_DEFINE "%define _build_id_links none")
158 | set(CPACK_RPM_PACKAGE_LICENSE "BSD")
159 | set(CPACK_RPM_PACKAGE_URL ${PROJECT_HOMEPAGE_URL})
160 |
161 | set(CPACK_DEBIAN_PACKAGE_DEPENDS "xsecurelock")
162 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
163 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${PROJECT_HOMEPAGE_URL})
164 |
165 | include(CPack)
166 |
--------------------------------------------------------------------------------
/src/powerkit_theme.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_theme.h"
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "powerkit_settings.h"
21 |
22 | #define DEFAULT_THEME "Adwaita"
23 |
24 | using namespace PowerKit;
25 |
26 | void Theme::setAppTheme(bool darker)
27 | {
28 | bool native = Settings::getValue(CONF_NATIVE_THEME, false).toBool();
29 | if (native) { return; }
30 | qApp->setStyle("Fusion");
31 | QPalette palette;
32 | palette.setColor(QPalette::Window, QColor(40, 40, 47));
33 | palette.setColor(QPalette::WindowText, Qt::white);
34 | palette.setColor(QPalette::Base, QColor(33, 33, 38));
35 | palette.setColor(QPalette::AlternateBase, QColor(40, 40, 47));
36 | palette.setColor(QPalette::Link, Qt::white);
37 | palette.setColor(QPalette::LinkVisited, Qt::white);
38 | palette.setColor(QPalette::ToolTipText, Qt::white);
39 | palette.setColor(QPalette::ToolTipBase, Qt::black);
40 | palette.setColor(QPalette::Text, Qt::white);
41 | palette.setColor(QPalette::Button, QColor(33, 33, 38));
42 | palette.setColor(QPalette::ButtonText, Qt::white);
43 | palette.setColor(QPalette::BrightText, Qt::red);
44 | palette.setColor(QPalette::Highlight, QColor(177, 16, 20));
45 | palette.setColor(QPalette::HighlightedText, Qt::white);
46 | palette.setColor(QPalette::Disabled, QPalette::Text, Qt::darkGray);
47 | palette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::darkGray);
48 | if (darker) {
49 | palette.setColor(QPalette::Window, QColor(33, 33, 38));
50 | palette.setColor(QPalette::Base, QColor(33, 33, 38));
51 | palette.setColor(QPalette::Button, QColor(33, 33, 38));
52 | }
53 | qApp->setPalette(palette);
54 | }
55 |
56 | void Theme::setIconTheme()
57 | {
58 | // setup icon theme search path
59 | QStringList iconsPath = QIcon::themeSearchPaths();
60 | QString iconsHomeLocal = QString("%1/.local/share/icons").arg(QDir::homePath());
61 | QString iconsHome = QString("%1/.icons").arg(QDir::homePath());
62 | if (QFile::exists(iconsHomeLocal) &&
63 | !iconsPath.contains(iconsHomeLocal)) { iconsPath.prepend(iconsHomeLocal); }
64 | if (QFile::exists(iconsHome) &&
65 | !iconsPath.contains(iconsHome)) { iconsPath.prepend(iconsHome); }
66 | iconsPath << QString("%1/../share/icons").arg(qApp->applicationDirPath());
67 | QIcon::setThemeSearchPaths(iconsPath);
68 | qDebug() << "using icon theme search path" << QIcon::themeSearchPaths();
69 |
70 | QString theme = QIcon::themeName();
71 | if (theme.isEmpty() || theme == "hicolor") { // try to load saved theme
72 | theme = Settings::getValue(CONF_ICON_THEME).toString();
73 | }
74 | if(theme.isEmpty() || theme == "hicolor") { // Nope, then scan for first available
75 | // gtk
76 | if(QFile::exists(QDir::homePath() + "/" + ".gtkrc-2.0")) {
77 | QSettings gtkFile(QDir::homePath() + "/.gtkrc-2.0", QSettings::IniFormat);
78 | theme = gtkFile.value("gtk-icon-theme-name").toString().remove("\"");
79 | } else {
80 | QSettings gtkFile(QDir::homePath() + "/.config/gtk-3.0/settings.ini", QSettings::IniFormat);
81 | theme = gtkFile.value("gtk-fallback-icon-theme").toString().remove("\"");
82 | }
83 | // fallback
84 | if(theme.isNull()) { theme = DEFAULT_THEME; }
85 | if (!theme.isEmpty()) { Settings::setValue(CONF_ICON_THEME, theme); }
86 | }
87 | qDebug() << "Using icon theme" << theme;
88 | QIcon::setThemeName(theme);
89 | }
90 |
91 | const QPixmap Theme::drawCircleProgress(const int &progress,
92 | const int &dimension,
93 | const int &width,
94 | const int &padding,
95 | const bool dash,
96 | const QString &text,
97 | const QColor &color1,
98 | const QColor &color2,
99 | const QColor &color3)
100 | {
101 | double value = (double)progress / 100;
102 | if (value < 0.) { value = 0.; }
103 | else if (value > 1.) { value = 1.; }
104 |
105 | QRectF circle(padding / 2,
106 | padding / 2,
107 | dimension - padding,
108 | dimension - padding);
109 |
110 | int startAngle = -90 * 16;
111 | int spanAngle = value * 360 * 16;
112 |
113 | QPixmap pix(dimension, dimension);
114 | pix.fill(Qt::transparent);
115 |
116 | QPainter p(&pix);
117 | p.setRenderHint(QPainter::Antialiasing);
118 |
119 | QPen pen;
120 | pen.setWidth(width);
121 | pen.setCapStyle(Qt::FlatCap);
122 | pen.setColor(color1);
123 | if (dash) { pen.setStyle(Qt::DashLine); }
124 |
125 | QPen pen2;
126 | pen2.setWidth(width);
127 | pen2.setColor(color2);
128 | pen2.setCapStyle(Qt::FlatCap);
129 |
130 | QPen pen3;
131 | pen3.setColor(color3);
132 |
133 | p.setPen(pen);
134 | p.drawArc(circle, startAngle, 360 * 16);
135 |
136 | p.setPen(pen2);
137 | p.drawArc(circle, startAngle, spanAngle);
138 |
139 | if (!text.isEmpty()) {
140 | p.setPen(pen3);
141 | int textPadding = padding * 4;
142 | p.drawText(QRectF(textPadding / 2,
143 | textPadding / 2,
144 | dimension - textPadding,
145 | dimension - textPadding),
146 | Qt::AlignCenter,
147 | text);
148 | }
149 |
150 | return pix;
151 | }
152 |
--------------------------------------------------------------------------------
/src/powerkit_client.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_client.h"
10 | #include
11 |
12 | using namespace PowerKit;
13 |
14 | double Client::getBatteryLeft(QDBusInterface *iface)
15 | {
16 | if (!iface) { return -1; }
17 | qDebug() << "check for battery left";
18 | if (!iface->isValid()) { return false; }
19 | QDBusMessage reply = iface->call("BatteryLeft");
20 | const auto args = reply.arguments();
21 | double ok = args.last().toDouble();
22 | qDebug() << "we have battery left" << ok;
23 | return ok;
24 | }
25 |
26 | bool Client::hasBattery(QDBusInterface *iface)
27 | {
28 | if (!iface) { return false; }
29 | qDebug() << "check if we have any battery";
30 | if (!iface->isValid()) { return false; }
31 | QDBusMessage reply = iface->call("HasBattery");
32 | const auto args = reply.arguments();
33 | bool ok = args.last().toBool();
34 | qDebug() << "we have any battery?" << ok;
35 | return ok;
36 | }
37 |
38 | bool Client::onBattery(QDBusInterface *iface)
39 | {
40 | if (!iface) { return false; }
41 | qDebug() << "check if we are on battery";
42 | if (!iface->isValid()) { return false; }
43 | QDBusMessage reply = iface->call("OnBattery");
44 | const auto args = reply.arguments();
45 | bool ok = args.last().toBool();
46 | qDebug() << "we are on battery?" << ok;
47 | return ok;
48 | }
49 |
50 | qlonglong Client::timeToEmpty(QDBusInterface *iface)
51 | {
52 | if (!iface) { return -1; }
53 | qDebug() << "check for time to empty";
54 | if (!iface->isValid()) { return false; }
55 | QDBusMessage reply = iface->call("TimeToEmpty");
56 | const auto args = reply.arguments();
57 | qlonglong ok = args.last().toLongLong();
58 | qDebug() << "we have time to empty?" << ok;
59 | return ok;
60 | }
61 |
62 | qlonglong Client::timeToFull(QDBusInterface *iface)
63 | {
64 | if (!iface) { return -1; }
65 | qDebug() << "check for time to full";
66 | if (!iface->isValid()) { return false; }
67 | QDBusMessage reply = iface->call("TimeToFull");
68 | const auto args = reply.arguments();
69 | qlonglong ok = args.last().toLongLong();
70 | qDebug() << "we have time to full?" << ok;
71 | return ok;
72 | }
73 |
74 | bool Client::canHibernate(QDBusInterface *iface)
75 | {
76 | if (!iface) { return false; }
77 | qDebug() << "check if we can hibernate";
78 | if (!iface->isValid()) { return false; }
79 | QDBusMessage reply = iface->call("CanHibernate");
80 | const auto args = reply.arguments();
81 | bool ok = args.last().toBool();
82 | qDebug() << "we can hibernate?" << ok;
83 | return ok;
84 | }
85 |
86 | bool Client::canSuspend(QDBusInterface *iface)
87 | {
88 | if (!iface) { return false; }
89 | qDebug() << "check if we can suspend";
90 | if (!iface->isValid()) { return false; }
91 | QDBusMessage reply = iface->call("CanSuspend");
92 | const auto args = reply.arguments();
93 | bool ok = args.last().toBool();
94 | qDebug() << "we can suspend?" << ok;
95 | return ok;
96 | }
97 |
98 | bool Client::canRestart(QDBusInterface *iface)
99 | {
100 | if (!iface) { return false; }
101 | qDebug() << "check if we can restart";
102 | if (!iface->isValid()) { return false; }
103 | QDBusMessage reply = iface->call("CanRestart");
104 | const auto args = reply.arguments();
105 | bool ok = args.last().toBool();
106 | qDebug() << "we can restart?" << ok;
107 | return ok;
108 | }
109 |
110 | bool Client::canPowerOff(QDBusInterface *iface)
111 | {
112 | if (!iface) { return false; }
113 | qDebug() << "check if we can poweroff";
114 | if (!iface->isValid()) { return false; }
115 | QDBusMessage reply = iface->call("CanPowerOff");
116 | const auto args = reply.arguments();
117 | bool ok = args.last().toBool();
118 | qDebug() << "we can poweroff?" << ok;
119 | return ok;
120 | }
121 |
122 | bool Client::lidIsPresent(QDBusInterface *iface)
123 | {
124 | if (!iface) { return false; }
125 | qDebug() << "check if we have a lid";
126 | if (!iface->isValid()) { return false; }
127 | QDBusMessage reply = iface->call("LidIsPresent");
128 | const auto args = reply.arguments();
129 | bool ok = args.last().toBool();
130 | qDebug() << "we have a lid?" << ok;
131 | return ok;
132 | }
133 |
134 | bool Client::lockScreen(QDBusInterface *iface)
135 | {
136 | if (!iface) { return false; }
137 | if (!iface->isValid()) { return false; }
138 | const auto reply = iface->call("LockScreen");
139 | return reply.errorMessage().isEmpty();
140 | }
141 |
142 | bool Client::hibernate(QDBusInterface *iface)
143 | {
144 | if (!iface) { return false; }
145 | if (!iface->isValid()) { return false; }
146 | const auto reply = iface->call("Hibernate");
147 | return reply.errorMessage().isEmpty();
148 | }
149 |
150 | bool Client::suspend(QDBusInterface *iface)
151 | {
152 | if (!iface) { return false; }
153 | if (!iface->isValid()) { return false; }
154 | const auto reply = iface->call("Suspend");
155 | return reply.errorMessage().isEmpty();
156 | }
157 |
158 | bool Client::suspendThenHibernate(QDBusInterface *iface)
159 | {
160 | if (!iface) { return false; }
161 | if (!iface->isValid()) { return false; }
162 | const auto reply = iface->call("SuspendThenHibernate");
163 | return reply.errorMessage().isEmpty();
164 | }
165 |
166 | bool Client::restart(QDBusInterface *iface)
167 | {
168 | if (!iface) { return false; }
169 | qDebug() << "restart";
170 | if (!iface->isValid()) { return false; }
171 | QDBusMessage reply = iface->call("Restart");
172 | bool ok = reply.errorMessage().isEmpty();
173 | qDebug() << "reply" << ok;
174 | return ok;
175 | }
176 |
177 | bool Client::poweroff(QDBusInterface *iface)
178 | {
179 | if (!iface) { return false; }
180 | qDebug() << "poweroff";
181 | if (!iface->isValid()) { return false; }
182 | QDBusMessage reply = iface->call("PowerOff");
183 | bool ok = reply.errorMessage().isEmpty();
184 | qDebug() << "reply" << ok;
185 | return ok;
186 | }
187 |
--------------------------------------------------------------------------------
/src/powerkit_screensaver.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_screensaver.h"
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "powerkit_common.h"
19 | #include "powerkit_settings.h"
20 |
21 | #include
22 | #include
23 |
24 | // fix Xrandr
25 | #ifdef Bool
26 | #undef Bool
27 | #endif
28 | #ifdef Unsorted
29 | #undef Unsorted
30 | #endif
31 | //#undef CursorShape
32 | //#undef Status
33 | //#undef None
34 | //#undef KeyPress
35 | //#undef KeyRelease
36 | //#undef FocusIn
37 | //#undef FocusOut
38 | //#undef FontChange
39 | //#undef Expose
40 | //#undef FrameFeature
41 |
42 | #define PK_SCREENSAVER_TIMER 10000
43 | #define PK_SCREENSAVER_MAX_INHIBIT 18000
44 | #define PK_SCREENSAVER_ACTIVITY "SimulateUserActivity"
45 |
46 | using namespace PowerKit;
47 |
48 | ScreenSaver::ScreenSaver(QObject *parent)
49 | : QObject(parent)
50 | , blank(POWERKIT_SCREENSAVER_TIMEOUT_BLANK)
51 | {
52 | timer.setInterval(PK_SCREENSAVER_TIMER);
53 | connect(&timer, SIGNAL(timeout()),
54 | this, SLOT(timeOut()));
55 | timer.start();
56 | Update();
57 | }
58 |
59 | quint32 ScreenSaver::genCookie()
60 | {
61 | quint32 cookie = QRandomGenerator::global()->generate();
62 | while (!clients.contains(cookie)) {
63 | if (!clients.contains(cookie)) { clients[cookie] = QTime::currentTime(); }
64 | else { cookie = QRandomGenerator::global()->generate(); }
65 | }
66 | return cookie;
67 | }
68 |
69 | void ScreenSaver::checkForExpiredClients()
70 | {
71 | QMapIterator client(clients);
72 | while (client.hasNext()) {
73 | client.next();
74 | if (client.value()
75 | .secsTo(QTime::currentTime()) >= PK_SCREENSAVER_MAX_INHIBIT) {
76 | clients.remove(client.key());
77 | }
78 | }
79 | }
80 |
81 | bool ScreenSaver::canInhibit()
82 | {
83 | checkForExpiredClients();
84 | if (clients.size() > 0) { return true; }
85 | return false;
86 | }
87 |
88 | void ScreenSaver::timeOut()
89 | {
90 | if (canInhibit()) {
91 | SimulateUserActivity();
92 | return;
93 | }
94 | int idle = GetSessionIdleTime();
95 | qDebug() << "screensaver idle" << idle << blank;
96 | if (idle >= blank) { Lock(); }
97 | }
98 |
99 | void ScreenSaver::Update()
100 | {
101 | xlock = Settings::getValue(CONF_SCREENSAVER_LOCK_CMD,
102 | POWERKIT_SCREENSAVER_LOCK_CMD).toString();
103 | blank = Settings::getValue(CONF_SCREENSAVER_TIMEOUT_BLANK,
104 | POWERKIT_SCREENSAVER_TIMEOUT_BLANK).toInt();
105 | int exe1 = QProcess::execute("xset",
106 | QStringList() << "-dpms");
107 | int exe2 = QProcess::execute("xset",
108 | QStringList() << "s" << "on");
109 | int exe3 = QProcess::execute("xset",
110 | QStringList() << "s" << QString::number(blank));
111 | qDebug() << "screensaver update" << exe1 << exe2 << exe3;
112 | SimulateUserActivity();
113 | }
114 |
115 | void ScreenSaver::Lock()
116 | {
117 | if (xlock.isEmpty()) { return; }
118 | qDebug() << "screensaver lock";
119 | QProcess::startDetached(xlock, QStringList());
120 | setDisplaysOff(true);
121 | }
122 |
123 | void ScreenSaver::SimulateUserActivity()
124 | {
125 | int exe = QProcess::execute("xset",
126 | QStringList() << "s" << "reset");
127 | qDebug() << "screensaver reset" << exe;
128 | }
129 |
130 | quint32 ScreenSaver::GetSessionIdleTime()
131 | {
132 | quint32 idle = 0;
133 | Display *display = XOpenDisplay(0);
134 | if (display != 0) {
135 | XScreenSaverInfo *info = XScreenSaverAllocInfo();
136 | XScreenSaverQueryInfo(display,
137 | DefaultRootWindow(display),
138 | info);
139 | if (info) {
140 | idle = info->idle;
141 | XFree(info);
142 | }
143 | }
144 | XCloseDisplay(display);
145 | quint32 secs = idle / 1000;
146 | return secs;
147 | }
148 |
149 | quint32 ScreenSaver::Inhibit(const QString &application_name,
150 | const QString &reason_for_inhibit)
151 | {
152 | quint32 cookie = genCookie();
153 | emit newInhibit(application_name,
154 | reason_for_inhibit,
155 | cookie);
156 | timeOut();
157 | return cookie;
158 | }
159 |
160 | void ScreenSaver::UnInhibit(quint32 cookie)
161 | {
162 | if (clients.contains(cookie)) { clients.remove(cookie); }
163 | timeOut();
164 | emit removedInhibit(cookie);
165 | }
166 |
167 | const QMap ScreenSaver::GetDisplays()
168 | {
169 | QMap result;
170 | Display *dpy;
171 | if ((dpy = XOpenDisplay(nullptr)) == nullptr) { return result; }
172 | XRRScreenResources *sr;
173 | XRROutputInfo *info;
174 | sr = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
175 | if (sr) {
176 | for (int i = 0; i < sr->noutput;++i) {
177 | info = XRRGetOutputInfo(dpy, sr, sr->outputs[i]);
178 | if (info == nullptr) {
179 | XRRFreeOutputInfo(info);
180 | continue;
181 | }
182 | QString output = info->name;
183 | result[output] = (info->connection == RR_Connected);
184 | XRRFreeOutputInfo(info);
185 | }
186 | }
187 | XRRFreeScreenResources(sr);
188 | XCloseDisplay(dpy);
189 | return result;
190 | }
191 |
192 | const QString ScreenSaver::GetInternalDisplay()
193 | {
194 | QString result;
195 | Display *dpy;
196 | if ((dpy = XOpenDisplay(nullptr)) == nullptr) { return result; }
197 | XRRScreenResources *sr;
198 | sr = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
199 | if (sr) {
200 | XRROutputInfo *info = XRRGetOutputInfo(dpy, sr, sr->outputs[0]);
201 | if (info) { result = info->name; }
202 | XRRFreeOutputInfo(info);
203 | }
204 | XRRFreeScreenResources(sr);
205 | XCloseDisplay(dpy);
206 | return result;
207 | }
208 |
209 | void ScreenSaver::setDisplaysOff(bool off)
210 | {
211 | int xset = QProcess::execute("xset",
212 | QStringList() << "dpms" << "force" << (off ? "off" : "on"));
213 | if (!off) {
214 | QProcess::execute("xset",
215 | QStringList() << "s" << "reset");
216 | }
217 | qDebug() << "xset dpms force" << off << xset;
218 | }
219 |
--------------------------------------------------------------------------------
/docs/powerkit.md:
--------------------------------------------------------------------------------
1 | # NAME
2 |
3 | *powerkit* - Desktop independent power manager for Linux
4 |
5 | # SYNOPSIS
6 |
7 | powerkit *`[--config]`* *`[--set-brightness-up]`* *`[--set-brightness-down]`* *`[--sleep]`* *`[--hibernate]`* *`[--lock]`*
8 |
9 | # DESCRIPTION
10 |
11 | Desktop independent power manager for use with alternative X11 desktop environments and window managers on Linux.
12 |
13 | * Implements *``org.freedesktop.ScreenSaver``* service
14 | * Implements *``org.freedesktop.PowerManagement.Inhibit``* service
15 | * Automatic actions on lid, idle and low battery
16 | * Sleep
17 | * Hibernate
18 | * HybridSleep
19 | * Suspend then Hibernate
20 | * Shutdown
21 | * Screen saver support
22 | * Screen lid support
23 | * Screen locking support
24 | * Screen backlight support
25 | * Notification support (can use *``org.freedesktop.Notifications``* if available)
26 |
27 | # USAGE
28 |
29 | powerkit should be started during the X11 user session. Consult the documentation for your desktop environment or window manager for launching startup applications.
30 |
31 | * In *Fluxbox* add *``powerkit &``* to the *``~/.fluxbox/startup``* file
32 | * In *Openbox* add *``powerkit &``* to the *``~/.config/openbox/autostart``* file.
33 |
34 | **Do use powerkit if your desktop environment or window manager already has a power manager or screen saver service running.**
35 |
36 | ## CONFIGURATION
37 |
38 | Settings are available directly from the system tray icon or run *``powerkit --config``*. You should also be able to lauch the powerkit settings from your desktop application menu (if available).
39 |
40 | ## SCREEN SAVER
41 |
42 | powerkit implements a basic screen saver to handle screen blanking, poweroff and locking feature.
43 |
44 | Locking feature depends on ``xsecurelock``.
45 |
46 | You can override the lock command with *``screensaver_lock_cmd=``* in *`~/.config/powerkit/powerkit.conf`*. Note that the command must not contain spaces.
47 |
48 | ## BACKLIGHT
49 |
50 | The current display brightness (on laptops and supported displays) can be adjusted with the mouse wheel on the system tray icon or through the system tray menu.
51 |
52 | powerkit also supports the following commands that can be used for global shortcuts, scripts etc:
53 |
54 | *`powerkit --set-brightness-up`*
55 | : Set default display brightness up.
56 |
57 | *`powerkit --set-brightness-down`*
58 | : Set default display brightness down.
59 |
60 | On Fluxbox you can add the commands to the *`~/.fluxbox/keys`* file:
61 |
62 | ```
63 | XF86MonBrightnessUp :Exec powerkit --set-brightness-up
64 | XF86MonBrightnessDown :Exec powerkit --set-brightness-down
65 | ```
66 |
67 | ## HIBERNATE
68 |
69 | If hibernate works depends on your system, a swap partition (or file) is needed by the kernel to support hibernate.
70 |
71 | ***Consult your system documentation regarding hibernation***.
72 |
73 | ## ICONS
74 |
75 | powerkit will use the existing icon theme from the running desktop environment or window manager.
76 |
77 | You can override the icon theme in the *`~/.config/powerkit/powerkit.conf`* file, use *``icon_theme=``*.
78 |
79 | # FAQ
80 |
81 | ## How does an application inhibit the screen saver?
82 |
83 | The preferred way to inhibit the screen saver from an application is to use the *org.freedesktop.ScreenSaver* specification. Any application that uses *org.freedesktop.ScreenSaver* will work with powerkit.
84 |
85 | Popular applications that uses this feature is Mozilla Firefox, Google Chrome, VideoLAN VLC and many more.
86 |
87 | ## How does an application inhibit suspend actions?
88 |
89 | The preferred way to inhibit suspend actions from an application is to use the *org.freedesktop.PowerManagement* specification. Any application that uses *org.freedesktop.PowerManagement* will work with powerkit.
90 |
91 | Common use cases are audio playback, downloading, rendering and similar.
92 |
93 | ## Google Chrome/Chromium does not inhibit the screen saver or power manager!?
94 |
95 | Chrome does not use *org.freedesktop.ScreenSaver* or *org.freedesktop.PowerManagement* until it detects a supported desktop environment. Add the following to *``~/.bashrc``* or the *``google-chrome``* launcher if you don't run a supported desktop environment:
96 |
97 | ```
98 | export DESKTOP_SESSION=xfce
99 | export XDG_CURRENT_DESKTOP=xfce
100 | ```
101 |
102 | ## Mozilla Firefox does not inhibit the power manager during audio playback and/or downloading!?
103 |
104 | This is an issue with Firefox (missing feature). Use a different browser or open a request on the Firefox issue tracker.
105 |
106 | Firefox should inhibit the power manager during audio playback (regardless of video) and during download (active queue). Currently Firefox only inhibit the screen saver during video playback. Chrome/Chromium does this correctly.
107 |
108 | # REQUIREMENTS
109 |
110 | powerkit requires the following dependencies:
111 |
112 | * *[X11](https://www.x.org)*
113 | * *[libXss](https://www.x.org/archive//X11R7.7/doc/man/man3/Xss.3.xhtml)*
114 | * *[libXrandr](https://www.x.org/wiki/libraries/libxrandr/)*
115 | * *[Qt](https://qt.io)* 5.15 *(Core/DBus/Gui/Widgets)*
116 | * *[logind](https://www.freedesktop.org/wiki/Software/systemd/logind/)* *(or compatible service)*
117 | * *[UPower](https://upower.freedesktop.org/)* *(or compatible service)*
118 | * *[xsecurelock](https://github.com/google/xsecurelock)*
119 |
120 | # BUILD
121 |
122 | First make sure you have the required dependencies installed, then review the most common build options:
123 |
124 | * *``CMAKE_INSTALL_PREFIX=``* - Install target. *``/usr``* recommended.
125 | * *``CMAKE_BUILD_TYPE=``* - Build type. *``Release``* recommended
126 |
127 | Now configure powerkit with CMake and build:
128 |
129 | ```
130 | mkdir build && cd build
131 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release ..
132 | make -j4
133 | ```
134 |
135 | All you need is the *``powerkit``* binary located in the build directory, you can run it from any location.
136 |
137 | ## Install
138 |
139 | Use regular *``make install``* with optional *``DESTDIR``*:
140 |
141 | ```
142 | make DESTDIR= install
143 | ```
144 |
145 | or make a native package:
146 |
147 | ```
148 | cpack -G DEB
149 | ```
150 | ```
151 | cpack -G RPM
152 | ```
153 |
154 | # CHANGELOG
155 |
156 | ## 2.0.0 (TBA)
157 |
158 | * Recommended locker is ``xsecurelock``
159 | * Added support for "modern" logind
160 | * Removed support for ConsoleKit
161 | * Removed support for XScreenSaver
162 | * Added basic screen saver
163 | * Easier to use (minimal/no setup)
164 | * New UI
165 | * Major code changes
166 |
167 | # OPTIONS
168 |
169 | *``--config``*
170 | : Launch configuration.
171 |
172 | *`--set-brightness-up`*
173 | : Set default display brightness up.
174 |
175 | *`--set-brightness-down`*
176 | : Set default display brightness down.
177 |
178 | *`--sleep`*
179 | : Suspend computer now. Can be combined with *`--hibernate`* for suspend then hibernate after X amount of time.
180 |
181 | *`--hibernate`*
182 | : Hibernate computer now. Can be combined with *`--sleep`* for suspend then hibernate after X amount of time.
183 |
184 | *`--lock`*
185 | : Lock screen.
186 |
187 | # FILES
188 |
189 | *``~/.config/powerkit/powerkit.conf``*
190 | : Per user configuration file.
191 |
192 | # SEE ALSO
193 |
194 | **``xsecurelock``**(1), **``UPower``**(7), **``systemd-logind``**(8)
195 |
196 | # BUGS
197 |
198 | See **https://github.com/rodlie/powerkit/issues**.
199 |
200 | # COPYRIGHT
201 |
202 | ```
203 | Copyright (c) Ole-André Rodlie
204 | All rights reserved.
205 |
206 | Redistribution and use in source and binary forms, with or without
207 | modification, are permitted provided that the following conditions are met:
208 |
209 | * Redistributions of source code must retain the above copyright notice, this
210 | list of conditions and the following disclaimer.
211 |
212 | * Redistributions in binary form must reproduce the above copyright notice,
213 | this list of conditions and the following disclaimer in the documentation
214 | and/or other materials provided with the distribution.
215 |
216 | * Neither the name of the copyright holder nor the names of its
217 | contributors may be used to endorse or promote products derived from
218 | this software without specific prior written permission.
219 |
220 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
221 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
222 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
223 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
224 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
225 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
226 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
227 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
228 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
229 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
230 | ```
231 |
--------------------------------------------------------------------------------
/docs/powerkit.1:
--------------------------------------------------------------------------------
1 | .\" Automatically generated by Pandoc 3.1.8
2 | .\"
3 | .TH "POWERKIT" "1" "February 2024" "Version 2.0.0" "PowerKit Documentation"
4 | .SH NAME
5 | \f[I]powerkit\f[R] - Desktop independent power manager for Linux
6 | .SH SYNOPSIS
7 | powerkit \f[I]\f[CI][--config]\f[I]\f[R]
8 | \f[I]\f[CI][--set-brightness-up]\f[I]\f[R]
9 | \f[I]\f[CI][--set-brightness-down]\f[I]\f[R]
10 | \f[I]\f[CI][--sleep]\f[I]\f[R] \f[I]\f[CI][--hibernate]\f[I]\f[R]
11 | \f[I]\f[CI][--lock]\f[I]\f[R]
12 | .SH DESCRIPTION
13 | Desktop independent power manager for use with alternative X11 desktop
14 | environments and window managers on Linux.
15 | .IP \[bu] 2
16 | Implements \f[I]\f[CI]org.freedesktop.ScreenSaver\f[I]\f[R] service
17 | .IP \[bu] 2
18 | Implements \f[I]\f[CI]org.freedesktop.PowerManagement.Inhibit\f[I]\f[R]
19 | service
20 | .IP \[bu] 2
21 | Automatic actions on lid, idle and low battery
22 | .RS 2
23 | .IP \[bu] 2
24 | Sleep
25 | .IP \[bu] 2
26 | Hibernate
27 | .IP \[bu] 2
28 | HybridSleep
29 | .IP \[bu] 2
30 | Suspend then Hibernate
31 | .IP \[bu] 2
32 | Shutdown
33 | .RE
34 | .IP \[bu] 2
35 | Screen saver support
36 | .IP \[bu] 2
37 | Screen lid support
38 | .IP \[bu] 2
39 | Screen locking support
40 | .IP \[bu] 2
41 | Screen backlight support
42 | .IP \[bu] 2
43 | Notification support (can use
44 | \f[I]\f[CI]org.freedesktop.Notifications\f[I]\f[R] if available)
45 | .SH USAGE
46 | powerkit should be started during the X11 user session.
47 | Consult the documentation for your desktop environment or window manager
48 | for launching startup applications.
49 | .IP \[bu] 2
50 | In \f[I]Fluxbox\f[R] add \f[I]\f[CI]powerkit &\f[I]\f[R] to the
51 | \f[I]\f[CI]\[ti]/.fluxbox/startup\f[I]\f[R] file
52 | .IP \[bu] 2
53 | In \f[I]Openbox\f[R] add \f[I]\f[CI]powerkit &\f[I]\f[R] to the
54 | \f[I]\f[CI]\[ti]/.config/openbox/autostart\f[I]\f[R] file.
55 | .PP
56 | \f[B]Do use powerkit if your desktop environment or window manager
57 | already has a power manager or screen saver service running.\f[R]
58 | .SS CONFIGURATION
59 | Settings are available directly from the system tray icon or run
60 | \f[I]\f[CI]powerkit --config\f[I]\f[R].
61 | You should also be able to lauch the powerkit settings from your desktop
62 | application menu (if available).
63 | .SS SCREEN SAVER
64 | powerkit implements a basic screen saver to handle screen blanking,
65 | poweroff and locking feature.
66 | .PP
67 | Locking feature depends on \f[CR]xsecurelock\f[R].
68 | .PP
69 | You can override the lock command with
70 | \f[I]\f[CI]screensaver_lock_cmd=\f[I]\f[R] in
71 | \f[I]\f[CI]\[ti]/.config/powerkit/powerkit.conf\f[I]\f[R].
72 | Note that the command must not contain spaces.
73 | .SS BACKLIGHT
74 | The current display brightness (on laptops and supported displays) can
75 | be adjusted with the mouse wheel on the system tray icon or through the
76 | system tray menu.
77 | .PP
78 | powerkit also supports the following commands that can be used for
79 | global shortcuts, scripts etc:
80 | .TP
81 | \f[I]\f[CI]powerkit --set-brightness-up\f[I]\f[R]
82 | Set default display brightness up.
83 | .TP
84 | \f[I]\f[CI]powerkit --set-brightness-down\f[I]\f[R]
85 | Set default display brightness down.
86 | .PP
87 | On Fluxbox you can add the commands to the
88 | \f[I]\f[CI]\[ti]/.fluxbox/keys\f[I]\f[R] file:
89 | .IP
90 | .EX
91 | XF86MonBrightnessUp :Exec powerkit --set-brightness-up
92 | XF86MonBrightnessDown :Exec powerkit --set-brightness-down
93 | .EE
94 | .SS HIBERNATE
95 | If hibernate works depends on your system, a swap partition (or file) is
96 | needed by the kernel to support hibernate.
97 | .PP
98 | \f[B]\f[BI]Consult your system documentation regarding
99 | hibernation\f[B]\f[R].
100 | .SS ICONS
101 | powerkit will use the existing icon theme from the running desktop
102 | environment or window manager.
103 | .PP
104 | You can override the icon theme in the
105 | \f[I]\f[CI]\[ti]/.config/powerkit/powerkit.conf\f[I]\f[R] file, use
106 | \f[I]\f[CI]icon_theme=\f[I]\f[R].
107 | .SH FAQ
108 | .SS How does an application inhibit the screen saver?
109 | The preferred way to inhibit the screen saver from an application is to
110 | use the \f[I]org.freedesktop.ScreenSaver\f[R] specification.
111 | Any application that uses \f[I]org.freedesktop.ScreenSaver\f[R] will
112 | work with powerkit.
113 | .PP
114 | Popular applications that uses this feature is Mozilla Firefox, Google
115 | Chrome, VideoLAN VLC and many more.
116 | .SS How does an application inhibit suspend actions?
117 | The preferred way to inhibit suspend actions from an application is to
118 | use the \f[I]org.freedesktop.PowerManagement\f[R] specification.
119 | Any application that uses \f[I]org.freedesktop.PowerManagement\f[R] will
120 | work with powerkit.
121 | .PP
122 | Common use cases are audio playback, downloading, rendering and similar.
123 | .SS Google Chrome/Chromium does not inhibit the screen saver or power manager!?
124 | Chrome does not use \f[I]org.freedesktop.ScreenSaver\f[R] or
125 | \f[I]org.freedesktop.PowerManagement\f[R] until it detects a supported
126 | desktop environment.
127 | Add the following to \f[I]\f[CI]\[ti]/.bashrc\f[I]\f[R] or the
128 | \f[I]\f[CI]google-chrome\f[I]\f[R] launcher if you don\[cq]t run a
129 | supported desktop environment:
130 | .IP
131 | .EX
132 | export DESKTOP_SESSION=xfce
133 | export XDG_CURRENT_DESKTOP=xfce
134 | .EE
135 | .SS Mozilla Firefox does not inhibit the power manager during audio playback and/or downloading!?
136 | This is an issue with Firefox (missing feature).
137 | Use a different browser or open a request on the Firefox issue tracker.
138 | .PP
139 | Firefox should inhibit the power manager during audio playback
140 | (regardless of video) and during download (active queue).
141 | Currently Firefox only inhibit the screen saver during video playback.
142 | Chrome/Chromium does this correctly.
143 | .SH REQUIREMENTS
144 | powerkit requires the following dependencies:
145 | .IP \[bu] 2
146 | \f[I]X11 (https://www.x.org)\f[R]
147 | .IP \[bu] 2
148 | \f[I]libXss (https://www.x.org/archive//X11R7.7/doc/man/man3/Xss.3.xhtml)\f[R]
149 | .IP \[bu] 2
150 | \f[I]libXrandr (https://www.x.org/wiki/libraries/libxrandr/)\f[R]
151 | .IP \[bu] 2
152 | \f[I]Qt (https://qt.io)\f[R] 5.15 \f[I](Core/DBus/Gui/Widgets)\f[R]
153 | .IP \[bu] 2
154 | \f[I]logind (https://www.freedesktop.org/wiki/Software/systemd/logind/)\f[R]
155 | \f[I](or compatible service)\f[R]
156 | .IP \[bu] 2
157 | \f[I]UPower (https://upower.freedesktop.org/)\f[R] \f[I](or compatible
158 | service)\f[R]
159 | .IP \[bu] 2
160 | \f[I]xsecurelock (https://github.com/google/xsecurelock)\f[R]
161 | .SH BUILD
162 | First make sure you have the required dependencies installed, then
163 | review the most common build options:
164 | .IP \[bu] 2
165 | \f[I]\f[CI]CMAKE_INSTALL_PREFIX=\f[I]\f[R] - Install target.
166 | \f[I]\f[CI]/usr\f[I]\f[R] recommended.
167 | .IP \[bu] 2
168 | \f[I]\f[CI]CMAKE_BUILD_TYPE=\f[I]\f[R] - Build type.
169 | \f[I]\f[CI]Release\f[I]\f[R] recommended
170 | .PP
171 | Now configure powerkit with CMake and build:
172 | .IP
173 | .EX
174 | mkdir build && cd build
175 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release ..
176 | make -j4
177 | .EE
178 | .PP
179 | All you need is the \f[I]\f[CI]powerkit\f[I]\f[R] binary located in the
180 | build directory, you can run it from any location.
181 | .SS Install
182 | Use regular \f[I]\f[CI]make install\f[I]\f[R] with optional
183 | \f[I]\f[CI]DESTDIR\f[I]\f[R]:
184 | .IP
185 | .EX
186 | make DESTDIR= install
187 | .EE
188 | .PP
189 | or make a native package:
190 | .IP
191 | .EX
192 | cpack -G DEB
193 | .EE
194 | .IP
195 | .EX
196 | cpack -G RPM
197 | .EE
198 | .SH CHANGELOG
199 | .SS 2.0.0 (TBA)
200 | .IP \[bu] 2
201 | Recommended locker is \f[CR]xsecurelock\f[R]
202 | .IP \[bu] 2
203 | Added support for \[lq]modern\[rq] logind
204 | .IP \[bu] 2
205 | Removed support for ConsoleKit
206 | .IP \[bu] 2
207 | Removed support for XScreenSaver
208 | .IP \[bu] 2
209 | Added basic screen saver
210 | .IP \[bu] 2
211 | Easier to use (minimal/no setup)
212 | .IP \[bu] 2
213 | New UI
214 | .IP \[bu] 2
215 | Major code changes
216 | .SH OPTIONS
217 | .TP
218 | \f[I]\f[CI]--config\f[I]\f[R]
219 | Launch configuration.
220 | .TP
221 | \f[I]\f[CI]--set-brightness-up\f[I]\f[R]
222 | Set default display brightness up.
223 | .TP
224 | \f[I]\f[CI]--set-brightness-down\f[I]\f[R]
225 | Set default display brightness down.
226 | .TP
227 | \f[I]\f[CI]--sleep\f[I]\f[R]
228 | Suspend computer now.
229 | Can be combined with \f[I]\f[CI]--hibernate\f[I]\f[R] for suspend then
230 | hibernate after X amount of time.
231 | .TP
232 | \f[I]\f[CI]--hibernate\f[I]\f[R]
233 | Hibernate computer now.
234 | Can be combined with \f[I]\f[CI]--sleep\f[I]\f[R] for suspend then
235 | hibernate after X amount of time.
236 | .TP
237 | \f[I]\f[CI]--lock\f[I]\f[R]
238 | Lock screen.
239 | .SH FILES
240 | .TP
241 | \f[I]\f[CI]\[ti]/.config/powerkit/powerkit.conf\f[I]\f[R]
242 | Per user configuration file.
243 | .SH SEE ALSO
244 | \f[B]\f[CB]xsecurelock\f[B]\f[R](1), \f[B]\f[CB]UPower\f[B]\f[R](7),
245 | \f[B]\f[CB]systemd-logind\f[B]\f[R](8)
246 | .SH BUGS
247 | See \f[B]https://github.com/rodlie/powerkit/issues\f[R].
248 | .SH COPYRIGHT
249 | .IP
250 | .EX
251 | Copyright (c) Ole-André Rodlie
252 | All rights reserved.
253 |
254 | Redistribution and use in source and binary forms, with or without
255 | modification, are permitted provided that the following conditions are met:
256 |
257 | * Redistributions of source code must retain the above copyright notice, this
258 | list of conditions and the following disclaimer.
259 |
260 | * Redistributions in binary form must reproduce the above copyright notice,
261 | this list of conditions and the following disclaimer in the documentation
262 | and/or other materials provided with the distribution.
263 |
264 | * Neither the name of the copyright holder nor the names of its
265 | contributors may be used to endorse or promote products derived from
266 | this software without specific prior written permission.
267 |
268 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \[dq]AS IS\[dq]
269 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
270 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
271 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
272 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
273 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
274 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
275 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
276 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
277 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278 | .EE
279 | .SH AUTHORS
280 | Ole-André Rodlie.
281 |
--------------------------------------------------------------------------------
/src/powerkit_cpu.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_cpu.h"
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | #define LINUX_CPU_SYS "/sys/devices/system/cpu"
16 | #define LINUX_CPU_DIR "cpufreq"
17 | #define LINUX_CPU_FREQUENCIES "scaling_available_frequencies"
18 | #define LINUX_CPU_FREQUENCY "scaling_cur_freq"
19 | #define LINUX_CPU_FREQUENCY_MAX "scaling_max_freq"
20 | #define LINUX_CPU_FREQUENCY_MIN "scaling_min_freq"
21 | #define LINUX_CPU_GOVERNORS "scaling_available_governors"
22 | #define LINUX_CPU_GOVERNOR "scaling_governor"
23 | #define LINUX_CPU_SET_SPEED "scaling_setspeed"
24 | #define LINUX_CPU_PSTATE "intel_pstate"
25 | #define LINUX_CPU_PSTATE_STATUS "status"
26 | #define LINUX_CPU_PSTATE_NOTURBO "no_turbo"
27 | #define LINUX_CPU_PSTATE_MAX_PERF "max_perf_pct"
28 | #define LINUX_CPU_PSTATE_MIN_PERF "min_perf_pct"
29 |
30 | #define LINUX_CORETEMP "/sys/class/hwmon/hwmon%1"
31 | #define LINUX_CORETEMP_CRIT "temp%1_crit"
32 | #define LINUX_CORETEMP_INPUT "temp%1_input"
33 | #define LINUX_CORETEMP_LABEL "temp%1_label"
34 | #define LINUX_CORETEMP_MAX "temp%1_max"
35 |
36 | #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
37 | #define QT_SKIP_EMPTY Qt::SkipEmptyParts
38 | #else
39 | #define QT_SKIP_EMPTY QString::SkipEmptyParts
40 | #endif
41 |
42 | using namespace PowerKit;
43 |
44 | int Cpu::getTotal()
45 | {
46 | int counter = 0;
47 | while(1) {
48 | if (QFile::exists(QString("%1/cpu%2")
49 | .arg(LINUX_CPU_SYS)
50 | .arg(counter))) { counter++; }
51 | else { break; }
52 | }
53 | if (counter>0) { return counter; }
54 | return -1;
55 | }
56 |
57 | const QString Cpu::getGovernor(int cpu)
58 | {
59 | QString result;
60 | QFile gov(QString("%1/cpu%2/%3/%4")
61 | .arg(LINUX_CPU_SYS)
62 | .arg(cpu)
63 | .arg(LINUX_CPU_DIR)
64 | .arg(LINUX_CPU_GOVERNOR));
65 | if (!gov.exists()) { return result; }
66 | if (gov.open(QIODevice::ReadOnly|QIODevice::Text)) {
67 | result = gov.readAll().trimmed();
68 | gov.close();
69 | }
70 | return result;
71 | }
72 |
73 | const QStringList Cpu::getGovernors()
74 | {
75 | QStringList result;
76 | for (int i=0;i freqMax) { val = QString::number(freqMax); }
229 | else if (freq.toInt() < freqMin) { val = QString::number(freqMin); }
230 | QFile file(QString("%1/cpu%2/%3/%4").arg(LINUX_CPU_SYS,
231 | QString::number(cpu),
232 | LINUX_CPU_DIR,
233 | LINUX_CPU_SET_SPEED));
234 | if (file.open(QIODevice::WriteOnly|QIODevice::Truncate)) {
235 | QTextStream out(&file);
236 | out << val;
237 | file.close();
238 | if (val == getFrequency(cpu)) { return true; }
239 | }
240 | return false;
241 | }
242 |
243 | bool Cpu::setFrequency(const QString &freq)
244 | {
245 | if (hasPState()) { return false; }
246 | if (!frequencyExists(freq)) { return false; }
247 | bool failed = false;
248 | for (int i=0;i Cpu::getCoreTemp()
373 | {
374 | QPair temp = {0.0, 0.0};
375 | if (!hasCoreTemp()) { return temp; }
376 |
377 | int temps = 1;
378 | int hwmons = 10;
379 | for (int hwmon = 0; hwmon < hwmons; ++hwmon) {
380 | bool foundPackage = false;
381 | QFile file(QString("%1/%2").arg(QString(LINUX_CORETEMP).arg(hwmon),
382 | QString(LINUX_CORETEMP_LABEL).arg(temps)));
383 | if (file.open(QIODevice::ReadOnly|QIODevice::Text)) {
384 | QString label = file.readAll().trimmed();
385 | if (label.startsWith("Package")) { foundPackage = true; }
386 | file.close();
387 | }
388 | if (foundPackage) {
389 | QFile fileInput(QString("%1/%2").arg(QString(LINUX_CORETEMP).arg(hwmon),
390 | QString(LINUX_CORETEMP_INPUT).arg(temps)));
391 | if (fileInput.open(QIODevice::ReadOnly|QIODevice::Text)) {
392 | double ctemp = fileInput.readAll().trimmed().toDouble();
393 | file.close();
394 | if (ctemp > temp.first) {
395 | temp.first = ctemp;
396 | }
397 | }
398 | QFile fileMax(QString("%1/%2").arg(QString(LINUX_CORETEMP).arg(hwmon),
399 | QString(LINUX_CORETEMP_MAX).arg(temps)));
400 | if (fileMax.open(QIODevice::ReadOnly|QIODevice::Text)) {
401 | double mtemp = fileMax.readAll().trimmed().toDouble();
402 | file.close();
403 | if (mtemp > temp.second) {
404 | temp.second = mtemp;
405 | }
406 | }
407 | if (temp.first > 0.0 && temp.second > 0.0) { break; }
408 | }
409 | }
410 | return temp;
411 | }
412 |
413 | const QPair Cpu::getCpuFreqLabel()
414 | {
415 | QStringList freqs = getFrequencies();
416 | int currentCpuFreq = 0;
417 | double currentFancyFreq = 0.;
418 | for (int i=0; i < freqs.size(); ++i) {
419 | auto freq = freqs.at(i).toLong();
420 | if (freq > currentCpuFreq) {
421 | currentCpuFreq = freq;
422 | currentFancyFreq = freqs.at(i).toDouble();
423 | }
424 | }
425 |
426 | QPair result;
427 |
428 | int freqMin = Cpu::getMinFrequency();
429 | int freqMax = Cpu::getMaxFrequency();
430 | int progress;
431 | if (freqMax == freqMin) {
432 | progress = 100;
433 | } else {
434 | progress = ((currentCpuFreq - freqMin) * 100) / (freqMax - freqMin);
435 | }
436 |
437 | result.first = progress;
438 | result.second = QString("%1\nGhz").arg(QString::number(currentFancyFreq / 1000000, 'f', 2));
439 | return result;
440 | }
441 |
442 | const QPair Cpu::getCpuTempLabel()
443 | {
444 | QPair result;
445 | const auto temps = getCoreTemp();
446 | int progress = (temps.first * 100) / temps.second;
447 |
448 | result.first = progress;
449 | result.second = QString("%1°C").arg(QString::number(temps.first / 1000, 'f', 0));
450 | return result;
451 | }
452 |
--------------------------------------------------------------------------------
/src/powerkit_manager.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_manager.h"
10 | #include "powerkit_common.h"
11 | #include "powerkit_settings.h"
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #define LOGIND_PATH "/org/freedesktop/login1"
23 | #define LOGIND_MANAGER "org.freedesktop.login1.Manager"
24 | #define LOGIND_DOCKED "Docked"
25 |
26 | #define UPOWER_PATH "/org/freedesktop/UPower"
27 | #define UPOWER_MANAGER "org.freedesktop.UPower"
28 | #define UPOWER_DEVICES "/org/freedesktop/UPower/devices/"
29 | #define UPOWER_DOCKED "IsDocked"
30 | #define UPOWER_LID_IS_PRESENT "LidIsPresent"
31 | #define UPOWER_LID_IS_CLOSED "LidIsClosed"
32 | #define UPOWER_ON_BATTERY "OnBattery"
33 | #define UPOWER_NOTIFY_RESUME "NotifyResume"
34 | #define UPOWER_NOTIFY_SLEEP "NotifySleep"
35 |
36 | #define DBUS_OK_REPLY "yes"
37 | #define DBUS_FAILED_CONN "Failed D-Bus connection."
38 | #define DBUS_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager"
39 |
40 | #define DBUS_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
41 | #define DBUS_JOBS "%1/jobs"
42 | #define DBUS_DEVICE_ADDED "DeviceAdded"
43 | #define DBUS_DEVICE_REMOVED "DeviceRemoved"
44 | #define DBUS_DEVICE_CHANGED "DeviceChanged"
45 | #define DBUS_PROPERTIES_CHANGED "PropertiesChanged"
46 |
47 | #define PK_PREPARE_FOR_SUSPEND "PrepareForSuspend"
48 | #define PK_PREPARE_FOR_SLEEP "PrepareForSleep"
49 | #define PK_CAN_RESTART "CanReboot"
50 | #define PK_RESTART "Reboot"
51 | #define PK_CAN_POWEROFF "CanPowerOff"
52 | #define PK_POWEROFF "PowerOff"
53 | #define PK_CAN_SUSPEND "CanSuspend"
54 | #define PK_SUSPEND_ALLOWED "SuspendAllowed"
55 | #define PK_SUSPEND "Suspend"
56 | #define PK_CAN_HIBERNATE "CanHibernate"
57 | #define PK_HIBERNATE_ALLOWED "HibernateAllowed"
58 | #define PK_HIBERNATE "Hibernate"
59 | #define PK_CAN_HYBRIDSLEEP "CanHybridSleep"
60 | #define PK_HYBRIDSLEEP "HybridSleep"
61 | #define PK_CAN_SUSPEND_THEN_HIBERNATE "CanSuspendThenHibernate"
62 | #define PK_SUSPEND_THEN_HIBERNATE "SuspendThenHibernate"
63 | #define PK_NO_BACKEND "No backend available."
64 | #define PK_NO_ACTION "Action no available."
65 |
66 | #define TIMEOUT_CHECK 60000
67 |
68 | using namespace PowerKit;
69 |
70 | Manager::Manager(QObject *parent) : QObject(parent)
71 | , upower(nullptr)
72 | , logind(nullptr)
73 | , wasDocked(false)
74 | , wasLidClosed(false)
75 | , wasOnBattery(false)
76 | {
77 | setup();
78 | timer.setInterval(TIMEOUT_CHECK);
79 | connect(&timer, SIGNAL(timeout()),
80 | this, SLOT(check()));
81 | timer.start();
82 | }
83 |
84 | Manager::~Manager()
85 | {
86 | clearDevices();
87 | ReleaseSuspendLock();
88 | }
89 |
90 | QMap Manager::getDevices()
91 | {
92 | return devices;
93 | }
94 |
95 | bool Manager::canLogind(const QString &method)
96 | {
97 | if (!logind->isValid() || method.isEmpty()) { return false; }
98 | QDBusMessage reply = logind->call(method);
99 | const auto args = reply.arguments();
100 | if (args.first().toString() == DBUS_OK_REPLY) { return true; }
101 | bool result = args.first().toBool();
102 | if (!reply.errorMessage().isEmpty()) {
103 | result = false;
104 | emit Warning(reply.errorMessage());
105 | }
106 | return result;
107 | }
108 |
109 | const QDBusMessage Manager::callLogind(const QString &method)
110 | {
111 | QDBusMessage reply;
112 | if (logind->isValid() && !method.isEmpty()) {
113 | reply = logind->call(method, true);
114 | }
115 | return reply;
116 | }
117 |
118 | QStringList Manager::find()
119 | {
120 | QStringList result;
121 | QDBusMessage call = QDBusMessage::createMethodCall(POWERKIT_UPOWER_SERVICE,
122 | QString("%1/devices").arg(UPOWER_PATH),
123 | DBUS_INTROSPECTABLE,
124 | "Introspect");
125 | QDBusPendingReply reply = QDBusConnection::systemBus().call(call);
126 | if (reply.isError()) {
127 | emit Warning(tr("Find devices failed, check the upower service!"));
128 | return result;
129 | }
130 | QList objects;
131 | QXmlStreamReader xml(reply.value());
132 | if (xml.hasError()) { return result; }
133 | while (!xml.atEnd()) {
134 | xml.readNext();
135 | if (xml.tokenType() == QXmlStreamReader::StartElement &&
136 | xml.name().toString() == "node" ) {
137 | QString name = xml.attributes().value("name").toString();
138 | if (!name.isEmpty()) { objects << QDBusObjectPath(UPOWER_DEVICES + name); }
139 | }
140 | }
141 | foreach (QDBusObjectPath device, objects) {
142 | result << device.path();
143 | }
144 | return result;
145 | }
146 |
147 | void Manager::setup()
148 | {
149 | QDBusConnection system = QDBusConnection::systemBus();
150 | if (!system.isConnected()) {
151 | emit Error(tr("Failed to connect to the system bus"));
152 | return;
153 | }
154 |
155 | system.connect(POWERKIT_UPOWER_SERVICE,
156 | UPOWER_PATH,
157 | POWERKIT_UPOWER_SERVICE,
158 | DBUS_DEVICE_ADDED,
159 | this,
160 | SLOT(deviceAdded(QDBusObjectPath)));
161 | system.connect(POWERKIT_UPOWER_SERVICE,
162 | UPOWER_PATH,
163 | POWERKIT_UPOWER_SERVICE,
164 | DBUS_DEVICE_ADDED,
165 | this,
166 | SLOT(deviceAdded(QString)));
167 | system.connect(POWERKIT_UPOWER_SERVICE,
168 | UPOWER_PATH,
169 | POWERKIT_UPOWER_SERVICE,
170 | DBUS_DEVICE_REMOVED,
171 | this,
172 | SLOT(deviceRemoved(QDBusObjectPath)));
173 | system.connect(POWERKIT_UPOWER_SERVICE,
174 | UPOWER_PATH,
175 | POWERKIT_UPOWER_SERVICE,
176 | DBUS_DEVICE_REMOVED,
177 | this,
178 | SLOT(deviceRemoved(QString)));
179 | system.connect(POWERKIT_UPOWER_SERVICE,
180 | UPOWER_PATH,
181 | POWERKIT_DBUS_PROPERTIES,
182 | DBUS_PROPERTIES_CHANGED,
183 | this,
184 | SLOT(propertiesChanged()));
185 |
186 | upower = new QDBusInterface(POWERKIT_UPOWER_SERVICE,
187 | UPOWER_PATH,
188 | UPOWER_MANAGER,
189 | system,
190 | this);
191 | logind = new QDBusInterface(POWERKIT_LOGIND_SERVICE,
192 | LOGIND_PATH,
193 | LOGIND_MANAGER,
194 | system,
195 | this);
196 |
197 | if (!upower->isValid()) {
198 | emit Error(tr("Failed to connect to upower"));
199 | return;
200 | }
201 | if (!logind->isValid()) {
202 | emit Error(tr("Failed to connect to logind"));
203 | return;
204 | }
205 |
206 | wasDocked = IsDocked();
207 | wasLidClosed = LidIsClosed();
208 | wasOnBattery = OnBattery();
209 |
210 | connect(logind,
211 | SIGNAL(PrepareForSleep(bool)),
212 | this,
213 | SLOT(handlePrepareForSuspend(bool)));
214 |
215 | if (!suspendLock) { registerSuspendLock(); }
216 | if (!lidLock) { registerLidLock(); }
217 |
218 | scan();
219 | }
220 |
221 | void Manager::check()
222 | {
223 | if (!suspendLock) { registerSuspendLock(); }
224 | if (!lidLock) { registerLidLock(); }
225 | }
226 |
227 | void Manager::scan()
228 | {
229 | QStringList foundDevices = find();
230 | for (int i=0; i < foundDevices.size(); i++) {
231 | QString foundDevicePath = foundDevices.at(i);
232 | if (devices.contains(foundDevicePath)) { continue; }
233 | Device *newDevice = new Device(foundDevicePath, this);
234 | connect(newDevice,
235 | SIGNAL(deviceChanged(QString)),
236 | this,
237 | SLOT(handleDeviceChanged(QString)));
238 | devices[foundDevicePath] = newDevice;
239 | }
240 | UpdateDevices();
241 | emit UpdatedDevices();
242 | }
243 |
244 | void Manager::deviceAdded(const QDBusObjectPath &obj)
245 | {
246 | deviceAdded(obj.path());
247 | }
248 |
249 | void Manager::deviceAdded(const QString &path)
250 | {
251 | qDebug() << "device added" << path;
252 | if (!upower->isValid()) { return; }
253 | if (path.startsWith(QString(DBUS_JOBS).arg(UPOWER_PATH))) { return; }
254 | emit DeviceWasAdded(path);
255 | scan();
256 | }
257 |
258 | void Manager::deviceRemoved(const QDBusObjectPath &obj)
259 | {
260 | deviceRemoved(obj.path());
261 | }
262 |
263 | void Manager::deviceRemoved(const QString &path)
264 | {
265 | qDebug() << "device removed" << path;
266 | if (!upower->isValid()) { return; }
267 | bool deviceExists = devices.contains(path);
268 | if (path.startsWith(QString(DBUS_JOBS).arg(UPOWER_PATH))) { return; }
269 | if (deviceExists) {
270 | if (find().contains(path)) { return; }
271 | delete devices.take(path);
272 | emit DeviceWasRemoved(path);
273 | }
274 | scan();
275 | }
276 |
277 | void Manager::deviceChanged()
278 | {
279 | emit UpdatedDevices();
280 | }
281 |
282 | void Manager::propertiesChanged()
283 | {
284 | bool closed = LidIsClosed();
285 | bool battery = OnBattery();
286 | bool docked = IsDocked();
287 |
288 | qDebug() << "properties changed:"
289 | << "lid closed?" << wasLidClosed << closed
290 | << "on battery?" << wasOnBattery << battery
291 | << "is docked?" << wasDocked << docked;
292 |
293 | if (wasLidClosed != closed) {
294 | if (!wasLidClosed && closed) {
295 | qDebug() << "lid changed to closed";
296 | emit LidClosed();
297 | } else if (wasLidClosed && !closed) {
298 | qDebug() << "lid changed to open";
299 | emit LidOpened();
300 | }
301 | emit isLidClosedChanged(closed);
302 | qDebug() << "is lid closed changed" << closed;
303 | }
304 | wasLidClosed = closed;
305 |
306 | if (wasOnBattery != battery) {
307 | if (!wasOnBattery && battery) {
308 | qDebug() << "switched to battery power";
309 | emit SwitchedToBattery();
310 | } else if (wasOnBattery && !battery) {
311 | qDebug() << "switched to ac power";
312 | emit SwitchedToAC();
313 | }
314 | qDebug() << "is on battery changed" << battery;
315 | emit isOnBatteryChanged(battery);
316 | }
317 | wasOnBattery = battery;
318 |
319 | if (wasDocked != docked) {
320 | qDebug() << "is docked changed" << docked;
321 | emit isDockedChanged(docked);
322 | }
323 | wasDocked = docked;
324 |
325 | deviceChanged();
326 | }
327 |
328 | void Manager::handleDeviceChanged(const QString &device)
329 | {
330 | Q_UNUSED(device)
331 | qDebug() << "device changed" << device;
332 | deviceChanged();
333 | }
334 |
335 | void Manager::handlePrepareForSuspend(bool prepare)
336 | {
337 | qDebug() << "handle prepare for suspend/resume" << prepare;
338 | if (prepare) {
339 | qDebug() << "ZZZ";
340 | LockScreen();
341 | emit PrepareForSuspend();
342 | QTimer::singleShot(500, this, SLOT(ReleaseSuspendLock()));
343 | }
344 | else {
345 | qDebug() << "WAKE UP!";
346 | UpdateDevices();
347 | emit PrepareForResume();
348 | QTimer::singleShot(500, this, SLOT(registerSuspendLock()));
349 | }
350 | }
351 |
352 | void Manager::clearDevices()
353 | {
354 | QMapIterator device(devices);
355 | while (device.hasNext()) {
356 | device.next();
357 | delete device.value();
358 | }
359 | devices.clear();
360 | }
361 |
362 | void Manager::handleNewInhibitScreenSaver(const QString &application,
363 | const QString &reason,
364 | quint32 cookie)
365 | {
366 | qDebug() << "new screensaver cookie" << application << reason << cookie;
367 | Q_UNUSED(reason)
368 | ssInhibitors[cookie] = application;
369 | emit UpdatedInhibitors();
370 | }
371 |
372 | void Manager::handleNewInhibitPowerManagement(const QString &application,
373 | const QString &reason,
374 | quint32 cookie)
375 | {
376 | qDebug() << "new power cookie" << application << reason << cookie;
377 | Q_UNUSED(reason)
378 | pmInhibitors[cookie] = application;
379 | emit UpdatedInhibitors();
380 | }
381 |
382 | void Manager::handleDelInhibitScreenSaver(quint32 cookie)
383 | {
384 | qDebug() << "remove screensaver cookie" << cookie;
385 | if (ssInhibitors.contains(cookie)) {
386 | ssInhibitors.remove(cookie);
387 | emit UpdatedInhibitors();
388 | }
389 | }
390 |
391 | void Manager::handleDelInhibitPowerManagement(quint32 cookie)
392 | {
393 | qDebug() << "remove power cookie" << cookie;
394 | if (pmInhibitors.contains(cookie)) {
395 | pmInhibitors.remove(cookie);
396 | emit UpdatedInhibitors();
397 | }
398 | }
399 |
400 | bool Manager::registerSuspendLock()
401 | {
402 | if (suspendLock) { return false; }
403 | qDebug() << "register suspend lock";
404 | QDBusReply reply;
405 | if (logind->isValid()) {
406 | reply = logind->call("Inhibit",
407 | "sleep",
408 | "powerkit",
409 | "Lock screen etc",
410 | "delay");
411 | }
412 | if (reply.isValid()) {
413 | suspendLock.reset(new QDBusUnixFileDescriptor(reply.value()));
414 | return true;
415 | } else {
416 | emit Warning(tr("Failed to set suspend lock: %1").arg(reply.error().message()));
417 | }
418 | return false;
419 | }
420 |
421 | bool Manager::registerLidLock()
422 | {
423 | if (lidLock) { return false; }
424 | qDebug() << "register lid lock";
425 | QDBusReply reply;
426 | if (logind->isValid()) {
427 | reply = logind->call("Inhibit",
428 | "handle-lid-switch",
429 | "powerkit",
430 | "Custom lid handler",
431 | "block");
432 | }
433 | if (reply.isValid()) {
434 | lidLock.reset(new QDBusUnixFileDescriptor(reply.value()));
435 | return true;
436 | } else {
437 | emit Warning(tr("Failed to set lid lock: %1").arg(reply.error().message()));
438 | }
439 | return false;
440 | }
441 |
442 | bool Manager::HasSuspendLock()
443 | {
444 | return suspendLock;
445 | }
446 |
447 | bool Manager::HasLidLock()
448 | {
449 | return lidLock;
450 | }
451 |
452 | bool Manager::CanRestart()
453 | {
454 | if (logind->isValid()) { return canLogind(PK_CAN_RESTART); }
455 | return false;
456 | }
457 |
458 | bool Manager::CanPowerOff()
459 | {
460 | if (logind->isValid()) { return canLogind(PK_CAN_POWEROFF); }
461 | return false;
462 | }
463 |
464 | bool Manager::CanSuspend()
465 | {
466 | if (logind->isValid()) { return canLogind(PK_CAN_SUSPEND); }
467 | return false;
468 | }
469 |
470 | bool Manager::CanHibernate()
471 | {
472 | if (logind->isValid()) { return canLogind(PK_CAN_HIBERNATE); }
473 | return false;
474 | }
475 |
476 | bool Manager::CanHybridSleep()
477 | {
478 | if (logind->isValid()) { return canLogind(PK_CAN_HYBRIDSLEEP); }
479 | return false;
480 | }
481 |
482 | bool Manager::CanSuspendThenHibernate()
483 | {
484 | if (logind->isValid()) { return canLogind(PK_CAN_SUSPEND_THEN_HIBERNATE); }
485 | return false;
486 | }
487 |
488 | const QString Manager::Restart()
489 | {
490 | const auto reply = callLogind(PK_RESTART);
491 | qDebug() << "restart reply" << reply;
492 | return reply.errorMessage();
493 | }
494 |
495 | const QString Manager::PowerOff()
496 | {
497 | const auto reply = callLogind(PK_POWEROFF);
498 | qDebug() << "poweroff reply" << reply;
499 | return reply.errorMessage();
500 | }
501 |
502 | const QString Manager::Suspend()
503 | {
504 | const auto reply = callLogind(PK_SUSPEND);
505 | qDebug() << "suspend reply" << reply;
506 | return reply.errorMessage();
507 | }
508 |
509 | const QString Manager::Hibernate()
510 | {
511 | const auto reply = callLogind(PK_HIBERNATE);
512 | qDebug() << "hibernate reply" << reply;
513 | return reply.errorMessage();
514 | }
515 |
516 | const QString Manager::HybridSleep()
517 | {
518 | const auto reply = callLogind(PK_HYBRIDSLEEP);
519 | qDebug() << "hybridsleep reply" << reply;
520 | return reply.errorMessage();
521 | }
522 |
523 | const QString Manager::SuspendThenHibernate()
524 | {
525 | const auto reply = callLogind(PK_SUSPEND_THEN_HIBERNATE);
526 | qDebug() << "suspend then hibernate reply" << reply;
527 | return reply.errorMessage();
528 | }
529 |
530 | bool Manager::IsDocked()
531 | {
532 | if (logind->isValid()) { return logind->property(LOGIND_DOCKED).toBool(); }
533 | return false;
534 | }
535 |
536 | bool Manager::LidIsPresent()
537 | {
538 | if (upower->isValid()) { return upower->property(UPOWER_LID_IS_PRESENT).toBool(); }
539 | return false;
540 | }
541 |
542 | bool Manager::LidIsClosed()
543 | {
544 | if (upower->isValid()) { return upower->property(UPOWER_LID_IS_CLOSED).toBool(); }
545 | return false;
546 | }
547 |
548 | bool Manager::OnBattery()
549 | {
550 | if (upower->isValid()) { return upower->property(UPOWER_ON_BATTERY).toBool(); }
551 | return false;
552 | }
553 |
554 | double Manager::BatteryLeft()
555 | {
556 | if (OnBattery()) { UpdateBattery(); }
557 | double batteryLeft = 0;
558 | QMapIterator device(devices);
559 | int batteries = 0;
560 | while (device.hasNext()) {
561 | device.next();
562 | if (device.value()->isBattery &&
563 | device.value()->isPresent &&
564 | !device.value()->nativePath.isEmpty())
565 | {
566 | batteryLeft += device.value()->percentage;
567 | batteries++;
568 | } else { continue; }
569 | }
570 | return batteryLeft/batteries;
571 | }
572 |
573 | void Manager::LockScreen()
574 | {
575 | qDebug() << "screen lock";
576 | QProcess::startDetached(Settings::getValue(CONF_SCREENSAVER_LOCK_CMD,
577 | POWERKIT_SCREENSAVER_LOCK_CMD).toString(),
578 | QStringList());
579 | QProcess::execute("xset",
580 | QStringList() << "dpms" << "force" << "off");
581 | }
582 |
583 | bool Manager::HasBattery()
584 | {
585 | QMapIterator device(devices);
586 | while (device.hasNext()) {
587 | device.next();
588 | if (device.value()->isBattery) { return true; }
589 | }
590 | return false;
591 | }
592 |
593 | qlonglong Manager::TimeToEmpty()
594 | {
595 | if (OnBattery()) { UpdateBattery(); }
596 | qlonglong result = 0;
597 | QMapIterator device(devices);
598 | while (device.hasNext()) {
599 | device.next();
600 | if (device.value()->isBattery &&
601 | device.value()->isPresent &&
602 | !device.value()->nativePath.isEmpty())
603 | { result += device.value()->timeToEmpty; }
604 | }
605 | return result;
606 | }
607 |
608 | qlonglong Manager::TimeToFull()
609 | {
610 | if (OnBattery()) { UpdateBattery(); }
611 | qlonglong result = 0;
612 | QMapIterator device(devices);
613 | while (device.hasNext()) {
614 | device.next();
615 | if (device.value()->isBattery &&
616 | device.value()->isPresent &&
617 | !device.value()->nativePath.isEmpty())
618 | { result += device.value()->timeToFull; }
619 | }
620 | return result;
621 | }
622 |
623 | void Manager::UpdateDevices()
624 | {
625 | QMapIterator device(devices);
626 | while (device.hasNext()) {
627 | device.next();
628 | device.value()->update();
629 | }
630 | }
631 |
632 | void Manager::UpdateBattery()
633 | {
634 | QMapIterator device(devices);
635 | while (device.hasNext()) {
636 | device.next();
637 | if (device.value()->isBattery) {
638 | device.value()->updateBattery();
639 | }
640 | }
641 | }
642 |
643 | void Manager::UpdateConfig()
644 | {
645 | emit Update();
646 | }
647 |
648 | const QStringList Manager::GetScreenSaverInhibitors()
649 | {
650 | QStringList result;
651 | QMapIterator i(ssInhibitors);
652 | while (i.hasNext()) {
653 | i.next();
654 | result << i.value();
655 | }
656 | return result;
657 | }
658 |
659 | const QStringList Manager::GetPowerManagementInhibitors()
660 | {
661 | QStringList result;
662 | QMapIterator i(pmInhibitors);
663 | while (i.hasNext()) {
664 | i.next();
665 | result << i.value();
666 | }
667 | return result;
668 | }
669 |
670 | QMap Manager::GetInhibitors()
671 | {
672 | QMap result;
673 | QMapIterator ss(ssInhibitors);
674 | while (ss.hasNext()) {
675 | ss.next();
676 | result.insert(ss.key(), ss.value());
677 | }
678 | QMapIterator pm(pmInhibitors);
679 | while (pm.hasNext()) {
680 | pm.next();
681 | result.insert(pm.key(), pm.value());
682 | }
683 | return result;
684 | }
685 |
686 | void Manager::ReleaseSuspendLock()
687 | {
688 | qDebug() << "release suspend lock";
689 | suspendLock.reset(nullptr);
690 | }
691 |
692 | void Manager::ReleaseLidLock()
693 | {
694 | qDebug() << "release lid lock";
695 | lidLock.reset(nullptr);
696 | }
697 |
--------------------------------------------------------------------------------
/src/powerkit_app.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_app.h"
10 | #include "powerkit_common.h"
11 | #include "powerkit_theme.h"
12 | #include "powerkit_notify.h"
13 | #include "powerkit_settings.h"
14 | #include "powerkit_backlight.h"
15 |
16 | #include "InhibitAdaptor.h"
17 | #include "ScreenSaverAdaptor.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #define VIRTUAL_MONITOR "VIRTUAL"
27 |
28 | #define PK_SCREENSAVER_SERVICE "org.freedesktop.ScreenSaver"
29 | #define PK_SCREENSAVER_PATH_ROOT "/ScreenSaver"
30 | #define PK_SCREENSAVER_PATH_FULL "/org/freedesktop/ScreenSaver"
31 |
32 | #define PM_SERVICE_INHIBIT "org.freedesktop.PowerManagement.Inhibit"
33 | #define PM_FULL_PATH_INHIBIT "/org/freedesktop/PowerManagement/Inhibit"
34 |
35 | #define PM_SERVICE "org.freedesktop.PowerManagement"
36 | #define PM_FULL_PATH "/org/freedesktop/PowerManagement"
37 | #define POWERKIT_FULL_PATH "/org/freedesktop/PowerKit"
38 |
39 | using namespace PowerKit;
40 |
41 | App::App(QObject *parent)
42 | : QObject(parent)
43 | , tray(nullptr)
44 | , man(nullptr)
45 | , pm(nullptr)
46 | , ss(nullptr)
47 | , wasLowBattery(false)
48 | , wasVeryLowBattery(false)
49 | , lowBatteryValue(POWERKIT_LOW_BATTERY)
50 | , critBatteryValue(POWERKIT_CRITICAL_BATTERY)
51 | , hasService(false)
52 | , lidActionBattery(POWERKIT_LID_BATTERY_ACTION)
53 | , lidActionAC(POWERKIT_LID_AC_ACTION)
54 | , criticalAction(POWERKIT_CRITICAL_ACTION)
55 | , autoSuspendBattery(POWERKIT_AUTO_SLEEP_BATTERY)
56 | , autoSuspendAC(0)
57 | , timer(nullptr)
58 | , timeouts(0)
59 | , showNotifications(true)
60 | , showTray(true)
61 | , disableLidOnExternalMonitors(false)
62 | , autoSuspendBatteryAction(POWERKIT_SUSPEND_BATTERY_ACTION)
63 | , autoSuspendACAction(POWERKIT_SUSPEND_AC_ACTION)
64 | , watcher(nullptr)
65 | , lidXrandr(false)
66 | , lidWasClosed(false)
67 | , hasBacklight(false)
68 | , backlightOnBattery(false)
69 | , backlightOnAC(false)
70 | , backlightBatteryValue(0)
71 | , backlightACValue(0)
72 | , backlightBatteryDisableIfLower(false)
73 | , backlightACDisableIfHigher(false)
74 | , warnOnLowBattery(true)
75 | , warnOnVeryLowBattery(true)
76 | , notifyOnBattery(true)
77 | , notifyOnAC(true)
78 | , notifyNewInhibitor(true)
79 | , backlightMouseWheel(true)
80 | , ignoreKernelResume(false)
81 | {
82 | // setup tray
83 | tray = new TrayIcon(this);
84 | connect(tray,
85 | SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
86 | this,
87 | SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
88 | connect(tray,
89 | SIGNAL(wheel(TrayIcon::WheelAction)),
90 | this,
91 | SLOT(handleTrayWheel(TrayIcon::WheelAction)));
92 |
93 | // setup org.freedesktop.PowerKit.Manager
94 | man = new Manager(this);
95 | connect(man,
96 | SIGNAL(UpdatedDevices()),
97 | this,
98 | SLOT(checkDevices()));
99 | connect(man,
100 | SIGNAL(LidClosed()),
101 | this,
102 | SLOT(handleClosedLid()));
103 | connect(man,
104 | SIGNAL(LidOpened()),
105 | this,
106 | SLOT(handleOpenedLid()));
107 | connect(man,
108 | SIGNAL(SwitchedToBattery()),
109 | this,
110 | SLOT(handleOnBattery()));
111 | connect(man,
112 | SIGNAL(SwitchedToAC()),
113 | this,
114 | SLOT(handleOnAC()));
115 | connect(man,
116 | SIGNAL(PrepareForSuspend()),
117 | this,
118 | SLOT(handlePrepareForSuspend()));
119 | connect(man,
120 | SIGNAL(PrepareForResume()),
121 | this,
122 | SLOT(handlePrepareForResume()));
123 | connect(man,
124 | SIGNAL(DeviceWasAdded(QString)),
125 | this,
126 | SLOT(handleDeviceChanged(QString)));
127 | connect(man,
128 | SIGNAL(DeviceWasRemoved(QString)),
129 | this,
130 | SLOT(handleDeviceChanged(QString)));
131 | connect(man,
132 | SIGNAL(Update()),
133 | this,
134 | SLOT(loadSettings()));
135 | connect(man,
136 | SIGNAL(Error(QString)),
137 | this,
138 | SLOT(handleError(QString)));
139 | connect(man,
140 | SIGNAL(Warning(QString)),
141 | this,
142 | SLOT(handleWarning(QString)));
143 |
144 | // setup org.freedesktop.PowerManagement
145 | pm = new PowerManagement(this);
146 | connect(pm,
147 | SIGNAL(HasInhibitChanged(bool)),
148 | this,
149 | SLOT(handleHasInhibitChanged(bool)));
150 | connect(pm,
151 | SIGNAL(newInhibit(QString,QString,quint32)),
152 | this,
153 | SLOT(handleNewInhibitPowerManagement(QString,QString,quint32)));
154 | connect(pm,
155 | SIGNAL(removedInhibit(quint32)),
156 | this,
157 | SLOT(handleDelInhibitPowerManagement(quint32)));
158 | connect(pm,
159 | SIGNAL(newInhibit(QString,QString,quint32)),
160 | man,
161 | SLOT(handleNewInhibitPowerManagement(QString,QString,quint32)));
162 | connect(pm,
163 | SIGNAL(removedInhibit(quint32)),
164 | man,
165 | SLOT(handleDelInhibitPowerManagement(quint32)));
166 |
167 | // setup org.freedesktop.ScreenSaver
168 | ss = new ScreenSaver(this);
169 | connect(ss,
170 | SIGNAL(newInhibit(QString,QString,quint32)),
171 | this,
172 | SLOT(handleNewInhibitScreenSaver(QString,QString,quint32)));
173 | connect(ss,
174 | SIGNAL(removedInhibit(quint32)),
175 | this,
176 | SLOT(handleDelInhibitScreenSaver(quint32)));
177 | connect(ss,
178 | SIGNAL(newInhibit(QString,QString,quint32)),
179 | man,
180 | SLOT(handleNewInhibitScreenSaver(QString,QString,quint32)));
181 | connect(ss,
182 | SIGNAL(removedInhibit(quint32)),
183 | man,
184 | SLOT(handleDelInhibitScreenSaver(quint32)));
185 |
186 | // setup timer
187 | timer = new QTimer(this);
188 | timer->setInterval(60000);
189 | connect(timer,
190 | SIGNAL(timeout()),
191 | this,
192 | SLOT(timeout()));
193 | timer->start();
194 |
195 | // check for config
196 | Settings::getConf();
197 |
198 | // setup theme
199 | Theme::setAppTheme();
200 | Theme::setIconTheme();
201 | if (tray->icon().isNull()) {
202 | tray->setIcon(QIcon::fromTheme(POWERKIT_ICON));
203 | }
204 |
205 | loadSettings();
206 | registerService();
207 |
208 | // device check
209 | QTimer::singleShot(10000,
210 | this,
211 | SLOT(checkDevices()));
212 | QTimer::singleShot(1000,
213 | this,
214 | SLOT(setInternalMonitor()));
215 |
216 | // setup watcher
217 | watcher = new QFileSystemWatcher(this);
218 | watcher->addPath(Settings::getDir());
219 | watcher->addPath(Settings::getConf());
220 | connect(watcher,
221 | SIGNAL(fileChanged(QString)),
222 | this,
223 | SLOT(handleConfChanged(QString)));
224 | connect(watcher,
225 | SIGNAL(directoryChanged(QString)),
226 | this,
227 | SLOT(handleConfChanged(QString)));
228 | }
229 |
230 | App::~App()
231 | {
232 | }
233 |
234 | void App::trayActivated(QSystemTrayIcon::ActivationReason reason)
235 | {
236 | Q_UNUSED(reason)
237 |
238 | openSettings();
239 | }
240 |
241 | void App::checkDevices()
242 | {
243 | updateTrayVisibility();
244 |
245 | double batteryLeft = man->BatteryLeft();
246 | qDebug() << "battery at" << batteryLeft;
247 |
248 | drawBattery(batteryLeft);
249 | updateToolTip();
250 |
251 | handleLow(batteryLeft);
252 | handleVeryLow(batteryLeft);
253 | handleCritical(batteryLeft);
254 | }
255 |
256 | void App::handleClosedLid()
257 | {
258 | qDebug() << "lid closed";
259 | lidWasClosed = true;
260 |
261 | int type = lidNone;
262 | if (man->OnBattery()) {
263 | type = lidActionBattery;
264 | } else { // on ac
265 | type = lidActionAC;
266 | }
267 |
268 | if (disableLidOnExternalMonitors &&
269 | externalMonitorIsConnected()) {
270 | qDebug() << "external monitor is connected, ignore lid action";
271 | switchInternalMonitor(false /* turn off screen */);
272 | return;
273 | }
274 |
275 | qDebug() << "lid action" << type;
276 | switch(type) {
277 | case lidLock:
278 | man->LockScreen();
279 | break;
280 | case lidSleep:
281 | man->Suspend();
282 | break;
283 | case lidHibernate:
284 | man->Hibernate();
285 | break;
286 | case lidShutdown:
287 | man->PowerOff();
288 | break;
289 | case lidHybridSleep:
290 | man->HybridSleep();
291 | break;
292 | case lidSleepHibernate:
293 | man->SuspendThenHibernate();
294 | break;
295 | default:;
296 | }
297 | }
298 |
299 | void App::handleOpenedLid()
300 | {
301 | qDebug() << "lid is now open";
302 | lidWasClosed = false;
303 | if (disableLidOnExternalMonitors) {
304 | switchInternalMonitor(true /* turn on screen */);
305 | }
306 | }
307 |
308 | void App::handleOnBattery()
309 | {
310 | if (notifyOnBattery) {
311 | showMessage(tr("On Battery"),
312 | tr("Switched to battery power."));
313 | }
314 |
315 | // brightness
316 | if (backlightOnBattery && backlightBatteryValue > 0) {
317 | qDebug() << "set brightness on battery";
318 | if (backlightBatteryDisableIfLower &&
319 | backlightBatteryValue > Backlight::getCurrentBrightness(backlightDevice)) {
320 | qDebug() << "brightness is lower than battery value, ignore";
321 | return;
322 | }
323 | Backlight::setBrightness(backlightDevice,
324 | backlightBatteryValue);
325 | }
326 | }
327 |
328 | void App::handleOnAC()
329 | {
330 | if (notifyOnAC) {
331 | showMessage(tr("On AC"),
332 | tr("Switched to AC power."));
333 | }
334 |
335 | wasLowBattery = false;
336 | wasVeryLowBattery = false;
337 |
338 | // brightness
339 | if (backlightOnAC && backlightACValue > 0) {
340 | qDebug() << "set brightness on ac";
341 | if (backlightACDisableIfHigher &&
342 | backlightACValue < Backlight::getCurrentBrightness(backlightDevice)) {
343 | qDebug() << "brightness is higher than ac value, ignore";
344 | return;
345 | }
346 | Backlight::setBrightness(backlightDevice,
347 | backlightACValue);
348 | }
349 | }
350 |
351 | void App::loadSettings()
352 | {
353 | qDebug() << "(re)load settings...";
354 |
355 | // set default settings
356 | if (Settings::isValid(CONF_SUSPEND_BATTERY_TIMEOUT)) {
357 | autoSuspendBattery = Settings::getValue(CONF_SUSPEND_BATTERY_TIMEOUT).toInt();
358 | }
359 | if (Settings::isValid(CONF_SUSPEND_AC_TIMEOUT)) {
360 | autoSuspendAC = Settings::getValue(CONF_SUSPEND_AC_TIMEOUT).toInt();
361 | }
362 | if (Settings::isValid(CONF_SUSPEND_BATTERY_ACTION)) {
363 | autoSuspendBatteryAction = Settings::getValue(CONF_SUSPEND_BATTERY_ACTION).toInt();
364 | }
365 | if (Settings::isValid(CONF_SUSPEND_AC_ACTION)) {
366 | autoSuspendACAction = Settings::getValue(CONF_SUSPEND_AC_ACTION).toInt();
367 | }
368 | if (Settings::isValid(CONF_CRITICAL_BATTERY_TIMEOUT)) {
369 | critBatteryValue = Settings::getValue(CONF_CRITICAL_BATTERY_TIMEOUT).toInt();
370 | }
371 | if (Settings::isValid(CONF_LID_BATTERY_ACTION)) {
372 | lidActionBattery = Settings::getValue(CONF_LID_BATTERY_ACTION).toInt();
373 | }
374 | if (Settings::isValid(CONF_LID_AC_ACTION)) {
375 | lidActionAC = Settings::getValue(CONF_LID_AC_ACTION).toInt();
376 | }
377 | if (Settings::isValid(CONF_CRITICAL_BATTERY_ACTION)) {
378 | criticalAction = Settings::getValue(CONF_CRITICAL_BATTERY_ACTION).toInt();
379 | }
380 | if (Settings::isValid(CONF_TRAY_NOTIFY)) {
381 | showNotifications = Settings::getValue(CONF_TRAY_NOTIFY).toBool();
382 | }
383 | if (Settings::isValid(CONF_TRAY_SHOW)) {
384 | showTray = Settings::getValue(CONF_TRAY_SHOW).toBool();
385 | }
386 | if (Settings::isValid(CONF_LID_DISABLE_IF_EXTERNAL)) {
387 | disableLidOnExternalMonitors = Settings::getValue(CONF_LID_DISABLE_IF_EXTERNAL).toBool();
388 | }
389 | if (Settings::isValid(CONF_LID_XRANDR)) {
390 | lidXrandr = Settings::getValue(CONF_LID_XRANDR).toBool();
391 | }
392 | if (Settings::isValid(CONF_BACKLIGHT_AC_ENABLE)) {
393 | backlightOnAC = Settings::getValue(CONF_BACKLIGHT_AC_ENABLE).toBool();
394 | }
395 | if (Settings::isValid(CONF_BACKLIGHT_AC)) {
396 | backlightACValue = Settings::getValue(CONF_BACKLIGHT_AC).toInt();
397 | }
398 | if (Settings::isValid(CONF_BACKLIGHT_BATTERY_ENABLE)) {
399 | backlightOnBattery = Settings::getValue(CONF_BACKLIGHT_BATTERY_ENABLE).toBool();
400 | }
401 | if (Settings::isValid(CONF_BACKLIGHT_BATTERY)) {
402 | backlightBatteryValue = Settings::getValue(CONF_BACKLIGHT_BATTERY).toInt();
403 | }
404 | if (Settings::isValid(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER)) {
405 | backlightBatteryDisableIfLower = Settings::getValue(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER)
406 | .toBool();
407 | }
408 | if (Settings::isValid(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER)) {
409 | backlightACDisableIfHigher = Settings::getValue(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER)
410 | .toBool();
411 | }
412 | if (Settings::isValid(CONF_WARN_ON_LOW_BATTERY)) {
413 | warnOnLowBattery = Settings::getValue(CONF_WARN_ON_LOW_BATTERY).toBool();
414 | }
415 | if (Settings::isValid(CONF_WARN_ON_VERYLOW_BATTERY)) {
416 | warnOnVeryLowBattery = Settings::getValue(CONF_WARN_ON_VERYLOW_BATTERY).toBool();
417 | }
418 | if (Settings::isValid(CONF_NOTIFY_ON_BATTERY)) {
419 | notifyOnBattery = Settings::getValue(CONF_NOTIFY_ON_BATTERY).toBool();
420 | }
421 | if (Settings::isValid(CONF_NOTIFY_ON_AC)) {
422 | notifyOnAC = Settings::getValue(CONF_NOTIFY_ON_AC).toBool();
423 | }
424 | if (Settings::isValid(CONF_NOTIFY_NEW_INHIBITOR)) {
425 | notifyNewInhibitor = Settings::getValue(CONF_NOTIFY_NEW_INHIBITOR).toBool();
426 | }
427 | /*if (Settings::isValid(CONF_SUSPEND_WAKEUP_HIBERNATE_BATTERY)) {
428 | man->SetSuspendWakeAlarmOnBattery(Settings::getValue(CONF_SUSPEND_WAKEUP_HIBERNATE_BATTERY).toInt());
429 | }
430 | if (Settings::isValid(CONF_SUSPEND_WAKEUP_HIBERNATE_AC)) {
431 | man->SetSuspendWakeAlarmOnAC(Settings::getValue(CONF_SUSPEND_WAKEUP_HIBERNATE_AC).toInt());
432 | }*/
433 |
434 | if (Settings::isValid(CONF_KERNEL_BYPASS)) {
435 | ignoreKernelResume = Settings::getValue(CONF_KERNEL_BYPASS).toBool();
436 | } else {
437 | ignoreKernelResume = false;
438 | }
439 |
440 | // verify
441 | /*if (!Common::kernelCanResume(ignoreKernelResume)) {
442 | qDebug() << "hibernate is not activated in kernel (add resume=...)";
443 | disableHibernate();
444 | }*/
445 | if (!man->CanHibernate()) {
446 | qWarning() << "hibernate is not supported";
447 | disableHibernate();
448 | }
449 | if (!man->CanSuspend()) {
450 | qWarning() << "suspend not supported";
451 | disableSuspend();
452 | }
453 |
454 | // backlight
455 | backlightDevice = Backlight::getDevice();
456 | hasBacklight = Backlight::canAdjustBrightness(backlightDevice);
457 | if (Settings::isValid(CONF_BACKLIGHT_MOUSE_WHEEL)) {
458 | backlightMouseWheel = Settings::getValue(CONF_BACKLIGHT_MOUSE_WHEEL).toBool();
459 | }
460 |
461 | // screensaver
462 | ss->Update();
463 | }
464 |
465 | void App::registerService()
466 | {
467 | if (hasService) { return; }
468 | if (!QDBusConnection::sessionBus().isConnected()) {
469 | qWarning() << tr("Cannot connect to D-Bus.");
470 | return;
471 | }
472 | hasService = true;
473 |
474 | // register org.freedesktop.PowerManagement
475 | bool hasDesktopPM = true;
476 | if (!QDBusConnection::sessionBus().registerService(PM_SERVICE)) {
477 | qWarning() << QDBusConnection::sessionBus().lastError().message();
478 | hasDesktopPM = false;
479 | } else {
480 | if (!QDBusConnection::sessionBus().registerService(PM_SERVICE_INHIBIT)) {
481 | qWarning() << QDBusConnection::sessionBus().lastError().message();
482 | hasDesktopPM = false;
483 | } else {
484 | new InhibitAdaptor(pm);
485 | if (!QDBusConnection::sessionBus().registerObject(PM_FULL_PATH_INHIBIT, pm)) {
486 | qWarning() << QDBusConnection::sessionBus().lastError().message();
487 | hasDesktopPM = false;
488 | }
489 | }
490 | }
491 | qWarning() << "Enabled org.freedesktop.PowerManagement" << hasDesktopPM;
492 |
493 | // register org.freedesktop.ScreenSaver
494 | bool hasScreenSaver = true;
495 | if (!QDBusConnection::sessionBus().registerService(PK_SCREENSAVER_SERVICE)) {
496 | qWarning() << "Failed to register screensaver service" << QDBusConnection::sessionBus().lastError().message();
497 | hasScreenSaver = false;
498 | } else {
499 | new ScreenSaverAdaptor(ss);
500 | if (!QDBusConnection::sessionBus().registerObject(PK_SCREENSAVER_PATH_ROOT, ss)) {
501 | qWarning() << "Failed to register screensaver object" << QDBusConnection::sessionBus().lastError().message();
502 | hasScreenSaver = false;
503 | }
504 | if (!QDBusConnection::sessionBus().registerObject(PK_SCREENSAVER_PATH_FULL, ss)) {
505 | qWarning() << "Failed to register screensaver object" << QDBusConnection::sessionBus().lastError().message();
506 | hasScreenSaver = false;
507 | }
508 | }
509 | qWarning() << "Enabled org.freedesktop.ScreenSaver" << hasScreenSaver;
510 |
511 | bool hasDesktopPK = true;
512 | if (!QDBusConnection::sessionBus().registerService(POWERKIT_SERVICE)) {
513 | qWarning() << QDBusConnection::sessionBus().lastError().message();
514 | hasDesktopPK = false;
515 | }
516 | if (!QDBusConnection::sessionBus().registerObject(POWERKIT_PATH,
517 | man,
518 | QDBusConnection::ExportAllContents)) {
519 | qWarning() << QDBusConnection::sessionBus().lastError().message();
520 | hasDesktopPK = false;
521 | }
522 | if (!QDBusConnection::sessionBus().registerObject(POWERKIT_FULL_PATH,
523 | man,
524 | QDBusConnection::ExportAllContents)) {
525 | qWarning() << QDBusConnection::sessionBus().lastError().message();
526 | hasDesktopPK = false;
527 | }
528 | qWarning() << "Enabled org.freedesktop.PowerKit" << hasDesktopPK;
529 |
530 | if (!hasDesktopPK || !hasDesktopPM || !hasScreenSaver) { hasService = false; }
531 |
532 | if (!hasService) { handleError(tr("Failed to setup and/or connect required services!")); }
533 | }
534 |
535 | // dbus session inhibit status handler
536 | void App::handleHasInhibitChanged(bool has_inhibit)
537 | {
538 | if (has_inhibit) { resetTimer(); }
539 | }
540 |
541 | void App::handleLow(double left)
542 | {
543 | if (!warnOnLowBattery) { return; }
544 | double batteryLow = (double)(lowBatteryValue+critBatteryValue);
545 | if (left<=batteryLow && man->OnBattery()) {
546 | if (!wasLowBattery) {
547 | showMessage(QString("%1 (%2%)").arg(tr("Low Battery!")).arg(left),
548 | tr("The battery is low,"
549 | " please consider connecting"
550 | " your computer to a power supply."),
551 | true);
552 | wasLowBattery = true;
553 | }
554 | }
555 | }
556 |
557 | void App::handleVeryLow(double left)
558 | {
559 | if (!warnOnVeryLowBattery) { return; }
560 | double batteryVeryLow = (double)(critBatteryValue+1);
561 | if (left<=batteryVeryLow && man->OnBattery()) {
562 | if (!wasVeryLowBattery) {
563 | showMessage(QString("%1 (%2%)").arg(tr("Very Low Battery!")).arg(left),
564 | tr("The battery is almost empty,"
565 | " please connect"
566 | " your computer to a power supply now."),
567 | true);
568 | wasVeryLowBattery = true;
569 | }
570 | }
571 | }
572 |
573 | void App::handleCritical(double left)
574 | {
575 | if (left<=0 ||
576 | left>(double)critBatteryValue ||
577 | !man->OnBattery()) { return; }
578 | qDebug() << "critical battery!" << criticalAction << left;
579 | switch(criticalAction) {
580 | case criticalHibernate:
581 | man->Hibernate();
582 | break;
583 | case criticalShutdown:
584 | man->PowerOff();
585 | break;
586 | case criticalSuspend:
587 | man->Suspend();
588 | break;
589 | default: ;
590 | }
591 | }
592 |
593 | void App::drawBattery(double left)
594 | {
595 | if (!showTray &&
596 | tray->isVisible()) {
597 | tray->hide();
598 | return;
599 | }
600 | if (tray->isSystemTrayAvailable() &&
601 | !tray->isVisible() &&
602 | showTray) { tray->show(); }
603 |
604 | QColor colorBg = Qt::green;
605 | QColor colorFg = Qt::white;
606 | int pixelSize = 22;
607 | if (man->OnBattery()) {
608 | if (left >= 26) {
609 | colorBg = QColor("orange");
610 | } else {
611 | colorBg = Qt::red;
612 | }
613 | } else {
614 | if (!man->HasBattery()) { left = 100; }
615 | else if (left == 100) { colorFg = Qt::green; }
616 | }
617 |
618 | tray->setIcon(Theme::drawCircleProgress(left,
619 | pixelSize,
620 | 4,
621 | 4,
622 | false,
623 | QString(),
624 | colorBg,
625 | colorFg));
626 | }
627 |
628 | void App::updateToolTip()
629 | {
630 | if (!tray->isSystemTrayAvailable() || !tray->isVisible()) { return; }
631 | double batteryLeft = man->BatteryLeft();
632 | if (batteryLeft > 0 && man->HasBattery()) {
633 | tray->setToolTip(QString("%1 %2%").arg(tr("Battery at")).arg(batteryLeft));
634 | if (man->TimeToEmpty()>0 && man->OnBattery()) {
635 | tray->setToolTip(tray->toolTip()
636 | .append(QString(", %1 %2")
637 | .arg(QDateTime::fromTime_t((uint)man->TimeToEmpty())
638 | .toUTC().toString("hh:mm")))
639 | .arg(tr("left")));
640 | }
641 | if (batteryLeft > 99) { tray->setToolTip(tr("Charged")); }
642 | if (!man->OnBattery() &&
643 | man->BatteryLeft() <= 99) {
644 | if (man->TimeToFull()>0) {
645 | tray->setToolTip(tray->toolTip()
646 | .append(QString(", %1 %2")
647 | .arg(QDateTime::fromTime_t((uint)man->TimeToFull())
648 | .toUTC().toString("hh:mm")))
649 | .arg(tr("left")));
650 | }
651 | tray->setToolTip(tray->toolTip().append(QString(" (%1)").arg(tr("Charging"))));
652 | }
653 | } else { tray->setToolTip(tr("On AC")); }
654 | }
655 |
656 | void App::updateTrayVisibility()
657 | {
658 | if (!showTray &&
659 | tray->isVisible()) { tray->hide(); }
660 | if (tray->isSystemTrayAvailable() &&
661 | !tray->isVisible() &&
662 | showTray) { tray->show(); }
663 | }
664 |
665 | // timeout, check if idle
666 | // timeouts and xss must be >= user value and service has to be empty before suspend
667 | void App::timeout()
668 | {
669 | updateTrayVisibility();
670 |
671 | int uIdle = ss->GetSessionIdleTime() / 60;
672 |
673 | qDebug() << "timeout?" << timeouts << "idle?" << uIdle << "inhibit?" << pm->HasInhibit() << man->GetInhibitors();
674 |
675 | int autoSuspend = 0;
676 | int autoSuspendAction = suspendNone;
677 | if (man->OnBattery()) {
678 | autoSuspend = autoSuspendBattery;
679 | autoSuspendAction = autoSuspendBatteryAction;
680 | }
681 | else {
682 | autoSuspend = autoSuspendAC;
683 | autoSuspendAction = autoSuspendACAction;
684 | }
685 |
686 | bool doSuspend = false;
687 | if (autoSuspend>0 &&
688 | timeouts>=autoSuspend &&
689 | uIdle>=autoSuspend &&
690 | !pm->HasInhibit()) { doSuspend = true; }
691 | if (!doSuspend) { timeouts++; }
692 | else {
693 | timeouts = 0;
694 | qDebug() << "auto suspend activated" << autoSuspendAction;
695 | switch (autoSuspendAction) {
696 | case suspendSleep:
697 | man->Suspend();
698 | break;
699 | case suspendHibernate:
700 | man->Hibernate();
701 | break;
702 | case suspendShutdown:
703 | man->PowerOff();
704 | break;
705 | case suspendHybrid:
706 | man->HybridSleep();
707 | break;
708 | case suspendSleepHibernate:
709 | man->SuspendThenHibernate();
710 | break;
711 | default:;
712 | }
713 | }
714 | }
715 |
716 | void App::resetTimer()
717 | {
718 | timeouts = 0;
719 | }
720 |
721 | void App::setInternalMonitor()
722 | {
723 | internalMonitor = ss->GetInternalDisplay();
724 | qDebug() << "internal monitor set to" << internalMonitor;
725 | qDebug() << ss->GetDisplays();
726 | }
727 |
728 | bool App::internalMonitorIsConnected()
729 | {
730 | QMapIterator i(ss->GetDisplays());
731 | while (i.hasNext()) {
732 | i.next();
733 | if (i.key() == internalMonitor) {
734 | qDebug() << "internal monitor connected?" << i.key() << i.value();
735 | return i.value();
736 | }
737 | }
738 | return false;
739 | }
740 |
741 | bool App::externalMonitorIsConnected()
742 | {
743 | QMapIterator i(ss->GetDisplays());
744 | while (i.hasNext()) {
745 | i.next();
746 | if (i.key()!=internalMonitor &&
747 | !i.key().startsWith(VIRTUAL_MONITOR)) {
748 | qDebug() << "external monitor connected?" << i.key() << i.value();
749 | if (i.value()) { return true; }
750 | }
751 | }
752 | return false;
753 | }
754 |
755 | void App::handleNewInhibitScreenSaver(const QString &application,
756 | const QString &reason,
757 | quint32 cookie)
758 | {
759 | Q_UNUSED(cookie)
760 | if (notifyNewInhibitor) {
761 | showMessage(tr("New screen inhibitor"),
762 | QString("%1: %2").arg(application, reason));
763 | }
764 |
765 | checkDevices();
766 | }
767 |
768 | void App::handleNewInhibitPowerManagement(const QString &application,
769 | const QString &reason,
770 | quint32 cookie)
771 | {
772 | Q_UNUSED(cookie)
773 | if (notifyNewInhibitor) {
774 | showMessage(tr("New power inhibitor"),
775 | QString("%1: %2").arg(application, reason));
776 | }
777 |
778 | checkDevices();
779 | }
780 |
781 | void App::handleDelInhibitScreenSaver(quint32 cookie)
782 | {
783 | Q_UNUSED(cookie)
784 | checkDevices();
785 | }
786 |
787 | void App::handleDelInhibitPowerManagement(quint32 cookie)
788 | {
789 | Q_UNUSED(cookie)
790 | checkDevices();
791 | }
792 |
793 | void App::showMessage(const QString &title,
794 | const QString &msg,
795 | bool critical)
796 | {
797 | if (!showNotifications) { return; }
798 | SystemNotification notifier;
799 | if (notifier.valid) {
800 | notifier.sendMessage(title, msg, critical);
801 | } else if (tray->isVisible()) {
802 | if (critical) {
803 | tray->showMessage(title,
804 | msg,
805 | QSystemTrayIcon::Critical,
806 | 900000);
807 | } else {
808 | tray->showMessage(title, msg);
809 | }
810 | }
811 | }
812 |
813 | void App::handleConfChanged(const QString &file)
814 | {
815 | Q_UNUSED(file)
816 | loadSettings();
817 | }
818 |
819 | void App::disableHibernate()
820 | {
821 | if (criticalAction == criticalHibernate) {
822 | qWarning() << "reset critical action to shutdown";
823 | criticalAction = criticalShutdown;
824 | Settings::setValue(CONF_CRITICAL_BATTERY_ACTION,
825 | criticalAction);
826 | }
827 | if (lidActionBattery == lidHibernate) {
828 | qWarning() << "reset lid battery action to lock";
829 | lidActionBattery = lidLock;
830 | Settings::setValue(CONF_LID_BATTERY_ACTION,
831 | lidActionBattery);
832 | }
833 | if (lidActionAC == lidHibernate) {
834 | qWarning() << "reset lid ac action to lock";
835 | lidActionAC = lidLock;
836 | Settings::setValue(CONF_LID_AC_ACTION,
837 | lidActionAC);
838 | }
839 | if (autoSuspendBatteryAction == suspendHibernate) {
840 | qWarning() << "reset auto suspend battery action to none";
841 | autoSuspendBatteryAction = suspendNone;
842 | Settings::setValue(CONF_SUSPEND_BATTERY_ACTION,
843 | autoSuspendBatteryAction);
844 | }
845 | if (autoSuspendACAction == suspendHibernate) {
846 | qWarning() << "reset auto suspend ac action to none";
847 | autoSuspendACAction = suspendNone;
848 | Settings::setValue(CONF_SUSPEND_AC_ACTION,
849 | autoSuspendACAction);
850 | }
851 | }
852 |
853 | void App::disableSuspend()
854 | {
855 | if (lidActionBattery == lidSleep) {
856 | qWarning() << "reset lid battery action to lock";
857 | lidActionBattery = lidLock;
858 | Settings::setValue(CONF_LID_BATTERY_ACTION,
859 | lidActionBattery);
860 | }
861 | if (lidActionAC == lidSleep) {
862 | qWarning() << "reset lid ac action to lock";
863 | lidActionAC = lidLock;
864 | Settings::setValue(CONF_LID_AC_ACTION,
865 | lidActionAC);
866 | }
867 | if (autoSuspendBatteryAction == suspendSleep) {
868 | qWarning() << "reset auto suspend battery action to none";
869 | autoSuspendBatteryAction = suspendNone;
870 | Settings::setValue(CONF_SUSPEND_BATTERY_ACTION,
871 | autoSuspendBatteryAction);
872 | }
873 | if (autoSuspendACAction == suspendSleep) {
874 | qWarning() << "reset auto suspend ac action to none";
875 | autoSuspendACAction = suspendNone;
876 | Settings::setValue(CONF_SUSPEND_AC_ACTION,
877 | autoSuspendACAction);
878 | }
879 | }
880 |
881 | void App::handlePrepareForSuspend()
882 | {
883 | /*qDebug() << "prepare for suspend";
884 | resetTimer();
885 | man->ReleaseSuspendLock();*/
886 | qDebug() << "do nothing";
887 | }
888 |
889 | void App::handlePrepareForResume()
890 | {
891 | qDebug() << "prepare for resume ...";
892 | resetTimer();
893 | ss->setDisplaysOff(false);
894 | }
895 |
896 | // turn off/on monitor using xrandr
897 | void App::switchInternalMonitor(bool toggle)
898 | {
899 | if (!lidXrandr) { return; }
900 | qDebug() << "using xrandr to turn on/off internal monitor" << internalMonitor << toggle;
901 | QStringList args;
902 | args << "--output" << internalMonitor << (toggle ? "--auto" : "--off");
903 | QProcess::startDetached("xrandr", args);
904 | }
905 |
906 | // adjust backlight on wheel event (on systray)
907 | void App::handleTrayWheel(TrayIcon::WheelAction action)
908 | {
909 | if (!backlightMouseWheel) { return; }
910 | switch (action) {
911 | case TrayIcon::WheelUp:
912 | Backlight::setBrightness(backlightDevice,
913 | Backlight::getCurrentBrightness(backlightDevice)+POWERKIT_BACKLIGHT_STEP);
914 | break;
915 | case TrayIcon::WheelDown:
916 | Backlight::setBrightness(backlightDevice,
917 | Backlight::getCurrentBrightness(backlightDevice)-POWERKIT_BACKLIGHT_STEP);
918 | break;
919 | default:;
920 | }
921 | }
922 |
923 | void App::handleDeviceChanged(const QString &path)
924 | {
925 | Q_UNUSED(path)
926 | checkDevices();
927 | }
928 |
929 | void App::openSettings()
930 | {
931 | QProcess::startDetached(qApp->applicationFilePath(),
932 | QStringList() << "--config");
933 | }
934 |
935 | void App::handleError(const QString &message)
936 | {
937 | qWarning() << "ERROR:" << message;
938 | showMessage(tr("Error"), message, true);
939 | QTimer::singleShot(5000, qApp, SLOT(quit()));
940 | }
941 |
942 | void App::handleWarning(const QString &message)
943 | {
944 | qWarning() << "WARNING:" << message;
945 | showMessage(tr("Warning"), message, true);
946 | }
947 |
948 | bool TrayIcon::event(QEvent *e)
949 | {
950 | if (e->type() == QEvent::Wheel) {
951 | QWheelEvent *w = (QWheelEvent*)e;
952 | //if (w->orientation() == Qt::Vertical) {
953 | wheel_delta += w->angleDelta().y();
954 | if (abs(wheel_delta) >= 120) {
955 | emit wheel(wheel_delta > 0 ? TrayIcon::WheelUp : TrayIcon::WheelDown);
956 | wheel_delta = 0;
957 | }
958 | //}
959 | return true;
960 | }
961 | return QSystemTrayIcon::event(e);
962 | }
963 |
--------------------------------------------------------------------------------
/src/powerkit_dialog.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | # PowerKit
3 | # Copyright (c) Ole-André Rodlie All rights reserved.
4 | #
5 | # Available under the 3-clause BSD license
6 | # See the LICENSE file for full details
7 | */
8 |
9 | #include "powerkit_dialog.h"
10 | #include "powerkit_common.h"
11 | #include "powerkit_theme.h"
12 | #include "powerkit_settings.h"
13 | #include "powerkit_backlight.h"
14 | #include "powerkit_client.h"
15 | #include "powerkit_cpu.h"
16 |
17 | #include
18 |
19 | #define MAX_WIDTH 175
20 |
21 | using namespace PowerKit;
22 |
23 | Dialog::Dialog(QWidget *parent,
24 | bool quitOnClose)
25 | : QDialog(parent)
26 | , cpuTimer(nullptr)
27 | , dbus(nullptr)
28 | , lidActionBattery(nullptr)
29 | , lidActionAC(nullptr)
30 | , criticalActionBattery(nullptr)
31 | , criticalBattery(nullptr)
32 | , autoSleepBattery(nullptr)
33 | , autoSleepAC(nullptr)
34 | , showNotifications(nullptr)
35 | , showSystemTray(nullptr)
36 | , disableLidAction(nullptr)
37 | , autoSleepBatteryAction(nullptr)
38 | , autoSleepACAction(nullptr)
39 | , backlightSliderBattery(nullptr)
40 | , backlightSliderAC(nullptr)
41 | , backlightBatteryCheck(nullptr)
42 | , backlightACCheck(nullptr)
43 | , backlightBatteryLowerCheck(nullptr)
44 | , backlightACHigherCheck(nullptr)
45 | , warnOnLowBattery(nullptr)
46 | , warnOnVeryLowBattery(nullptr)
47 | , lidActionACLabel(nullptr)
48 | , lidActionBatteryLabel(nullptr)
49 | , batteryBacklightLabel(nullptr)
50 | , acBacklightLabel(nullptr)
51 | , backlightMouseWheel(nullptr)
52 | , batteryStatusLabel(nullptr)
53 | , cpuFreqLabel(nullptr)
54 | , cpuTempLabel(nullptr)
55 | , screensaverBlank(nullptr)
56 | , hasCpuCoreTemp(false)
57 | , hasBattery(false)
58 | {
59 | // setup dialog
60 | if (quitOnClose) { setAttribute(Qt::WA_QuitOnClose, true); }
61 | setWindowTitle(tr("Power Manager"));
62 | setMinimumSize(QSize(680, 360));
63 |
64 | // setup cpu timer
65 | cpuTimer = new QTimer(this);
66 | cpuTimer->setInterval(1000);
67 | connect(cpuTimer,
68 | SIGNAL(timeout()),
69 | this,
70 | SLOT(drawCpu()));
71 | cpuTimer->start();
72 |
73 | // setup dbus
74 | QDBusConnection session = QDBusConnection::sessionBus();
75 | dbus = new QDBusInterface(POWERKIT_SERVICE,
76 | POWERKIT_PATH,
77 | POWERKIT_MANAGER,
78 | session, this);
79 | if (!dbus->isValid()) {
80 | QMessageBox::warning(this,
81 | tr("powerkit not running"),
82 | tr("powerkit is not running, please start powerkit before running this application."));
83 | QTimer::singleShot(100, qApp, SLOT(quit()));
84 | return;
85 | }
86 |
87 | // detect device changes
88 | connect(dbus, SIGNAL(UpdatedDevices()),
89 | this, SLOT(handleUpdatedDevices()));
90 |
91 | // trigger generation of powerkit.conf if not exists
92 | Settings::getConf();
93 |
94 | setupWidgets();
95 | populateWidgets();
96 | loadSettings();
97 | connectWidgets();
98 | handleUpdatedDevices();
99 | }
100 |
101 | Dialog::~Dialog()
102 | {
103 | const auto lastGeo = Settings::getValue(CONF_DIALOG).toByteArray();
104 | const auto newGeo = saveGeometry();
105 | if (lastGeo != newGeo) {
106 | Settings::setValue(CONF_DIALOG, newGeo);
107 | }
108 | }
109 |
110 | void Dialog::setupWidgets()
111 | {
112 | // setup theme
113 | Theme::setAppTheme();
114 | Theme::setIconTheme();
115 | setStyleSheet("QLabel { font-weight: bold; }");
116 | setWindowIcon(QIcon::fromTheme(POWERKIT_ICON));
117 |
118 | // setup widgets
119 | const auto layout = new QVBoxLayout(this);
120 | layout->setMargin(5);
121 | layout->setSpacing(0);
122 |
123 | // status widgets
124 | const auto statusWidget = new QWidget(this);
125 | statusWidget->setSizePolicy(QSizePolicy::Expanding,
126 | QSizePolicy::Fixed);
127 | const auto statusLayout = new QHBoxLayout(statusWidget);
128 |
129 | batteryStatusLabel = new QLabel(this);
130 |
131 | int iconLabelSize = 64;
132 | batteryStatusLabel->setMaximumSize(iconLabelSize, iconLabelSize);
133 | batteryStatusLabel->setMinimumSize(iconLabelSize, iconLabelSize);
134 |
135 | cpuFreqLabel = new QLabel(this);
136 | cpuFreqLabel->setMaximumSize(iconLabelSize, iconLabelSize);
137 | cpuFreqLabel->setMinimumSize(iconLabelSize, iconLabelSize);
138 |
139 | cpuTempLabel = new QLabel(this);
140 | cpuTempLabel->setMaximumSize(iconLabelSize, iconLabelSize);
141 | cpuTempLabel->setMinimumSize(iconLabelSize, iconLabelSize);
142 |
143 | statusLayout->addWidget(batteryStatusLabel);
144 | statusLayout->addWidget(cpuFreqLabel);
145 | statusLayout->addWidget(cpuTempLabel);
146 |
147 | // battery
148 | const auto batteryContainer = new QGroupBox(this);
149 | batteryContainer->setTitle(tr("On Battery"));
150 | batteryContainer->setSizePolicy(QSizePolicy::Expanding,
151 | QSizePolicy::Expanding);
152 | const auto batteryContainerLayout = new QVBoxLayout(batteryContainer);
153 | batteryContainerLayout->setSpacing(0);
154 |
155 | const auto lidActionBatteryContainer = new QWidget(this);
156 | const auto lidActionBatteryContainerLayout = new QHBoxLayout(lidActionBatteryContainer);
157 | lidActionBatteryContainerLayout->setMargin(0);
158 |
159 | lidActionBattery = new QComboBox(this);
160 | lidActionBattery->setMaximumWidth(MAX_WIDTH);
161 | lidActionBattery->setMinimumWidth(MAX_WIDTH);
162 |
163 | lidActionBatteryLabel = new QLabel(this);
164 | lidActionBatteryLabel->setText(tr("Lid action"));
165 | lidActionBatteryLabel->setToolTip(tr("What to do when the lid is closed and running on battery."));
166 |
167 | lidActionBatteryContainerLayout->addWidget(lidActionBatteryLabel);
168 | lidActionBatteryContainerLayout->addStretch();
169 | lidActionBatteryContainerLayout->addWidget(lidActionBattery);
170 |
171 | const auto criticalBatteryContainer = new QWidget(this);
172 | const auto criticalBatteryContainerLayout = new QHBoxLayout(criticalBatteryContainer);
173 | criticalBatteryContainerLayout->setMargin(0);
174 |
175 | criticalBattery = new QSpinBox(this);
176 | criticalBattery->setMaximumWidth(MAX_WIDTH);
177 | criticalBattery->setMinimumWidth(MAX_WIDTH);
178 | criticalBattery->setMinimum(0);
179 | criticalBattery->setMaximum(99);
180 | criticalBattery->setSuffix(tr(" %"));
181 | criticalBattery->setPrefix(tr("At "));
182 |
183 | const auto criticalBatteryLabel = new QLabel(this);
184 | const auto criticalActionBatteryContainer = new QWidget(this);
185 | criticalActionBatteryContainer->setContentsMargins(0, 0, 0, 0);
186 |
187 | const auto criticalActionBatteryContainerLayout = new QVBoxLayout(criticalActionBatteryContainer);
188 | criticalActionBatteryContainerLayout->setMargin(0);
189 |
190 | criticalActionBatteryContainerLayout->setMargin(0);
191 | criticalActionBatteryContainerLayout->setSpacing(0);
192 | criticalActionBattery = new QComboBox(this);
193 | criticalActionBattery->setMaximumWidth(MAX_WIDTH);
194 | criticalActionBattery->setMinimumWidth(MAX_WIDTH);
195 | criticalActionBatteryContainerLayout->addWidget(criticalBattery);
196 | criticalActionBatteryContainerLayout->addWidget(criticalActionBattery);
197 |
198 | criticalBatteryLabel->setText(tr("Critical Action"));
199 | criticalBatteryLabel->setToolTip(tr("What to do when your battery is critical."));
200 | criticalBatteryContainerLayout->addWidget(criticalBatteryLabel);
201 | criticalBatteryContainerLayout->addStretch();
202 | criticalBatteryContainerLayout->addWidget(criticalActionBatteryContainer);
203 |
204 | const auto sleepBatteryContainer = new QWidget(this);
205 | const auto sleepBatteryContainerLayout = new QHBoxLayout(sleepBatteryContainer);
206 | sleepBatteryContainerLayout->setMargin(0);
207 |
208 | autoSleepBattery = new QSpinBox(this);
209 | autoSleepBattery->setMaximumWidth(MAX_WIDTH);
210 | autoSleepBattery->setMinimumWidth(MAX_WIDTH);
211 | autoSleepBattery->setMinimum(0);
212 | autoSleepBattery->setMaximum(1000);
213 | autoSleepBattery->setSuffix(QString(" %1").arg(tr("min")));
214 | autoSleepBattery->setPrefix(QString("%1 ").arg(tr("After")));
215 |
216 | const auto sleepBatteryLabel = new QLabel(this);
217 | const auto sleepActionBatteryContainer = new QWidget(this);
218 | const auto sleepActionBatteryContainerLayout = new QVBoxLayout(sleepActionBatteryContainer);
219 |
220 | sleepActionBatteryContainer->setContentsMargins(0, 0, 0, 0);
221 | sleepActionBatteryContainerLayout->setMargin(0);
222 | sleepActionBatteryContainerLayout->setSpacing(0);
223 | autoSleepBatteryAction = new QComboBox(this);
224 | autoSleepBatteryAction->setMaximumWidth(MAX_WIDTH);
225 | autoSleepBatteryAction->setMinimumWidth(MAX_WIDTH);
226 | sleepActionBatteryContainerLayout->addWidget(autoSleepBattery);
227 | sleepActionBatteryContainerLayout->addWidget(autoSleepBatteryAction);
228 |
229 | sleepBatteryLabel->setText(tr("Suspend Action"));
230 | sleepBatteryLabel->setToolTip(tr("Enable automatically suspend when on battery."));
231 | sleepBatteryContainerLayout->addWidget(sleepBatteryLabel);
232 | sleepBatteryContainerLayout->addStretch();
233 | sleepBatteryContainerLayout->addWidget(sleepActionBatteryContainer);
234 |
235 | // backlight battery
236 | backlightSliderBattery = new QSlider(this);
237 | backlightSliderBattery->setOrientation(Qt::Horizontal);
238 | backlightSliderBattery->setMinimum(1);
239 | backlightSliderBattery->setMaximum(1);
240 | backlightSliderBattery->setValue(0);
241 |
242 | backlightBatteryCheck = new QCheckBox(this);
243 | backlightBatteryCheck->setCheckable(true);
244 | backlightBatteryCheck->setChecked(false);
245 | backlightBatteryCheck->setToolTip(tr("Enable/Disable brightness override on battery."));
246 | backlightBatteryCheck->setText(QString(" ")); // qt ui bug workaround
247 |
248 | backlightBatteryLowerCheck = new QCheckBox(this);
249 | backlightBatteryLowerCheck->setCheckable(true);
250 | backlightBatteryLowerCheck->setChecked(false);
251 | backlightBatteryLowerCheck->setText(tr("Don't apply if lower"));
252 | backlightBatteryLowerCheck->setToolTip(tr("If your current brightness value is lower"
253 | " do not apply a brightness override (on battery)."));
254 |
255 | const auto backlightSliderBatteryContainer = new QWidget(this);
256 | const auto backlightSliderBatteryLayout = new QHBoxLayout(backlightSliderBatteryContainer);
257 | backlightSliderBatteryContainer->setContentsMargins(0, 0, 0, 0);
258 | backlightSliderBatteryLayout->setMargin(0);
259 |
260 | backlightSliderBatteryLayout->addWidget(backlightBatteryCheck);
261 | backlightSliderBatteryLayout->addWidget(backlightSliderBattery);
262 |
263 | const auto batteryBacklightOptContainer = new QWidget(this);
264 | const auto batteryBacklightOptContainerLayout = new QVBoxLayout(batteryBacklightOptContainer);
265 |
266 | batteryBacklightOptContainer->setContentsMargins(0, 0, 0, 0);
267 | batteryBacklightOptContainer->setMaximumWidth(MAX_WIDTH);
268 | batteryBacklightOptContainer->setMinimumWidth(MAX_WIDTH);
269 | batteryBacklightOptContainerLayout->setMargin(0);
270 | batteryBacklightOptContainerLayout->setContentsMargins(0, 0, 0, 0);
271 | batteryBacklightOptContainerLayout->addWidget(backlightSliderBatteryContainer);
272 | batteryBacklightOptContainerLayout->addWidget(backlightBatteryLowerCheck);
273 |
274 | const auto batteryBacklightContainer = new QWidget(this);
275 | const auto batteryBacklightContainerLayout = new QHBoxLayout(batteryBacklightContainer);
276 | batteryBacklightContainerLayout->setMargin(0);
277 |
278 | batteryBacklightLabel = new QLabel(this);
279 | batteryBacklightLabel->setText(tr("Brightness"));
280 | batteryBacklightLabel->setToolTip(tr("Override brightness when switched to battery power."));
281 |
282 | batteryBacklightContainerLayout->addWidget(batteryBacklightLabel);
283 | batteryBacklightContainerLayout->addStretch();
284 | batteryBacklightContainerLayout->addWidget(batteryBacklightOptContainer);
285 |
286 | // add battery widgets to container
287 | batteryContainerLayout->addWidget(lidActionBatteryContainer);
288 | batteryContainerLayout->addSpacing(10);
289 | batteryContainerLayout->addWidget(sleepBatteryContainer);
290 | batteryContainerLayout->addSpacing(10);
291 | batteryContainerLayout->addWidget(criticalBatteryContainer);
292 | batteryContainerLayout->addSpacing(10);
293 | batteryContainerLayout->addStretch();
294 | batteryContainerLayout->addWidget(batteryBacklightContainer);
295 |
296 | // AC
297 | const auto acContainer = new QGroupBox(this);
298 | acContainer->setTitle(tr("On AC"));
299 | const auto acContainerLayout = new QVBoxLayout(acContainer);
300 | acContainerLayout->setSpacing(0);
301 |
302 | const auto lidActionACContainer = new QWidget(this);
303 | const auto lidActionACContainerLayout = new QHBoxLayout(lidActionACContainer);
304 | lidActionACContainerLayout->setMargin(0);
305 |
306 | lidActionAC = new QComboBox(this);
307 | lidActionAC->setMaximumWidth(MAX_WIDTH);
308 | lidActionAC->setMinimumWidth(MAX_WIDTH);
309 | lidActionACLabel = new QLabel(this);
310 |
311 | lidActionACLabel->setText(tr("Lid action"));
312 | lidActionACLabel->setToolTip(tr("What to do when the lid is closed and running on AC."));
313 | lidActionACContainerLayout->addWidget(lidActionACLabel);
314 | lidActionACContainerLayout->addStretch();
315 | lidActionACContainerLayout->addWidget(lidActionAC);
316 | acContainerLayout->addWidget(lidActionACContainer);
317 |
318 | const auto sleepACContainer = new QWidget(this);
319 | const auto sleepACContainerLayout = new QHBoxLayout(sleepACContainer);
320 | sleepACContainerLayout->setMargin(0);
321 |
322 | autoSleepAC = new QSpinBox(this);
323 | autoSleepAC->setMaximumWidth(MAX_WIDTH);
324 | autoSleepAC->setMinimumWidth(MAX_WIDTH);
325 | autoSleepAC->setMinimum(0);
326 | autoSleepAC->setMaximum(1000);
327 | autoSleepAC->setSuffix(QString(" %1").arg(tr("min")));
328 | autoSleepAC->setPrefix(QString("%1 ").arg(tr("After")));
329 |
330 | const auto sleepACLabel = new QLabel(this);
331 |
332 | sleepACContainerLayout->addWidget(sleepACLabel);
333 | acContainerLayout->addWidget(sleepACContainer);
334 |
335 | const auto sleepActionACContainer = new QWidget(this);
336 | const auto sleepActionACContainerLayout = new QVBoxLayout(sleepActionACContainer);
337 |
338 | sleepActionACContainer->setContentsMargins(0, 0, 0, 0);
339 | sleepActionACContainerLayout->setMargin(0);
340 | sleepActionACContainerLayout->setSpacing(0);
341 | autoSleepACAction = new QComboBox(this);
342 | autoSleepACAction->setMaximumWidth(MAX_WIDTH);
343 | autoSleepACAction->setMinimumWidth(MAX_WIDTH);
344 | sleepActionACContainerLayout->addWidget(autoSleepAC);
345 | sleepActionACContainerLayout->addWidget(autoSleepACAction);
346 |
347 | sleepACLabel->setText(tr("Suspend Action"));
348 | sleepACLabel->setToolTip(tr("Enable automatically suspend when on AC."));
349 | sleepACContainerLayout->addWidget(sleepACLabel);
350 | sleepACContainerLayout->addStretch();
351 | sleepACContainerLayout->addWidget(sleepActionACContainer);
352 |
353 | // backlight ac
354 | backlightSliderAC = new QSlider(this);
355 | backlightSliderAC->setOrientation(Qt::Horizontal);
356 | backlightSliderAC->setMinimum(1);
357 | backlightSliderAC->setMaximum(1);
358 | backlightSliderAC->setValue(0);
359 |
360 | backlightACCheck = new QCheckBox(this);
361 | backlightACCheck->setCheckable(true);
362 | backlightACCheck->setChecked(false);
363 | backlightACCheck->setToolTip(tr("Enable/Disable brightness override on AC."));
364 | backlightACCheck->setText(QString(" ")); // qt ui bug workaround
365 |
366 | backlightACHigherCheck = new QCheckBox(this);
367 | backlightACHigherCheck->setCheckable(true);
368 | backlightACHigherCheck->setChecked(false);
369 | backlightACHigherCheck->setText(tr("Don't apply if higher"));
370 | backlightACHigherCheck->setToolTip(tr("If your current brightness value is higher"
371 | " do not apply a brightness override (on AC)."));
372 |
373 | const auto backlightSliderAcContainer = new QWidget(this);
374 | const auto backlightSliderAcLayout = new QHBoxLayout(backlightSliderAcContainer);
375 | backlightSliderAcContainer->setContentsMargins(0, 0, 0, 0);
376 | backlightSliderAcLayout->setMargin(0);
377 |
378 | backlightSliderAcLayout->addWidget(backlightACCheck);
379 | backlightSliderAcLayout->addWidget(backlightSliderAC);
380 |
381 | const auto acBacklightOptContainer = new QWidget(this);
382 | const auto acBacklightOptContainerLayout = new QVBoxLayout(acBacklightOptContainer);
383 |
384 | acBacklightOptContainer->setContentsMargins(0, 0, 0, 0);
385 | acBacklightOptContainer->setMaximumWidth(MAX_WIDTH);
386 | acBacklightOptContainer->setMinimumWidth(MAX_WIDTH);
387 | acBacklightOptContainerLayout->setMargin(0);
388 | acBacklightOptContainerLayout->setContentsMargins(0, 0, 0, 0);
389 | acBacklightOptContainerLayout->addWidget(backlightSliderAcContainer);
390 | acBacklightOptContainerLayout->addWidget(backlightACHigherCheck);
391 |
392 | const auto acBacklightContainer = new QWidget(this);
393 | const auto acBacklightContainerLayout = new QHBoxLayout(acBacklightContainer);
394 | acBacklightContainerLayout->setMargin(0);
395 |
396 | acBacklightLabel = new QLabel(this);
397 |
398 | acBacklightLabel->setText(tr("Brightness"));
399 | acBacklightLabel->setToolTip(tr("Override brightness when switched to AC power."));
400 | acBacklightContainerLayout->addWidget(acBacklightLabel);
401 | acBacklightContainerLayout->addStretch();
402 | acBacklightContainerLayout->addWidget(acBacklightOptContainer);
403 |
404 | // add widgets to ac
405 | acContainerLayout->addSpacing(10);
406 | acContainerLayout->addWidget(sleepACContainer);
407 | acContainerLayout->addSpacing(10);
408 | acContainerLayout->addStretch();
409 | acContainerLayout->addWidget(acBacklightContainer);
410 |
411 | // common
412 | const auto daemonContainer = new QGroupBox(this);
413 | daemonContainer->setTitle(tr("Options"));
414 | const auto daemonContainerLayout = new QVBoxLayout(daemonContainer);
415 |
416 | showSystemTray = new QCheckBox(this);
417 | showSystemTray->setText(tr("Show system tray"));
418 | showSystemTray->setToolTip(tr("Enable/Disable the system tray icon."
419 | " Note that notifications will not work when the systemtray is disabled."));
420 |
421 | disableLidAction = new QCheckBox(this);
422 | disableLidAction->setText(tr("Disable lid action if external monitor connected"));
423 | disableLidAction->setToolTip(tr("Disable lid action if an external monitor is connected"
424 | " to your laptop."));
425 |
426 | backlightMouseWheel = new QCheckBox(this);
427 | backlightMouseWheel->setText(tr("Adjust brightness in system tray"));
428 | backlightMouseWheel->setToolTip(tr("Adjust the display backlight brightness with the mouse wheel on the system tray icon."));
429 |
430 | daemonContainerLayout->addWidget(showSystemTray);
431 | daemonContainerLayout->addWidget(backlightMouseWheel);
432 | daemonContainerLayout->addWidget(disableLidAction);
433 | daemonContainerLayout->addStretch();
434 |
435 | // screensaver
436 | const auto ssContainer = new QWidget(this);
437 | const auto ssContainerLayout = new QHBoxLayout(ssContainer);
438 | ssContainerLayout->setMargin(0);
439 |
440 | const auto screensaverBlankLabel = new QLabel(tr("Screen Saver Timeout"), this);
441 | screensaverBlank = new QSpinBox(this);
442 | screensaverBlank->setMaximumWidth(MAX_WIDTH);
443 | screensaverBlank->setMinimumWidth(MAX_WIDTH);
444 | screensaverBlank->setMinimum(1);
445 | screensaverBlank->setMaximum(1000);
446 | screensaverBlank->setSuffix(QString(" %1").arg(tr("min")));
447 | screensaverBlank->setPrefix(tr("After "));
448 |
449 | ssContainerLayout->addWidget(screensaverBlankLabel);
450 | ssContainerLayout->addWidget(screensaverBlank);
451 |
452 | // notify
453 | const auto notifyContainer = new QGroupBox(this);
454 | notifyContainer->setTitle(tr("Notifications"));
455 | const auto notifyContainerLayout = new QVBoxLayout(notifyContainer);
456 |
457 | showNotifications = new QCheckBox(this);
458 | showNotifications->setText(tr("Show notifications"));
459 | showNotifications->setToolTip(tr("Show notifications for power related events."));
460 |
461 | warnOnLowBattery = new QCheckBox(this);
462 | warnOnLowBattery->setText(tr("Notify on low battery"));
463 | warnOnLowBattery->setToolTip(tr("Show a notification when on low battery (%1% over critical)")
464 | .arg(POWERKIT_LOW_BATTERY));
465 |
466 | warnOnVeryLowBattery = new QCheckBox(this);
467 | warnOnVeryLowBattery->setText(tr("Notify on very low battery"));
468 | warnOnVeryLowBattery->setToolTip(tr("Show a notification when on very low battery (1% over critical)"));
469 |
470 | notifyOnBattery = new QCheckBox(this);
471 | notifyOnBattery->setText(tr("Notify on battery"));
472 | notifyOnBattery->setToolTip(tr("Notify when switched on battery power"));
473 |
474 | notifyOnAC = new QCheckBox(this);
475 | notifyOnAC->setText(tr("Notify on AC"));
476 | notifyOnAC->setToolTip(tr("Notify when switched on AC power"));
477 |
478 | notifyNewInhibitor = new QCheckBox(this);
479 | notifyNewInhibitor->setText(tr("Notify on new inhibitors"));
480 | notifyNewInhibitor->setToolTip(tr("Notify on new screensaver or power inhibitors"));
481 |
482 | notifyContainerLayout->addWidget(showNotifications);
483 | notifyContainerLayout->addWidget(warnOnLowBattery);
484 | notifyContainerLayout->addWidget(warnOnVeryLowBattery);
485 | notifyContainerLayout->addWidget(notifyOnBattery);
486 | notifyContainerLayout->addWidget(notifyOnAC);
487 | notifyContainerLayout->addWidget(notifyNewInhibitor);
488 | notifyContainerLayout->addStretch();
489 |
490 | const auto commonWidget = new QWidget(this);
491 | const auto commonWidgetLayout = new QVBoxLayout(commonWidget);
492 |
493 | const auto optContainer = new QWidget(this);
494 | const auto optContainerLayout = new QHBoxLayout(optContainer);
495 | optContainerLayout->setMargin(0);
496 |
497 | const auto batteryAcContainer = new QWidget(this);
498 | const auto batteryAcContainerLayout = new QHBoxLayout(batteryAcContainer);
499 | batteryAcContainerLayout->setMargin(0);
500 |
501 | batteryAcContainerLayout->addWidget(batteryContainer);
502 | batteryAcContainerLayout->addWidget(acContainer);
503 |
504 | optContainerLayout->addWidget(daemonContainer);
505 | optContainerLayout->addWidget(notifyContainer);
506 |
507 | commonWidgetLayout->addWidget(batteryAcContainer);
508 | commonWidgetLayout->addWidget(optContainer);
509 | commonWidgetLayout->addWidget(ssContainer);
510 |
511 | const auto scrollArea = new QScrollArea(this);
512 | scrollArea->setSizePolicy(QSizePolicy::Expanding,
513 | QSizePolicy::Expanding);
514 | scrollArea->setWidgetResizable(true);
515 | scrollArea->setStyleSheet("QScrollArea { border: 0; }");
516 | scrollArea->setWidget(commonWidget);
517 |
518 | layout->addWidget(statusWidget);
519 | layout->addWidget(scrollArea);
520 |
521 | handleUpdatedDevices();
522 | }
523 |
524 | // populate widgets with default values
525 | void Dialog::populateWidgets()
526 | {
527 | lidActionBattery->clear();
528 | lidActionBattery->addItem(tr("None"), lidNone);
529 | lidActionBattery->addItem(tr("Lock Screen"), lidLock);
530 | lidActionBattery->addItem(tr("Sleep"), lidSleep);
531 | lidActionBattery->addItem(tr("Hibernate"), lidHibernate);
532 | lidActionBattery->addItem(tr("Shutdown"), lidShutdown);
533 | lidActionBattery->addItem(tr("Hybrid Sleep"), lidHybridSleep);
534 | lidActionBattery->addItem(tr("Sleep then Hibernate"), lidSleepHibernate);
535 |
536 | lidActionAC->clear();
537 | lidActionAC->addItem(tr("None"), lidNone);
538 | lidActionAC->addItem(tr("Lock Screen"), lidLock);
539 | lidActionAC->addItem(tr("Sleep"), lidSleep);
540 | lidActionAC->addItem(tr("Hibernate"), lidHibernate);
541 | lidActionAC->addItem(tr("Shutdown"), lidShutdown);
542 | lidActionAC->addItem(tr("Hybrid Sleep"), lidHybridSleep);
543 | lidActionAC->addItem(tr("Sleep then Hibernate"), lidSleepHibernate);
544 |
545 | criticalActionBattery->clear();
546 | criticalActionBattery->addItem(tr("None"), criticalNone);
547 | criticalActionBattery->addItem(tr("Sleep"), criticalSuspend);
548 | criticalActionBattery->addItem(tr("Hibernate"), criticalHibernate);
549 | criticalActionBattery->addItem(tr("Shutdown"), criticalShutdown);
550 |
551 | autoSleepBatteryAction->clear();
552 | autoSleepBatteryAction->addItem(tr("None"), suspendNone);
553 | autoSleepBatteryAction->addItem(tr("Sleep"), suspendSleep);
554 | autoSleepBatteryAction->addItem(tr("Hibernate"), suspendHibernate);
555 | autoSleepBatteryAction->addItem(tr("Shutdown"), suspendShutdown);
556 | autoSleepBatteryAction->addItem(tr("Hybrid Sleep"), suspendHybrid);
557 | autoSleepBatteryAction->addItem(tr("Sleep then Hibernate"), suspendSleepHibernate);
558 |
559 | autoSleepACAction->clear();
560 | autoSleepACAction->addItem(tr("None"), suspendNone);
561 | autoSleepACAction->addItem(tr("Sleep"), suspendSleep);
562 | autoSleepACAction->addItem(tr("Hibernate"), suspendHibernate);
563 | autoSleepACAction->addItem(tr("Shutdown"), suspendShutdown);
564 | autoSleepACAction->addItem(tr("Hybrid Sleep"), suspendHybrid);
565 | autoSleepACAction->addItem(tr("Sleep then Hibernate"), suspendSleepHibernate);
566 | }
567 |
568 | void Dialog::connectWidgets()
569 | {
570 | connect(lidActionBattery, SIGNAL(currentIndexChanged(int)),
571 | this, SLOT(handleLidActionBattery(int)));
572 | connect(lidActionAC, SIGNAL(currentIndexChanged(int)),
573 | this, SLOT(handleLidActionAC(int)));
574 | connect(criticalActionBattery, SIGNAL(currentIndexChanged(int)),
575 | this, SLOT(handleCriticalAction(int)));
576 | connect(criticalBattery, SIGNAL(valueChanged(int)),
577 | this, SLOT(handleCriticalBattery(int)));
578 | connect(autoSleepBattery, SIGNAL(valueChanged(int)),
579 | this, SLOT(handleAutoSleepBattery(int)));
580 | connect(autoSleepAC, SIGNAL(valueChanged(int)),
581 | this, SLOT(handleAutoSleepAC(int)));
582 | connect(showNotifications, SIGNAL(toggled(bool)),
583 | this, SLOT(handleShowNotifications(bool)));
584 | connect(showSystemTray, SIGNAL(toggled(bool)),
585 | this, SLOT(handleShowSystemTray(bool)));
586 | connect(disableLidAction, SIGNAL(toggled(bool)),
587 | this, SLOT(handleDisableLidAction(bool)));
588 | connect(autoSleepBatteryAction, SIGNAL(currentIndexChanged(int)),
589 | this, SLOT(handleAutoSleepBatteryAction(int)));
590 | connect(autoSleepACAction, SIGNAL(currentIndexChanged(int)),
591 | this, SLOT(handleAutoSleepACAction(int)));
592 | connect(backlightBatteryCheck, SIGNAL(toggled(bool)),
593 | this, SLOT(handleBacklightBatteryCheck(bool)));
594 | connect(backlightACCheck, SIGNAL(toggled(bool)),
595 | this, SLOT(handleBacklightACCheck(bool)));
596 | connect(backlightSliderBattery, SIGNAL(valueChanged(int)),
597 | this, SLOT(handleBacklightBatterySlider(int)));
598 | connect(backlightSliderAC, SIGNAL(valueChanged(int)),
599 | this, SLOT(handleBacklightACSlider(int)));
600 | connect(backlightBatteryLowerCheck, SIGNAL(toggled(bool)),
601 | this, SLOT(handleBacklightBatteryCheckLower(bool)));
602 | connect(backlightACHigherCheck, SIGNAL(toggled(bool)),
603 | this, SLOT(handleBacklightACCheckHigher(bool)));
604 | connect(warnOnLowBattery, SIGNAL(toggled(bool)),
605 | this, SLOT(handleWarnOnLowBattery(bool)));
606 | connect(warnOnVeryLowBattery, SIGNAL(toggled(bool)),
607 | this, SLOT(handleWarnOnVeryLowBattery(bool)));
608 | connect(notifyOnBattery, SIGNAL(toggled(bool)),
609 | this, SLOT(handleNotifyBattery(bool)));
610 | connect(notifyOnAC, SIGNAL(toggled(bool)),
611 | this, SLOT(handleNotifyAC(bool)));
612 | connect(notifyNewInhibitor, SIGNAL(toggled(bool)),
613 | this, SLOT(handleNotifyNewInhibitor(bool)));
614 | connect(backlightMouseWheel, SIGNAL(toggled(bool)),
615 | this, SLOT(handleBacklightMouseWheel(bool)));
616 | connect(screensaverBlank, SIGNAL(valueChanged(int)),
617 | this, SLOT(handleScreensaverBlank(int)));
618 | }
619 |
620 | // load settings and set defaults
621 | void Dialog::loadSettings()
622 | {
623 | if (Settings::isValid(CONF_DIALOG_GEOMETRY)) {
624 | restoreGeometry(Settings::getValue(CONF_DIALOG_GEOMETRY).toByteArray());
625 | }
626 |
627 | int defaultAutoSleepBattery = POWERKIT_AUTO_SLEEP_BATTERY;
628 | if (Settings::isValid(CONF_SUSPEND_BATTERY_TIMEOUT)) {
629 | defaultAutoSleepBattery = Settings::getValue(CONF_SUSPEND_BATTERY_TIMEOUT).toInt();
630 | }
631 | setDefaultAction(autoSleepBattery, defaultAutoSleepBattery);
632 |
633 | int defaultAutoSleepBatteryAction = POWERKIT_SUSPEND_BATTERY_ACTION;
634 | if (Settings::isValid(CONF_SUSPEND_BATTERY_ACTION)) {
635 | defaultAutoSleepBatteryAction = Settings::getValue(CONF_SUSPEND_BATTERY_ACTION).toInt();
636 | }
637 | setDefaultAction(autoSleepBatteryAction, defaultAutoSleepBatteryAction);
638 |
639 | int defaultAutoSleepAC = 0;
640 | if (Settings::isValid(CONF_SUSPEND_AC_TIMEOUT)) {
641 | defaultAutoSleepAC = Settings::getValue(CONF_SUSPEND_AC_TIMEOUT).toInt();
642 | }
643 | setDefaultAction(autoSleepAC, defaultAutoSleepAC);
644 |
645 | int defaultAutoSleepACAction = POWERKIT_SUSPEND_AC_ACTION;
646 | if (Settings::isValid(CONF_SUSPEND_AC_ACTION)) {
647 | defaultAutoSleepACAction = Settings::getValue(CONF_SUSPEND_AC_ACTION).toInt();
648 | }
649 | setDefaultAction(autoSleepACAction, defaultAutoSleepACAction);
650 |
651 | int defaultCriticalBattery = POWERKIT_CRITICAL_BATTERY;
652 | if (Settings::isValid(CONF_CRITICAL_BATTERY_TIMEOUT)) {
653 | defaultCriticalBattery = Settings::getValue(CONF_CRITICAL_BATTERY_TIMEOUT).toInt();
654 | }
655 | setDefaultAction(criticalBattery, defaultCriticalBattery);
656 |
657 | int defaultLidActionBattery = POWERKIT_LID_BATTERY_ACTION;
658 | if (Settings::isValid(CONF_LID_BATTERY_ACTION)) {
659 | defaultLidActionBattery = Settings::getValue(CONF_LID_BATTERY_ACTION).toInt();
660 | }
661 | setDefaultAction(lidActionBattery, defaultLidActionBattery);
662 |
663 | int defaultLidActionAC = POWERKIT_LID_AC_ACTION;
664 | if (Settings::isValid(CONF_LID_AC_ACTION)) {
665 | defaultLidActionAC = Settings::getValue(CONF_LID_AC_ACTION).toInt();
666 | }
667 | setDefaultAction(lidActionAC, defaultLidActionAC);
668 |
669 | int defaultCriticalAction = POWERKIT_CRITICAL_ACTION;
670 | if (Settings::isValid(CONF_CRITICAL_BATTERY_ACTION)) {
671 | defaultCriticalAction = Settings::getValue(CONF_CRITICAL_BATTERY_ACTION).toInt();
672 | }
673 | setDefaultAction(criticalActionBattery, defaultCriticalAction);
674 |
675 | bool defaultShowNotifications = true;
676 | if (Settings::isValid(CONF_TRAY_NOTIFY)) {
677 | defaultShowNotifications = Settings::getValue(CONF_TRAY_NOTIFY).toBool();
678 | }
679 | showNotifications->setChecked(defaultShowNotifications);
680 |
681 | bool defaultShowTray = true;
682 | if (Settings::isValid(CONF_TRAY_SHOW)) {
683 | defaultShowTray = Settings::getValue(CONF_TRAY_SHOW).toBool();
684 | }
685 | showSystemTray->setChecked(defaultShowTray);
686 |
687 | bool defaultDisableLidAction = true;
688 | if (Settings::isValid(CONF_LID_DISABLE_IF_EXTERNAL)) {
689 | defaultDisableLidAction = Settings::getValue(CONF_LID_DISABLE_IF_EXTERNAL).toBool();
690 | }
691 | disableLidAction->setChecked(defaultDisableLidAction);
692 |
693 | bool defaultWarnOnLowBattery = true;
694 | if (Settings::isValid(CONF_WARN_ON_LOW_BATTERY)) {
695 | defaultWarnOnLowBattery = Settings::getValue(CONF_WARN_ON_LOW_BATTERY).toBool();
696 | }
697 | warnOnLowBattery->setChecked(defaultWarnOnLowBattery);
698 |
699 | bool defaultWarnOnVeryLowBattery = true;
700 | if (Settings::isValid(CONF_WARN_ON_VERYLOW_BATTERY)) {
701 | defaultWarnOnVeryLowBattery = Settings::getValue(CONF_WARN_ON_VERYLOW_BATTERY).toBool();
702 | }
703 | warnOnVeryLowBattery->setChecked(defaultWarnOnVeryLowBattery);
704 |
705 | bool defaultNotifyOnBattery = true;
706 | if (Settings::isValid(CONF_NOTIFY_ON_BATTERY)) {
707 | defaultNotifyOnBattery = Settings::getValue(CONF_NOTIFY_ON_BATTERY).toBool();
708 | }
709 | notifyOnBattery->setChecked(defaultNotifyOnBattery);
710 |
711 | bool defaultNotifyOnAC = true;
712 | if (Settings::isValid(CONF_NOTIFY_ON_AC)) {
713 | defaultNotifyOnAC = Settings::getValue(CONF_NOTIFY_ON_AC).toBool();
714 | }
715 | notifyOnAC->setChecked(defaultNotifyOnAC);
716 |
717 | bool defaultNotifyNewInhibitor = true;
718 | if (Settings::isValid(CONF_NOTIFY_NEW_INHIBITOR)) {
719 | defaultNotifyNewInhibitor = Settings::getValue(CONF_NOTIFY_NEW_INHIBITOR).toBool();
720 | }
721 | notifyNewInhibitor->setChecked(defaultNotifyNewInhibitor);
722 |
723 | // check
724 | checkPerms();
725 |
726 | // backlight
727 | backlightDevice = Backlight::getDevice();
728 |
729 | backlightSliderAC->setEnabled(true);
730 | backlightSliderBattery->setEnabled(true);
731 |
732 | int backlightMin = 1;
733 | int backlightMax = Backlight::getMaxBrightness(backlightDevice);
734 |
735 | backlightSliderBattery->setMinimum(backlightMin);
736 | backlightSliderBattery->setMaximum(backlightMax);
737 | backlightSliderBattery->setValue(backlightSliderBattery->maximum());
738 | backlightSliderAC->setMinimum(backlightMin);
739 | backlightSliderAC->setMaximum(backlightMax);
740 | backlightSliderAC->setValue(backlightSliderAC->maximum());
741 |
742 | backlightBatteryCheck->setChecked(Settings::getValue(CONF_BACKLIGHT_BATTERY_ENABLE)
743 | .toBool());
744 | backlightACCheck->setChecked(Settings::getValue(CONF_BACKLIGHT_AC_ENABLE)
745 | .toBool());
746 | if (Settings::isValid(CONF_BACKLIGHT_BATTERY)) {
747 | backlightSliderBattery->setValue(Settings::getValue(CONF_BACKLIGHT_BATTERY)
748 | .toInt());
749 | }
750 | if (Settings::isValid(CONF_BACKLIGHT_AC)) {
751 | backlightSliderAC->setValue(Settings::getValue(CONF_BACKLIGHT_AC)
752 | .toInt());
753 | }
754 | if (Settings::isValid(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER)) {
755 | backlightBatteryLowerCheck->setChecked(
756 | Settings::getValue(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER)
757 | .toBool());
758 | }
759 | if (Settings::isValid(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER)) {
760 | backlightACHigherCheck->setChecked(
761 | Settings::getValue(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER)
762 | .toBool());
763 | }
764 | bool defaultBacklightMouseWheel = true;
765 | if (Settings::isValid(CONF_BACKLIGHT_MOUSE_WHEEL)) {
766 | defaultBacklightMouseWheel = Settings::getValue(CONF_BACKLIGHT_MOUSE_WHEEL).toBool();
767 | }
768 | backlightMouseWheel->setChecked(defaultBacklightMouseWheel);
769 |
770 | enableBacklight(true);
771 | enableLid(Client::lidIsPresent(dbus));
772 | hasCpuCoreTemp = Cpu::hasCoreTemp();
773 | if (!hasCpuCoreTemp) { cpuTempLabel->setVisible(false); }
774 |
775 | screensaverBlank->setValue(Settings::getValue(CONF_SCREENSAVER_TIMEOUT_BLANK,
776 | POWERKIT_SCREENSAVER_TIMEOUT_BLANK).toInt() / 60);
777 | }
778 |
779 | void Dialog::saveSettings()
780 | {
781 | Settings::setValue(CONF_LID_BATTERY_ACTION,
782 | lidActionBattery->currentData().toInt());
783 | Settings::setValue(CONF_LID_AC_ACTION,
784 | lidActionAC->currentData().toInt());
785 | Settings::setValue(CONF_CRITICAL_BATTERY_ACTION,
786 | criticalActionBattery->currentData().toInt());
787 | Settings::setValue(CONF_CRITICAL_BATTERY_TIMEOUT,
788 | criticalBattery->value());
789 | Settings::setValue(CONF_SUSPEND_BATTERY_TIMEOUT,
790 | autoSleepBattery->value());
791 | Settings::setValue(CONF_SUSPEND_AC_TIMEOUT,
792 | autoSleepAC->value());
793 | Settings::setValue(CONF_TRAY_NOTIFY,
794 | showNotifications->isChecked());
795 | Settings::setValue(CONF_TRAY_SHOW,
796 | showSystemTray->isChecked());
797 | Settings::setValue(CONF_LID_DISABLE_IF_EXTERNAL,
798 | disableLidAction->isChecked());
799 | Settings::setValue(CONF_SUSPEND_BATTERY_ACTION,
800 | autoSleepBatteryAction->currentData().toInt());
801 | Settings::setValue(CONF_SUSPEND_AC_ACTION,
802 | autoSleepACAction->currentData().toInt());
803 | Settings::setValue(CONF_BACKLIGHT_BATTERY_ENABLE,
804 | backlightBatteryCheck->isChecked());
805 | Settings::setValue(CONF_BACKLIGHT_AC_ENABLE,
806 | backlightACCheck->isChecked());
807 | Settings::setValue(CONF_BACKLIGHT_BATTERY,
808 | backlightSliderBattery->value());
809 | Settings::setValue(CONF_BACKLIGHT_AC,
810 | backlightSliderAC->value());
811 | Settings::setValue(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER,
812 | backlightBatteryLowerCheck->isChecked());
813 | Settings::setValue(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER,
814 | backlightACHigherCheck->isChecked());
815 | Settings::setValue(CONF_DIALOG,
816 | saveGeometry());
817 | Settings::setValue(CONF_WARN_ON_LOW_BATTERY,
818 | warnOnLowBattery->isChecked());
819 | Settings::setValue(CONF_WARN_ON_VERYLOW_BATTERY,
820 | warnOnVeryLowBattery->isChecked());
821 | Settings::setValue(CONF_NOTIFY_ON_BATTERY,
822 | notifyOnBattery->isChecked());
823 | Settings::setValue(CONF_NOTIFY_ON_AC,
824 | notifyOnAC->isChecked());
825 | Settings::setValue(CONF_NOTIFY_NEW_INHIBITOR,
826 | notifyNewInhibitor->isChecked());
827 | Settings::setValue(CONF_BACKLIGHT_MOUSE_WHEEL,
828 | backlightMouseWheel->isChecked());
829 | }
830 |
831 | // set default action in combobox
832 | void Dialog::setDefaultAction(QComboBox *box, int action)
833 | {
834 | for (int i=0;icount();i++) {
835 | if (box->itemData(i).toInt() == action) {
836 | box->setCurrentIndex(i);
837 | return;
838 | }
839 | }
840 | }
841 |
842 | // set default value in spinbox
843 | void Dialog::setDefaultAction(QSpinBox *box, int action)
844 | {
845 | box->setValue(action);
846 | }
847 |
848 | // set default value in combobox
849 | void Dialog::setDefaultAction(QComboBox *box, QString value)
850 | {
851 | for (int i=0;icount();i++) {
852 | if (box->itemText(i) == value) {
853 | box->setCurrentIndex(i);
854 | return;
855 | }
856 | }
857 | }
858 |
859 | void Dialog::drawBattery()
860 | {
861 | if (!hasBattery) { return; }
862 | const auto battery = Client::getBatteryLeft(dbus);
863 | const auto onBattery = Client::onBattery(dbus);
864 | QString batteryTime = QDateTime::fromTime_t(onBattery ? Client::timeToEmpty(dbus) : Client::timeToFull(dbus)).toUTC().toString("hh:mm");
865 | QColor colorBg = Qt::green;
866 | QColor colorFg = Qt::white;
867 | QString status = QString("%1%\n%2").arg(QString::number(battery), batteryTime);
868 | if (onBattery) {
869 | if (battery >= 26) {
870 | colorBg = QColor("orange");
871 | } else {
872 | colorBg = Qt::red;
873 | }
874 | } else {
875 | if (battery == 100) {
876 | colorFg = Qt::green;
877 | status = QString("%1%").arg(QString::number(battery));
878 | }
879 | }
880 | batteryStatusLabel->setPixmap(Theme::drawCircleProgress(battery,
881 | 64,
882 | 4,
883 | 4,
884 | true,
885 | status,
886 | colorBg,
887 | colorFg));
888 | }
889 |
890 | void Dialog::drawCpu()
891 | {
892 | if (cpuFreqLabel) {
893 | const auto freq = Cpu::getCpuFreqLabel();
894 | QColor color = Qt::gray;
895 | if (freq.first >= 50) { color = QColor("orange"); }
896 | cpuFreqLabel->setPixmap(Theme::drawCircleProgress(freq.first,
897 | 64,
898 | 4,
899 | 4,
900 | true,
901 | freq.second,
902 | color,
903 | Qt::white));
904 | }
905 | if (cpuTempLabel && hasCpuCoreTemp) {
906 | const auto temp = Cpu::getCpuTempLabel();
907 | QColor color = Qt::gray;
908 | if (temp.first >= 75) { color = Qt::red; }
909 | else if (temp.first >= 50) { color = QColor("orange"); }
910 | cpuTempLabel->setPixmap(Theme::drawCircleProgress(temp.first,
911 | 64,
912 | 4,
913 | 4,
914 | true,
915 | temp.second,
916 | color,
917 | Qt::white));
918 | }
919 | }
920 |
921 | void Dialog::handleUpdatedDevices()
922 | {
923 | hasBattery = Client::hasBattery(dbus);
924 | batteryStatusLabel->setVisible(hasBattery);
925 | drawBattery();
926 | drawCpu();
927 | }
928 |
929 | // save current value and update power manager
930 | void Dialog::handleLidActionBattery(int index)
931 | {
932 | checkPerms();
933 | Settings::setValue(CONF_LID_BATTERY_ACTION,
934 | lidActionBattery->itemData(index).toInt());
935 | }
936 |
937 | void Dialog::handleLidActionAC(int index)
938 | {
939 | checkPerms();
940 | Settings::setValue(CONF_LID_AC_ACTION,
941 | lidActionAC->itemData(index).toInt());
942 | }
943 |
944 | void Dialog::handleCriticalAction(int index)
945 | {
946 | checkPerms();
947 | Settings::setValue(CONF_CRITICAL_BATTERY_ACTION,
948 | criticalActionBattery->itemData(index).toInt());
949 | }
950 |
951 | void Dialog::handleCriticalBattery(int value)
952 | {
953 | Settings::setValue(CONF_CRITICAL_BATTERY_TIMEOUT, value);
954 | }
955 |
956 | void Dialog::handleAutoSleepBattery(int value)
957 | {
958 | Settings::setValue(CONF_SUSPEND_BATTERY_TIMEOUT, value);
959 | }
960 |
961 | void Dialog::handleAutoSleepAC(int value)
962 | {
963 | Settings::setValue(CONF_SUSPEND_AC_TIMEOUT, value);
964 | }
965 |
966 | void Dialog::handleShowNotifications(bool triggered)
967 | {
968 | Settings::setValue(CONF_TRAY_NOTIFY, triggered);
969 | }
970 |
971 | void Dialog::handleShowSystemTray(bool triggered)
972 | {
973 | Settings::setValue(CONF_TRAY_SHOW, triggered);
974 | }
975 |
976 | void Dialog::handleDisableLidAction(bool triggered)
977 | {
978 | Settings::setValue(CONF_LID_DISABLE_IF_EXTERNAL, triggered);
979 | }
980 |
981 | void Dialog::handleAutoSleepBatteryAction(int index)
982 | {
983 | checkPerms();
984 | Settings::setValue(CONF_SUSPEND_BATTERY_ACTION,
985 | autoSleepBatteryAction->itemData(index).toInt());
986 | }
987 |
988 | void Dialog::handleAutoSleepACAction(int index)
989 | {
990 | checkPerms();
991 | Settings::setValue(CONF_SUSPEND_AC_ACTION,
992 | autoSleepACAction->itemData(index).toInt());
993 | }
994 |
995 | void Dialog::checkPerms()
996 | {
997 | if (!Client::canHibernate(dbus)) {
998 | bool warnCantHibernate = false;
999 | if (criticalActionBattery->currentData().toInt() == criticalHibernate) {
1000 | warnCantHibernate = true;
1001 | criticalActionBattery->setCurrentIndex(criticalShutdown);
1002 | handleCriticalAction(criticalShutdown);
1003 | }
1004 | if (lidActionAC->currentData().toInt() == lidHibernate ||
1005 | lidActionAC->currentData().toInt() == lidHybridSleep) {
1006 | warnCantHibernate = true;
1007 | lidActionAC->setCurrentIndex(lidSleep);
1008 | handleLidActionAC(lidSleep);
1009 | }
1010 | if (lidActionBattery->currentData().toInt() == lidHibernate ||
1011 | lidActionBattery->currentData().toInt() == lidHybridSleep) {
1012 | warnCantHibernate = true;
1013 | lidActionBattery->setCurrentIndex(lidSleep);
1014 | handleLidActionBattery(lidSleep);
1015 | }
1016 | if (autoSleepACAction->currentData().toInt() == suspendHibernate ||
1017 | autoSleepACAction->currentData().toInt() == suspendHybrid) {
1018 | warnCantHibernate = true;
1019 | autoSleepACAction->setCurrentIndex(suspendSleep);
1020 | handleAutoSleepACAction(suspendSleep);
1021 | }
1022 | if (autoSleepBatteryAction->currentData().toInt() == suspendHibernate ||
1023 | autoSleepBatteryAction->currentData().toInt() == suspendHybrid) {
1024 | warnCantHibernate = true;
1025 | autoSleepBatteryAction->setCurrentIndex(suspendSleep);
1026 | handleAutoSleepBatteryAction(suspendSleep);
1027 | }
1028 | if (warnCantHibernate) { hibernateWarn(); }
1029 | }
1030 | if (!Client::canSuspend(dbus)) {
1031 | bool warnCantSleep = false;
1032 | if (lidActionAC->currentData().toInt() == lidSleep) {
1033 | warnCantSleep = true;
1034 | lidActionAC->setCurrentIndex(lidLock);
1035 | handleLidActionAC(lidLock);
1036 | }
1037 | if (lidActionBattery->currentData().toInt() == lidSleep) {
1038 | warnCantSleep = true;
1039 | lidActionBattery->setCurrentIndex(lidLock);
1040 | handleLidActionBattery(lidLock);
1041 | }
1042 | if (autoSleepACAction->currentData().toInt() == suspendSleep) {
1043 | warnCantSleep = true;
1044 | autoSleepACAction->setCurrentIndex(suspendNone);
1045 | handleAutoSleepACAction(suspendNone);
1046 | }
1047 | if (autoSleepBatteryAction->currentData().toInt() == suspendSleep) {
1048 | warnCantSleep = true;
1049 | autoSleepBatteryAction->setCurrentIndex(suspendNone);
1050 | handleAutoSleepBatteryAction(suspendNone);
1051 | }
1052 | if (warnCantSleep) { sleepWarn(); }
1053 | }
1054 | }
1055 |
1056 | void Dialog::handleBacklightBatteryCheck(bool triggered)
1057 | {
1058 | Settings::setValue(CONF_BACKLIGHT_BATTERY_ENABLE, triggered);
1059 | }
1060 |
1061 | void Dialog::handleBacklightACCheck(bool triggered)
1062 | {
1063 | Settings::setValue(CONF_BACKLIGHT_AC_ENABLE, triggered);
1064 | }
1065 |
1066 | void Dialog::handleBacklightBatterySlider(int value)
1067 | {
1068 | Settings::setValue(CONF_BACKLIGHT_BATTERY, value);
1069 | }
1070 |
1071 | void Dialog::handleBacklightACSlider(int value)
1072 | {
1073 | Settings::setValue(CONF_BACKLIGHT_AC, value);
1074 | }
1075 |
1076 | void Dialog::hibernateWarn()
1077 | {
1078 | QMessageBox::warning(this, tr("Hibernate not supported"),
1079 | tr("Hibernate not supported, consult your OS documentation."));
1080 | }
1081 |
1082 | void Dialog::sleepWarn()
1083 | {
1084 | QMessageBox::warning(this, tr("Sleep not supported"),
1085 | tr("Sleep not supported, consult your OS documentation."));
1086 | }
1087 |
1088 | void Dialog::handleBacklightBatteryCheckLower(bool triggered)
1089 | {
1090 | Settings::setValue(CONF_BACKLIGHT_BATTERY_DISABLE_IF_LOWER, triggered);
1091 | }
1092 |
1093 | void Dialog::handleBacklightACCheckHigher(bool triggered)
1094 | {
1095 | Settings::setValue(CONF_BACKLIGHT_AC_DISABLE_IF_HIGHER, triggered);
1096 | }
1097 |
1098 | void Dialog::enableBacklight(bool enabled)
1099 | {
1100 | backlightSliderBattery->setEnabled(enabled);
1101 | backlightSliderAC->setEnabled(enabled);
1102 | backlightBatteryCheck->setEnabled(enabled);
1103 | backlightACCheck->setEnabled(enabled);
1104 | backlightBatteryLowerCheck->setEnabled(enabled);
1105 | backlightACHigherCheck->setEnabled(enabled);
1106 | batteryBacklightLabel->setEnabled(enabled);
1107 | acBacklightLabel->setEnabled(enabled);
1108 | backlightMouseWheel->setEnabled(enabled);
1109 | }
1110 |
1111 | void Dialog::handleWarnOnLowBattery(bool triggered)
1112 | {
1113 | Settings::setValue(CONF_WARN_ON_LOW_BATTERY, triggered);
1114 | }
1115 |
1116 | void Dialog::handleWarnOnVeryLowBattery(bool triggered)
1117 | {
1118 | Settings::setValue(CONF_WARN_ON_VERYLOW_BATTERY, triggered);
1119 | }
1120 |
1121 | void Dialog::handleNotifyBattery(bool triggered)
1122 | {
1123 | Settings::setValue(CONF_NOTIFY_ON_BATTERY, triggered);
1124 | }
1125 |
1126 | void Dialog::handleNotifyAC(bool triggered)
1127 | {
1128 | Settings::setValue(CONF_NOTIFY_ON_AC, triggered);
1129 | }
1130 |
1131 | void Dialog::handleNotifyNewInhibitor(bool triggered)
1132 | {
1133 | Settings::setValue(CONF_NOTIFY_NEW_INHIBITOR, triggered);
1134 | }
1135 |
1136 | void Dialog::enableLid(bool enabled)
1137 | {
1138 | lidActionAC->setEnabled(enabled);
1139 | lidActionBattery->setEnabled(enabled);
1140 | lidActionACLabel->setEnabled(enabled);
1141 | lidActionBatteryLabel->setEnabled(enabled);
1142 | disableLidAction->setEnabled(enabled);
1143 | }
1144 |
1145 | void Dialog::handleBacklightMouseWheel(bool triggered)
1146 | {
1147 | Settings::setValue(CONF_BACKLIGHT_MOUSE_WHEEL, triggered);
1148 | }
1149 |
1150 | void Dialog::handleScreensaverBlank(int value)
1151 | {
1152 | Settings::setValue(CONF_SCREENSAVER_TIMEOUT_BLANK, value * 60);
1153 | }
1154 |
--------------------------------------------------------------------------------