151 lines
4.8 KiB
C++

/*
Gwenview: an image viewer
Copyright 2013 Martin Gräßlin <mgraesslin@kde.org>
Copyright 2018 Friedrich W. H. Kossebau <kossebau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "lockscreenwatcher.h"
// lib
#include <screensaverdbusinterface.h>
// Qt
#include <QDBusServiceWatcher>
#include <QFutureWatcher>
#include <QtConcurrentRun>
namespace Gwenview
{
using DBusBoolReplyWatcher = QFutureWatcher<QDBusReply<bool>>;
using DBusStringReplyWatcher = QFutureWatcher<QDBusReply<QString>>;
inline QString screenSaverServiceName()
{
return QStringLiteral("org.freedesktop.ScreenSaver");
}
LockScreenWatcher::LockScreenWatcher(QObject *parent)
: QObject(parent)
{
auto screenLockServiceWatcher = new QDBusServiceWatcher(this);
connect(screenLockServiceWatcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &LockScreenWatcher::onScreenSaverServiceOwnerChanged);
screenLockServiceWatcher->setWatchMode(QDBusServiceWatcher::WatchForOwnerChange);
screenLockServiceWatcher->addWatchedService(screenSaverServiceName());
if (QDBusConnection::sessionBus().interface()) {
auto watcher = new DBusBoolReplyWatcher(this);
connect(watcher, &DBusBoolReplyWatcher::finished, this, &LockScreenWatcher::onServiceRegisteredQueried);
connect(watcher, &DBusBoolReplyWatcher::canceled, watcher, &DBusBoolReplyWatcher::deleteLater);
watcher->setFuture(
QtConcurrent::run(&QDBusConnectionInterface::isServiceRegistered, QDBusConnection::sessionBus().interface(), screenSaverServiceName()));
}
}
LockScreenWatcher::~LockScreenWatcher() = default;
bool LockScreenWatcher::isLocked() const
{
return mLocked;
}
void LockScreenWatcher::onScreenSaverServiceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
{
Q_UNUSED(oldOwner)
if (serviceName != screenSaverServiceName()) {
return;
}
delete mScreenSaverInterface;
mScreenSaverInterface = nullptr;
if (!newOwner.isEmpty()) {
mScreenSaverInterface = new OrgFreedesktopScreenSaverInterface(newOwner, QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus(), this);
connect(mScreenSaverInterface, &OrgFreedesktopScreenSaverInterface::ActiveChanged, this, &LockScreenWatcher::onScreenSaverActiveChanged);
auto watcher = new QDBusPendingCallWatcher(mScreenSaverInterface->GetActive(), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, &LockScreenWatcher::onActiveQueried);
} else {
if (mLocked) {
// reset
mLocked = false;
Q_EMIT isLockedChanged(mLocked);
}
}
}
void LockScreenWatcher::onServiceRegisteredQueried()
{
auto watcher = dynamic_cast<DBusBoolReplyWatcher *>(sender());
if (!watcher) {
return;
}
const QDBusReply<bool> &reply = watcher->result();
if (reply.isValid() && reply.value()) {
auto ownerWatcher = new DBusStringReplyWatcher(this);
connect(ownerWatcher, &DBusStringReplyWatcher::finished, this, &LockScreenWatcher::onServiceOwnerQueried);
connect(ownerWatcher, &DBusStringReplyWatcher::canceled, ownerWatcher, &DBusStringReplyWatcher::deleteLater);
ownerWatcher->setFuture(
QtConcurrent::run(&QDBusConnectionInterface::serviceOwner, QDBusConnection::sessionBus().interface(), screenSaverServiceName()));
}
watcher->deleteLater();
}
void LockScreenWatcher::onServiceOwnerQueried()
{
auto watcher = dynamic_cast<DBusStringReplyWatcher *>(sender());
if (!watcher) {
return;
}
const QDBusReply<QString> reply = watcher->result();
if (reply.isValid()) {
onScreenSaverServiceOwnerChanged(screenSaverServiceName(), QString(), reply.value());
}
watcher->deleteLater();
}
void LockScreenWatcher::onActiveQueried(QDBusPendingCallWatcher *watcher)
{
QDBusPendingReply<bool> reply = *watcher;
if (!reply.isError()) {
onScreenSaverActiveChanged(reply.value());
}
watcher->deleteLater();
}
void LockScreenWatcher::onScreenSaverActiveChanged(bool isActive)
{
if (mLocked == isActive) {
return;
}
mLocked = isActive;
Q_EMIT isLockedChanged(mLocked);
}
}
#include "moc_lockscreenwatcher.cpp"