Skip to content
Open
4 changes: 4 additions & 0 deletions changelog/next.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## New Features

- Added opt-in logind LockedHint updates for WlSessionLock.

## Bug Fixes

- Fixed ScreencopyView not displaying when only lock surfaces are shown.
Expand Down
3 changes: 1 addition & 2 deletions src/dbus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ qt_add_library(quickshell-dbus STATIC

# 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
Expand Down
2 changes: 1 addition & 1 deletion src/dbus/objectmanager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ class DBusObjectManager: public QObject {
DBusObjectManagerInterface* mInterface = nullptr;
};

} // namespace qs::dbus
} // namespace qs::dbus
57 changes: 41 additions & 16 deletions src/wayland/session_lock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,35 @@
#include "../window/proxywindow.hpp"
#include "session_lock/session_lock.hpp"

bool WlSessionLock::exposeDbus() const { return this->mExposeDbus; }

void WlSessionLock::setExposeDbus(bool exposeDbus) {
if (this->mExposeDbus == exposeDbus) return;
if (this->manager != nullptr) {
qWarning() << "WlSessionLock.exposeDbus cannot be changed after initialization.";
return;
}
this->mExposeDbus = exposeDbus;
emit this->exposeDbusChanged();
}

void WlSessionLock::onReload(QObject* oldInstance) {
auto* old = qobject_cast<WlSessionLock*>(oldInstance);

if (old != nullptr) {
auto* app = QCoreApplication::instance();
auto* guiApp = qobject_cast<QGuiApplication*>(app);

if (old != nullptr && guiApp != nullptr) {
// Ensure we don't leave stale connections to the old instance behind.
QObject::disconnect(guiApp, nullptr, old, nullptr);
}

if (old != nullptr && old->manager != nullptr) {
QObject::disconnect(old->manager, nullptr, old, nullptr);
this->manager = old->manager;
this->manager->setParent(this);
} else {
this->manager = new SessionLockManager(this);
this->manager = new SessionLockManager(this->mExposeDbus, this);
}

// clang-format off
Expand All @@ -39,9 +59,6 @@ void WlSessionLock::onReload(QObject* oldInstance) {

QObject::connect(this->manager, &SessionLockManager::unlocked, this, &WlSessionLock::unlock);

auto* app = QCoreApplication::instance();
auto* guiApp = qobject_cast<QGuiApplication*>(app);

if (guiApp != nullptr) {
QObject::connect(guiApp, &QGuiApplication::primaryScreenChanged, this, &WlSessionLock::onScreensChanged);
QObject::connect(guiApp, &QGuiApplication::screenAdded, this, &WlSessionLock::onScreensChanged);
Expand Down Expand Up @@ -99,7 +116,7 @@ void WlSessionLock::updateSurfaces(bool show, WlSessionLock* old) {
}

if (show) {
if (!this->manager->isLocked()) {
if (this->manager == nullptr || !this->manager->isLocked()) {
qFatal() << "Tried to show lockscreen surfaces without active lock";
}

Expand All @@ -126,9 +143,13 @@ void WlSessionLock::realizeLockTarget(WlSessionLock* old) {

// preload initial surfaces to make the chance of the compositor displaying a blank
// frame before the lock surfaces are shown as low as possible.
this->updateSurfaces(false);
this->updateSurfaces(false, old);

if (!this->manager->lock()) this->lockTarget = false;
if (this->manager == nullptr || !this->manager->lock()) {
this->lockTarget = false;
this->unlock();
return;
}

this->updateSurfaces(true, old);
} else {
Expand All @@ -137,18 +158,22 @@ void WlSessionLock::realizeLockTarget(WlSessionLock* old) {
}

void WlSessionLock::unlock() {
if (this->isLocked()) {
this->lockTarget = false;
this->manager->unlock();
if (!this->isLocked()) return;

for (auto* surface: this->surfaces) {
surface->deleteLater();
}
this->lockTarget = false;

this->surfaces.clear();
// Manager may legitimately be null during early reload/init paths.
if (this->manager != nullptr) {
this->manager->unlock();
}

emit this->lockStateChanged();
for (auto* surface: this->surfaces) {
surface->deleteLater();
}

this->surfaces.clear();

emit this->lockStateChanged();
}

void WlSessionLock::onScreensChanged() {
Expand Down
7 changes: 6 additions & 1 deletion src/wayland/session_lock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class WlSessionLock: public Reloadable {
Q_PROPERTY(bool secure READ isSecure NOTIFY secureStateChanged);
/// The surface that will be created for each screen. Must create a @@WlSessionLockSurface$.
Q_PROPERTY(QQmlComponent* surface READ surfaceComponent WRITE setSurfaceComponent NOTIFY surfaceComponentChanged);
Q_PROPERTY(bool exposeDbus READ exposeDbus WRITE setExposeDbus NOTIFY exposeDbusChanged);
// clang-format on
QML_ELEMENT;
Q_CLASSINFO("DefaultProperty", "surface");
Expand All @@ -84,10 +85,14 @@ class WlSessionLock: public Reloadable {
[[nodiscard]] QQmlComponent* surfaceComponent() const;
void setSurfaceComponent(QQmlComponent* surfaceComponent);

[[nodiscard]] bool exposeDbus() const;
void setExposeDbus(bool exposeDbus);

signals:
void lockStateChanged();
void secureStateChanged();
void surfaceComponentChanged();
void exposeDbusChanged();

private slots:
void unlock();
Expand All @@ -101,6 +106,7 @@ private slots:
QQmlComponent* mSurfaceComponent = nullptr;
QMap<QScreen*, WlSessionLockSurface*> surfaces;
bool lockTarget = false;
bool mExposeDbus = false;

friend class WlSessionLockSurface;
};
Expand Down Expand Up @@ -132,7 +138,6 @@ class WlSessionLockSurface: public Reloadable {
/// > // your content here
/// > }
/// > }
/// > ```
/// > ... but you probably shouldn't make a transparent lock,
/// > and most compositors will ignore an attempt to do so.
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged);
Expand Down
3 changes: 1 addition & 2 deletions src/wayland/session_lock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ 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_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
)

Expand Down
5 changes: 3 additions & 2 deletions src/wayland/session_lock/lock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class QSWaylandSessionLockManager;

class QSWaylandSessionLock
class QSWaylandSessionLock // NOLINT(misc-multiple-inheritance)
: public QObject
, public QtWayland::ext_session_lock_v1 {
Q_OBJECT;
Expand All @@ -27,10 +27,11 @@ class QSWaylandSessionLock
void compositorLocked();
void unlocked();

private:
protected:
void ext_session_lock_v1_locked() override;
void ext_session_lock_v1_finished() override;

private:
QSWaylandSessionLockManager* manager; // static and not dealloc'd

// true when the compositor determines the session is locked
Expand Down
2 changes: 1 addition & 1 deletion src/wayland/session_lock/manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#include "lock.hpp"

class QSWaylandSessionLockManager
class QSWaylandSessionLockManager // NOLINT(misc-multiple-inheritance)
: public QWaylandClientExtensionTemplate<QSWaylandSessionLockManager>
, public QtWayland::ext_session_lock_manager_v1 {
public:
Expand Down
Loading
Loading