From ed62193978b41af5abfd304a6f687f04c18ac3f3 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 17 Feb 2024 04:13:37 -0800 Subject: [PATCH] feat: use an intermediary content item for proxy windows (fixes in desc) fix: combo boxes not opening after a soft reload fix: anchors breaking after a soft reload --- src/cpp/proxywindow.cpp | 121 ++++++---------------------------------- src/cpp/proxywindow.hpp | 15 ++--- 2 files changed, 20 insertions(+), 116 deletions(-) diff --git a/src/cpp/proxywindow.cpp b/src/cpp/proxywindow.cpp index 0fee2d8b..02b05fe3 100644 --- a/src/cpp/proxywindow.cpp +++ b/src/cpp/proxywindow.cpp @@ -12,6 +12,14 @@ #include "region.hpp" #include "reload.hpp" +ProxyWindowBase::ProxyWindowBase(QObject* parent): Reloadable(parent) { + this->contentItem = new QQuickItem(); // NOLINT + this->contentItem->setParent(this); + + QObject::connect(this, &ProxyWindowBase::widthChanged, this, &ProxyWindowBase::onWidthChanged); + QObject::connect(this, &ProxyWindowBase::heightChanged, this, &ProxyWindowBase::onHeightChanged); +} + ProxyWindowBase::~ProxyWindowBase() { if (this->window != nullptr) { this->window->deleteLater(); @@ -29,20 +37,12 @@ void ProxyWindowBase::onReload(QObject* oldInstance) { this->setupWindow(); - for (auto* child: this->pendingChildren) { - Reloadable::reloadRecursive(child, oldInstance); - } + Reloadable::reloadRecursive(this->contentItem, oldInstance); - auto backer = this->dataBacker(); - for (auto* child: this->pendingChildren) { - // Reparent QQuickItems to the content element, - // while leaving QObjects parented to the proxy window. - if (qobject_cast(child) != nullptr) { - backer.append(&backer, child); - } - } + this->contentItem->setParentItem(this->window->contentItem()); - this->pendingChildren.clear(); + this->contentItem->setWidth(this->width()); + this->contentItem->setHeight(this->height()); emit this->windowConnected(); this->window->setVisible(this->mVisible); @@ -69,9 +69,7 @@ void ProxyWindowBase::setupWindow() { QQuickWindow* ProxyWindowBase::disownWindow() { QObject::disconnect(this->window, nullptr, this, nullptr); - auto data = this->data(); - ProxyWindowBase::dataClear(&data); - data.clear(&data); + this->contentItem->setParentItem(nullptr); auto* window = this->window; this->window = nullptr; @@ -162,100 +160,13 @@ void ProxyWindowBase::updateMask() { this->window->setMask(mask); } -// see: -// https://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/quick/items/qquickwindow.cpp -// https://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/quick/items/qquickitem.cpp -// -// relevant functions are private so we call them via the property - QQmlListProperty ProxyWindowBase::data() { - return QQmlListProperty( - this, - nullptr, - ProxyWindowBase::dataAppend, - ProxyWindowBase::dataCount, - ProxyWindowBase::dataAt, - ProxyWindowBase::dataClear, - ProxyWindowBase::dataReplace, - ProxyWindowBase::dataRemoveLast - ); + return this->contentItem->property("data").value>(); } -QQmlListProperty ProxyWindowBase::dataBacker() { - return this->window->property("data").value>(); -} +void ProxyWindowBase::onWidthChanged() { this->contentItem->setWidth(this->width()); } -void ProxyWindowBase::dataAppend(QQmlListProperty* prop, QObject* obj) { - auto* self = static_cast(prop->object); // NOLINT - - if (self->window == nullptr) { - if (obj != nullptr) { - obj->setParent(self); - self->pendingChildren.append(obj); - } - } else { - auto backer = self->dataBacker(); - backer.append(&backer, obj); - } -} - -qsizetype ProxyWindowBase::dataCount(QQmlListProperty* prop) { - auto* self = static_cast(prop->object); // NOLINT - - if (self->window == nullptr) { - return self->pendingChildren.count(); - } else { - auto backer = self->dataBacker(); - return backer.count(&backer); - } -} - -QObject* ProxyWindowBase::dataAt(QQmlListProperty* prop, qsizetype i) { - auto* self = static_cast(prop->object); // NOLINT - - if (self->window == nullptr) { - return self->pendingChildren.at(i); - } else { - auto backer = self->dataBacker(); - return backer.at(&backer, i); - } -} - -void ProxyWindowBase::dataClear(QQmlListProperty* prop) { - auto* self = static_cast(prop->object); // NOLINT - - if (self->window == nullptr) { - self->pendingChildren.clear(); - } else { - auto backer = self->dataBacker(); - backer.clear(&backer); - } -} - -void ProxyWindowBase::dataReplace(QQmlListProperty* prop, qsizetype i, QObject* obj) { - auto* self = static_cast(prop->object); // NOLINT - - if (self->window == nullptr) { - if (obj != nullptr) { - obj->setParent(self); - self->pendingChildren.replace(i, obj); - } - } else { - auto backer = self->dataBacker(); - backer.replace(&backer, i, obj); - } -} - -void ProxyWindowBase::dataRemoveLast(QQmlListProperty* prop) { - auto* self = static_cast(prop->object); // NOLINT - - if (self->window == nullptr) { - self->pendingChildren.removeLast(); - } else { - auto backer = self->dataBacker(); - backer.removeLast(&backer); - } -} +void ProxyWindowBase::onHeightChanged() { this->contentItem->setHeight(this->height()); } void ProxyFloatingWindow::setWidth(qint32 width) { if (this->window == nullptr || !this->window->isVisible()) this->ProxyWindowBase::setWidth(width); diff --git a/src/cpp/proxywindow.hpp b/src/cpp/proxywindow.hpp index 2f42f465..568d1bae 100644 --- a/src/cpp/proxywindow.hpp +++ b/src/cpp/proxywindow.hpp @@ -100,7 +100,7 @@ class ProxyWindowBase: public Reloadable { Q_CLASSINFO("DefaultProperty", "data"); public: - explicit ProxyWindowBase(QObject* parent = nullptr): Reloadable(parent) {} + explicit ProxyWindowBase(QObject* parent = nullptr); ~ProxyWindowBase() override; ProxyWindowBase(ProxyWindowBase&) = delete; @@ -144,6 +144,8 @@ signals: private slots: void onMaskChanged(); + void onWidthChanged(); + void onHeightChanged(); protected: bool mVisible = false; @@ -152,19 +154,10 @@ protected: QColor mColor = Qt::white; PendingRegion* mMask = nullptr; QQuickWindow* window = nullptr; + QQuickItem* contentItem = nullptr; private: void updateMask(); - QQmlListProperty dataBacker(); - - static void dataAppend(QQmlListProperty* prop, QObject* obj); - static qsizetype dataCount(QQmlListProperty* prop); - static QObject* dataAt(QQmlListProperty* prop, qsizetype i); - static void dataClear(QQmlListProperty* prop); - static void dataReplace(QQmlListProperty* prop, qsizetype i, QObject* obj); - static void dataRemoveLast(QQmlListProperty* prop); - - QVector pendingChildren; }; // qt attempts to resize the window but fails because wayland