#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../core/qmlscreen.hpp" #include "../core/reload.hpp" #include "session_lock/session_lock.hpp" class SessionLockSurface; /// Note: Very untested. Do anything outside of the obvious use cases and you WILL red screen. class SessionLock: public Reloadable { Q_OBJECT; // clang-format off /// Note: only one SessionLock may be locked at a time. Q_PROPERTY(bool locked READ isLocked WRITE setLocked NOTIFY lockStateChanged); /// Returns the *compositor* lock state, which will only be set to true after all surfaces are in place. Q_PROPERTY(bool secure READ isSecure NOTIFY secureStateChanged); /// Component that will be instantiated for each screen. Must be a `SessionLockSurface`. Q_PROPERTY(QQmlComponent* surface READ surfaceComponent WRITE setSurfaceComponent NOTIFY surfaceComponentChanged); // clang-format on QML_ELEMENT; Q_CLASSINFO("DefaultProperty", "surface"); public: explicit SessionLock(QObject* parent = nullptr): Reloadable(parent) {} void onReload(QObject* oldInstance) override; [[nodiscard]] bool isLocked() const; void setLocked(bool locked); [[nodiscard]] bool isSecure() const; [[nodiscard]] QQmlComponent* surfaceComponent() const; void setSurfaceComponent(QQmlComponent* surfaceComponent); signals: void lockStateChanged(); void secureStateChanged(); void surfaceComponentChanged(); private slots: void unlock(); void onScreensChanged(); private: void updateSurfaces(SessionLock* old = nullptr); SessionLockManager* manager = nullptr; QQmlComponent* mSurfaceComponent = nullptr; QMap surfaces; bool lockTarget = false; friend class SessionLockSurface; }; class SessionLockSurface: public Reloadable { Q_OBJECT; // clang-format off Q_PROPERTY(QQuickItem* contentItem READ contentItem); /// If the window has been presented yet. Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged); Q_PROPERTY(qint32 width READ width NOTIFY widthChanged); Q_PROPERTY(qint32 height READ height NOTIFY heightChanged); /// The screen that the window currently occupies. /// /// > [!INFO] This cannot be changed after windowConnected. Q_PROPERTY(QuickshellScreenInfo* screen READ screen NOTIFY screenChanged); /// The background color of the window. Defaults to white. /// /// > [!WARNING] This seems to behave weirdly when using transparent colors on some systems. /// > Using a colored content item over a transparent window is the recommended way to work around this: /// > ```qml /// > ProxyWindow { /// > Rectangle { /// > anchors.fill: parent /// > color: "#20ffffff" /// > /// > // 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); Q_PROPERTY(QQmlListProperty data READ data); // clang-format on QML_ELEMENT; Q_CLASSINFO("DefaultProperty", "data"); public: explicit SessionLockSurface(QObject* parent = nullptr); ~SessionLockSurface() override; Q_DISABLE_COPY_MOVE(SessionLockSurface); void onReload(QObject* oldInstance) override; QQuickWindow* disownWindow(); void show(); [[nodiscard]] QQuickItem* contentItem() const; [[nodiscard]] bool isVisible() const; [[nodiscard]] qint32 width() const; [[nodiscard]] qint32 height() const; [[nodiscard]] QuickshellScreenInfo* screen() const; void setScreen(QScreen* qscreen); [[nodiscard]] QColor color() const; void setColor(QColor color); [[nodiscard]] QQmlListProperty data(); signals: void visibleChanged(); void widthChanged(); void heightChanged(); void screenChanged(); void colorChanged(); private slots: void onScreenDestroyed(); void onWidthChanged(); void onHeightChanged(); private: QQuickWindow* window = nullptr; QQuickItem* mContentItem; QScreen* mScreen = nullptr; QColor mColor = Qt::white; LockWindowExtension* ext; };