1 /*
2     SPDX-FileCopyrightText: 2012 Alejandro Fiestas Olivares <afiestas@kde.org>
3     SPDX-FileCopyrightText: 2015 Daniel Vrátil <dvratil@redhat.com>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #include "device.h"
9 #include "freedesktop_interface.h"
10 #include "kscreen_daemon_debug.h"
11 
12 Device *Device::m_instance = nullptr;
13 
self()14 Device *Device::self()
15 {
16     if (!Device::m_instance) {
17         m_instance = new Device();
18     }
19 
20     return m_instance;
21 }
22 
destroy()23 void Device::destroy()
24 {
25     delete m_instance;
26     m_instance = nullptr;
27 }
28 
Device(QObject * parent)29 Device::Device(QObject *parent)
30     : QObject(parent)
31     , m_isReady(false)
32     , m_isLaptop(false)
33     , m_isLidClosed(false)
34     , m_isDocked(false)
35 {
36     m_freedesktop = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.freedesktop.UPower"),
37                                                               QStringLiteral("/org/freedesktop/UPower"),
38                                                               QDBusConnection::systemBus(),
39                                                               this);
40     if (!m_freedesktop->isValid()) {
41         qCWarning(KSCREEN_KDED) << "UPower not available, lid detection won't work";
42         qCDebug(KSCREEN_KDED) << m_freedesktop->lastError().message();
43     } else {
44         QDBusConnection::systemBus().connect(QStringLiteral("org.freedesktop.UPower"),
45                                              QStringLiteral("/org/freedesktop/UPower"),
46                                              QStringLiteral("org.freedesktop.DBus.Properties"),
47                                              QStringLiteral("PropertiesChanged"),
48                                              this,
49                                              SLOT(changed()));
50         fetchIsLaptop();
51     }
52 
53     m_suspendSession = new QDBusInterface(QStringLiteral("org.kde.Solid.PowerManagement"),
54                                           QStringLiteral("/org/kde/Solid/PowerManagement/Actions/SuspendSession"),
55                                           QStringLiteral("org.kde.Solid.PowerManagement.Actions.SuspendSession"),
56                                           QDBusConnection::sessionBus(),
57                                           this);
58     if (m_suspendSession->isValid()) {
59         connect(m_suspendSession, SIGNAL(resumingFromSuspend()), this, SIGNAL(resumingFromSuspend()));
60         connect(m_suspendSession, SIGNAL(aboutToSuspend()), this, SIGNAL(aboutToSuspend()));
61     } else {
62         qCWarning(KSCREEN_KDED) << "PowerDevil SuspendSession action not available!";
63         qCDebug(KSCREEN_KDED) << m_suspendSession->lastError().message();
64     }
65 
66     fetchIsLaptop();
67 }
68 
~Device()69 Device::~Device()
70 {
71 }
72 
changed()73 void Device::changed()
74 {
75     fetchLidIsClosed();
76 }
77 
setReady()78 void Device::setReady()
79 {
80     if (m_isReady) {
81         return;
82     }
83 
84     m_isReady = true;
85     Q_EMIT ready();
86 }
87 
isReady() const88 bool Device::isReady() const
89 {
90     return m_isReady;
91 }
92 
isLaptop() const93 bool Device::isLaptop() const
94 {
95     return m_isLaptop;
96 }
97 
isLidClosed() const98 bool Device::isLidClosed() const
99 {
100     return m_isLidClosed;
101 }
102 
isDocked() const103 bool Device::isDocked() const
104 {
105     return m_isDocked;
106 }
107 
fetchIsLaptop()108 void Device::fetchIsLaptop()
109 {
110     QDBusPendingReply<QVariant> res = m_freedesktop->Get(QStringLiteral("org.freedesktop.UPower"), QStringLiteral("LidIsPresent"));
111     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(res);
112     connect(watcher, &QDBusPendingCallWatcher::finished, this, &Device::isLaptopFetched);
113 }
114 
isLaptopFetched(QDBusPendingCallWatcher * watcher)115 void Device::isLaptopFetched(QDBusPendingCallWatcher *watcher)
116 {
117     const QDBusPendingReply<QVariant> reply = *watcher;
118     if (reply.isError()) {
119         qCDebug(KSCREEN_KDED) << "Couldn't get if the device is a laptop: " << reply.error().message();
120         return;
121     }
122 
123     m_isLaptop = reply.value().toBool();
124     watcher->deleteLater();
125 
126     if (!m_isLaptop) {
127         setReady();
128         return;
129     }
130 
131     fetchLidIsClosed();
132 }
133 
fetchLidIsClosed()134 void Device::fetchLidIsClosed()
135 {
136     QDBusPendingReply<QVariant> res = m_freedesktop->Get(QStringLiteral("org.freedesktop.UPower"), QStringLiteral("LidIsClosed"));
137     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(res);
138     connect(watcher, &QDBusPendingCallWatcher::finished, this, &Device::isLidClosedFetched);
139 }
140 
isLidClosedFetched(QDBusPendingCallWatcher * watcher)141 void Device::isLidClosedFetched(QDBusPendingCallWatcher *watcher)
142 {
143     const QDBusPendingReply<QVariant> reply = *watcher;
144     if (reply.isError()) {
145         qCDebug(KSCREEN_KDED) << "Couldn't get if the laptop has the lid closed: " << reply.error().message();
146         return;
147     }
148 
149     if (reply.argumentAt<0>() != m_isLidClosed) {
150         m_isLidClosed = reply.value().toBool();
151         if (m_isReady) {
152             Q_EMIT lidClosedChanged(m_isLidClosed);
153             ;
154         }
155     }
156     watcher->deleteLater();
157 
158     fetchIsDocked();
159 }
160 
fetchIsDocked()161 void Device::fetchIsDocked()
162 {
163     setReady();
164 }
165