diff --git a/src/window/floatingwindow.cpp b/src/window/floatingwindow.cpp index 0b9e9b1c..85641e91 100644 --- a/src/window/floatingwindow.cpp +++ b/src/window/floatingwindow.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -17,6 +17,13 @@ void ProxyFloatingWindow::connectWindow() { this->window->setMaximumSize(this->bMaximumSize); } +void ProxyFloatingWindow::postCompleteWindow() { + auto* parentBacking = + this->mParentProxyWindow ? this->mParentProxyWindow->backingWindow() : nullptr; + + this->window->setTransientParent(parentBacking); +} + void ProxyFloatingWindow::trySetWidth(qint32 implicitWidth) { if (!this->window->isVisible()) { this->ProxyWindowBase::trySetWidth(implicitWidth); @@ -44,6 +51,28 @@ void ProxyFloatingWindow::onMaximumSizeChanged() { emit this->maximumSizeChanged(); } +QObject* ProxyFloatingWindow::parentWindow() const { return this->mParentWindow; } + +void ProxyFloatingWindow::setParentWindow(QObject* window) { + if (window == this->mParentWindow) return; + + if (window) { + if (auto* proxy = qobject_cast(window)) { + this->mParentProxyWindow = proxy; + } else if (auto* interface = qobject_cast(window)) { + this->mParentProxyWindow = interface->proxyWindow(); + } else { + qmlWarning(this) << "parentWindow must be a quickshell window."; + return; + } + + this->mParentWindow = window; + } else { + this->mParentWindow = nullptr; + this->mParentProxyWindow = nullptr; + } +} + // FloatingWindowInterface FloatingWindowInterface::FloatingWindowInterface(QObject* parent) @@ -66,3 +95,9 @@ void FloatingWindowInterface::onReload(QObject* oldInstance) { } ProxyWindowBase* FloatingWindowInterface::proxyWindow() const { return this->window; } + +QObject* FloatingWindowInterface::parentWindow() const { return this->window->parentWindow(); } + +void FloatingWindowInterface::setParentWindow(QObject* window) { + this->window->setParentWindow(window); +} diff --git a/src/window/floatingwindow.hpp b/src/window/floatingwindow.hpp index f9cd5ced..0dbb9888 100644 --- a/src/window/floatingwindow.hpp +++ b/src/window/floatingwindow.hpp @@ -18,6 +18,10 @@ class ProxyFloatingWindow: public ProxyWindowBase { explicit ProxyFloatingWindow(QObject* parent = nullptr): ProxyWindowBase(parent) {} void connectWindow() override; + void postCompleteWindow() override; + + [[nodiscard]] QObject* parentWindow() const; + void setParentWindow(QObject* window); // Setting geometry while the window is visible makes the content item shrink but not the window // which is awful so we disable it for floating windows. @@ -34,6 +38,9 @@ class ProxyFloatingWindow: public ProxyWindowBase { void onMaximumSizeChanged(); void onTitleChanged(); + QObject* mParentWindow = nullptr; + ProxyWindowBase* mParentProxyWindow = nullptr; + public: Q_OBJECT_BINDABLE_PROPERTY( ProxyFloatingWindow, @@ -68,6 +75,11 @@ class FloatingWindowInterface: public WindowInterface { Q_PROPERTY(QSize minimumSize READ default WRITE default NOTIFY minimumSizeChanged BINDABLE bindableMinimumSize); /// Maximum window size given to the window system. Q_PROPERTY(QSize maximumSize READ default WRITE default NOTIFY maximumSizeChanged BINDABLE bindableMaximumSize); + /// The parent window of this window. Setting this makes the window a child of the parent, + /// which affects window stacking behavior. + /// + /// > [!NOTE] This property cannot be changed after the window is visible. + Q_PROPERTY(QObject* parentWindow READ parentWindow WRITE setParentWindow); // clang-format on QML_NAMED_ELEMENT(FloatingWindow); @@ -82,6 +94,9 @@ class FloatingWindowInterface: public WindowInterface { QBindable bindableMaximumSize() { return &this->window->bMaximumSize; } QBindable bindableTitle() { return &this->window->bTitle; } + [[nodiscard]] QObject* parentWindow() const; + void setParentWindow(QObject* window); + signals: void minimumSizeChanged(); void maximumSizeChanged();