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
6 changed files with 67 additions and 26 deletions
Showing only changes of commit 016dcc008f - Show all commits
+4 -3
View File
@@ -5,11 +5,12 @@ import QtQuick
Scope {
id: root
required property var lock
signal requestLock
Connections {
function onLidClosing(): void {
root.lock.lock.locked = true;
function onStateChanged(): void {
if (LidWatcher.state === LidWatcher.Closed)
AramJonghu marked this conversation as resolved Outdated
Outdated
Review

You need to create a signal in the root Scope and call it here rather than setting the locked value directly.

Scope {
    id: root
    
    signal requestLock
    
    Connections {
    // ...

Is what I suggest, ties in nicely with a similar signal related to locking.

You need to create a signal in the root `Scope` and call it here rather than setting the locked value directly. ```qml Scope { id: root signal requestLock Connections { // ... ``` Is what I suggest, ties in nicely with a similar signal related to locking.
root.requestLock();
}
target: LidWatcher
+3
View File
@@ -18,6 +18,9 @@ Scope {
signal requestLock
signal unlock
onRequestLock: lock.locked = true
onUnlock: lock.locked = false
LockSurface {
id: lockSurface
+35 -10
View File
@@ -1,6 +1,8 @@
#include "lidwatcher.hpp"
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.lidwatcher", QtInfoMsg)
@@ -10,11 +12,12 @@ namespace ZShell {
static constexpr auto kLogin1Service = "org.freedesktop.login1";
static constexpr auto kLogin1Path = "/org/freedesktop/login1";
static constexpr auto kLogin1Interface = "org.freedesktop.login1.Manager";
static constexpr auto kPrepareForSleep = "PrepareForSleep";
static constexpr auto kDBusPropertiesInterface = "org.freedesktop.DBus.Properties";
LidWatcher::LidWatcher(QObject* parent)
: QObject(parent)
, m_available(false) {
, m_available(false)
, m_state(Opened) {
QDBusConnection bus = QDBusConnection::systemBus();
m_available = bus.isConnected();
@@ -24,26 +27,48 @@ LidWatcher::LidWatcher(QObject* parent)
return;
}
const auto ok = bus.connect(kLogin1Service, kLogin1Path, kLogin1Interface, kPrepareForSleep, this,
SLOT(onPrepareForSleep(bool)));
const auto ok = bus.connect(kLogin1Service, kLogin1Path, kDBusPropertiesInterface, "PropertiesChanged",
this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
m_available = ok;
emit availableChanged();
if (!m_available) {
qCWarning(lcLidWatcher) << "login1 lid signal unavailable";
qCWarning(lcLidWatcher) << "login1 properties signal unavailable";
return;
}
queryInitialState();
}
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.
bool LidWatcher::available() const {
return m_available;
}
void LidWatcher::onPrepareForSleep(bool goingDown) {
if (goingDown) {
emit lidClosing();
} else {
emit lidOpened();
LidWatcher::LidState LidWatcher::state() const {
return m_state;
}
void LidWatcher::queryInitialState() {
const auto msg = QDBusMessage::createMethodCall(
kLogin1Service, kLogin1Path,
kDBusPropertiesInterface, "Get");
msg << kLogin1Interface << "LidClosed";
const QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(msg);
if (!reply.isValid()) {
qCWarning(lcLidWatcher) << "cannot query LidClosed:" << reply.error().message();
return;
}
m_state = reply.value().toBool() ? Closed : Opened;
emit stateChanged();
}
void LidWatcher::onPropertiesChanged(const QString& interface, const QVariantMap& changed, const QStringList& /*invalidated*/) {
if (interface != kLogin1Interface)
return;
if (!changed.contains("LidClosed"))
return;
m_state = changed.value("LidClosed").toBool() ? Closed : Opened;
emit stateChanged();
}
} // namespace ZShell
+18 -6
View File
@@ -1,6 +1,8 @@
#pragma once
#include <QObject>
#include <QStringList>
#include <QVariantMap>
#include <qqmlintegration.h>
namespace ZShell {
@@ -11,22 +13,32 @@ class LidWatcher : public QObject {
QML_SINGLETON
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
Q_PROPERTY(LidState state READ state NOTIFY stateChanged)
public:
enum LidState {
Opened,
Closed
};
Q_ENUM(LidState)
explicit LidWatcher(QObject* parent = nullptr);
[[nodiscard]] bool available() const;
[[nodiscard]] LidState state() const;
private:
void queryInitialState();
bool m_available;
LidState m_state = Opened;
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.
private Q_SLOTS:
void onPrepareForSleep(bool goingDown);
void onPropertiesChanged(const QString& interface, const QVariantMap& changed, const QStringList& invalidated);
Q_SIGNALS:
void availableChanged();
void lidClosing();
void lidOpened();
private:
bool m_available;
void stateChanged();
};
} // namespace ZShell
+1 -1
View File
@@ -331,7 +331,7 @@ export const settingsIndex = [
category: "lockscreen",
categoryName: "Lockscreen",
section: "Lockscreen",
keywords: ["lid", "lcck", "watch", "session", "laptop"],
keywords: ["lid", "lock", "watch", "session", "laptop"],
AramJonghu marked this conversation as resolved Outdated
Outdated
Review

Typo probably. "lcck" should be "lock"

Typo probably. `"lcck"` should be `"lock"`
},
{
name: "Blur amount",
+6 -6
View File
@@ -47,12 +47,12 @@ ShellRoot {
Polkit {
}
LazyLoader {
activeAsync: Config.lock.lidWatch && Battery.isLaptop
component: LidService {
lock: lock
}
}
LazyLoader {
activeAsync: Config.lock.lidWatch && Battery.isLaptop
component: LidService {
onRequestLock: lock.requestLock()
}
}
LazyLoader {
activeAsync: root.laptop