diff --git a/src/dbus/CMakeLists.txt b/src/dbus/CMakeLists.txt
index fc004f3d..e5ca75e5 100644
--- a/src/dbus/CMakeLists.txt
+++ b/src/dbus/CMakeLists.txt
@@ -7,6 +7,11 @@ set_source_files_properties(org.freedesktop.DBus.ObjectManager.xml PROPERTIES
INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/dbus_objectmanager_types.hpp
)
+set_source_files_properties(org.quickshell.SessionLock.xml PROPERTIES
+ CLASSNAME SessionLockAdaptor
+ INCLUDE session_lock_dbus.hpp
+)
+
qt_add_dbus_interface(DBUS_INTERFACES
org.freedesktop.DBus.Properties.xml
dbus_properties
@@ -17,20 +22,26 @@ qt_add_dbus_interface(DBUS_INTERFACES
dbus_objectmanager
)
+qt_add_dbus_adaptor(DBUS_INTERFACES
+ org.quickshell.SessionLock.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/session_lock_dbus.hpp
+ qs::dbus::SessionLockAdaptor
+)
+
qt_add_library(quickshell-dbus STATIC
properties.cpp
objectmanager.cpp
bus.cpp
+ session_lock_dbus.cpp
${DBUS_INTERFACES}
)
# dbus headers
target_include_directories(quickshell-dbus PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-
target_link_libraries(quickshell-dbus PRIVATE Qt::Core Qt::DBus)
+
# todo: link dbus to quickshell here instead of in modules that use it directly
# linker does not like this as is
-
qs_add_pchset(dbus
DEPENDENCIES Qt::DBus
HEADERS
diff --git a/src/dbus/objectmanager.hpp b/src/dbus/objectmanager.hpp
index 4246ea28..ea88d499 100644
--- a/src/dbus/objectmanager.hpp
+++ b/src/dbus/objectmanager.hpp
@@ -34,4 +34,4 @@ class DBusObjectManager: public QObject {
DBusObjectManagerInterface* mInterface = nullptr;
};
-} // namespace qs::dbus
\ No newline at end of file
+} // namespace qs::dbus
diff --git a/src/dbus/org.quickshell.SessionLock.xml b/src/dbus/org.quickshell.SessionLock.xml
new file mode 100644
index 00000000..3b5c477c
--- /dev/null
+++ b/src/dbus/org.quickshell.SessionLock.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/dbus/session_lock_dbus.cpp b/src/dbus/session_lock_dbus.cpp
new file mode 100644
index 00000000..9bb57d37
--- /dev/null
+++ b/src/dbus/session_lock_dbus.cpp
@@ -0,0 +1,66 @@
+#include "session_lock_dbus.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../core/logcat.hpp"
+
+namespace {
+QS_LOGGING_CATEGORY(logDbusSessionLock, "quickshell.dbus.sessionlock", QtWarningMsg);
+}
+
+namespace qs::dbus {
+
+SessionLockAdaptor::SessionLockAdaptor(QObject* parent): QDBusAbstractAdaptor(parent) {
+ // Register on session bus
+ auto connection = QDBusConnection::sessionBus();
+
+ if (!connection.registerService("org.quickshell.SessionLock")) {
+ qCWarning(logDbusSessionLock) << "Failed to register DBus service org.quickshell.SessionLock:"
+ << connection.lastError().message();
+ } else {
+ qCInfo(logDbusSessionLock) << "Registered DBus service org.quickshell.SessionLock";
+ }
+
+ if (!connection
+ .registerObject("/org/quickshell/SessionLock", parent, QDBusConnection::ExportAdaptors))
+ {
+ qCWarning(logDbusSessionLock) << "Failed to register DBus object /org/quickshell/SessionLock:"
+ << connection.lastError().message();
+ } else {
+ qCInfo(logDbusSessionLock) << "Registered DBus object /org/quickshell/SessionLock";
+ }
+}
+
+void SessionLockAdaptor::setLocked(bool locked) {
+ if (this->mLocked != locked) {
+ this->mLocked = locked;
+ qCDebug(logDbusSessionLock) << "Lock state changed to:" << locked;
+ emit this->LockedChanged(locked);
+ }
+}
+
+void SessionLockAdaptor::setSecure(bool secure) {
+ if (this->mSecure != secure) {
+ this->mSecure = secure;
+ qCDebug(logDbusSessionLock) << "Secure state changed to:" << secure;
+ emit this->SecureChanged(secure);
+ }
+}
+
+bool SessionLockAdaptor::GetLocked() const {
+ qCDebug(logDbusSessionLock) << "GetLocked called, returning:" << this->mLocked;
+ return this->mLocked;
+}
+
+bool SessionLockAdaptor::GetSecure() const {
+ qCDebug(logDbusSessionLock) << "GetSecure called, returning:" << this->mSecure;
+ return this->mSecure;
+}
+
+} // namespace qs::dbus
diff --git a/src/dbus/session_lock_dbus.hpp b/src/dbus/session_lock_dbus.hpp
new file mode 100644
index 00000000..46aca932
--- /dev/null
+++ b/src/dbus/session_lock_dbus.hpp
@@ -0,0 +1,33 @@
+#pragma once
+#include
+#include
+#include
+
+namespace qs::dbus {
+
+class SessionLockAdaptor: public QDBusAbstractAdaptor {
+ Q_OBJECT;
+ Q_CLASSINFO("D-Bus Interface", "org.quickshell.SessionLock")
+
+public:
+ explicit SessionLockAdaptor(QObject* parent);
+ ~SessionLockAdaptor() override = default;
+ Q_DISABLE_COPY_MOVE(SessionLockAdaptor);
+
+ void setLocked(bool locked);
+ void setSecure(bool secure);
+
+public slots:
+ [[nodiscard]] bool GetLocked() const; // NOLINT(readability-identifier-naming)
+ [[nodiscard]] bool GetSecure() const; // NOLINT(readability-identifier-naming)
+
+signals:
+ void LockedChanged(bool locked); // NOLINT(readability-identifier-naming)
+ void SecureChanged(bool secure); // NOLINT(readability-identifier-naming)
+
+private:
+ bool mLocked = false;
+ bool mSecure = false;
+};
+
+} // namespace qs::dbus
diff --git a/src/wayland/session_lock/CMakeLists.txt b/src/wayland/session_lock/CMakeLists.txt
index d157fc13..a73dc8b0 100644
--- a/src/wayland/session_lock/CMakeLists.txt
+++ b/src/wayland/session_lock/CMakeLists.txt
@@ -5,14 +5,12 @@ qt_add_library(quickshell-wayland-sessionlock STATIC
shell_integration.cpp
session_lock.cpp
)
-
wl_proto(wlp-session-lock ext-session-lock-v1 "${WAYLAND_PROTOCOLS}/staging/ext-session-lock")
-
+target_include_directories(quickshell-wayland-sessionlock PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(quickshell-wayland-sessionlock PRIVATE
- Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate wayland-client
+ Qt::Quick Qt::WaylandClient Qt::WaylandClientPrivate Qt::DBus wayland-client
wlp-session-lock
+ quickshell-dbus
)
-
qs_pch(quickshell-wayland-sessionlock SET large)
-
target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-sessionlock)
diff --git a/src/wayland/session_lock/session_lock.cpp b/src/wayland/session_lock/session_lock.cpp
index c32dd90a..32bd287b 100644
--- a/src/wayland/session_lock/session_lock.cpp
+++ b/src/wayland/session_lock/session_lock.cpp
@@ -3,14 +3,17 @@
#include
#include
#include
+#include
#include
+#include "../../dbus/session_lock_dbus.hpp"
#include "lock.hpp"
#include "manager.hpp"
#include "shell_integration.hpp"
#include "surface.hpp"
namespace {
+
QSWaylandSessionLockManager* manager() {
static QSWaylandSessionLockManager* manager = nullptr; // NOLINT
@@ -20,33 +23,59 @@ QSWaylandSessionLockManager* manager() {
return manager;
}
+
} // namespace
+SessionLockManager::SessionLockManager(QObject* parent)
+ : QObject(parent)
+ , mDbusAdaptor(new qs::dbus::SessionLockAdaptor(this)) {
+ // DBus adaptor initialized in member initializer list so the service is always available
+}
+
bool SessionLockManager::lockAvailable() { return manager()->isActive(); }
bool SessionLockManager::lock() {
if (this->isLocked() || SessionLockManager::sessionLocked()) return false;
+
this->mLock = manager()->acquireLock();
this->mLock->setParent(this);
+ // Notify DBus that we're attempting to lock (not yet secure)
+ this->mDbusAdaptor->setLocked(true);
+ this->mDbusAdaptor->setSecure(false);
+
// clang-format off
- QObject::connect(this->mLock, &QSWaylandSessionLock::compositorLocked, this, &SessionLockManager::locked);
- QObject::connect(this->mLock, &QSWaylandSessionLock::unlocked, this, &SessionLockManager::unlocked);
+ QObject::connect(this->mLock, &QSWaylandSessionLock::compositorLocked, this, [this]() {
+ this->mDbusAdaptor->setSecure(true);
+ emit this->locked();
+ });
+
+ QObject::connect(this->mLock, &QSWaylandSessionLock::unlocked, this, [this]() {
+ this->mDbusAdaptor->setLocked(false);
+ this->mDbusAdaptor->setSecure(false);
+ emit this->unlocked();
+ });
// clang-format on
+
return true;
}
bool SessionLockManager::unlock() {
if (!this->isLocked()) return false;
+
this->mLock->unlock();
+
auto* lock = this->mLock;
this->mLock = nullptr;
delete lock;
+
return true;
}
bool SessionLockManager::isLocked() const { return this->mLock != nullptr; }
+
bool SessionLockManager::sessionLocked() { return manager()->isLocked(); }
+
bool SessionLockManager::isSecure() { return manager()->isSecure(); }
LockWindowExtension::~LockWindowExtension() {
@@ -83,14 +112,17 @@ bool LockWindowExtension::attach(QWindow* window, SessionLockManager* manager) {
window->setScreen(screen);
waylandWindow = dynamic_cast(window->handle());
+
if (waylandWindow == nullptr) {
qWarning() << window << "is not a wayland window. Cannot create lock surface.";
return false;
}
static QSWaylandSessionLockIntegration* lockIntegration = nullptr; // NOLINT
+
if (lockIntegration == nullptr) {
lockIntegration = new QSWaylandSessionLockIntegration();
+
if (!lockIntegration->initialize(waylandWindow->display())) {
delete lockIntegration;
lockIntegration = nullptr;
@@ -103,6 +135,7 @@ bool LockWindowExtension::attach(QWindow* window, SessionLockManager* manager) {
this->setParent(window);
window->setProperty("sessionlock_ext", QVariant::fromValue(this));
+
this->lock = manager->mLock;
if (waylandWindow != nullptr) {
diff --git a/src/wayland/session_lock/session_lock.hpp b/src/wayland/session_lock/session_lock.hpp
index 5a558966..80002533 100644
--- a/src/wayland/session_lock/session_lock.hpp
+++ b/src/wayland/session_lock/session_lock.hpp
@@ -1,5 +1,4 @@
#pragma once
-
#include
#include
#include
@@ -9,11 +8,15 @@ class QSWaylandSessionLock;
class QSWaylandSessionLockSurface;
class QSWaylandSessionLockIntegration;
+namespace qs::dbus {
+class SessionLockAdaptor;
+}
+
class SessionLockManager: public QObject {
Q_OBJECT;
public:
- explicit SessionLockManager(QObject* parent = nullptr): QObject(parent) {}
+ explicit SessionLockManager(QObject* parent = nullptr); // Declare only, implement in .cpp
[[nodiscard]] static bool lockAvailable();
@@ -46,11 +49,9 @@ class SessionLockManager: public QObject {
// After receiving this event the caller should destroy all of its lock surfaces.
void unlocked();
-private slots:
- //void onUnlocked();
-
private:
QSWaylandSessionLock* mLock = nullptr;
+ qs::dbus::SessionLockAdaptor* mDbusAdaptor = nullptr;
friend class LockWindowExtension;
};