Skip to content

Commit d1df932

Browse files
committed
core/popupanchor: add margins property
1 parent ef077dd commit d1df932

File tree

3 files changed

+42
-21
lines changed

3 files changed

+42
-21
lines changed

src/core/popupanchor.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <qquickitem.h>
88
#include <qsize.h>
99
#include <qtmetamacros.h>
10+
#include <qvectornd.h>
1011
#include <qwindow.h>
1112

1213
#include "../window/proxywindow.hpp"
@@ -126,12 +127,21 @@ void PopupAnchor::setRect(Box rect) {
126127
this->mUserRect = rect;
127128
emit this->rectChanged();
128129

129-
this->setWindowRect(rect);
130+
this->setWindowRect(rect.qrect().marginsRemoved(this->mMargins.qmargins()));
130131
}
131132

132-
void PopupAnchor::setWindowRect(Box rect) {
133-
if (rect.w <= 0) rect.w = 1;
134-
if (rect.h <= 0) rect.h = 1;
133+
void PopupAnchor::setMargins(Margins margins) {
134+
if (margins == this->mMargins) return;
135+
136+
this->mMargins = margins;
137+
emit this->marginsChanged();
138+
139+
this->setWindowRect(this->mUserRect.qrect().marginsRemoved(margins.qmargins()));
140+
}
141+
142+
void PopupAnchor::setWindowRect(QRect rect) {
143+
if (rect.width() <= 0) rect.setWidth(1);
144+
if (rect.height() <= 0) rect.setHeight(1);
135145
if (rect == this->state.rect) return;
136146

137147
this->state.rect = rect;
@@ -177,12 +187,14 @@ void PopupAnchor::updatePlacement(const QPoint& anchorpoint, const QSize& size)
177187

178188
void PopupAnchor::updateAnchor() {
179189
if (this->mItem && this->mProxyWindow) {
180-
auto rect = this->mProxyWindow->contentItem()->mapRectFromItem(
190+
auto baseRect =
191+
this->mUserRect.isEmpty() ? this->mItem->boundingRect() : this->mUserRect.qrect();
192+
auto rect = this->mProxyWindow->contentItem()->mapFromItem(
181193
this->mItem,
182-
this->mUserRect.isEmpty() ? this->mItem->boundingRect() : this->mUserRect.qrect()
194+
baseRect.marginsRemoved(this->mMargins.qmargins())
183195
);
184196

185-
this->setWindowRect(rect);
197+
this->setWindowRect(rect.toRect());
186198
}
187199

188200
emit this->anchoring();
@@ -207,7 +219,7 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
207219

208220
auto adjustment = anchor->adjustment();
209221
auto screenGeometry = parentWindow->screen()->geometry();
210-
auto anchorRectGeometry = anchor->windowRect().qrect().translated(parentGeometry.topLeft());
222+
auto anchorRectGeometry = anchor->windowRect().translated(parentGeometry.topLeft());
211223

212224
auto anchorEdges = anchor->edges();
213225
auto anchorGravity = anchor->gravity();

src/core/popupanchor.hpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <qtclasshelpermacros.h>
1313
#include <qtmetamacros.h>
1414
#include <qtypes.h>
15+
#include <qvariant.h>
16+
#include <qvectornd.h>
1517
#include <qwindow.h>
1618

1719
#include "../window/proxywindow.hpp"
@@ -61,7 +63,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(PopupAdjustment::Flags);
6163
struct PopupAnchorState {
6264
bool operator==(const PopupAnchorState& other) const;
6365

64-
Box rect = {0, 0, 1, 1};
66+
QRect rect = {0, 0, 1, 1};
6567
Edges::Flags edges = Edges::Top | Edges::Left;
6668
Edges::Flags gravity = Edges::Bottom | Edges::Right;
6769
PopupAdjustment::Flags adjustment = PopupAdjustment::Slide;
@@ -90,12 +92,19 @@ class PopupAnchor: public QObject {
9092
/// The anchorpoints the popup will attach to, relative to @@item or @@window.
9193
/// Which anchors will be used is determined by the @@edges, @@gravity, and @@adjustment.
9294
///
95+
/// If using @@item, the default anchor rectangle matches the dimensions of the item.
96+
///
9397
/// If you leave @@edges, @@gravity and @@adjustment at their default values,
9498
/// setting more than `x` and `y` does not matter. The anchor rect cannot
9599
/// be smaller than 1x1 pixels.
96100
///
97101
/// [coordinate mapping functions]: https://doc.qt.io/qt-6/qml-qtquick-item.html#mapFromItem-method
98102
Q_PROPERTY(Box rect READ rect WRITE setRect RESET resetRect NOTIFY rectChanged);
103+
/// A margin applied to the anchor rect.
104+
///
105+
/// This is most useful when @@item is used and @@rect is left at its default
106+
/// value (matching the Item's dimensions).
107+
Q_PROPERTY(Margins margins READ margins WRITE setMargins NOTIFY marginsChanged);
99108
/// The point on the anchor rectangle the popup should anchor to.
100109
/// Opposing edges suchs as `Edges.Left | Edges.Right` are not allowed.
101110
///
@@ -138,13 +147,16 @@ class PopupAnchor: public QObject {
138147
[[nodiscard]] QQuickItem* item() const { return this->mItem; }
139148
void setItem(QQuickItem* item);
140149

141-
[[nodiscard]] Box windowRect() const { return this->state.rect; }
142-
void setWindowRect(Box rect);
150+
[[nodiscard]] QRect windowRect() const { return this->state.rect; }
151+
void setWindowRect(QRect rect);
143152

144153
[[nodiscard]] Box rect() const { return this->mUserRect; }
145154
void setRect(Box rect);
146155
void resetRect();
147156

157+
[[nodiscard]] Margins margins() const { return this->mMargins; }
158+
void setMargins(Margins margins);
159+
148160
[[nodiscard]] Edges::Flags edges() const { return this->state.edges; }
149161
void setEdges(Edges::Flags edges);
150162

@@ -168,6 +180,7 @@ class PopupAnchor: public QObject {
168180
QSDOC_HIDE void backingWindowVisibilityChanged();
169181
QSDOC_HIDE void windowRectChanged();
170182
void rectChanged();
183+
void marginsChanged();
171184
void edgesChanged();
172185
void gravityChanged();
173186
void adjustmentChanged();
@@ -183,6 +196,7 @@ private slots:
183196
ProxyWindowBase* mProxyWindow = nullptr;
184197
PopupAnchorState state;
185198
Box mUserRect;
199+
Margins mMargins;
186200
std::optional<PopupAnchorState> lastState;
187201
};
188202

src/wayland/popupanchor.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,11 @@ void WaylandPopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bo
4646
auto anchorRect = anchor->windowRect();
4747

4848
if (auto* p = window->transientParent()) {
49-
anchorRect.x = QHighDpi::toNativePixels(anchorRect.x, p);
50-
anchorRect.y = QHighDpi::toNativePixels(anchorRect.y, p);
51-
anchorRect.w = QHighDpi::toNativePixels(anchorRect.w, p);
52-
anchorRect.h = QHighDpi::toNativePixels(anchorRect.h, p);
49+
anchorRect = QHighDpi::toNativePixels(anchorRect, p);
5350
}
5451

55-
positioner.set_anchor_rect(anchorRect.x, anchorRect.y, anchorRect.w, anchorRect.h);
52+
positioner
53+
.set_anchor_rect(anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height());
5654

5755
XdgPositioner::anchor anchorFlag = XdgPositioner::anchor_none;
5856
switch (anchor->edges()) {
@@ -107,15 +105,12 @@ void WaylandPopupPositioner::setFlags(PopupAnchor* anchor, QWindow* window) {
107105
auto anchorRect = anchor->windowRect();
108106

109107
if (auto* p = window->transientParent()) {
110-
anchorRect.x = QHighDpi::toNativePixels(anchorRect.x, p);
111-
anchorRect.y = QHighDpi::toNativePixels(anchorRect.y, p);
112-
anchorRect.w = QHighDpi::toNativePixels(anchorRect.w, p);
113-
anchorRect.h = QHighDpi::toNativePixels(anchorRect.h, p);
108+
anchorRect = QHighDpi::toNativePixels(anchorRect, p);
114109
}
115110

116111
// clang-format off
117112
window->setProperty("_q_waylandPopupConstraintAdjustment", anchor->adjustment().toInt());
118-
window->setProperty("_q_waylandPopupAnchorRect", anchorRect.qrect());
113+
window->setProperty("_q_waylandPopupAnchorRect", anchorRect);
119114
window->setProperty("_q_waylandPopupAnchor", QVariant::fromValue(Edges::toQt(anchor->edges())));
120115
window->setProperty("_q_waylandPopupGravity", QVariant::fromValue(Edges::toQt(anchor->gravity())));
121116
// clang-format on

0 commit comments

Comments
 (0)