1 /********************************************************************
2 KSld - the KDE Screenlocker Daemon
3 This file is part of the KDE project.
4
5 Copyright 1999 Martin R. Jones <mjones@kde.org>
6 Copyright 2003 Oswald Buddenhagen <ossi@kde.org>
7 Copyright 2008 Chani Armitage <chanika@gmail.com>
8 Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 *********************************************************************/
23 #include "ksldapp.h"
24 #include "globalaccel.h"
25 #include "interface.h"
26 #include "kscreensaversettings.h"
27 #include "logind.h"
28 #include "powermanagement_inhibition.h"
29 #include "waylandlocker.h"
30 #include "x11locker.h"
31
32 #include "kscreenlocker_logging.h"
33 #include <config-kscreenlocker.h>
34
35 #include "waylandserver.h"
36 #include <config-X11.h>
37 // KDE
38 #include <KAuthorized>
39 #include <KGlobalAccel>
40 #include <KIdleTime>
41 #include <KLocalizedString>
42 #include <KNotification>
43
44 // Qt
45 #include <QAction>
46 #include <QKeyEvent>
47 #include <QProcess>
48 #include <QTimer>
49 #include <QX11Info>
50 // X11
51 #include <X11/Xlib.h>
52 #include <xcb/xcb.h>
53 #ifdef X11_Xinput_FOUND
54 #include <X11/extensions/XInput2.h>
55 #endif
56 // other
57 #include <signal.h>
58 #include <unistd.h>
59
60 #include <sys/socket.h>
61 #include <sys/types.h>
62
63 namespace ScreenLocker
64 {
65 static const QString s_qtQuickBackend = QStringLiteral("QT_QUICK_BACKEND");
66
67 static KSldApp *s_instance = nullptr;
68
self()69 KSldApp *KSldApp::self()
70 {
71 if (!s_instance) {
72 s_instance = new KSldApp();
73 }
74
75 return s_instance;
76 }
77
KSldApp(QObject * parent)78 KSldApp::KSldApp(QObject *parent)
79 : QObject(parent)
80 , m_lockState(Unlocked)
81 , m_lockProcess(nullptr)
82 , m_lockWindow(nullptr)
83 , m_waylandServer(new WaylandServer(this))
84 , m_lockedTimer(QElapsedTimer())
85 , m_idleId(0)
86 , m_lockGrace(0)
87 , m_inGraceTime(false)
88 , m_graceTimer(new QTimer(this))
89 , m_inhibitCounter(0)
90 , m_logind(nullptr)
91 , m_greeterEnv(QProcessEnvironment::systemEnvironment())
92 , m_powerManagementInhibition(new PowerManagementInhibition(this))
93 {
94 m_isX11 = QX11Info::isPlatformX11();
95 m_isWayland = QCoreApplication::instance()->property("platformName").toString().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive);
96 }
97
~KSldApp()98 KSldApp::~KSldApp()
99 {
100 }
101
102 static int s_XTimeout;
103 static int s_XInterval;
104 static int s_XBlanking;
105 static int s_XExposures;
106
cleanUp()107 void KSldApp::cleanUp()
108 {
109 if (m_lockProcess && m_lockProcess->state() != QProcess::NotRunning) {
110 m_lockProcess->terminate();
111 }
112 delete m_lockProcess;
113 delete m_lockWindow;
114
115 // Restore X screensaver parameters
116 XSetScreenSaver(QX11Info::display(), s_XTimeout, s_XInterval, s_XBlanking, s_XExposures);
117 }
118
119 static bool s_graceTimeKill = false;
120 static bool s_logindExit = false;
121
hasXInput()122 static bool hasXInput()
123 {
124 #ifdef X11_Xinput_FOUND
125 Display *dpy = QX11Info::display();
126 int xi_opcode, event, error;
127 // init XInput extension
128 if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) {
129 return false;
130 }
131
132 // verify that the XInput extension is at at least version 2.0
133 int major = 2, minor = 0;
134 int result = XIQueryVersion(dpy, &major, &minor);
135 if (result == BadImplementation) {
136 // Xinput 2.2 returns BadImplementation if checked against 2.0
137 major = 2;
138 minor = 2;
139 return XIQueryVersion(dpy, &major, &minor) == Success;
140 }
141 return result == Success;
142 #else
143 return false;
144 #endif
145 }
146
initializeX11()147 void KSldApp::initializeX11()
148 {
149 m_hasXInput2 = hasXInput();
150 // Save X screensaver parameters
151 XGetScreenSaver(QX11Info::display(), &s_XTimeout, &s_XInterval, &s_XBlanking, &s_XExposures);
152 // And disable it. The internal X screensaver is not used at all, but we use its
153 // internal idle timer (and it is also used by DPMS support in X). This timer must not
154 // be altered by this code, since e.g. resetting the counter after activating our
155 // screensaver would prevent DPMS from activating. We use the timer merely to detect
156 // user activity.
157 XSetScreenSaver(QX11Info::display(), 0, s_XInterval, s_XBlanking, s_XExposures);
158 }
159
initialize()160 void KSldApp::initialize()
161 {
162 if (m_isX11) {
163 initializeX11();
164 }
165
166 // Global keys
167 if (KAuthorized::authorizeAction(QStringLiteral("lock_screen"))) {
168 qCDebug(KSCREENLOCKER) << "Configuring Lock Action";
169 QAction *a = new QAction(this);
170 a->setObjectName(QStringLiteral("Lock Session"));
171 a->setProperty("componentName", QStringLiteral("ksmserver"));
172 a->setText(i18n("Lock Session"));
173 KGlobalAccel::self()->setGlobalShortcut(a, KScreenSaverSettings::defaultShortcuts());
174 connect(a, &QAction::triggered, this, [this]() {
175 lock(EstablishLock::Immediate);
176 });
177 }
178
179 // idle support
180 auto idleTimeSignal = static_cast<void (KIdleTime::*)(int)>(&KIdleTime::timeoutReached);
181 connect(KIdleTime::instance(), idleTimeSignal, this, [this](int identifier) {
182 if (identifier != m_idleId) {
183 // not our identifier
184 return;
185 }
186 if (lockState() != Unlocked) {
187 return;
188 }
189 if (m_inhibitCounter // either we got a direct inhibit request thru our outdated o.f.Screensaver iface ...
190 || isFdoPowerInhibited()) { // ... or the newer one at o.f.PowerManagement.Inhibit
191 // there is at least one process blocking the auto lock of screen locker
192 return;
193 }
194 if (m_lockGrace) { // short-circuit if grace time is zero
195 m_inGraceTime = true;
196 } else if (m_lockGrace == -1) {
197 m_inGraceTime = true; // if no timeout configured, grace time lasts forever
198 }
199
200 lock(EstablishLock::Delayed);
201 });
202
203 m_lockProcess = new QProcess();
204 m_lockProcess->setProcessChannelMode(QProcess::ForwardedErrorChannel);
205 m_lockProcess->setReadChannel(QProcess::StandardOutput);
206 auto finishedSignal = static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished);
207 connect(m_lockProcess, finishedSignal, this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
208 qCDebug(KSCREENLOCKER) << "Greeter process exitted with status:" << exitStatus << "exit code:" << exitCode;
209
210 const bool regularExit = !exitCode && exitStatus == QProcess::NormalExit;
211 if (regularExit || s_graceTimeKill || s_logindExit) {
212 // unlock process finished successfully - we can remove the lock grab
213
214 if (regularExit) {
215 qCDebug(KSCREENLOCKER) << "Unlocking now on regular exit.";
216 } else if (s_graceTimeKill) {
217 qCDebug(KSCREENLOCKER) << "Unlocking anyway due to grace time.";
218 } else {
219 Q_ASSERT(s_logindExit);
220 qCDebug(KSCREENLOCKER) << "Unlocking anyway since forced through logind.";
221 }
222
223 s_graceTimeKill = false;
224 s_logindExit = false;
225 doUnlock();
226 return;
227 }
228
229 qCWarning(KSCREENLOCKER) << "Greeter process exit unregular. Restarting lock.";
230
231 m_greeterCrashedCounter++;
232 if (m_greeterCrashedCounter < 4) {
233 // Perhaps it crashed due to a graphics driver issue, force software rendering now
234 qCDebug(KSCREENLOCKER, "Trying to lock again with software rendering (%d/4).", m_greeterCrashedCounter);
235 setForceSoftwareRendering(true);
236 startLockProcess(EstablishLock::Immediate);
237 } else if (m_lockWindow) {
238 qCWarning(KSCREENLOCKER) << "Everything else failed. Need to put Greeter in emergency mode.";
239 m_lockWindow->emergencyShow();
240 } else {
241 qCCritical(KSCREENLOCKER) << "Greeter process exitted and we could in no way recover from that!";
242 }
243 });
244 connect(m_lockProcess, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) {
245 if (error == QProcess::FailedToStart) {
246 qCDebug(KSCREENLOCKER) << "Greeter Process failed to start. Trying to directly unlock again.";
247 doUnlock();
248 m_waylandServer->stop();
249 qCCritical(KSCREENLOCKER) << "Greeter Process not available";
250 } else {
251 qCWarning(KSCREENLOCKER) << "Greeter Process encountered an unhandled error:" << error;
252 }
253 });
254 m_lockedTimer.invalidate();
255 m_graceTimer->setSingleShot(true);
256 connect(m_graceTimer, &QTimer::timeout, this, &KSldApp::endGraceTime);
257 // create our D-Bus interface
258 new Interface(this);
259
260 // connect to logind
261 m_logind = new LogindIntegration(this);
262 connect(m_logind, &LogindIntegration::requestLock, this, [this]() {
263 lock(EstablishLock::Immediate);
264 });
265 connect(m_logind, &LogindIntegration::requestUnlock, this, [this]() {
266 if (lockState() == Locked || lockState() == AcquiringLock) {
267 if (m_lockProcess->state() != QProcess::NotRunning) {
268 s_logindExit = true;
269 m_lockProcess->terminate();
270 } else {
271 doUnlock();
272 }
273 }
274 });
275 connect(m_logind, &LogindIntegration::prepareForSleep, this, [this](bool goingToSleep) {
276 if (!goingToSleep) {
277 // not interested in doing anything on wakeup
278 return;
279 }
280 if (KScreenSaverSettings::lockOnResume()) {
281 lock(EstablishLock::Immediate);
282 }
283 });
284 connect(m_logind, &LogindIntegration::inhibited, this, [this]() {
285 // if we are already locked, we immediately remove the inhibition lock
286 if (m_lockState == KSldApp::Locked) {
287 m_logind->uninhibit();
288 }
289 });
290 connect(m_logind, &LogindIntegration::connectedChanged, this, [this]() {
291 if (!m_logind->isConnected()) {
292 return;
293 }
294 if (m_lockState == ScreenLocker::KSldApp::Unlocked && KScreenSaverSettings::lockOnResume()) {
295 m_logind->inhibit();
296 }
297 if (m_logind->isLocked()) {
298 lock(EstablishLock::Immediate);
299 }
300 });
301 connect(this, &KSldApp::locked, this, [this]() {
302 m_logind->uninhibit();
303 m_logind->setLocked(true);
304 if (m_lockGrace > 0 && m_inGraceTime) {
305 m_graceTimer->start(m_lockGrace);
306 }
307 });
308 connect(this, &KSldApp::unlocked, this, [this]() {
309 m_logind->setLocked(false);
310 if (KScreenSaverSettings::lockOnResume()) {
311 m_logind->inhibit();
312 }
313 });
314
315 m_globalAccel = new GlobalAccel(this);
316 connect(this, &KSldApp::locked, m_globalAccel, &GlobalAccel::prepare);
317 connect(this, &KSldApp::unlocked, m_globalAccel, &GlobalAccel::release);
318
319 // fallback for non-logind systems:
320 // connect to signal emitted by Solid. This is emitted unconditionally also on logind enabled systems
321 // ksld ignores it in case logind is used
322 QDBusConnection::sessionBus().connect(QStringLiteral("org.kde.Solid.PowerManagement"),
323 QStringLiteral("/org/kde/Solid/PowerManagement/Actions/SuspendSession"),
324 QStringLiteral("org.kde.Solid.PowerManagement.Actions.SuspendSession"),
325 QStringLiteral("aboutToSuspend"),
326 this,
327 SLOT(solidSuspend()));
328
329 configure();
330
331 if (m_logind->isLocked()) {
332 lock(EstablishLock::Immediate);
333 }
334 }
335
configure()336 void KSldApp::configure()
337 {
338 KScreenSaverSettings::self()->load();
339 // idle support
340 if (m_idleId) {
341 KIdleTime::instance()->removeIdleTimeout(m_idleId);
342 m_idleId = 0;
343 }
344 const int timeout = KScreenSaverSettings::timeout();
345 // screen saver enabled means there is an auto lock timer
346 // timeout > 0 is for backwards compatibility with old configs
347 if (KScreenSaverSettings::autolock() && timeout > 0) {
348 // timeout stored in minutes
349 m_idleId = KIdleTime::instance()->addIdleTimeout(timeout * 1000 * 60);
350 }
351 if (KScreenSaverSettings::lock()) {
352 // lockGrace is stored in seconds
353 m_lockGrace = KScreenSaverSettings::lockGrace() * 1000;
354 } else {
355 m_lockGrace = -1;
356 }
357 if (m_logind && m_logind->isConnected()) {
358 if (KScreenSaverSettings::lockOnResume() && !m_logind->isInhibited()) {
359 m_logind->inhibit();
360 } else if (!KScreenSaverSettings::lockOnResume() && m_logind->isInhibited()) {
361 m_logind->uninhibit();
362 }
363 }
364 }
365
lock(EstablishLock establishLock,int attemptCount)366 void KSldApp::lock(EstablishLock establishLock, int attemptCount)
367 {
368 if (lockState() != Unlocked) {
369 // already locked or acquiring lock, no need to lock again
370 // but make sure it's really locked
371 endGraceTime();
372 if (establishLock == EstablishLock::Immediate) {
373 // signal the greeter to switch to immediateLock mode
374 kill(m_lockProcess->processId(), SIGUSR1);
375 }
376 return;
377 }
378
379 if (attemptCount == 0) {
380 Q_EMIT aboutToLock();
381 }
382
383 qCDebug(KSCREENLOCKER) << "lock called";
384 if (!establishGrab()) {
385 if (attemptCount < 3) {
386 qCWarning(KSCREENLOCKER) << "Could not establish screen lock. Trying again in 10ms";
387 QTimer::singleShot(10, this, [=]() {
388 lock(establishLock, attemptCount + 1);
389 });
390 } else {
391 qCCritical(KSCREENLOCKER) << "Could not establish screen lock";
392 }
393 return;
394 }
395
396 KNotification::event(QStringLiteral("locked"), i18n("Screen locked"), QPixmap(), nullptr, KNotification::CloseOnTimeout, QStringLiteral("ksmserver"));
397
398 // blank the screen
399 showLockWindow();
400
401 m_lockState = AcquiringLock;
402
403 setForceSoftwareRendering(false);
404 // start unlock screen process
405 startLockProcess(establishLock);
406 Q_EMIT lockStateChanged();
407 }
408
409 /*
410 * Forward declarations:
411 * Only called from KSldApp::establishGrab(). Using from somewhere else is incorrect usage!
412 **/
413 static bool grabKeyboard();
414 static bool grabMouse();
415
416 class XServerGrabber
417 {
418 public:
XServerGrabber()419 XServerGrabber()
420 {
421 xcb_grab_server(QX11Info::connection());
422 }
~XServerGrabber()423 ~XServerGrabber()
424 {
425 xcb_ungrab_server(QX11Info::connection());
426 xcb_flush(QX11Info::connection());
427 }
428 };
429
establishGrab()430 bool KSldApp::establishGrab()
431 {
432 if (m_isWayland) {
433 return m_waylandFd >= 0;
434 }
435 if (!m_isX11) {
436 return true;
437 }
438 XSync(QX11Info::display(), False);
439 XServerGrabber serverGrabber;
440 if (!grabKeyboard()) {
441 return false;
442 }
443
444 if (!grabMouse()) {
445 XUngrabKeyboard(QX11Info::display(), CurrentTime);
446 XFlush(QX11Info::display());
447 return false;
448 }
449
450 #ifdef X11_Xinput_FOUND
451 if (m_hasXInput2) {
452 // get all devices
453 Display *dpy = QX11Info::display();
454 int numMasters;
455 XIDeviceInfo *masters = XIQueryDevice(dpy, XIAllMasterDevices, &numMasters);
456 bool success = true;
457 for (int i = 0; i < numMasters; ++i) {
458 // ignoring core pointer and core keyboard as we already grabbed them
459 if (qstrcmp(masters[i].name, "Virtual core pointer") == 0) {
460 continue;
461 }
462 if (qstrcmp(masters[i].name, "Virtual core keyboard") == 0) {
463 continue;
464 }
465 XIEventMask mask;
466 uchar bitmask[] = {0, 0};
467 mask.deviceid = masters[i].deviceid;
468 mask.mask = bitmask;
469 mask.mask_len = sizeof(bitmask);
470 XISetMask(bitmask, XI_ButtonPress);
471 XISetMask(bitmask, XI_ButtonRelease);
472 XISetMask(bitmask, XI_Motion);
473 XISetMask(bitmask, XI_Enter);
474 XISetMask(bitmask, XI_Leave);
475 const int result = XIGrabDevice(dpy,
476 masters[i].deviceid,
477 QX11Info::appRootWindow(),
478 XCB_TIME_CURRENT_TIME,
479 XCB_CURSOR_NONE,
480 XIGrabModeAsync,
481 XIGrabModeAsync,
482 True,
483 &mask);
484 if (result != XIGrabSuccess) {
485 success = false;
486 break;
487 }
488 }
489 if (!success) {
490 // ungrab all devices again
491 for (int i = 0; i < numMasters; ++i) {
492 XIUngrabDevice(dpy, masters[i].deviceid, XCB_TIME_CURRENT_TIME);
493 }
494 xcb_connection_t *c = QX11Info::connection();
495 xcb_ungrab_keyboard(c, XCB_CURRENT_TIME);
496 xcb_ungrab_pointer(c, XCB_CURRENT_TIME);
497 }
498 XIFreeDeviceInfo(masters);
499 XFlush(dpy);
500 return success;
501 }
502 #endif
503
504 return true;
505 }
506
grabKeyboard()507 static bool grabKeyboard()
508 {
509 int rv = XGrabKeyboard(QX11Info::display(), QX11Info::appRootWindow(), True, GrabModeAsync, GrabModeAsync, CurrentTime);
510
511 return (rv == GrabSuccess);
512 }
513
grabMouse()514 static bool grabMouse()
515 {
516 #define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask
517 int rv = XGrabPointer(QX11Info::display(), QX11Info::appRootWindow(), True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
518 #undef GRABEVENTS
519
520 return (rv == GrabSuccess);
521 }
522
doUnlock()523 void KSldApp::doUnlock()
524 {
525 qCDebug(KSCREENLOCKER) << "Grab Released";
526 if (m_isX11) {
527 xcb_connection_t *c = QX11Info::connection();
528 xcb_ungrab_keyboard(c, XCB_CURRENT_TIME);
529 xcb_ungrab_pointer(c, XCB_CURRENT_TIME);
530 xcb_flush(c);
531 #ifdef X11_Xinput_FOUND
532 if (m_hasXInput2) {
533 // get all devices
534 Display *dpy = QX11Info::display();
535 int numMasters;
536 XIDeviceInfo *masters = XIQueryDevice(dpy, XIAllMasterDevices, &numMasters);
537 // ungrab all devices again
538 for (int i = 0; i < numMasters; ++i) {
539 XIUngrabDevice(dpy, masters[i].deviceid, XCB_TIME_CURRENT_TIME);
540 }
541 XIFreeDeviceInfo(masters);
542 XFlush(dpy);
543 }
544 #endif
545 }
546 hideLockWindow();
547 // delete the window again, to get rid of event filter
548 delete m_lockWindow;
549 m_lockWindow = nullptr;
550 m_lockState = Unlocked;
551 m_lockedTimer.invalidate();
552 m_greeterCrashedCounter = 0;
553 endGraceTime();
554 m_waylandServer->stop();
555 KNotification::event(QStringLiteral("unlocked"), i18n("Screen unlocked"), QPixmap(), nullptr, KNotification::CloseOnTimeout, QStringLiteral("ksmserver"));
556 Q_EMIT unlocked();
557 Q_EMIT lockStateChanged();
558 }
559
isFdoPowerInhibited() const560 bool KSldApp::isFdoPowerInhibited() const
561 {
562 return m_powerManagementInhibition->isInhibited();
563 }
564
setWaylandFd(int fd)565 void KSldApp::setWaylandFd(int fd)
566 {
567 m_waylandFd = fd;
568 }
569
startLockProcess(EstablishLock establishLock)570 void KSldApp::startLockProcess(EstablishLock establishLock)
571 {
572 QProcessEnvironment env = m_greeterEnv;
573
574 if (m_isWayland && m_waylandFd >= 0) {
575 int socket = dup(m_waylandFd);
576 if (socket >= 0) {
577 env.insert(QStringLiteral("WAYLAND_SOCKET"), QString::number(socket));
578 }
579 }
580
581 QStringList args;
582 if (establishLock == EstablishLock::Immediate) {
583 args << QStringLiteral("--immediateLock");
584 }
585 if (establishLock == EstablishLock::DefaultToSwitchUser) {
586 args << QStringLiteral("--immediateLock");
587 args << QStringLiteral("--switchuser");
588 }
589
590 if (m_lockGrace > 0) {
591 args << QStringLiteral("--graceTime");
592 args << QString::number(m_lockGrace);
593 }
594 if (m_lockGrace == -1) {
595 args << QStringLiteral("--nolock");
596 }
597 if (m_forceSoftwareRendering) {
598 env.insert(s_qtQuickBackend, QStringLiteral("software"));
599 }
600
601 // start the Wayland server
602 int fd = m_waylandServer->start();
603 if (fd == -1) {
604 qCWarning(KSCREENLOCKER) << "Could not start the Wayland server.";
605 Q_EMIT m_lockProcess->errorOccurred(QProcess::FailedToStart);
606 return;
607 }
608
609 args << QStringLiteral("--ksldfd");
610 args << QString::number(fd);
611
612 m_lockProcess->setProcessEnvironment(env);
613 m_lockProcess->start(QStringLiteral(KSCREENLOCKER_GREET_BIN), args);
614 close(fd);
615 }
616
userActivity()617 void KSldApp::userActivity()
618 {
619 if (isGraceTime()) {
620 unlock();
621 }
622 if (m_lockWindow) {
623 m_lockWindow->userActivity();
624 }
625 }
626
showLockWindow()627 void KSldApp::showLockWindow()
628 {
629 if (!m_lockWindow) {
630 if (m_isX11) {
631 m_lockWindow = new X11Locker(this);
632
633 connect(
634 m_lockWindow,
635 &AbstractLocker::userActivity,
636 m_lockWindow,
637 [this]() {
638 if (isGraceTime()) {
639 unlock();
640 }
641 },
642 Qt::QueuedConnection);
643 }
644
645 if (m_isWayland) {
646 m_lockWindow = new WaylandLocker(this);
647 }
648 if (!m_lockWindow) {
649 return;
650 }
651 m_lockWindow->setGlobalAccel(m_globalAccel);
652
653 connect(m_lockWindow, &AbstractLocker::lockWindowShown, this, &KSldApp::lockScreenShown);
654
655 connect(m_waylandServer, &WaylandServer::x11WindowAdded, m_lockWindow, &AbstractLocker::addAllowedWindow);
656 }
657 m_lockWindow->showLockWindow();
658 if (m_isX11) {
659 XSync(QX11Info::display(), False);
660 }
661 }
662
hideLockWindow()663 void KSldApp::hideLockWindow()
664 {
665 if (!m_lockWindow) {
666 return;
667 }
668 m_lockWindow->hideLockWindow();
669 }
670
activeTime() const671 uint KSldApp::activeTime() const
672 {
673 if (m_lockedTimer.isValid()) {
674 return m_lockedTimer.elapsed();
675 }
676 return 0;
677 }
678
isGraceTime() const679 bool KSldApp::isGraceTime() const
680 {
681 return m_inGraceTime;
682 }
683
endGraceTime()684 void KSldApp::endGraceTime()
685 {
686 m_graceTimer->stop();
687 m_inGraceTime = false;
688 }
689
unlock()690 void KSldApp::unlock()
691 {
692 if (!isGraceTime()) {
693 return;
694 }
695 s_graceTimeKill = true;
696 m_lockProcess->terminate();
697 }
698
inhibit()699 void KSldApp::inhibit()
700 {
701 ++m_inhibitCounter;
702 }
703
uninhibit()704 void KSldApp::uninhibit()
705 {
706 --m_inhibitCounter;
707 }
708
solidSuspend()709 void KSldApp::solidSuspend()
710 {
711 // ignore in case that we use logind
712 if (m_logind && m_logind->isConnected()) {
713 return;
714 }
715 if (KScreenSaverSettings::lockOnResume()) {
716 lock(EstablishLock::Immediate);
717 }
718 }
719
lockScreenShown()720 void KSldApp::lockScreenShown()
721 {
722 if (m_lockState == Locked) {
723 return;
724 }
725 m_lockState = Locked;
726 m_lockedTimer.restart();
727 Q_EMIT locked();
728 Q_EMIT lockStateChanged();
729 }
730
setGreeterEnvironment(const QProcessEnvironment & env)731 void KSldApp::setGreeterEnvironment(const QProcessEnvironment &env)
732 {
733 m_greeterEnv = env;
734 if (m_isWayland) {
735 m_greeterEnv.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland"));
736 }
737 }
738
event(QEvent * event)739 bool KSldApp::event(QEvent *event)
740 {
741 if (event->type() == QEvent::KeyPress && m_globalAccel) {
742 if (m_globalAccel->keyEvent(static_cast<QKeyEvent *>(event))) {
743 event->setAccepted(true);
744 }
745 }
746 return false;
747 }
748
749 } // namespace
750