lid behavior watcher to lock session #115
@@ -3,7 +3,9 @@
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusMessage>
|
||||
#include <QtDBus/QDBusReply>
|
||||
#include <QtDBus/QDBusServiceWatcher>
|
||||
#include <QLoggingCategory>
|
||||
#include <QTimer>
|
||||
|
||||
Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.lidwatcher", QtInfoMsg)
|
||||
|
||||
@@ -15,32 +17,32 @@ static constexpr auto kLogin1Interface = "org.freedesktop.login1.Manager";
|
||||
static constexpr auto kDBusPropertiesInterface =
|
||||
"org.freedesktop.DBus.Properties";
|
||||
|
||||
LidWatcher::LidWatcher(QObject* parent) : QObject(parent), m_available(false) {
|
||||
LidWatcher::LidWatcher(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_watcher(nullptr)
|
||||
, m_pollTimer(nullptr)
|
||||
, m_available(false)
|
||||
{
|
||||
QDBusConnection bus = QDBusConnection::systemBus();
|
||||
m_available = bus.isConnected();
|
||||
|
||||
if (!m_available) {
|
||||
if (!bus.isConnected()) {
|
||||
qCWarning(lcLidWatcher) << "system bus unavailable";
|
||||
emit availableChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto ok = bus.connect(
|
||||
m_pollTimer = new QTimer(this);
|
||||
m_pollTimer->setInterval(5000);
|
||||
connect(m_pollTimer, &QTimer::timeout, this, &LidWatcher::queryLidState);
|
||||
|
||||
m_watcher = new QDBusServiceWatcher(
|
||||
kLogin1Service,
|
||||
kLogin1Path,
|
||||
kDBusPropertiesInterface,
|
||||
"PropertiesChanged",
|
||||
this,
|
||||
SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)));
|
||||
bus,
|
||||
QDBusServiceWatcher::WatchForRegistration,
|
||||
this);
|
||||
|
AramJonghu marked this conversation as resolved
Outdated
|
||||
connect(m_watcher, &QDBusServiceWatcher::serviceRegistered,
|
||||
this, &LidWatcher::tryConnect);
|
||||
|
||||
m_available = ok;
|
||||
emit availableChanged();
|
||||
if (!m_available) {
|
||||
qCWarning(lcLidWatcher) << "login1 properties signal unavailable";
|
||||
return;
|
||||
}
|
||||
|
||||
queryInitialState();
|
||||
tryConnect();
|
||||
}
|
||||
|
||||
bool LidWatcher::available() const {
|
||||
@@ -51,7 +53,37 @@ LidWatcher::LidState LidWatcher::state() const {
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void LidWatcher::queryInitialState() {
|
||||
void LidWatcher::tryConnect() {
|
||||
QDBusConnection bus = QDBusConnection::systemBus();
|
||||
|
||||
const auto connected = bus.connect(
|
||||
kLogin1Service,
|
||||
kLogin1Path,
|
||||
kDBusPropertiesInterface,
|
||||
"PropertiesChanged",
|
||||
this,
|
||||
SLOT(onPropertiesChanged(QString, QVariantMap, QStringList)));
|
||||
|
||||
queryLidState();
|
||||
|
||||
if (connected) {
|
||||
m_pollTimer->stop();
|
||||
qCInfo(lcLidWatcher) << "login1 PropertiesChanged connected";
|
||||
} else {
|
||||
qCWarning(lcLidWatcher)
|
||||
<< "login1 PropertiesChanged unavailable, polling";
|
||||
if (!m_pollTimer->isActive()) {
|
||||
m_pollTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_available) {
|
||||
m_available = true;
|
||||
emit availableChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void LidWatcher::queryLidState() {
|
||||
auto msg = QDBusMessage::createMethodCall(kLogin1Service,
|
||||
kLogin1Path,
|
||||
kDBusPropertiesInterface,
|
||||
@@ -63,8 +95,11 @@ void LidWatcher::queryInitialState() {
|
||||
<< "cannot query LidClosed:" << reply.error().message();
|
||||
return;
|
||||
}
|
||||
m_state = reply.value().toBool() ? Closed : Opened;
|
||||
emit stateChanged();
|
||||
const auto newState = reply.value().toBool() ? Closed : Opened;
|
||||
if (m_state != newState) {
|
||||
m_state = newState;
|
||||
emit stateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void LidWatcher::onPropertiesChanged(const QString& interface,
|
||||
@@ -76,8 +111,11 @@ void LidWatcher::onPropertiesChanged(const QString& interface,
|
||||
if (!changed.contains("LidClosed")) {
|
||||
return;
|
||||
}
|
||||
m_state = changed.value("LidClosed").toBool() ? Closed : Opened;
|
||||
emit stateChanged();
|
||||
const auto newState = changed.value("LidClosed").toBool() ? Closed : Opened;
|
||||
if (m_state != newState) {
|
||||
m_state = newState;
|
||||
emit stateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZShell
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include <cstdint>
|
||||
#include <qqmlintegration.h>
|
||||
|
||||
class QDBusServiceWatcher;
|
||||
class QTimer;
|
||||
|
||||
namespace ZShell {
|
||||
|
||||
class LidWatcher : public QObject {
|
||||
@@ -26,16 +29,17 @@ class LidWatcher : public QObject {
|
||||
[[nodiscard]] LidState state() const;
|
||||
|
||||
private:
|
||||
void queryInitialState();
|
||||
|
||||
bool m_available;
|
||||
LidState m_state = Opened;
|
||||
|
||||
|
||||
void tryConnect();
|
||||
void queryLidState();
|
||||
void onPropertiesChanged(const QString& interface,
|
||||
const QVariantMap& changed,
|
||||
|
AramJonghu marked this conversation as resolved
Outdated
zach
commented
`extracted()` is declared but never implemented in the `.cpp` file.
|
||||
const QStringList& invalidated);
|
||||
|
||||
QDBusServiceWatcher* m_watcher;
|
||||
QTimer* m_pollTimer;
|
||||
bool m_available;
|
||||
LidState m_state = Opened;
|
||||
|
||||
Q_SIGNALS:
|
||||
void availableChanged();
|
||||
void stateChanged();
|
||||
|
||||
Reference in New Issue
Block a user
Doesn't this trigger only when the system is about to suspend/hibernate? There should be a way to query the lid state directly.
Correct. And in retrospect, not every distro has defaults where the system suspends when laptop is on AC. The idea was that it should only trigger when the system suspends or hibernates to cover it more broadly for desktops (if wished). Could be a separate plugin or addition to current implementation if that is a wish separate from laptop lid behavior.