forked from quickshell/quickshell
		
	core/popupanchor: add margins property
This commit is contained in:
		
							parent
							
								
									ef077ddd24
								
							
						
					
					
						commit
						d1df932d60
					
				
					 3 changed files with 42 additions and 21 deletions
				
			
		| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
#include <qquickitem.h>
 | 
					#include <qquickitem.h>
 | 
				
			||||||
#include <qsize.h>
 | 
					#include <qsize.h>
 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qvectornd.h>
 | 
				
			||||||
#include <qwindow.h>
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../window/proxywindow.hpp"
 | 
					#include "../window/proxywindow.hpp"
 | 
				
			||||||
| 
						 | 
					@ -126,12 +127,21 @@ void PopupAnchor::setRect(Box rect) {
 | 
				
			||||||
	this->mUserRect = rect;
 | 
						this->mUserRect = rect;
 | 
				
			||||||
	emit this->rectChanged();
 | 
						emit this->rectChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->setWindowRect(rect);
 | 
						this->setWindowRect(rect.qrect().marginsRemoved(this->mMargins.qmargins()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PopupAnchor::setWindowRect(Box rect) {
 | 
					void PopupAnchor::setMargins(Margins margins) {
 | 
				
			||||||
	if (rect.w <= 0) rect.w = 1;
 | 
						if (margins == this->mMargins) return;
 | 
				
			||||||
	if (rect.h <= 0) rect.h = 1;
 | 
					
 | 
				
			||||||
 | 
						this->mMargins = margins;
 | 
				
			||||||
 | 
						emit this->marginsChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->setWindowRect(this->mUserRect.qrect().marginsRemoved(margins.qmargins()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PopupAnchor::setWindowRect(QRect rect) {
 | 
				
			||||||
 | 
						if (rect.width() <= 0) rect.setWidth(1);
 | 
				
			||||||
 | 
						if (rect.height() <= 0) rect.setHeight(1);
 | 
				
			||||||
	if (rect == this->state.rect) return;
 | 
						if (rect == this->state.rect) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->state.rect = rect;
 | 
						this->state.rect = rect;
 | 
				
			||||||
| 
						 | 
					@ -177,12 +187,14 @@ void PopupAnchor::updatePlacement(const QPoint& anchorpoint, const QSize& size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PopupAnchor::updateAnchor() {
 | 
					void PopupAnchor::updateAnchor() {
 | 
				
			||||||
	if (this->mItem && this->mProxyWindow) {
 | 
						if (this->mItem && this->mProxyWindow) {
 | 
				
			||||||
		auto rect = this->mProxyWindow->contentItem()->mapRectFromItem(
 | 
							auto baseRect =
 | 
				
			||||||
 | 
							    this->mUserRect.isEmpty() ? this->mItem->boundingRect() : this->mUserRect.qrect();
 | 
				
			||||||
 | 
							auto rect = this->mProxyWindow->contentItem()->mapFromItem(
 | 
				
			||||||
		    this->mItem,
 | 
							    this->mItem,
 | 
				
			||||||
		    this->mUserRect.isEmpty() ? this->mItem->boundingRect() : this->mUserRect.qrect()
 | 
							    baseRect.marginsRemoved(this->mMargins.qmargins())
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this->setWindowRect(rect);
 | 
							this->setWindowRect(rect.toRect());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	emit this->anchoring();
 | 
						emit this->anchoring();
 | 
				
			||||||
| 
						 | 
					@ -207,7 +219,7 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto adjustment = anchor->adjustment();
 | 
						auto adjustment = anchor->adjustment();
 | 
				
			||||||
	auto screenGeometry = parentWindow->screen()->geometry();
 | 
						auto screenGeometry = parentWindow->screen()->geometry();
 | 
				
			||||||
	auto anchorRectGeometry = anchor->windowRect().qrect().translated(parentGeometry.topLeft());
 | 
						auto anchorRectGeometry = anchor->windowRect().translated(parentGeometry.topLeft());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto anchorEdges = anchor->edges();
 | 
						auto anchorEdges = anchor->edges();
 | 
				
			||||||
	auto anchorGravity = anchor->gravity();
 | 
						auto anchorGravity = anchor->gravity();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,8 @@
 | 
				
			||||||
#include <qtclasshelpermacros.h>
 | 
					#include <qtclasshelpermacros.h>
 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
#include <qtypes.h>
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					#include <qvariant.h>
 | 
				
			||||||
 | 
					#include <qvectornd.h>
 | 
				
			||||||
#include <qwindow.h>
 | 
					#include <qwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../window/proxywindow.hpp"
 | 
					#include "../window/proxywindow.hpp"
 | 
				
			||||||
| 
						 | 
					@ -61,7 +63,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(PopupAdjustment::Flags);
 | 
				
			||||||
struct PopupAnchorState {
 | 
					struct PopupAnchorState {
 | 
				
			||||||
	bool operator==(const PopupAnchorState& other) const;
 | 
						bool operator==(const PopupAnchorState& other) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Box rect = {0, 0, 1, 1};
 | 
						QRect rect = {0, 0, 1, 1};
 | 
				
			||||||
	Edges::Flags edges = Edges::Top | Edges::Left;
 | 
						Edges::Flags edges = Edges::Top | Edges::Left;
 | 
				
			||||||
	Edges::Flags gravity = Edges::Bottom | Edges::Right;
 | 
						Edges::Flags gravity = Edges::Bottom | Edges::Right;
 | 
				
			||||||
	PopupAdjustment::Flags adjustment = PopupAdjustment::Slide;
 | 
						PopupAdjustment::Flags adjustment = PopupAdjustment::Slide;
 | 
				
			||||||
| 
						 | 
					@ -90,12 +92,19 @@ class PopupAnchor: public QObject {
 | 
				
			||||||
	/// The anchorpoints the popup will attach to, relative to @@item or @@window.
 | 
						/// The anchorpoints the popup will attach to, relative to @@item or @@window.
 | 
				
			||||||
	/// Which anchors will be used is determined by the @@edges, @@gravity, and @@adjustment.
 | 
						/// Which anchors will be used is determined by the @@edges, @@gravity, and @@adjustment.
 | 
				
			||||||
	///
 | 
						///
 | 
				
			||||||
 | 
						/// If using @@item, the default anchor rectangle matches the dimensions of the item.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
	/// If you leave @@edges, @@gravity and @@adjustment at their default values,
 | 
						/// If you leave @@edges, @@gravity and @@adjustment at their default values,
 | 
				
			||||||
	/// setting more than `x` and `y` does not matter. The anchor rect cannot
 | 
						/// setting more than `x` and `y` does not matter. The anchor rect cannot
 | 
				
			||||||
	/// be smaller than 1x1 pixels.
 | 
						/// be smaller than 1x1 pixels.
 | 
				
			||||||
	///
 | 
						///
 | 
				
			||||||
	/// [coordinate mapping functions]: https://doc.qt.io/qt-6/qml-qtquick-item.html#mapFromItem-method
 | 
						/// [coordinate mapping functions]: https://doc.qt.io/qt-6/qml-qtquick-item.html#mapFromItem-method
 | 
				
			||||||
	Q_PROPERTY(Box rect READ rect WRITE setRect RESET resetRect NOTIFY rectChanged);
 | 
						Q_PROPERTY(Box rect READ rect WRITE setRect RESET resetRect NOTIFY rectChanged);
 | 
				
			||||||
 | 
						/// A margin applied to the anchor rect.
 | 
				
			||||||
 | 
						///
 | 
				
			||||||
 | 
						/// This is most useful when @@item is used and @@rect is left at its default
 | 
				
			||||||
 | 
						/// value (matching the Item's dimensions).
 | 
				
			||||||
 | 
						Q_PROPERTY(Margins margins READ margins WRITE setMargins NOTIFY marginsChanged);
 | 
				
			||||||
	/// The point on the anchor rectangle the popup should anchor to.
 | 
						/// The point on the anchor rectangle the popup should anchor to.
 | 
				
			||||||
	/// Opposing edges suchs as `Edges.Left | Edges.Right` are not allowed.
 | 
						/// Opposing edges suchs as `Edges.Left | Edges.Right` are not allowed.
 | 
				
			||||||
	///
 | 
						///
 | 
				
			||||||
| 
						 | 
					@ -138,13 +147,16 @@ public:
 | 
				
			||||||
	[[nodiscard]] QQuickItem* item() const { return this->mItem; }
 | 
						[[nodiscard]] QQuickItem* item() const { return this->mItem; }
 | 
				
			||||||
	void setItem(QQuickItem* item);
 | 
						void setItem(QQuickItem* item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] Box windowRect() const { return this->state.rect; }
 | 
						[[nodiscard]] QRect windowRect() const { return this->state.rect; }
 | 
				
			||||||
	void setWindowRect(Box rect);
 | 
						void setWindowRect(QRect rect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] Box rect() const { return this->mUserRect; }
 | 
						[[nodiscard]] Box rect() const { return this->mUserRect; }
 | 
				
			||||||
	void setRect(Box rect);
 | 
						void setRect(Box rect);
 | 
				
			||||||
	void resetRect();
 | 
						void resetRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] Margins margins() const { return this->mMargins; }
 | 
				
			||||||
 | 
						void setMargins(Margins margins);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] Edges::Flags edges() const { return this->state.edges; }
 | 
						[[nodiscard]] Edges::Flags edges() const { return this->state.edges; }
 | 
				
			||||||
	void setEdges(Edges::Flags edges);
 | 
						void setEdges(Edges::Flags edges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,6 +180,7 @@ signals:
 | 
				
			||||||
	QSDOC_HIDE void backingWindowVisibilityChanged();
 | 
						QSDOC_HIDE void backingWindowVisibilityChanged();
 | 
				
			||||||
	QSDOC_HIDE void windowRectChanged();
 | 
						QSDOC_HIDE void windowRectChanged();
 | 
				
			||||||
	void rectChanged();
 | 
						void rectChanged();
 | 
				
			||||||
 | 
						void marginsChanged();
 | 
				
			||||||
	void edgesChanged();
 | 
						void edgesChanged();
 | 
				
			||||||
	void gravityChanged();
 | 
						void gravityChanged();
 | 
				
			||||||
	void adjustmentChanged();
 | 
						void adjustmentChanged();
 | 
				
			||||||
| 
						 | 
					@ -183,6 +196,7 @@ private:
 | 
				
			||||||
	ProxyWindowBase* mProxyWindow = nullptr;
 | 
						ProxyWindowBase* mProxyWindow = nullptr;
 | 
				
			||||||
	PopupAnchorState state;
 | 
						PopupAnchorState state;
 | 
				
			||||||
	Box mUserRect;
 | 
						Box mUserRect;
 | 
				
			||||||
 | 
						Margins mMargins;
 | 
				
			||||||
	std::optional<PopupAnchorState> lastState;
 | 
						std::optional<PopupAnchorState> lastState;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,13 +46,11 @@ void WaylandPopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bo
 | 
				
			||||||
		auto anchorRect = anchor->windowRect();
 | 
							auto anchorRect = anchor->windowRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (auto* p = window->transientParent()) {
 | 
							if (auto* p = window->transientParent()) {
 | 
				
			||||||
			anchorRect.x = QHighDpi::toNativePixels(anchorRect.x, p);
 | 
								anchorRect = QHighDpi::toNativePixels(anchorRect, p);
 | 
				
			||||||
			anchorRect.y = QHighDpi::toNativePixels(anchorRect.y, p);
 | 
					 | 
				
			||||||
			anchorRect.w = QHighDpi::toNativePixels(anchorRect.w, p);
 | 
					 | 
				
			||||||
			anchorRect.h = QHighDpi::toNativePixels(anchorRect.h, p);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		positioner.set_anchor_rect(anchorRect.x, anchorRect.y, anchorRect.w, anchorRect.h);
 | 
							positioner
 | 
				
			||||||
 | 
							    .set_anchor_rect(anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		XdgPositioner::anchor anchorFlag = XdgPositioner::anchor_none;
 | 
							XdgPositioner::anchor anchorFlag = XdgPositioner::anchor_none;
 | 
				
			||||||
		switch (anchor->edges()) {
 | 
							switch (anchor->edges()) {
 | 
				
			||||||
| 
						 | 
					@ -107,15 +105,12 @@ void WaylandPopupPositioner::setFlags(PopupAnchor* anchor, QWindow* window) {
 | 
				
			||||||
	auto anchorRect = anchor->windowRect();
 | 
						auto anchorRect = anchor->windowRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (auto* p = window->transientParent()) {
 | 
						if (auto* p = window->transientParent()) {
 | 
				
			||||||
		anchorRect.x = QHighDpi::toNativePixels(anchorRect.x, p);
 | 
							anchorRect = QHighDpi::toNativePixels(anchorRect, p);
 | 
				
			||||||
		anchorRect.y = QHighDpi::toNativePixels(anchorRect.y, p);
 | 
					 | 
				
			||||||
		anchorRect.w = QHighDpi::toNativePixels(anchorRect.w, p);
 | 
					 | 
				
			||||||
		anchorRect.h = QHighDpi::toNativePixels(anchorRect.h, p);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// clang-format off
 | 
						// clang-format off
 | 
				
			||||||
	window->setProperty("_q_waylandPopupConstraintAdjustment", anchor->adjustment().toInt());
 | 
						window->setProperty("_q_waylandPopupConstraintAdjustment", anchor->adjustment().toInt());
 | 
				
			||||||
	window->setProperty("_q_waylandPopupAnchorRect", anchorRect.qrect());
 | 
						window->setProperty("_q_waylandPopupAnchorRect", anchorRect);
 | 
				
			||||||
	window->setProperty("_q_waylandPopupAnchor", QVariant::fromValue(Edges::toQt(anchor->edges())));
 | 
						window->setProperty("_q_waylandPopupAnchor", QVariant::fromValue(Edges::toQt(anchor->edges())));
 | 
				
			||||||
	window->setProperty("_q_waylandPopupGravity", QVariant::fromValue(Edges::toQt(anchor->gravity())));
 | 
						window->setProperty("_q_waylandPopupGravity", QVariant::fromValue(Edges::toQt(anchor->gravity())));
 | 
				
			||||||
	// clang-format on
 | 
						// clang-format on
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue