lid behavior watcher to lock session #115

Merged
zach merged 25 commits from lid-switch-behavior into main 2026-06-03 18:02:21 +02:00
2 changed files with 71 additions and 29 deletions
Showing only changes of commit f9ab1e2a10 - Show all commits
+61 -23
View File
@@ -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
Outdated
Review

Doesn't this trigger only when the system is about to suspend/hibernate? There should be a way to query the lid state directly.

Doesn't this trigger only when the system is about to suspend/hibernate? There should be a way to query the lid state directly.
Outdated
Review

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.

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.
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
+10 -6
View File
@@ -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
Outdated
Review

extracted() is declared but never implemented in the .cpp file.

`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();