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
+59 -21
View File
@@ -3,7 +3,9 @@
#include <QtDBus/QDBusConnection> #include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage> #include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply> #include <QtDBus/QDBusReply>
#include <QtDBus/QDBusServiceWatcher>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QTimer>
Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.lidwatcher", QtInfoMsg) Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.lidwatcher", QtInfoMsg)
@@ -15,32 +17,32 @@ static constexpr auto kLogin1Interface = "org.freedesktop.login1.Manager";
static constexpr auto kDBusPropertiesInterface = static constexpr auto kDBusPropertiesInterface =
"org.freedesktop.DBus.Properties"; "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(); QDBusConnection bus = QDBusConnection::systemBus();
m_available = bus.isConnected(); if (!bus.isConnected()) {
if (!m_available) {
qCWarning(lcLidWatcher) << "system bus unavailable"; qCWarning(lcLidWatcher) << "system bus unavailable";
emit availableChanged(); emit availableChanged();
return; 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, kLogin1Service,
kLogin1Path, bus,
kDBusPropertiesInterface, QDBusServiceWatcher::WatchForRegistration,
"PropertiesChanged", 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.
this, connect(m_watcher, &QDBusServiceWatcher::serviceRegistered,
SLOT(onPropertiesChanged(QString, QVariantMap, QStringList))); this, &LidWatcher::tryConnect);
m_available = ok; tryConnect();
emit availableChanged();
if (!m_available) {
qCWarning(lcLidWatcher) << "login1 properties signal unavailable";
return;
}
queryInitialState();
} }
bool LidWatcher::available() const { bool LidWatcher::available() const {
@@ -51,7 +53,37 @@ LidWatcher::LidState LidWatcher::state() const {
return m_state; 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, auto msg = QDBusMessage::createMethodCall(kLogin1Service,
kLogin1Path, kLogin1Path,
kDBusPropertiesInterface, kDBusPropertiesInterface,
@@ -63,8 +95,11 @@ void LidWatcher::queryInitialState() {
<< "cannot query LidClosed:" << reply.error().message(); << "cannot query LidClosed:" << reply.error().message();
return; return;
} }
m_state = reply.value().toBool() ? Closed : Opened; const auto newState = reply.value().toBool() ? Closed : Opened;
if (m_state != newState) {
m_state = newState;
emit stateChanged(); emit stateChanged();
}
} }
void LidWatcher::onPropertiesChanged(const QString& interface, void LidWatcher::onPropertiesChanged(const QString& interface,
@@ -76,8 +111,11 @@ void LidWatcher::onPropertiesChanged(const QString& interface,
if (!changed.contains("LidClosed")) { if (!changed.contains("LidClosed")) {
return; return;
} }
m_state = changed.value("LidClosed").toBool() ? Closed : Opened; const auto newState = changed.value("LidClosed").toBool() ? Closed : Opened;
if (m_state != newState) {
m_state = newState;
emit stateChanged(); emit stateChanged();
}
} }
} // namespace ZShell } // namespace ZShell
+10 -6
View File
@@ -6,6 +6,9 @@
#include <cstdint> #include <cstdint>
#include <qqmlintegration.h> #include <qqmlintegration.h>
class QDBusServiceWatcher;
class QTimer;
namespace ZShell { namespace ZShell {
class LidWatcher : public QObject { class LidWatcher : public QObject {
@@ -26,16 +29,17 @@ class LidWatcher : public QObject {
[[nodiscard]] LidState state() const; [[nodiscard]] LidState state() const;
private: private:
void queryInitialState(); void tryConnect();
void queryLidState();
bool m_available;
LidState m_state = Opened;
void onPropertiesChanged(const QString& interface, void onPropertiesChanged(const QString& interface,
const QVariantMap& changed, 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); const QStringList& invalidated);
QDBusServiceWatcher* m_watcher;
QTimer* m_pollTimer;
bool m_available;
LidState m_state = Opened;
Q_SIGNALS: Q_SIGNALS:
void availableChanged(); void availableChanged();
void stateChanged(); void stateChanged();