1 #include <QCoreApplication>
2 #include <QDBusPendingReply>
3 #include <QDBusPendingCall>
4 #include <QDBusPendingCallWatcher>
5 #include <QDBusReply>
6 #include "screensaver_unix.h"
7 
ScreenSaverUnix(QObject * parent)8 ScreenSaverUnix::ScreenSaverUnix(QObject *parent)
9     : ScreenSaver(parent),
10       dbusScreensaver("org.freedesktop.ScreenSaver",
11            "/ScreenSaver",
12            "org.freedesktop.ScreenSaver"),
13       dbusLogin("org.freedesktop.login1",
14                 "/org/freedesktop/login1",
15                 "org.freedesktop.login1.Manager",
16                QDBusConnection::systemBus()),
17       dbusLoginSelf("org.freedesktop.login1",
18                     "/org/freedesktop/login1/user/self",
19                     "org.freedesktop.login1.User",
20                     QDBusConnection::systemBus())
21 {
22 }
23 
abilities()24 QSet<ScreenSaverUnix::Ability> ScreenSaverUnix::abilities()
25 {
26     QSet<Ability> abilities;
27 
28     if (dbusScreensaver.isValid())
29         abilities << Inhibit << Uninhibit << LaunchSaver << LockScreen;
30 
31     if (dbusLogin.isValid()) {
32         auto check = [&](QString method, ScreenSaverUnix::Ability ability) {
33             QDBusReply<QString> reply = dbusLogin.call(method);
34             if (reply.isValid() && reply.value() == "yes")
35                 abilities << ability;
36         };
37         check("CanHibernate", Hibernate);
38         check("CanSuspend", Suspend);
39         check("CanPowerOff", Shutdown);
40     }
41     if (dbusLoginSelf.isValid()
42             && dbusLoginSelf.metaObject()->indexOfMethod("Terminate()") != -1) {
43         abilities << LogOff;
44     }
45     return abilities;
46 }
47 
inhibitSaver(const QString & reason)48 void ScreenSaverUnix::inhibitSaver(const QString &reason)
49 {
50     if (isInhibiting || inhibitCalled)
51         return;
52 
53     inhibitCalled = true;
54 
55     QDBusPendingCall async = dbusScreensaver.asyncCall("Inhibit",
56         QCoreApplication::applicationName(), reason);
57     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
58 
59     connect(watcher, &QDBusPendingCallWatcher::finished,
60             this, &ScreenSaverUnix::dbusScreensaver_inhibit);
61 }
62 
uninhibitSaver()63 void ScreenSaverUnix::uninhibitSaver()
64 {
65     if (!isInhibiting)
66         return;
67 
68     QDBusPendingCall async = dbusScreensaver.asyncCall("UnInhibit", inhibitToken);
69     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
70 
71     connect(watcher, &QDBusPendingCallWatcher::finished,
72             this, &ScreenSaverUnix::dbusScreensaver_uninhibit);
73 
74 }
75 
launchSaver()76 void ScreenSaverUnix::launchSaver()
77 {
78     QDBusPendingCall async = dbusScreensaver.asyncCall("SetActive", true);
79     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
80 
81     connect(watcher, &QDBusPendingCallWatcher::finished,
82             this, &ScreenSaverUnix::dbusScreensaver_launch);
83 
84 }
85 
lockScreen()86 void ScreenSaverUnix::lockScreen()
87 {
88     QDBusPendingCall async = dbusScreensaver.asyncCall("Lock");
89     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
90 
91     connect(watcher, &QDBusPendingCallWatcher::finished,
92             this, &ScreenSaverUnix::dbusScreensaver_lock);
93 
94 }
95 
hibernateSystem()96 void ScreenSaverUnix::hibernateSystem()
97 {
98     if (!isInhibiting)
99         return;
100 
101     QDBusPendingCall async = dbusLogin.asyncCall("Hibernate");
102     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
103 
104     connect(watcher, &QDBusPendingCallWatcher::finished,
105             this, &ScreenSaverUnix::dbusLogin_hibernate);
106 }
107 
suspendSystem()108 void ScreenSaverUnix::suspendSystem()
109 {
110     if (!isInhibiting)
111         return;
112 
113     QDBusPendingCall async = dbusLogin.asyncCall("Suspend");
114     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
115 
116     connect(watcher, &QDBusPendingCallWatcher::finished,
117             this, &ScreenSaverUnix::dbusLogin_suspend);
118 }
119 
shutdownSystem()120 void ScreenSaverUnix::shutdownSystem()
121 {
122     if (!isInhibiting)
123         return;
124 
125     QDBusPendingCall async = dbusLogin.asyncCall("PowerOff");
126     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
127 
128     connect(watcher, &QDBusPendingCallWatcher::finished,
129             this, &ScreenSaverUnix::dbusLogin_shutdown);
130 }
131 
132 
logOff()133 void ScreenSaverUnix::logOff()
134 {
135     QDBusPendingCall async = dbusLoginSelf.asyncCall("Terminate");
136     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
137 
138     connect(watcher, &QDBusPendingCallWatcher::finished,
139             this, &ScreenSaverUnix::dbusLoginSelf_logoff);
140 
141     emit failed(LogOff);
142 }
143 
dbusScreensaver_inhibit(QDBusPendingCallWatcher * call)144 void ScreenSaverUnix::dbusScreensaver_inhibit(QDBusPendingCallWatcher *call)
145 {
146     QDBusPendingReply<uint32_t> reply = *call;
147     if (reply.isError()) {
148         emit failed(Inhibit);
149     } else {
150         inhibitToken = reply.argumentAt<0>();
151         isInhibiting = true;
152         emit inhibitedSaver();
153     }
154     inhibitCalled = false;
155     call->deleteLater();
156 }
157 
dbusScreensaver_uninhibit(QDBusPendingCallWatcher * call)158 void ScreenSaverUnix::dbusScreensaver_uninhibit(QDBusPendingCallWatcher *call)
159 {
160     QDBusPendingReply<> reply = *call;
161     if (reply.isError()) {
162         emit failed(Uninhibit);
163     } else {
164         isInhibiting = false;
165         emit uninhibitedSaver();
166     }
167     call->deleteLater();
168 }
169 
dbusScreensaver_launch(QDBusPendingCallWatcher * call)170 void ScreenSaverUnix::dbusScreensaver_launch(QDBusPendingCallWatcher *call)
171 {
172     QDBusPendingReply<> reply = *call;
173     if (reply.isError())
174         emit failed(LaunchSaver);
175     else
176         emit launchedSaver();
177     call->deleteLater();
178 }
179 
dbusScreensaver_lock(QDBusPendingCallWatcher * call)180 void ScreenSaverUnix::dbusScreensaver_lock(QDBusPendingCallWatcher *call)
181 {
182     QDBusPendingReply<> reply = *call;
183     if (reply.isError())
184         emit failed(LockScreen);
185     else
186         emit screenLocked();
187     call->deleteLater();
188 }
189 
dbusLogin_hibernate(QDBusPendingCallWatcher * call)190 void ScreenSaverUnix::dbusLogin_hibernate(QDBusPendingCallWatcher *call)
191 {
192     QDBusPendingReply<> reply = *call;
193     if (reply.isError())
194         emit failed(Hibernate);
195     else
196         emit systemHibernated();
197     call->deleteLater();
198 }
199 
dbusLogin_suspend(QDBusPendingCallWatcher * call)200 void ScreenSaverUnix::dbusLogin_suspend(QDBusPendingCallWatcher *call)
201 {
202     QDBusPendingReply<> reply = *call;
203     if (reply.isError())
204         emit failed(Suspend);
205     else
206         emit systemSuspended();
207     call->deleteLater();
208 }
209 
dbusLogin_shutdown(QDBusPendingCallWatcher * call)210 void ScreenSaverUnix::dbusLogin_shutdown(QDBusPendingCallWatcher *call)
211 {
212     QDBusPendingReply<> reply = *call;
213     if (reply.isError())
214         emit failed(Shutdown);
215     else
216         emit systemShutdown();
217     call->deleteLater();
218 }
219 
dbusLoginSelf_logoff(QDBusPendingCallWatcher * call)220 void ScreenSaverUnix::dbusLoginSelf_logoff(QDBusPendingCallWatcher *call)
221 {
222     QDBusPendingReply<> reply = *call;
223     if (reply.isError())
224         emit failed(LogOff);
225     else
226         emit loggedOff();
227     call->deleteLater();
228 }
229 
230 
231