forked from quickshell/quickshell
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
This commit is contained in:
parent
5e58f0ba9f
commit
ed62193978
|
@ -12,6 +12,14 @@
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
#include "reload.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() {
|
ProxyWindowBase::~ProxyWindowBase() {
|
||||||
if (this->window != nullptr) {
|
if (this->window != nullptr) {
|
||||||
this->window->deleteLater();
|
this->window->deleteLater();
|
||||||
|
@ -29,20 +37,12 @@ void ProxyWindowBase::onReload(QObject* oldInstance) {
|
||||||
|
|
||||||
this->setupWindow();
|
this->setupWindow();
|
||||||
|
|
||||||
for (auto* child: this->pendingChildren) {
|
Reloadable::reloadRecursive(this->contentItem, oldInstance);
|
||||||
Reloadable::reloadRecursive(child, oldInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto backer = this->dataBacker();
|
this->contentItem->setParentItem(this->window->contentItem());
|
||||||
for (auto* child: this->pendingChildren) {
|
|
||||||
// Reparent QQuickItems to the content element,
|
|
||||||
// while leaving QObjects parented to the proxy window.
|
|
||||||
if (qobject_cast<QQuickItem*>(child) != nullptr) {
|
|
||||||
backer.append(&backer, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->pendingChildren.clear();
|
this->contentItem->setWidth(this->width());
|
||||||
|
this->contentItem->setHeight(this->height());
|
||||||
|
|
||||||
emit this->windowConnected();
|
emit this->windowConnected();
|
||||||
this->window->setVisible(this->mVisible);
|
this->window->setVisible(this->mVisible);
|
||||||
|
@ -69,9 +69,7 @@ void ProxyWindowBase::setupWindow() {
|
||||||
QQuickWindow* ProxyWindowBase::disownWindow() {
|
QQuickWindow* ProxyWindowBase::disownWindow() {
|
||||||
QObject::disconnect(this->window, nullptr, this, nullptr);
|
QObject::disconnect(this->window, nullptr, this, nullptr);
|
||||||
|
|
||||||
auto data = this->data();
|
this->contentItem->setParentItem(nullptr);
|
||||||
ProxyWindowBase::dataClear(&data);
|
|
||||||
data.clear(&data);
|
|
||||||
|
|
||||||
auto* window = this->window;
|
auto* window = this->window;
|
||||||
this->window = nullptr;
|
this->window = nullptr;
|
||||||
|
@ -162,100 +160,13 @@ void ProxyWindowBase::updateMask() {
|
||||||
this->window->setMask(mask);
|
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<QObject> ProxyWindowBase::data() {
|
QQmlListProperty<QObject> ProxyWindowBase::data() {
|
||||||
return QQmlListProperty<QObject>(
|
return this->contentItem->property("data").value<QQmlListProperty<QObject>>();
|
||||||
this,
|
|
||||||
nullptr,
|
|
||||||
ProxyWindowBase::dataAppend,
|
|
||||||
ProxyWindowBase::dataCount,
|
|
||||||
ProxyWindowBase::dataAt,
|
|
||||||
ProxyWindowBase::dataClear,
|
|
||||||
ProxyWindowBase::dataReplace,
|
|
||||||
ProxyWindowBase::dataRemoveLast
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlListProperty<QObject> ProxyWindowBase::dataBacker() {
|
void ProxyWindowBase::onWidthChanged() { this->contentItem->setWidth(this->width()); }
|
||||||
return this->window->property("data").value<QQmlListProperty<QObject>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyWindowBase::dataAppend(QQmlListProperty<QObject>* prop, QObject* obj) {
|
void ProxyWindowBase::onHeightChanged() { this->contentItem->setHeight(this->height()); }
|
||||||
auto* self = static_cast<ProxyWindowBase*>(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<QObject>* prop) {
|
|
||||||
auto* self = static_cast<ProxyWindowBase*>(prop->object); // NOLINT
|
|
||||||
|
|
||||||
if (self->window == nullptr) {
|
|
||||||
return self->pendingChildren.count();
|
|
||||||
} else {
|
|
||||||
auto backer = self->dataBacker();
|
|
||||||
return backer.count(&backer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QObject* ProxyWindowBase::dataAt(QQmlListProperty<QObject>* prop, qsizetype i) {
|
|
||||||
auto* self = static_cast<ProxyWindowBase*>(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<QObject>* prop) {
|
|
||||||
auto* self = static_cast<ProxyWindowBase*>(prop->object); // NOLINT
|
|
||||||
|
|
||||||
if (self->window == nullptr) {
|
|
||||||
self->pendingChildren.clear();
|
|
||||||
} else {
|
|
||||||
auto backer = self->dataBacker();
|
|
||||||
backer.clear(&backer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyWindowBase::dataReplace(QQmlListProperty<QObject>* prop, qsizetype i, QObject* obj) {
|
|
||||||
auto* self = static_cast<ProxyWindowBase*>(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<QObject>* prop) {
|
|
||||||
auto* self = static_cast<ProxyWindowBase*>(prop->object); // NOLINT
|
|
||||||
|
|
||||||
if (self->window == nullptr) {
|
|
||||||
self->pendingChildren.removeLast();
|
|
||||||
} else {
|
|
||||||
auto backer = self->dataBacker();
|
|
||||||
backer.removeLast(&backer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyFloatingWindow::setWidth(qint32 width) {
|
void ProxyFloatingWindow::setWidth(qint32 width) {
|
||||||
if (this->window == nullptr || !this->window->isVisible()) this->ProxyWindowBase::setWidth(width);
|
if (this->window == nullptr || !this->window->isVisible()) this->ProxyWindowBase::setWidth(width);
|
||||||
|
|
|
@ -100,7 +100,7 @@ class ProxyWindowBase: public Reloadable {
|
||||||
Q_CLASSINFO("DefaultProperty", "data");
|
Q_CLASSINFO("DefaultProperty", "data");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ProxyWindowBase(QObject* parent = nullptr): Reloadable(parent) {}
|
explicit ProxyWindowBase(QObject* parent = nullptr);
|
||||||
~ProxyWindowBase() override;
|
~ProxyWindowBase() override;
|
||||||
|
|
||||||
ProxyWindowBase(ProxyWindowBase&) = delete;
|
ProxyWindowBase(ProxyWindowBase&) = delete;
|
||||||
|
@ -144,6 +144,8 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onMaskChanged();
|
void onMaskChanged();
|
||||||
|
void onWidthChanged();
|
||||||
|
void onHeightChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool mVisible = false;
|
bool mVisible = false;
|
||||||
|
@ -152,19 +154,10 @@ protected:
|
||||||
QColor mColor = Qt::white;
|
QColor mColor = Qt::white;
|
||||||
PendingRegion* mMask = nullptr;
|
PendingRegion* mMask = nullptr;
|
||||||
QQuickWindow* window = nullptr;
|
QQuickWindow* window = nullptr;
|
||||||
|
QQuickItem* contentItem = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateMask();
|
void updateMask();
|
||||||
QQmlListProperty<QObject> dataBacker();
|
|
||||||
|
|
||||||
static void dataAppend(QQmlListProperty<QObject>* prop, QObject* obj);
|
|
||||||
static qsizetype dataCount(QQmlListProperty<QObject>* prop);
|
|
||||||
static QObject* dataAt(QQmlListProperty<QObject>* prop, qsizetype i);
|
|
||||||
static void dataClear(QQmlListProperty<QObject>* prop);
|
|
||||||
static void dataReplace(QQmlListProperty<QObject>* prop, qsizetype i, QObject* obj);
|
|
||||||
static void dataRemoveLast(QQmlListProperty<QObject>* prop);
|
|
||||||
|
|
||||||
QVector<QObject*> pendingChildren;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// qt attempts to resize the window but fails because wayland
|
// qt attempts to resize the window but fails because wayland
|
||||||
|
|
Loading…
Reference in a new issue