File indexing completed on 2024-05-12 04:19:46

0001 /*
0002 Gwenview: an image viewer
0003 Copyright 2013 Martin Gräßlin <mgraesslin@kde.org>
0004 Copyright 2018 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006 This program is free software; you can redistribute it and/or
0007 modify it under the terms of the GNU General Public License
0008 as published by the Free Software Foundation; either version 2
0009 of the License, or (at your option) any later version.
0010 
0011 This program is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU General Public License for more details.
0015 
0016 You should have received a copy of the GNU General Public License
0017 along with this program; if not, write to the Free Software
0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0019 */
0020 
0021 #include "lockscreenwatcher.h"
0022 
0023 // lib
0024 #include <screensaverdbusinterface.h>
0025 // Qt
0026 #include <QDBusServiceWatcher>
0027 #include <QFutureWatcher>
0028 #include <QtConcurrentRun>
0029 
0030 namespace Gwenview
0031 {
0032 using DBusBoolReplyWatcher = QFutureWatcher<QDBusReply<bool>>;
0033 using DBusStringReplyWatcher = QFutureWatcher<QDBusReply<QString>>;
0034 
0035 inline QString screenSaverServiceName()
0036 {
0037     return QStringLiteral("org.freedesktop.ScreenSaver");
0038 }
0039 
0040 LockScreenWatcher::LockScreenWatcher(QObject *parent)
0041     : QObject(parent)
0042 {
0043     auto screenLockServiceWatcher = new QDBusServiceWatcher(this);
0044     connect(screenLockServiceWatcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &LockScreenWatcher::onScreenSaverServiceOwnerChanged);
0045     screenLockServiceWatcher->setWatchMode(QDBusServiceWatcher::WatchForOwnerChange);
0046     screenLockServiceWatcher->addWatchedService(screenSaverServiceName());
0047 
0048     if (QDBusConnection::sessionBus().interface()) {
0049         auto watcher = new DBusBoolReplyWatcher(this);
0050         connect(watcher, &DBusBoolReplyWatcher::finished, this, &LockScreenWatcher::onServiceRegisteredQueried);
0051         connect(watcher, &DBusBoolReplyWatcher::canceled, watcher, &DBusBoolReplyWatcher::deleteLater);
0052 
0053         watcher->setFuture(
0054             QtConcurrent::run(&QDBusConnectionInterface::isServiceRegistered, QDBusConnection::sessionBus().interface(), screenSaverServiceName()));
0055     }
0056 }
0057 
0058 LockScreenWatcher::~LockScreenWatcher() = default;
0059 
0060 bool LockScreenWatcher::isLocked() const
0061 {
0062     return mLocked;
0063 }
0064 
0065 void LockScreenWatcher::onScreenSaverServiceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
0066 {
0067     Q_UNUSED(oldOwner)
0068 
0069     if (serviceName != screenSaverServiceName()) {
0070         return;
0071     }
0072 
0073     delete mScreenSaverInterface;
0074     mScreenSaverInterface = nullptr;
0075 
0076     if (!newOwner.isEmpty()) {
0077         mScreenSaverInterface = new OrgFreedesktopScreenSaverInterface(newOwner, QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus(), this);
0078         connect(mScreenSaverInterface, &OrgFreedesktopScreenSaverInterface::ActiveChanged, this, &LockScreenWatcher::onScreenSaverActiveChanged);
0079 
0080         auto watcher = new QDBusPendingCallWatcher(mScreenSaverInterface->GetActive(), this);
0081         connect(watcher, &QDBusPendingCallWatcher::finished, this, &LockScreenWatcher::onActiveQueried);
0082     } else {
0083         if (mLocked) {
0084             // reset
0085             mLocked = false;
0086             Q_EMIT isLockedChanged(mLocked);
0087         }
0088     }
0089 }
0090 
0091 void LockScreenWatcher::onServiceRegisteredQueried()
0092 {
0093     auto watcher = dynamic_cast<DBusBoolReplyWatcher *>(sender());
0094     if (!watcher) {
0095         return;
0096     }
0097 
0098     const QDBusReply<bool> &reply = watcher->result();
0099 
0100     if (reply.isValid() && reply.value()) {
0101         auto ownerWatcher = new DBusStringReplyWatcher(this);
0102         connect(ownerWatcher, &DBusStringReplyWatcher::finished, this, &LockScreenWatcher::onServiceOwnerQueried);
0103         connect(ownerWatcher, &DBusStringReplyWatcher::canceled, ownerWatcher, &DBusStringReplyWatcher::deleteLater);
0104         ownerWatcher->setFuture(
0105             QtConcurrent::run(&QDBusConnectionInterface::serviceOwner, QDBusConnection::sessionBus().interface(), screenSaverServiceName()));
0106     }
0107 
0108     watcher->deleteLater();
0109 }
0110 
0111 void LockScreenWatcher::onServiceOwnerQueried()
0112 {
0113     auto watcher = dynamic_cast<DBusStringReplyWatcher *>(sender());
0114     if (!watcher) {
0115         return;
0116     }
0117 
0118     const QDBusReply<QString> reply = watcher->result();
0119 
0120     if (reply.isValid()) {
0121         onScreenSaverServiceOwnerChanged(screenSaverServiceName(), QString(), reply.value());
0122     }
0123 
0124     watcher->deleteLater();
0125 }
0126 
0127 void LockScreenWatcher::onActiveQueried(QDBusPendingCallWatcher *watcher)
0128 {
0129     QDBusPendingReply<bool> reply = *watcher;
0130     if (!reply.isError()) {
0131         onScreenSaverActiveChanged(reply.value());
0132     }
0133 
0134     watcher->deleteLater();
0135 }
0136 
0137 void LockScreenWatcher::onScreenSaverActiveChanged(bool isActive)
0138 {
0139     if (mLocked == isActive) {
0140         return;
0141     }
0142 
0143     mLocked = isActive;
0144 
0145     Q_EMIT isLockedChanged(mLocked);
0146 }
0147 
0148 }
0149 
0150 #include "moc_lockscreenwatcher.cpp"