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
15class QQuickItem;
16
17/**
18 * This attached property manages z-index for stacking overlays relative to each other.
19 *
20 * When a popup is about to show, OverlayZStacking object kicks in, searches for the
21 * next nearest popup in the QtQuick hierarchy of items, and sets its z value to the
22 * biggest of two: current stacking value for its layer, or parent's z index + 1.
23 * This way OverlayZStacking algorithm ensures that a popup is always stacked higher
24 * than its logical parent popup, but also no lower than its siblings on the same
25 * logical layer.
26 *
27 * @code
28 * import QtQuick.Controls as QQC2
29 * import org.kde.kirigami as Kirigami
30 *
31 * QQC2.Popup {
32 * Kirigami.OverlayZStacking.layer: Kirigami.OverlayZStacking.ToolTip
33 * z: Kirigami.OverlayZStacking.z
34 * }
35 * @endcode
36 *
37 * @since 6.0
38 */
39class OverlayZStackingAttached : public QObject
40{
41 Q_OBJECT
42 QML_ELEMENT
43 QML_NAMED_ELEMENT(OverlayZStacking)
44 QML_UNCREATABLE("Cannot create objects of type OverlayZStacking, use it as an attached property")
45 QML_ATTACHED(OverlayZStackingAttached)
46 /**
47 * An optimal z-index that attachee popup should bind to.
48 */
49 Q_PROPERTY(qreal z READ z NOTIFY zChanged FINAL)
50
51 /**
52 * The logical stacking layer of attachee popup, akin to window manager's layers.
53 */
54 Q_PROPERTY(Layer layer READ layer WRITE setLayer NOTIFY layerChanged FINAL)
55
56public:
57 enum Layer {
58 DefaultLowest = 0,
59 Drawer,
60 FullScreen,
61 Dialog,
62 Menu,
63 Notification,
64 ToolTip,
65 };
66 Q_ENUM(Layer)
67
68 explicit OverlayZStackingAttached(QObject *parent = nullptr);
69 ~OverlayZStackingAttached() override;
70
71 qreal z() const;
72
73 Layer layer() const;
74 void setLayer(Layer layer);
75
76 // QML attached property
77 static OverlayZStackingAttached *qmlAttachedProperties(QObject *object);
78
79Q_SIGNALS:
80 void zChanged();
81 void layerChanged();
82
83private Q_SLOTS:
84 // Popup shall not change z index while being open, so if changes arrive, we defer it until closed.
85 void enqueueSignal();
86 void dispatchPendingSignal();
87
88 void updateParentPopup();
89
90private:
91 void updateParentPopupSilent();
92 void setParentPopup(QObject *popup);
93 qreal parentPopupZ() const;
94 static bool isVisible(const QObject *popup);
95 static bool isPopup(const QObject *object);
96 static QObject *findParentPopup(const QObject *popup);
97 static QQuickItem *findParentPopupItem(const QObject *popup);
98 static Layer defaultLayerForPopupType(const QObject *popup);
99 static qreal defaultZForLayer(Layer layer);
100
101 Layer m_layer = Layer::DefaultLowest;
102 QPointer<QObject> m_parentPopup;
103 bool m_pending;
104};
105
106QML_DECLARE_TYPEINFO(OverlayZStackingAttached, QML_HAS_ATTACHED_PROPERTIES)
107
108#endif // OVERLAYZSTACKINGATTACHED_H
109

source code of kirigami/src/overlayzstackingattached.h