Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
PopupWindow.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <PhosphorShell/phosphorshell_export.h>
7
8#include <QPointer>
9#include <QQmlListProperty>
10#include <QQuickItem>
11#include <QRect>
12
13#include <memory>
14
15QT_BEGIN_NAMESPACE
16class QQuickWindow;
17QT_END_NAMESPACE
18
19namespace PhosphorShell {
20
21class PHOSPHORSHELL_EXPORT PopupWindow : public QQuickItem
22{
23 Q_OBJECT
24
25 // QML default property — children declared inside PopupWindow {}
26 // land on the persistent m_contentItem rather than on PopupWindow
27 // itself. This matters because m_contentItem is the only thing that
28 // ever gets re-parented to the popup's QQuickWindow contentItem;
29 // declared children stay rooted in m_contentItem from creation,
30 // which keeps QML scope/binding-context paths stable across the
31 // popup's first show. Without this, declared children become
32 // direct children of the PopupWindow QQuickItem, get reparented to
33 // the popup's window contentItem on first show, and bindings that
34 // walk back through `root.<...>` lose their property-change
35 // notifications post-reparent — manifests as content not updating
36 // when the host swaps state while the popup stays mapped.
37 Q_PROPERTY(QQmlListProperty<QObject> data READ data)
38 Q_CLASSINFO("DefaultProperty", "data")
39
40 Q_PROPERTY(QQuickItem* anchor READ anchor WRITE setAnchor NOTIFY anchorChanged)
41 Q_PROPERTY(int popupWidth READ popupWidth WRITE setPopupWidth NOTIFY popupWidthChanged)
42 Q_PROPERTY(int popupHeight READ popupHeight WRITE setPopupHeight NOTIFY popupHeightChanged)
43 Q_PROPERTY(PopupEdge popupEdge READ popupEdge WRITE setPopupEdge NOTIFY popupEdgeChanged)
44 Q_PROPERTY(int gap READ gap WRITE setGap NOTIFY gapChanged)
45 Q_PROPERTY(bool popupVisible READ isPopupVisible WRITE setPopupVisible NOTIFY popupVisibleChanged)
46
47public:
54 Q_ENUM(PopupEdge)
55
56 explicit PopupWindow(QQuickItem* parent = nullptr);
57 ~PopupWindow() override;
58
62 [[nodiscard]] QQmlListProperty<QObject> data();
63
64 [[nodiscard]] QQuickItem* anchor() const;
65 void setAnchor(QQuickItem* anchor);
66
67 [[nodiscard]] int popupWidth() const;
68 void setPopupWidth(int width);
69
70 [[nodiscard]] int popupHeight() const;
71 void setPopupHeight(int height);
72
73 [[nodiscard]] PopupEdge popupEdge() const;
74 void setPopupEdge(PopupEdge edge);
75
76 [[nodiscard]] int gap() const;
77 void setGap(int gap);
78
79 [[nodiscard]] bool isPopupVisible() const;
80 void setPopupVisible(bool visible);
81
82 Q_INVOKABLE void close();
83
84Q_SIGNALS:
85 void anchorChanged();
86 void popupWidthChanged();
87 void popupHeightChanged();
88 void popupEdgeChanged();
89 void gapChanged();
90 void popupVisibleChanged();
91
92private:
93 void showPopup();
94 void hidePopup();
95 [[nodiscard]] QRect computeAnchorRect() const;
101 [[nodiscard]] QRect resolvedAnchorRect() const;
108 void reapplyIfVisible();
113 bool repositionInPlace();
114
115 // Externally owned anchor item — QPointer lets us detect destruction
116 // (the QML author may delete the anchor while the popup is alive).
117 QPointer<QQuickItem> m_anchor;
118 int m_popupWidth = 200;
119 int m_popupHeight = 200;
120 PopupEdge m_popupEdge = Below;
121 int m_gap = 4;
122 bool m_popupVisible = false;
123 std::unique_ptr<QQuickWindow> m_popupWindow;
130 QQuickItem* m_contentItem = nullptr;
131};
132
133} // namespace PhosphorShell
Definition PopupWindow.h:22
PopupEdge
Definition PopupWindow.h:48
@ RightOf
Definition PopupWindow.h:52
@ Below
Definition PopupWindow.h:49
@ LeftOf
Definition PopupWindow.h:51
@ Above
Definition PopupWindow.h:50
Definition Environment.h:11