forked from quickshell/quickshell
feat(slock): implement ext_session_lock_v1 backend
note: did not run lints or fully test yet
This commit is contained in:
parent
70c5cf1e16
commit
1fa87b7c5a
|
@ -22,7 +22,7 @@ message(STATUS "Found wayland-scanner at ${waylandscanner}")
|
||||||
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
||||||
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
|
OUTPUT_VARIABLE WAYLAND_PROTOCOLS
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ qt_add_qml_module(quickshell-wayland URI Quickshell.Wayland)
|
||||||
add_library(quickshell-wayland-init OBJECT init.cpp)
|
add_library(quickshell-wayland-init OBJECT init.cpp)
|
||||||
|
|
||||||
add_subdirectory(wlr_layershell)
|
add_subdirectory(wlr_layershell)
|
||||||
|
add_subdirectory(session_lock)
|
||||||
target_link_libraries(quickshell-wayland PRIVATE ${QT_DEPS})
|
target_link_libraries(quickshell-wayland PRIVATE ${QT_DEPS})
|
||||||
target_link_libraries(quickshell-wayland-init PRIVATE ${QT_DEPS})
|
target_link_libraries(quickshell-wayland-init PRIVATE ${QT_DEPS})
|
||||||
|
|
||||||
|
|
12
src/wayland/session_lock/CMakeLists.txt
Normal file
12
src/wayland/session_lock/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
qt_add_library(quickshell-wayland-sessionlock STATIC
|
||||||
|
manager.cpp
|
||||||
|
surface.cpp
|
||||||
|
lock.cpp
|
||||||
|
shell_integration.cpp
|
||||||
|
session_lock.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
wl_proto(quickshell-wayland-sessionlock ext-session-lock-v1 "${WAYLAND_PROTOCOLS}/staging/ext-session-lock/ext-session-lock-v1.xml")
|
||||||
|
target_link_libraries(quickshell-wayland-sessionlock PRIVATE ${QT_DEPS} wayland-client)
|
||||||
|
|
||||||
|
target_link_libraries(quickshell-wayland PRIVATE quickshell-wayland-sessionlock)
|
42
src/wayland/session_lock/lock.cpp
Normal file
42
src/wayland/session_lock/lock.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#include "lock.hpp"
|
||||||
|
|
||||||
|
#include <private/qwaylandshellintegration_p.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
#include "manager.hpp"
|
||||||
|
|
||||||
|
QSWaylandSessionLock::QSWaylandSessionLock(
|
||||||
|
QSWaylandSessionLockManager* manager,
|
||||||
|
::ext_session_lock_v1* lock
|
||||||
|
)
|
||||||
|
: manager(manager) {
|
||||||
|
this->init(lock); // if isInitialized is false that means we already unlocked.
|
||||||
|
}
|
||||||
|
|
||||||
|
QSWaylandSessionLock::~QSWaylandSessionLock() { this->unlock(); }
|
||||||
|
|
||||||
|
void QSWaylandSessionLock::unlock() {
|
||||||
|
if (this->isInitialized()) {
|
||||||
|
if (this->locked) this->unlock_and_destroy();
|
||||||
|
else this->destroy();
|
||||||
|
|
||||||
|
this->locked = false;
|
||||||
|
this->manager->active = nullptr;
|
||||||
|
|
||||||
|
emit this->unlocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QSWaylandSessionLock::active() const { return this->isInitialized(); }
|
||||||
|
|
||||||
|
bool QSWaylandSessionLock::hasCompositorLock() const { return this->locked; }
|
||||||
|
|
||||||
|
void QSWaylandSessionLock::ext_session_lock_v1_locked() {
|
||||||
|
this->locked = true;
|
||||||
|
emit this->compositorLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSWaylandSessionLock::ext_session_lock_v1_finished() {
|
||||||
|
this->locked = false;
|
||||||
|
this->unlock();
|
||||||
|
}
|
38
src/wayland/session_lock/lock.hpp
Normal file
38
src/wayland/session_lock/lock.hpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qtclasshelpermacros.h>
|
||||||
|
#include <qwayland-ext-session-lock-v1.h>
|
||||||
|
|
||||||
|
class QSWaylandSessionLockManager;
|
||||||
|
|
||||||
|
class QSWaylandSessionLock
|
||||||
|
: public QObject
|
||||||
|
, public QtWayland::ext_session_lock_v1 {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QSWaylandSessionLock(QSWaylandSessionLockManager* manager, ::ext_session_lock_v1* lock);
|
||||||
|
~QSWaylandSessionLock() override;
|
||||||
|
Q_DISABLE_COPY_MOVE(QSWaylandSessionLock);
|
||||||
|
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
// Returns true if the lock has not finished.
|
||||||
|
[[nodiscard]] bool active() const;
|
||||||
|
// Returns true if the compositor considers the session to be locked.
|
||||||
|
[[nodiscard]] bool hasCompositorLock() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void compositorLocked();
|
||||||
|
void unlocked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ext_session_lock_v1_locked() override;
|
||||||
|
void ext_session_lock_v1_finished() override;
|
||||||
|
|
||||||
|
QSWaylandSessionLockManager* manager; // static and not dealloc'd
|
||||||
|
|
||||||
|
// true when the compositor determines the session is locked
|
||||||
|
bool locked = false;
|
||||||
|
};
|
22
src/wayland/session_lock/manager.cpp
Normal file
22
src/wayland/session_lock/manager.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include "manager.hpp"
|
||||||
|
|
||||||
|
#include <qdebug.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <qwaylandclientextension.h>
|
||||||
|
|
||||||
|
#include "lock.hpp"
|
||||||
|
|
||||||
|
QSWaylandSessionLockManager::QSWaylandSessionLockManager()
|
||||||
|
: QWaylandClientExtensionTemplate<QSWaylandSessionLockManager>(1) {
|
||||||
|
this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSWaylandSessionLockManager::~QSWaylandSessionLockManager() { this->destroy(); }
|
||||||
|
|
||||||
|
QSWaylandSessionLock* QSWaylandSessionLockManager::acquireLock() {
|
||||||
|
if (this->isLocked()) return nullptr;
|
||||||
|
this->active = new QSWaylandSessionLock(this, this->lock());
|
||||||
|
return this->active;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QSWaylandSessionLockManager::isLocked() const { return this->active != nullptr; }
|
27
src/wayland/session_lock/manager.hpp
Normal file
27
src/wayland/session_lock/manager.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qtclasshelpermacros.h>
|
||||||
|
#include <qwayland-ext-session-lock-v1.h>
|
||||||
|
#include <qwaylandclientextension.h>
|
||||||
|
|
||||||
|
#include "lock.hpp"
|
||||||
|
|
||||||
|
class QSWaylandSessionLockManager
|
||||||
|
: public QWaylandClientExtensionTemplate<QSWaylandSessionLockManager>
|
||||||
|
, public QtWayland::ext_session_lock_manager_v1 {
|
||||||
|
public:
|
||||||
|
QSWaylandSessionLockManager();
|
||||||
|
~QSWaylandSessionLockManager() override;
|
||||||
|
Q_DISABLE_COPY_MOVE(QSWaylandSessionLockManager);
|
||||||
|
|
||||||
|
// Create a new session lock if there is no currently active lock, otherwise null.
|
||||||
|
QSWaylandSessionLock* acquireLock();
|
||||||
|
[[nodiscard]] bool isLocked() const;
|
||||||
|
|
||||||
|
static bool sessionLocked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSWaylandSessionLock* active = nullptr;
|
||||||
|
|
||||||
|
friend class QSWaylandSessionLock;
|
||||||
|
};
|
107
src/wayland/session_lock/session_lock.cpp
Normal file
107
src/wayland/session_lock/session_lock.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#include "session_lock.hpp"
|
||||||
|
|
||||||
|
#include <private/qwaylanddisplay_p.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qwindow.h>
|
||||||
|
|
||||||
|
#include "lock.hpp"
|
||||||
|
#include "manager.hpp"
|
||||||
|
#include "shell_integration.hpp"
|
||||||
|
#include "surface.hpp"
|
||||||
|
|
||||||
|
static QSWaylandSessionLockManager* manager() {
|
||||||
|
static QSWaylandSessionLockManager* manager = nullptr;
|
||||||
|
|
||||||
|
if (manager == nullptr) {
|
||||||
|
manager = new QSWaylandSessionLockManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SessionLockManager::lock() {
|
||||||
|
if (SessionLockManager::sessionLocked()) return false;
|
||||||
|
this->mLock = manager()->acquireLock();
|
||||||
|
this->mLock->setParent(this);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
QObject::connect(this->mLock, &QSWaylandSessionLock::compositorLocked, this, &SessionLockManager::locked);
|
||||||
|
QObject::connect(this->mLock, &QSWaylandSessionLock::unlocked, this, &SessionLockManager::unlocked);
|
||||||
|
// clang-format on
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SessionLockManager::unlock() {
|
||||||
|
if (!this->isLocked()) return false;
|
||||||
|
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(); }
|
||||||
|
|
||||||
|
LockWindowExtension::~LockWindowExtension() {
|
||||||
|
if (this->surface != nullptr) {
|
||||||
|
this->surface->setExtension(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LockWindowExtension* LockWindowExtension::get(QWindow* window) {
|
||||||
|
auto v = window->property("sessionlock_ext");
|
||||||
|
|
||||||
|
if (v.canConvert<LockWindowExtension*>()) {
|
||||||
|
return v.value<LockWindowExtension*>();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LockWindowExtension::attach(QWindow* window, SessionLockManager* manager) {
|
||||||
|
if (this->surface != nullptr) throw "Cannot change the attached window of a LockWindowExtension";
|
||||||
|
|
||||||
|
auto* current = LockWindowExtension::get(window);
|
||||||
|
QtWaylandClient::QWaylandWindow* waylandWindow = nullptr;
|
||||||
|
|
||||||
|
if (current != nullptr) {
|
||||||
|
current->surface->setExtension(this);
|
||||||
|
} else {
|
||||||
|
window->create();
|
||||||
|
|
||||||
|
waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow*>(window->handle());
|
||||||
|
if (waylandWindow == nullptr) {
|
||||||
|
qWarning() << window << "is not a wayland window. Cannot create lock surface.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QSWaylandSessionLockIntegration* lockIntegration = nullptr;
|
||||||
|
if (lockIntegration == nullptr) {
|
||||||
|
lockIntegration = new QSWaylandSessionLockIntegration();
|
||||||
|
if (!lockIntegration->initialize(waylandWindow->display())) {
|
||||||
|
delete lockIntegration;
|
||||||
|
lockIntegration = nullptr;
|
||||||
|
qWarning() << "Failed to initialize lockscreen integration";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
waylandWindow->setShellIntegration(lockIntegration);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setParent(window);
|
||||||
|
window->setProperty("sessionlock_ext", QVariant::fromValue(this));
|
||||||
|
this->lock = manager->mLock;
|
||||||
|
|
||||||
|
if (waylandWindow != nullptr) {
|
||||||
|
this->surface = new QSWaylandSessionLockSurface(waylandWindow);
|
||||||
|
if (this->immediatelyVisible) this->surface->setVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LockWindowExtension::setVisible() {
|
||||||
|
if (this->surface == nullptr) immediatelyVisible = true;
|
||||||
|
else this->surface->setVisible();
|
||||||
|
}
|
92
src/wayland/session_lock/session_lock.hpp
Normal file
92
src/wayland/session_lock/session_lock.hpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qtclasshelpermacros.h>
|
||||||
|
#include <qtmetamacros.h>
|
||||||
|
#include <qwindow.h>
|
||||||
|
|
||||||
|
class QSWaylandSessionLock;
|
||||||
|
class QSWaylandSessionLockSurface;
|
||||||
|
class QSWaylandSessionLockIntegration;
|
||||||
|
|
||||||
|
class SessionLockManager: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SessionLockManager(QObject* parent = nullptr): QObject(parent) {}
|
||||||
|
Q_DISABLE_COPY_MOVE(SessionLockManager);
|
||||||
|
|
||||||
|
// Returns true if a lock was acquired.
|
||||||
|
// If true is returned the caller must watch the global screen list and create/destroy
|
||||||
|
// windows with an attached LockWindowExtension to match it.
|
||||||
|
bool lock();
|
||||||
|
|
||||||
|
// Returns true if the session was locked and is now unlocked.
|
||||||
|
bool unlock();
|
||||||
|
|
||||||
|
[[nodiscard]] bool isLocked() const;
|
||||||
|
|
||||||
|
static bool sessionLocked();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// This signal is sent once the compositor considers the session to be fully locked.
|
||||||
|
// This corrosponds to the ext_session_lock_v1::locked event.
|
||||||
|
void locked();
|
||||||
|
|
||||||
|
// This signal is sent once the compositor considers the session to be unlocked.
|
||||||
|
// This corrosponds to the ext_session_lock_v1::finished event.
|
||||||
|
//
|
||||||
|
// The session lock will end in one of three cases.
|
||||||
|
// 1. unlock() is called.
|
||||||
|
// 2. The SessionLockManager is destroyed.
|
||||||
|
// 3. The compositor forcibly unlocks the session.
|
||||||
|
//
|
||||||
|
// After receiving this event the caller should destroy all of its lock surfaces.
|
||||||
|
void unlocked();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
//void onUnlocked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSWaylandSessionLock* mLock = nullptr;
|
||||||
|
|
||||||
|
friend class LockWindowExtension;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LockWindowExtension: public QObject {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LockWindowExtension(QObject* parent = nullptr): QObject(parent) {}
|
||||||
|
~LockWindowExtension() override;
|
||||||
|
|
||||||
|
// Attach this lock extension to the given window.
|
||||||
|
// The extension is reparented to the window and replaces any existing lock extension.
|
||||||
|
// Returns false if the window cannot be used.
|
||||||
|
bool attach(QWindow* window, SessionLockManager* manager);
|
||||||
|
|
||||||
|
// This must be called in place of QWindow::setVisible. Calling QWindow::setVisible will result in a crash.
|
||||||
|
// To make a window invisible, destroy it as it cannot be recovered.
|
||||||
|
void setVisible();
|
||||||
|
|
||||||
|
[[nodiscard]] bool isLocked() const;
|
||||||
|
|
||||||
|
static LockWindowExtension* get(QWindow* window);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// This signal is sent once the compositor considers the session to be fully locked.
|
||||||
|
// See SessionLockManager::locked for details.
|
||||||
|
void locked();
|
||||||
|
|
||||||
|
// After receiving this signal the window is no longer in use by the compositor
|
||||||
|
// and should be destroyed. See SessionLockManager::unlocked for details.
|
||||||
|
void unlocked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSWaylandSessionLockSurface* surface = nullptr;
|
||||||
|
QSWaylandSessionLock* lock = nullptr;
|
||||||
|
bool immediatelyVisible = false;
|
||||||
|
|
||||||
|
friend class QSWaylandSessionLockSurface;
|
||||||
|
friend class QSWaylandSessionLockIntegration;
|
||||||
|
};
|
20
src/wayland/session_lock/shell_integration.cpp
Normal file
20
src/wayland/session_lock/shell_integration.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "shell_integration.hpp"
|
||||||
|
|
||||||
|
#include <private/qwaylandshellsurface_p.h>
|
||||||
|
#include <private/qwaylandwindow_p.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
|
||||||
|
#include "session_lock.hpp"
|
||||||
|
#include "surface.hpp"
|
||||||
|
|
||||||
|
QtWaylandClient::QWaylandShellSurface*
|
||||||
|
QSWaylandSessionLockIntegration::createShellSurface(QtWaylandClient::QWaylandWindow* window) {
|
||||||
|
auto* lock = LockWindowExtension::get(window->window());
|
||||||
|
if (lock == nullptr || lock->surface == nullptr || !lock->surface->isExposed()) {
|
||||||
|
qFatal() << "Visibility canary failed. A window with a LockWindowExtension MUST be set to "
|
||||||
|
"visible via LockWindowExtension::setVisible";
|
||||||
|
throw nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lock->surface;
|
||||||
|
}
|
13
src/wayland/session_lock/shell_integration.hpp
Normal file
13
src/wayland/session_lock/shell_integration.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <private/qwaylanddisplay_p.h>
|
||||||
|
#include <private/qwaylandshellintegration_p.h>
|
||||||
|
#include <private/qwaylandshellsurface_p.h>
|
||||||
|
#include <private/qwaylandwindow_p.h>
|
||||||
|
|
||||||
|
class QSWaylandSessionLockIntegration: public QtWaylandClient::QWaylandShellIntegration {
|
||||||
|
public:
|
||||||
|
bool initialize(QtWaylandClient::QWaylandDisplay* /* display */) override { return true; }
|
||||||
|
QtWaylandClient::QWaylandShellSurface* createShellSurface(QtWaylandClient::QWaylandWindow* window
|
||||||
|
) override;
|
||||||
|
};
|
111
src/wayland/session_lock/surface.cpp
Normal file
111
src/wayland/session_lock/surface.cpp
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#include "surface.hpp"
|
||||||
|
|
||||||
|
#include <private/qwaylandscreen_p.h>
|
||||||
|
#include <private/qwaylandshellsurface_p.h>
|
||||||
|
#include <private/qwaylandshmbackingstore_p.h>
|
||||||
|
#include <private/qwaylandsurface_p.h>
|
||||||
|
#include <private/qwaylandwindow_p.h>
|
||||||
|
#include <qlogging.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
|
||||||
|
#include "lock.hpp"
|
||||||
|
#include "session_lock.hpp"
|
||||||
|
|
||||||
|
QSWaylandSessionLockSurface::QSWaylandSessionLockSurface(QtWaylandClient::QWaylandWindow* window)
|
||||||
|
: QtWaylandClient::QWaylandShellSurface(window) {
|
||||||
|
auto* qwindow = window->window();
|
||||||
|
this->setExtension(LockWindowExtension::get(qwindow));
|
||||||
|
|
||||||
|
if (this->ext == nullptr) {
|
||||||
|
qFatal() << "QSWaylandSessionLockSurface created with null LockWindowExtension";
|
||||||
|
throw nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->ext->lock == nullptr) {
|
||||||
|
qFatal() << "QSWaylandSessionLock for QSWaylandSessionLockSurface died";
|
||||||
|
throw nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_output* output = nullptr;
|
||||||
|
auto* waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen*>(qwindow->screen()->handle());
|
||||||
|
|
||||||
|
if (waylandScreen != nullptr) {
|
||||||
|
output = waylandScreen->output();
|
||||||
|
} else {
|
||||||
|
qFatal() << "Session lock screen does not corrospond to a real screen. Force closing window";
|
||||||
|
throw nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->init(this->ext->lock->get_lock_surface(window->waylandSurface()->object(), output));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSWaylandSessionLockSurface::~QSWaylandSessionLockSurface() { this->destroy(); }
|
||||||
|
|
||||||
|
bool QSWaylandSessionLockSurface::isExposed() const { return this->configured; }
|
||||||
|
|
||||||
|
void QSWaylandSessionLockSurface::applyConfigure() {
|
||||||
|
this->window()->resizeFromApplyConfigure(this->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QSWaylandSessionLockSurface::handleExpose(const QRegion& region) {
|
||||||
|
if (this->initBuf != nullptr) {
|
||||||
|
// at this point qt's next commit to the surface will have a new buffer, and we can safely delete this one.
|
||||||
|
delete this->initBuf;
|
||||||
|
this->initBuf = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->QtWaylandClient::QWaylandShellSurface::handleExpose(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSWaylandSessionLockSurface::setExtension(LockWindowExtension* ext) {
|
||||||
|
if (ext == nullptr) {
|
||||||
|
this->window()->window()->close();
|
||||||
|
} else {
|
||||||
|
if (this->ext != nullptr) {
|
||||||
|
this->ext->surface = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ext = ext;
|
||||||
|
this->ext->surface = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSWaylandSessionLockSurface::setVisible() {
|
||||||
|
if (this->configured && !this->visible) initVisible();
|
||||||
|
this->visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSWaylandSessionLockSurface::ext_session_lock_surface_v1_configure(
|
||||||
|
quint32 serial,
|
||||||
|
quint32 width,
|
||||||
|
quint32 height
|
||||||
|
) {
|
||||||
|
this->ack_configure(serial);
|
||||||
|
|
||||||
|
this->size = QSize(static_cast<qint32>(width), static_cast<qint32>(height));
|
||||||
|
if (!this->configured) {
|
||||||
|
this->configured = true;
|
||||||
|
|
||||||
|
this->window()->resizeFromApplyConfigure(this->size);
|
||||||
|
this->window()->handleExpose(QRect(QPoint(), this->size));
|
||||||
|
if (this->visible) initVisible();
|
||||||
|
} else {
|
||||||
|
this->window()->applyConfigureWhenPossible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSWaylandSessionLockSurface::initVisible() {
|
||||||
|
this->visible = true;
|
||||||
|
|
||||||
|
// qt always commits a null buffer in QWaylandWindow::initWindow.
|
||||||
|
// We attach a dummy buffer to satisfy ext_session_lock_v1.
|
||||||
|
this->initBuf = new QtWaylandClient::QWaylandShmBuffer(
|
||||||
|
this->window()->display(),
|
||||||
|
size,
|
||||||
|
QImage::Format_ARGB32
|
||||||
|
);
|
||||||
|
|
||||||
|
this->window()->waylandSurface()->attach(initBuf->buffer(), 0, 0);
|
||||||
|
this->window()->window()->setVisible(true);
|
||||||
|
}
|
39
src/wayland/session_lock/surface.hpp
Normal file
39
src/wayland/session_lock/surface.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <private/qwaylandshellsurface_p.h>
|
||||||
|
#include <private/qwaylandshmbackingstore_p.h>
|
||||||
|
#include <private/qwaylandwindow_p.h>
|
||||||
|
#include <qregion.h>
|
||||||
|
#include <qtclasshelpermacros.h>
|
||||||
|
#include <qtypes.h>
|
||||||
|
#include <qwayland-ext-session-lock-v1.h>
|
||||||
|
|
||||||
|
#include "session_lock.hpp"
|
||||||
|
|
||||||
|
class QSWaylandSessionLockSurface
|
||||||
|
: public QtWaylandClient::QWaylandShellSurface
|
||||||
|
, public QtWayland::ext_session_lock_surface_v1 {
|
||||||
|
public:
|
||||||
|
QSWaylandSessionLockSurface(QtWaylandClient::QWaylandWindow* window);
|
||||||
|
~QSWaylandSessionLockSurface() override;
|
||||||
|
Q_DISABLE_COPY_MOVE(QSWaylandSessionLockSurface);
|
||||||
|
|
||||||
|
[[nodiscard]] bool isExposed() const override;
|
||||||
|
void applyConfigure() override;
|
||||||
|
bool handleExpose(const QRegion& region) override;
|
||||||
|
|
||||||
|
void setExtension(LockWindowExtension*);
|
||||||
|
void setVisible();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
ext_session_lock_surface_v1_configure(quint32 serial, quint32 width, quint32 height) override;
|
||||||
|
|
||||||
|
void initVisible();
|
||||||
|
|
||||||
|
LockWindowExtension* ext = nullptr;
|
||||||
|
QSize size;
|
||||||
|
bool configured = false;
|
||||||
|
bool visible = false;
|
||||||
|
QtWaylandClient::QWaylandShmBuffer* initBuf = nullptr;
|
||||||
|
};
|
Loading…
Reference in a new issue