diff --git a/Modules/Lock/IdleMonitors.qml b/Modules/Lock/IdleMonitors.qml index 26b2854..647cf22 100644 --- a/Modules/Lock/IdleMonitors.qml +++ b/Modules/Lock/IdleMonitors.qml @@ -29,6 +29,10 @@ Scope { Quickshell.execDetached(action); } + LidWatcher { + onAboutToSleep: root.lock.lock.locked = true + } + Variants { model: Config.general.idle.timeouts diff --git a/Modules/Lock/Lock.qml b/Modules/Lock/Lock.qml index 5de21c6..68d8a46 100644 --- a/Modules/Lock/Lock.qml +++ b/Modules/Lock/Lock.qml @@ -9,7 +9,6 @@ import qs.Components Scope { id: root - required property var lid property alias lock: lock property int seenOnce: 0 @@ -22,13 +21,6 @@ Scope { onRequestLock: lock.locked = true onUnlock: lock.locked = false - Connections { - target: root.lid - function onRequestLock(): void { - lock.locked = true - } - } - LockSurface { id: lockSurface diff --git a/Plugins/ZShell/CMakeLists.txt b/Plugins/ZShell/CMakeLists.txt index 1e04ea7..f691bc9 100644 --- a/Plugins/ZShell/CMakeLists.txt +++ b/Plugins/ZShell/CMakeLists.txt @@ -45,7 +45,6 @@ qml_module(ZShell requests.hpp requests.cpp toaster.hpp toaster.cpp qalculator.hpp qalculator.cpp - lidwatcher.hpp lidwatcher.cpp LIBRARIES Qt::Gui Qt::Quick diff --git a/Plugins/ZShell/Internal/CMakeLists.txt b/Plugins/ZShell/Internal/CMakeLists.txt index dd353a3..93f1ca9 100644 --- a/Plugins/ZShell/Internal/CMakeLists.txt +++ b/Plugins/ZShell/Internal/CMakeLists.txt @@ -9,6 +9,7 @@ qml_module(ZShell-internal sparklineitem.hpp sparklineitem.cpp arcgauge.hpp arcgauge.cpp wallpaperimage.hpp wallpaperimage.cpp + lidwatcher.hpp lidwatcher.cpp LIBRARIES Qt::Gui Qt::Quick diff --git a/Plugins/ZShell/Internal/lidwatcher.cpp b/Plugins/ZShell/Internal/lidwatcher.cpp new file mode 100644 index 0000000..b6a8773 --- /dev/null +++ b/Plugins/ZShell/Internal/lidwatcher.cpp @@ -0,0 +1,86 @@ +#include "lidwatcher.hpp" + +#include +#include +#include +#include +#include + +Q_LOGGING_CATEGORY(lcLidWatcher, "caelestia.internal.logindmanager", QtInfoMsg) + +namespace ZShell::internal { + +LidWatcher::LidWatcher(QObject* parent) : QObject(parent) { + auto bus = QDBusConnection::systemBus(); + if (!bus.isConnected()) { + qCWarning(lcLidWatcher) + << "Failed to connect to system bus:" << bus.lastError().message(); + return; + } + + bool ok = bus.connect("org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "PrepareForSleep", + this, + SLOT(handlePrepareForSleep(bool))); + + if (!ok) { + qCWarning(lcLidWatcher) + << "Failed to connect to PrepareForSleep signal:" + << bus.lastError().message(); + } + + QDBusInterface login1("org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + bus); + const QDBusReply reply = login1.call("GetSession", "auto"); + if (!reply.isValid()) { + qCWarning(lcLidWatcher) << "Failed to get session path"; + return; + } + const auto sessionPath = reply.value().path(); + + ok = bus.connect("org.freedesktop.login1", + sessionPath, + "org.freedesktop.login1.Session", + "Lock", + this, + SLOT(handleLockRequested())); + + if (!ok) { + qCWarning(lcLidWatcher) + << "Failed to connect to Lock signal:" << bus.lastError().message(); + } + + ok = bus.connect("org.freedesktop.login1", + sessionPath, + "org.freedesktop.login1.Session", + "Unlock", + this, + SLOT(handleUnlockRequested())); + + if (!ok) { + qCWarning(lcLidWatcher) << "Failed to connect to Unlock signal:" + << bus.lastError().message(); + } +} + +void LidWatcher::handlePrepareForSleep(bool sleep) { + if (sleep) { + emit aboutToSleep(); + } else { + emit resumed(); + } +} + +void LidWatcher::handleLockRequested() { + emit lockRequested(); +} + +void LidWatcher::handleUnlockRequested() { + emit unlockRequested(); +} + +} // namespace ZShell::internal diff --git a/Plugins/ZShell/Internal/lidwatcher.hpp b/Plugins/ZShell/Internal/lidwatcher.hpp new file mode 100644 index 0000000..6a6f4dc --- /dev/null +++ b/Plugins/ZShell/Internal/lidwatcher.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace ZShell::internal { + +class LidWatcher : public QObject { + Q_OBJECT + QML_ELEMENT + + public: + explicit LidWatcher(QObject* parent = nullptr); + + signals: + void aboutToSleep(); + void resumed(); + void lockRequested(); + void unlockRequested(); + + private slots: + void handlePrepareForSleep(bool sleep); + void handleLockRequested(); + void handleUnlockRequested(); +}; + +} // namespace ZShell::internal diff --git a/Plugins/ZShell/lidwatcher.cpp b/Plugins/ZShell/lidwatcher.cpp deleted file mode 100644 index 7a6105f..0000000 --- a/Plugins/ZShell/lidwatcher.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "lidwatcher.hpp" - -#include -#include -#include -#include -#include -#include -#include - -Q_LOGGING_CATEGORY(lcLidWatcher, "ZShell.lidwatcher", QtInfoMsg) - -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 kDBusPropertiesInterface = - "org.freedesktop.DBus.Properties"; - -LidWatcher::LidWatcher(QObject* parent) - : QObject(parent) - , m_watcher(nullptr) - , m_pollTimer(nullptr) - , m_available(false) -{ - QDBusConnection bus = QDBusConnection::systemBus(); - if (!bus.isConnected()) { - qCWarning(lcLidWatcher) << "system bus unavailable"; - emit availableChanged(); - return; - } - - m_pollTimer = new QTimer(this); - m_pollTimer->setInterval(5000); - connect(m_pollTimer, &QTimer::timeout, this, &LidWatcher::queryLidState); - - m_watcher = new QDBusServiceWatcher( - kLogin1Service, - bus, - QDBusServiceWatcher::WatchForRegistration, - this); - connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, - this, &LidWatcher::tryConnect); - - tryConnect(); -} - -bool LidWatcher::available() const { - return m_available; -} - -LidWatcher::LidState LidWatcher::state() const { - return m_state; -} - -void LidWatcher::tryConnect() { - QDBusConnection bus = QDBusConnection::systemBus(); - - const auto iface = bus.interface(); - if (!iface) { - queryLidState(); - if (!m_available) { - m_available = true; - emit availableChanged(); - } - if (!m_pollTimer->isActive()) { - m_pollTimer->start(); -} - return; - } - const auto reply = iface->isServiceRegistered(kLogin1Service); - if (!reply.isValid() || !reply.value()) { - queryLidState(); - qCInfo(lcLidWatcher) << "login1 not available, polling"; - if (!m_available) { - m_available = true; - emit availableChanged(); - } - if (!m_pollTimer->isActive()) { - m_pollTimer->start(); -} - return; - } - - 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, - "Get"); - msg << kLogin1Interface << "LidClosed"; - const QDBusReply reply = QDBusConnection::systemBus().call(msg); - if (!reply.isValid()) { - qCWarning(lcLidWatcher) - << "cannot query LidClosed:" << reply.error().message(); - return; - } - const auto newState = reply.value().toBool() ? Closed : Opened; - if (m_state != newState) { - m_state = newState; - emit stateChanged(); - } -} - -void LidWatcher::onPropertiesChanged(const QString& interface, - const QVariantMap& changed, - const QStringList& ) { - if (interface != kLogin1Interface) { - return; - } - if (!changed.contains("LidClosed")) { - return; - } - const auto newState = changed.value("LidClosed").toBool() ? Closed : Opened; - if (m_state != newState) { - m_state = newState; - emit stateChanged(); - } -} - -} // namespace ZShell diff --git a/Plugins/ZShell/lidwatcher.hpp b/Plugins/ZShell/lidwatcher.hpp deleted file mode 100644 index ec74ca1..0000000 --- a/Plugins/ZShell/lidwatcher.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -class QDBusServiceWatcher; -class QTimer; - -namespace ZShell { - -class LidWatcher : public QObject { - Q_OBJECT - QML_ELEMENT - QML_SINGLETON - - Q_PROPERTY(bool available READ available NOTIFY availableChanged) - Q_PROPERTY(LidState state READ state NOTIFY stateChanged) - - public: - enum LidState : std::uint8_t{ Opened, Closed }; - Q_ENUM(LidState) - - explicit LidWatcher(QObject* parent = nullptr); - - [[nodiscard]] bool available() const; - [[nodiscard]] LidState state() const; - - private: - void tryConnect(); - void queryLidState(); - - QDBusServiceWatcher* m_watcher; - QTimer* m_pollTimer; - bool m_available; - LidState m_state = Opened; - - private Q_SLOTS: - void onPropertiesChanged(const QString& interface, - const QVariantMap& changed, - const QStringList& invalidated); - - Q_SIGNALS: - void availableChanged(); - void stateChanged(); -}; - -} // namespace ZShell diff --git a/shell.qml b/shell.qml index 9063f58..83a43ab 100644 --- a/shell.qml +++ b/shell.qml @@ -35,8 +35,6 @@ ShellRoot { Lock { id: lock - - lid: lid } Shortcuts { @@ -49,16 +47,6 @@ ShellRoot { Polkit { } - LazyLoader { - id: lid - - activeAsync: Config.lock.lidWatch && Battery.isLaptop - - component: LidService { - onRequestLock: lock.lock.requestLock() - } - } - LazyLoader { activeAsync: root.laptop