Lomiri
Loading...
Searching...
No Matches
dbuslomirisessionservice.cpp
1/*
2 * Copyright (C) 2014, 2015 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17// local
18#include "dbuslomirisessionservice.h"
19
20// system
21#include <grp.h>
22#include <sys/types.h>
23#include <unistd.h>
24#include <pwd.h>
25
26// Qt
27#include <QDebug>
28#include <QDBusPendingCall>
29#include <QDBusReply>
30#include <QElapsedTimer>
31#include <QDateTime>
32#include <QDBusUnixFileDescriptor>
33
34// Glib
35#include <glib.h>
36
37#define LOGIN1_SERVICE QStringLiteral("org.freedesktop.login1")
38#define LOGIN1_PATH QStringLiteral("/org/freedesktop/login1")
39#define LOGIN1_IFACE QStringLiteral("org.freedesktop.login1.Manager")
40#define LOGIN1_SESSION_IFACE QStringLiteral("org.freedesktop.login1.Session")
41
42#define ACTIVE_KEY QStringLiteral("Active")
43#define IDLE_SINCE_KEY QStringLiteral("IdleSinceHint")
44
45// TODO: migrate defines to constant variables in the future.
46static const QString LOGIN1_USER_SELF_PATH =
47 QStringLiteral("/org/freedesktop/login1/user/self");
48static const QString LOGIN1_USER_IFACE =
49 QStringLiteral("org.freedesktop.login1.User");
50static const QString DBUS_PROPERTIES_IFACE =
51 QStringLiteral("org.freedesktop.DBus.Properties");
52
53static const QString DISPLAY_KEY = QStringLiteral("Display");
54
55class DBusLomiriSessionServicePrivate: public QObject
56{
57 Q_OBJECT
58public:
59 QString logindSessionPath;
60 bool isSessionActive = true;
61 QElapsedTimer screensaverActiveTimer;
62 QDBusUnixFileDescriptor m_systemdInhibitFd;
63
64 DBusLomiriSessionServicePrivate(): QObject() {
65 init();
66 checkActive();
67 }
68
69 QString determineLogindSessionPath() {
70 // Simple case: environment variable.
71 auto sessionEnv = qgetenv("XDG_SESSION_ID");
72 if (!sessionEnv.isEmpty()) {
73 QDBusMessage msg = QDBusMessage::createMethodCall(
74 LOGIN1_SERVICE,
75 LOGIN1_PATH,
76 LOGIN1_IFACE,
77 QStringLiteral("GetSession"));
78 // Can't use QByteArray as-is; QDbus will interpret it as 'ay'
79 msg << QString::fromLocal8Bit(sessionEnv);
80 QDBusReply<QDBusObjectPath> reply = QDBusConnection::SM_BUSNAME().call(msg);
81
82 if (reply.isValid()) {
83 return reply.value().path();
84 } else {
85 qWarning() << "Failed to get logind session path for"
86 << sessionEnv << ":"
87 << reply.error().message();
88 }
89 }
90
91 // We're not under the session. If we're running as a systemd user unit,
92 // use the user's Display session, which is what gnome-shell does.
93 // Care must be taken to check if this is actually the case, otherwise
94 // any invocation of Lomiri will become session-like.
95
96 if (qEnvironmentVariableIsSet("LOMIRI_AS_SYSTEMD_UNIT")) {
97 QDBusMessage msg = QDBusMessage::createMethodCall(
98 LOGIN1_SERVICE,
99 LOGIN1_USER_SELF_PATH,
100 DBUS_PROPERTIES_IFACE,
101 QStringLiteral("Get"));
102 msg << LOGIN1_USER_IFACE;
103 msg << DISPLAY_KEY;
104
105 // org.freedesktop.DBus.Properties.Get returns DBus variant.
106 QDBusReply<QDBusVariant> reply = QDBusConnection::SM_BUSNAME().call(msg);
107
108 if (reply.isValid()) {
109 // We're the only callsite, so it's not worth writing full
110 // C++ struct (un-)marshaling. Let's just un-marshall here.
111 QString sessionName;
112 QDBusObjectPath sessionPath;
113
114 QVariant variant = reply.value().variant();
115 const QDBusArgument arg = variant.value<QDBusArgument>();
116
117 arg.beginStructure();
118 arg >> sessionName >> sessionPath;
119 arg.endStructure();
120
121 return sessionPath.path();
122 } else {
123 qWarning() << "Failed to get user's Display session:"
124 << reply.error().message();
125 }
126 }
127
128 // Can't find anything, return empty QString.
129 return QString();
130 }
131
132 void init()
133 {
134 // get our logind session path
135 logindSessionPath = determineLogindSessionPath();
136
137 if (!logindSessionPath.isEmpty()) {
138 // start watching the Active property
139 QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, logindSessionPath, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"),
140 this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
141
142 setupSystemdInhibition();
143
144 // re-enable the inhibition upon resume from sleep
145 QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QStringLiteral("PrepareForSleep"),
146 this, SLOT(onResuming(bool)));
147 }
148 }
149
150 void setupSystemdInhibition()
151 {
152 if (m_systemdInhibitFd.isValid())
153 return;
154
155 // inhibit systemd handling of power/sleep/hibernate buttons
156 // http://www.freedesktop.org/wiki/Software/systemd/inhibit
157
158 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QStringLiteral("Inhibit"));
159 msg << "handle-power-key:handle-suspend-key:handle-hibernate-key"; // what
160 msg << "Lomiri"; // who
161 msg << "Lomiri handles power events"; // why
162 msg << "block"; // mode
163
164 QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
165 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
166 connect(watcher, &QDBusPendingCallWatcher::finished,
167 this, [this](QDBusPendingCallWatcher* watcher) {
168 QDBusPendingReply<QDBusUnixFileDescriptor> reply = *watcher;
169 watcher->deleteLater();
170 if (reply.isError()) {
171 qWarning() << "Failed to inhibit systemd powersave handling" << reply.error().message();
172 return;
173 }
174
175 m_systemdInhibitFd = reply.value();
176 });
177 }
178
179 bool checkLogin1Call(const QString &method) const
180 {
181 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
182 QDBusReply<QString> reply = QDBusConnection::SM_BUSNAME().call(msg);
183 return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
184 }
185
186 void makeLogin1Call(const QString &method, const QVariantList &args)
187 {
188 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
189 LOGIN1_PATH,
190 LOGIN1_IFACE,
191 method);
192 msg.setArguments(args);
193 QDBusConnection::SM_BUSNAME().asyncCall(msg);
194 }
195
196 void setActive(bool active)
197 {
198 isSessionActive = active;
199
200 Q_EMIT screensaverActiveChanged(!isSessionActive);
201
202 if (isSessionActive) {
203 screensaverActiveTimer.invalidate();
204 setIdleHint(false);
205 } else {
206 screensaverActiveTimer.start();
207 setIdleHint(true);
208 }
209 }
210
211 void checkActive()
212 {
213 if (logindSessionPath.isEmpty()) {
214 qWarning() << "Invalid session path";
215 return;
216 }
217
218 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
219 logindSessionPath,
220 QStringLiteral("org.freedesktop.DBus.Properties"),
221 QStringLiteral("Get"));
222 msg << LOGIN1_SESSION_IFACE;
223 msg << ACTIVE_KEY;
224
225 QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
226 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
227 connect(watcher, &QDBusPendingCallWatcher::finished,
228 this, [this](QDBusPendingCallWatcher* watcher) {
229
230 QDBusPendingReply<QVariant> reply = *watcher;
231 watcher->deleteLater();
232 if (reply.isError()) {
233 qWarning() << "Failed to get Active property" << reply.error().message();
234 return;
235 }
236
237 setActive(reply.value().toBool());
238 });
239 }
240
241 quint32 screensaverActiveTime() const
242 {
243 if (!isSessionActive && screensaverActiveTimer.isValid()) {
244 return screensaverActiveTimer.elapsed() / 1000;
245 }
246
247 return 0;
248 }
249
250 quint64 idleSinceUSecTimestamp() const
251 {
252 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
253 logindSessionPath,
254 QStringLiteral("org.freedesktop.DBus.Properties"),
255 QStringLiteral("Get"));
256 msg << LOGIN1_SESSION_IFACE;
257 msg << IDLE_SINCE_KEY;
258
259 QDBusReply<QVariant> reply = QDBusConnection::SM_BUSNAME().call(msg);
260 if (reply.isValid()) {
261 return reply.value().value<quint64>();
262 } else {
263 qWarning() << "Failed to get IdleSinceHint property" << reply.error().message();
264 }
265
266 return 0;
267 }
268
269 void setIdleHint(bool idle)
270 {
271 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE,
272 logindSessionPath,
273 LOGIN1_SESSION_IFACE,
274 QStringLiteral("SetIdleHint"));
275 msg << idle;
276 QDBusConnection::SM_BUSNAME().asyncCall(msg);
277 }
278
279 bool isUserInGroup(const QString &user, const QString &groupName) const
280 {
281 auto group = getgrnam(groupName.toUtf8().data());
282
283 if (group && group->gr_mem)
284 {
285 for (int i = 0; group->gr_mem[i]; ++i)
286 {
287 if (g_strcmp0(group->gr_mem[i], user.toUtf8().data()) == 0) {
288 return true;
289 }
290 }
291 }
292
293 return false;
294 }
295
296private Q_SLOTS:
297 void onPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps)
298 {
299 Q_UNUSED(iface)
300
301 if (changedProps.contains(ACTIVE_KEY)) {
302 setActive(changedProps.value(ACTIVE_KEY).toBool());
303 } else if (invalidatedProps.contains(ACTIVE_KEY)) {
304 checkActive();
305 }
306 }
307
308 void onResuming(bool active)
309 {
310 if (!active) {
311 setupSystemdInhibition();
312 } else {
313 Q_EMIT prepareForSleep();
314 }
315 }
316
317Q_SIGNALS:
318 void screensaverActiveChanged(bool active);
319 void prepareForSleep();
320};
321
322Q_GLOBAL_STATIC(DBusLomiriSessionServicePrivate, d)
323
324DBusLomiriSessionService::DBusLomiriSessionService()
325 : LomiriDBusObject(QStringLiteral("/com/lomiri/Shell/Session"), QStringLiteral("com.lomiri.Shell"))
326{
327 if (!d->logindSessionPath.isEmpty()) {
328 // connect our PromptLock() slot to the logind's session Lock() signal
329 QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Lock"), this, SLOT(PromptLock()));
330 // ... and our Unlocked() signal to the logind's session Unlock() signal
331 // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to)
332 QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SLOT(doUnlock()));
333 connect(d, &DBusLomiriSessionServicePrivate::prepareForSleep, this, &DBusLomiriSessionService::PromptLock);
334 } else {
335 qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
336 }
337}
338
340{
341 // TODO ask the apps to quit and then emit the signal
342 Q_EMIT LogoutReady();
343 Q_EMIT logoutReady();
344}
345
347{
348 const QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("com.lomiri.Upstart"),
349 QStringLiteral("/com/lomiri/Upstart"),
350 QStringLiteral("com.lomiri.Upstart0_6"),
351 QStringLiteral("EndSession"));
352 QDBusConnection::sessionBus().asyncCall(msg);
353}
354
356{
357 return d->checkLogin1Call(QStringLiteral("CanHibernate"));
358}
359
361{
362 return d->checkLogin1Call(QStringLiteral("CanSuspend"));
363}
364
366{
367 return d->checkLogin1Call(QStringLiteral("CanHybridSleep"));
368}
369
371{
372 return d->checkLogin1Call(QStringLiteral("CanReboot"));
373}
374
376{
377 return d->checkLogin1Call(QStringLiteral("CanPowerOff"));
378}
379
381{
382 auto user = UserName();
383 if (user.startsWith(QStringLiteral("guest-")) ||
384 d->isUserInGroup(user, QStringLiteral("nopasswdlogin"))) {
385 return false;
386 } else {
387 return true;
388 }
389}
390
392{
393 return QString::fromUtf8(g_get_user_name());
394}
395
397{
398 struct passwd *p = getpwuid(geteuid());
399 if (p) {
400 const QString gecos = QString::fromLocal8Bit(p->pw_gecos);
401 if (!gecos.isEmpty()) {
402 const QStringList splitGecos = gecos.split(QLatin1Char(','));
403 return splitGecos.first();
404 }
405 }
406
407 return QString();
408}
409
411{
412 char hostName[512];
413 if (gethostname(hostName, sizeof(hostName)) == -1) {
414 qWarning() << "Could not determine local hostname";
415 return QString();
416 }
417 hostName[sizeof(hostName) - 1] = '\0';
418 return QString::fromLocal8Bit(hostName);
419}
420
422{
423 // Prompt as in quick. No locking animation needed. Usually used by
424 // indicator-session in combination with a switch to greeter or other
425 // user session.
426 if (CanLock()) {
427 Q_EMIT LockRequested();
428 Q_EMIT lockRequested();
429 }
430}
431
433{
434 // Normal lock (with animation, as compared to PromptLock above). Usually
435 // used by indicator-session to lock the session in place.
436 //
437 // FIXME: We also -- as a bit of a hack around indicator-session not fully
438 // supporting a phone profile -- switch to greeter here. The lomiri7 flow is
439 // that the user chooses "Lock/Switch" from the indicator, and then can go
440 // to greeter by selecting "Switch" again from the indicator, which is now
441 // exposed by the desktop_lockscreen profile. But since in lomiri, we try
442 // to expose most things all the time, we don't use the separate lockscreen
443 // profile. Instead, we just go directly to the greeter the first time
444 // a user presses "Lock/Switch". This isn't what this DBus call is
445 // supposed to do, but we can live with it for now.
446 //
447 // Here's a bug about indicator-session growing a converged Touch profile:
448 // https://launchpad.net/bugs/1557716
449 //
450 // We only do this here in the animated-lock call because that's the only
451 // time the indicator locks without also asking the display manager to
452 // switch sessions on us. And since we are switching screens, we also
453 // don't bother respecting the animate request, simply doing a PromptLock.
454 PromptLock();
455 switchToGreeter();
456}
457
458void DBusLomiriSessionService::switchToGreeter()
459{
460 // lock the session using the org.freedesktop.DisplayManager system DBUS service
461 const QString sessionPath = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
462 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DisplayManager"),
463 sessionPath,
464 QStringLiteral("org.freedesktop.DisplayManager.Session"),
465 QStringLiteral("Lock"));
466
467 QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
468 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
469 connect(watcher, &QDBusPendingCallWatcher::finished,
470 this, [this](QDBusPendingCallWatcher* watcher) {
471
472 QDBusPendingReply<void> reply = *watcher;
473 watcher->deleteLater();
474 if (reply.isError()) {
475 qWarning() << "Lock call failed" << reply.error().message();
476 return;
477 }
478
479 // emit Locked when the call succeeds
480 Q_EMIT Locked();
481 });
482}
483
484void DBusLomiriSessionService::doUnlock()
485{
486 Q_EMIT Unlocked();
487 Q_EMIT unlocked();
488}
489
491{
492 return !d->isSessionActive;
493}
494
496{
497 Q_EMIT LogoutRequested(false);
498 Q_EMIT logoutRequested(false);
499}
500
502{
503 d->makeLogin1Call(QStringLiteral("Reboot"), {false});
504}
505
507{
508 Q_EMIT RebootRequested(false);
509 Q_EMIT rebootRequested(false);
510}
511
513{
514 d->makeLogin1Call(QStringLiteral("PowerOff"), {false});
515}
516
518{
519 PromptLock();
520 d->makeLogin1Call(QStringLiteral("Suspend"), {false});
521}
522
524{
525 PromptLock();
526 d->makeLogin1Call(QStringLiteral("Hibernate"), {false});
527}
528
530{
531 PromptLock();
532 d->makeLogin1Call(QStringLiteral("HybridSleep"), {false});
533}
534
536{
537 Q_EMIT ShutdownRequested(false);
538 Q_EMIT shutdownRequested(false);
539}
540
541enum class Action : unsigned
542{
543 LOGOUT = 0,
544 SHUTDOWN,
545 REBOOT,
546 NONE
547};
548
549
550void performAsyncLomiriCall(const QString &method)
551{
552 const QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("com.lomiri.Shell"),
553 QStringLiteral("/com/lomiri/Shell/Session"),
554 QStringLiteral("com.lomiri.Shell.Session"),
555 method);
556 QDBusConnection::sessionBus().asyncCall(msg);
557}
558
559
560DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
561 : LomiriDBusObject(QStringLiteral("/org/gnome/SessionManager"), QStringLiteral("org.gnome.SessionManager"))
562{
563}
564
565void DBusGnomeSessionManagerWrapper::Logout(quint32 mode)
566{
567 auto call = QStringLiteral("RequestLogout");
568
569 // These modes are documented as bitwise flags, not an enum, even though
570 // they only ever seem to be used as enums.
571
572 if (mode & 1) // without dialog
573 call = QStringLiteral("Logout");
574 if (mode & 2) // without dialog, ignoring inhibitors (which we don't have)
575 call = QStringLiteral("Logout");
576
577 performAsyncLomiriCall(call);
578}
579
580void DBusGnomeSessionManagerWrapper::Reboot()
581{
582 // GNOME's Reboot means with dialog (they use Request differently than us).
583 performAsyncLomiriCall(QStringLiteral("RequestReboot"));
584}
585
586void DBusGnomeSessionManagerWrapper::RequestReboot()
587{
588 // GNOME's RequestReboot means no dialog (they use Request differently than us).
589 performAsyncLomiriCall(QStringLiteral("Reboot"));
590}
591
592void DBusGnomeSessionManagerWrapper::RequestShutdown()
593{
594 // GNOME's RequestShutdown means no dialog (they use Request differently than us).
595 performAsyncLomiriCall(QStringLiteral("Shutdown"));
596}
597
598void DBusGnomeSessionManagerWrapper::Shutdown()
599{
600 // GNOME's Shutdown means with dialog (they use Request differently than us).
601 performAsyncLomiriCall(QStringLiteral("RequestShutdown"));
602}
603
604
605DBusGnomeSessionManagerDialogWrapper::DBusGnomeSessionManagerDialogWrapper()
606 : LomiriDBusObject(QStringLiteral("/org/gnome/SessionManager/EndSessionDialog"), QStringLiteral("com.lomiri.Shell"))
607{
608}
609
610void DBusGnomeSessionManagerDialogWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
611{
612 Q_UNUSED(arg_1);
613 Q_UNUSED(max_wait);
614 Q_UNUSED(inhibitors);
615
616 switch (static_cast<Action>(type))
617 {
618 case Action::LOGOUT:
619 performAsyncLomiriCall(QStringLiteral("RequestLogout"));
620 break;
621
622 case Action::REBOOT:
623 performAsyncLomiriCall(QStringLiteral("RequestReboot"));
624 break;
625
626 case Action::SHUTDOWN:
627 performAsyncLomiriCall(QStringLiteral("RequestShutdown"));
628 break;
629
630 default:
631 break;
632 }
633}
634
635
636DBusGnomeScreensaverWrapper::DBusGnomeScreensaverWrapper()
637 : LomiriDBusObject(QStringLiteral("/org/gnome/ScreenSaver"), QStringLiteral("org.gnome.ScreenSaver"))
638{
639 connect(d, &DBusLomiriSessionServicePrivate::screensaverActiveChanged, this, &DBusGnomeScreensaverWrapper::ActiveChanged);
640}
641
642bool DBusGnomeScreensaverWrapper::GetActive() const
643{
644 return !d->isSessionActive; // return whether the session is not active
645}
646
647void DBusGnomeScreensaverWrapper::SetActive(bool lock)
648{
649 if (lock) {
650 Lock();
651 }
652}
653
654void DBusGnomeScreensaverWrapper::Lock()
655{
656 performAsyncLomiriCall(QStringLiteral("PromptLock"));
657}
658
659quint32 DBusGnomeScreensaverWrapper::GetActiveTime() const
660{
661 return d->screensaverActiveTime();
662}
663
664void DBusGnomeScreensaverWrapper::SimulateUserActivity()
665{
666 d->setIdleHint(false);
667}
668
669
670DBusScreensaverWrapper::DBusScreensaverWrapper()
671 : LomiriDBusObject(QStringLiteral("/org/freedesktop/ScreenSaver"), QStringLiteral("org.freedesktop.ScreenSaver"))
672{
673 QDBusConnection::sessionBus().registerObject(QStringLiteral("/ScreenSaver"), this, QDBusConnection::ExportScriptableContents); // compat path, also register here
674 connect(d, &DBusLomiriSessionServicePrivate::screensaverActiveChanged, this, &DBusScreensaverWrapper::ActiveChanged);
675}
676
677bool DBusScreensaverWrapper::GetActive() const
678{
679 return !d->isSessionActive; // return whether the session is not active
680}
681
682bool DBusScreensaverWrapper::SetActive(bool lock)
683{
684 if (lock) {
685 Lock();
686 return true;
687 }
688 return false;
689}
690
691void DBusScreensaverWrapper::Lock()
692{
693 performAsyncLomiriCall(QStringLiteral("PromptLock"));
694}
695
696quint32 DBusScreensaverWrapper::GetActiveTime() const
697{
698 return d->screensaverActiveTime();
699}
700
701quint32 DBusScreensaverWrapper::GetSessionIdleTime() const
702{
703 return QDateTime::fromMSecsSinceEpoch(d->idleSinceUSecTimestamp()/1000).secsTo(QDateTime::currentDateTime());
704}
705
706void DBusScreensaverWrapper::SimulateUserActivity()
707{
708 d->setIdleHint(false);
709}
710
711#include "dbuslomirisessionservice.moc"
Q_SCRIPTABLE void LogoutReady()
Q_SCRIPTABLE QString HostName() const
Q_SCRIPTABLE bool IsLocked() const
Q_SCRIPTABLE void Unlocked()
Q_SCRIPTABLE void LockRequested()
Q_SCRIPTABLE void ShutdownRequested(bool have_inhibitors)
Q_SCRIPTABLE void RebootRequested(bool have_inhibitors)
Q_SCRIPTABLE void Locked()
Q_SCRIPTABLE bool CanHybridSleep() const
Q_SCRIPTABLE bool CanHibernate() const
Q_SCRIPTABLE void LogoutRequested(bool have_inhibitors)
Q_SCRIPTABLE bool CanShutdown() const
Q_SCRIPTABLE bool CanLock() const
Q_SCRIPTABLE QString RealName() const
Q_SCRIPTABLE bool CanReboot() const
Q_SCRIPTABLE QString UserName() const
Q_SCRIPTABLE bool CanSuspend() const