File indexing completed on 2024-04-21 03:56:01
0001 /* 0002 * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef OVERLAYZSTACKINGATTACHED_H 0008 #define OVERLAYZSTACKINGATTACHED_H 0009 0010 #include <QObject> 0011 #include <QQmlEngine> 0012 0013 #include <qqmlregistration.h> 0014 0015 class QQuickItem; 0016 0017 /** 0018 * This attached property manages z-index for stacking overlays relative to each other. 0019 * 0020 * When a popup is about to show, OverlayZStacking object kicks in, searches for the 0021 * next nearest popup in the QtQuick hierarchy of items, and sets its z value to the 0022 * biggest of two: current stacking value for its layer, or parent's z index + 1. 0023 * This way OverlayZStacking algorithm ensures that a popup is always stacked higher 0024 * than its logical parent popup, but also no lower than its siblings on the same 0025 * logical layer. 0026 * 0027 * @code 0028 * import QtQuick.Controls as QQC2 0029 * import org.kde.kirigami as Kirigami 0030 * 0031 * QQC2.Popup { 0032 * Kirigami.OverlayZStacking.layer: Kirigami.OverlayZStacking.ToolTip 0033 * z: Kirigami.OverlayZStacking.z 0034 * } 0035 * @endcode 0036 * 0037 * @since 6.0 0038 */ 0039 class OverlayZStackingAttached : public QObject 0040 { 0041 Q_OBJECT 0042 QML_ELEMENT 0043 QML_NAMED_ELEMENT(OverlayZStacking) 0044 QML_UNCREATABLE("Cannot create objects of type OverlayZStacking, use it as an attached property") 0045 QML_ATTACHED(OverlayZStackingAttached) 0046 /** 0047 * An optimal z-index that attachee popup should bind to. 0048 */ 0049 Q_PROPERTY(qreal z READ z NOTIFY zChanged FINAL) 0050 0051 /** 0052 * The logical stacking layer of attachee popup, akin to window manager's layers. 0053 */ 0054 Q_PROPERTY(Layer layer READ layer WRITE setLayer NOTIFY layerChanged FINAL) 0055 0056 public: 0057 enum Layer { 0058 DefaultLowest = 0, 0059 Drawer, 0060 FullScreen, 0061 Dialog, 0062 Menu, 0063 Notification, 0064 ToolTip, 0065 }; 0066 Q_ENUM(Layer) 0067 0068 explicit OverlayZStackingAttached(QObject *parent = nullptr); 0069 ~OverlayZStackingAttached() override; 0070 0071 qreal z() const; 0072 0073 Layer layer() const; 0074 void setLayer(Layer layer); 0075 0076 // QML attached property 0077 static OverlayZStackingAttached *qmlAttachedProperties(QObject *object); 0078 0079 Q_SIGNALS: 0080 void zChanged(); 0081 void layerChanged(); 0082 0083 private Q_SLOTS: 0084 // Popup shall not change z index while being open, so if changes arrive, we defer it until closed. 0085 void enqueueSignal(); 0086 void dispatchPendingSignal(); 0087 0088 void updateParentPopup(); 0089 0090 private: 0091 void updateParentPopupSilent(); 0092 void setParentPopup(QObject *popup); 0093 qreal parentPopupZ() const; 0094 static bool isVisible(const QObject *popup); 0095 static bool isPopup(const QObject *object); 0096 static QObject *findParentPopup(const QObject *popup); 0097 static QQuickItem *findParentPopupItem(const QObject *popup); 0098 static Layer defaultLayerForPopupType(const QObject *popup); 0099 static qreal defaultZForLayer(Layer layer); 0100 0101 Layer m_layer = Layer::DefaultLowest; 0102 QPointer<QObject> m_parentPopup; 0103 bool m_pending; 0104 }; 0105 0106 QML_DECLARE_TYPEINFO(OverlayZStackingAttached, QML_HAS_ATTACHED_PROPERTIES) 0107 0108 #endif // OVERLAYZSTACKINGATTACHED_H