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(
|
||||
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
||||
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
|
||||
OUTPUT_VARIABLE WAYLAND_PROTOCOLS
|
||||
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_subdirectory(wlr_layershell)
|
||||
add_subdirectory(session_lock)
|
||||
target_link_libraries(quickshell-wayland 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