1 | /* |
2 | * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> |
3 | * |
4 | * SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | #ifndef OVERLAYZSTACKINGATTACHED_H |
8 | #define OVERLAYZSTACKINGATTACHED_H |
9 | |
10 | #include <QObject> |
11 | #include <QQmlEngine> |
12 | |
13 | #include <qqmlregistration.h> |
14 | |
15 | class QQuickItem; |
16 | |
17 | /*! |
18 | * \qmltype OverlayZStacking |
19 | * \inqmlmodule org.kde.kirigami |
20 | * |
21 | * \brief An attached property that manages z-index for stacking overlays relative to each other. |
22 | * |
23 | * When a popup is about to show, OverlayZStacking object kicks in, searches for the |
24 | * next nearest popup in the QtQuick hierarchy of items, and sets its z value to the |
25 | * biggest of two: current stacking value for its layer, or parent's z index + 1. |
26 | * |
27 | * This way OverlayZStacking algorithm ensures that a popup is always stacked higher |
28 | * than its logical parent popup, but also no lower than its siblings on the same |
29 | * logical layer. |
30 | * |
31 | * \code |
32 | * import QtQuick.Controls as QQC2 |
33 | * import org.kde.kirigami as Kirigami |
34 | * |
35 | * QQC2.Popup { |
36 | * Kirigami.OverlayZStacking.layer: Kirigami.OverlayZStacking.ToolTip |
37 | * z: Kirigami.OverlayZStacking.z |
38 | * } |
39 | * \endcode |
40 | * |
41 | * \since 6.0 |
42 | */ |
43 | class OverlayZStackingAttached : public QObject |
44 | { |
45 | Q_OBJECT |
46 | QML_ELEMENT |
47 | QML_NAMED_ELEMENT(OverlayZStacking) |
48 | QML_UNCREATABLE("Cannot create objects of type OverlayZStacking, use it as an attached property" ) |
49 | QML_ATTACHED(OverlayZStackingAttached) |
50 | /*! |
51 | * \qmlattachedproperty real OverlayZStacking::z |
52 | * |
53 | * An optimal z-index that attachee popup should bind to. |
54 | */ |
55 | Q_PROPERTY(qreal z READ z NOTIFY zChanged FINAL) |
56 | |
57 | /*! |
58 | * \qmlattachedproperty enumeration OverlayZStacking::layer |
59 | * |
60 | * \qmlenumeratorsfrom OverlayZStackingAttached::Layer |
61 | * |
62 | * The logical stacking layer of attachee popup, akin to window manager's layers. |
63 | */ |
64 | Q_PROPERTY(Layer layer READ layer WRITE setLayer NOTIFY layerChanged FINAL) |
65 | |
66 | public: |
67 | /*! |
68 | * \value DefaultLowest |
69 | * \value Drawer |
70 | * \value FullScreen |
71 | * \value Dialog |
72 | * \value Menu |
73 | * \value Notification |
74 | * \value ToolTip |
75 | */ |
76 | enum Layer { |
77 | DefaultLowest = 0, |
78 | Drawer, |
79 | FullScreen, |
80 | Dialog, |
81 | , |
82 | Notification, |
83 | ToolTip, |
84 | }; |
85 | Q_ENUM(Layer) |
86 | |
87 | explicit OverlayZStackingAttached(QObject *parent = nullptr); |
88 | ~OverlayZStackingAttached() override; |
89 | |
90 | qreal z() const; |
91 | |
92 | Layer layer() const; |
93 | void setLayer(Layer layer); |
94 | |
95 | // QML attached property |
96 | static OverlayZStackingAttached *qmlAttachedProperties(QObject *object); |
97 | |
98 | Q_SIGNALS: |
99 | void zChanged(); |
100 | void layerChanged(); |
101 | |
102 | private Q_SLOTS: |
103 | // Popup shall not change z index while being open, so if changes arrive, we defer it until closed. |
104 | void enqueueSignal(); |
105 | void dispatchPendingSignal(); |
106 | |
107 | void (); |
108 | |
109 | private: |
110 | void (); |
111 | void (QObject *); |
112 | qreal () const; |
113 | static bool isVisible(const QObject *); |
114 | static bool (const QObject *object); |
115 | static QObject *(const QObject *); |
116 | static QQuickItem *(const QObject *); |
117 | static Layer (const QObject *); |
118 | static qreal defaultZForLayer(Layer layer); |
119 | |
120 | Layer m_layer = Layer::DefaultLowest; |
121 | QPointer<QObject> ; |
122 | bool m_pending; |
123 | }; |
124 | |
125 | QML_DECLARE_TYPEINFO(OverlayZStackingAttached, QML_HAS_ATTACHED_PROPERTIES) |
126 | |
127 | #endif // OVERLAYZSTACKINGATTACHED_H |
128 | |