mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-02-23 03:33:57 +11:00
core/popupwindow: clean up popup lifecycle and window init
- Makes popup lifecycle less complex - Creates all QWindows lazily - May break live reloading of open popups to some degree
This commit is contained in:
parent
db37dc580a
commit
de1bfe028d
8 changed files with 127 additions and 100 deletions
|
|
@ -28,7 +28,7 @@ void PopupAnchor::markClean() { this->lastState = this->state; }
|
||||||
void PopupAnchor::markDirty() { this->lastState.reset(); }
|
void PopupAnchor::markDirty() { this->lastState.reset(); }
|
||||||
|
|
||||||
QWindow* PopupAnchor::backingWindow() const {
|
QWindow* PopupAnchor::backingWindow() const {
|
||||||
return this->mProxyWindow ? this->mProxyWindow->backingWindow() : nullptr;
|
return this->bProxyWindow ? this->bProxyWindow->backingWindow() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupAnchor::setWindowInternal(QObject* window) {
|
void PopupAnchor::setWindowInternal(QObject* window) {
|
||||||
|
|
@ -36,14 +36,14 @@ void PopupAnchor::setWindowInternal(QObject* window) {
|
||||||
|
|
||||||
if (this->mWindow) {
|
if (this->mWindow) {
|
||||||
QObject::disconnect(this->mWindow, nullptr, this, nullptr);
|
QObject::disconnect(this->mWindow, nullptr, this, nullptr);
|
||||||
QObject::disconnect(this->mProxyWindow, nullptr, this, nullptr);
|
QObject::disconnect(this->bProxyWindow, nullptr, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
if (auto* proxy = qobject_cast<ProxyWindowBase*>(window)) {
|
if (auto* proxy = qobject_cast<ProxyWindowBase*>(window)) {
|
||||||
this->mProxyWindow = proxy;
|
this->bProxyWindow = proxy;
|
||||||
} else if (auto* interface = qobject_cast<WindowInterface*>(window)) {
|
} else if (auto* interface = qobject_cast<WindowInterface*>(window)) {
|
||||||
this->mProxyWindow = interface->proxyWindow();
|
this->bProxyWindow = interface->proxyWindow();
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Tried to set popup anchor window to" << window
|
qWarning() << "Tried to set popup anchor window to" << window
|
||||||
<< "which is not a quickshell window.";
|
<< "which is not a quickshell window.";
|
||||||
|
|
@ -55,7 +55,7 @@ void PopupAnchor::setWindowInternal(QObject* window) {
|
||||||
QObject::connect(this->mWindow, &QObject::destroyed, this, &PopupAnchor::onWindowDestroyed);
|
QObject::connect(this->mWindow, &QObject::destroyed, this, &PopupAnchor::onWindowDestroyed);
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
this->mProxyWindow,
|
this->bProxyWindow,
|
||||||
&ProxyWindowBase::backerVisibilityChanged,
|
&ProxyWindowBase::backerVisibilityChanged,
|
||||||
this,
|
this,
|
||||||
&PopupAnchor::backingWindowVisibilityChanged
|
&PopupAnchor::backingWindowVisibilityChanged
|
||||||
|
|
@ -70,7 +70,7 @@ void PopupAnchor::setWindowInternal(QObject* window) {
|
||||||
setnull:
|
setnull:
|
||||||
if (this->mWindow) {
|
if (this->mWindow) {
|
||||||
this->mWindow = nullptr;
|
this->mWindow = nullptr;
|
||||||
this->mProxyWindow = nullptr;
|
this->bProxyWindow = nullptr;
|
||||||
|
|
||||||
emit this->windowChanged();
|
emit this->windowChanged();
|
||||||
emit this->backingWindowVisibilityChanged();
|
emit this->backingWindowVisibilityChanged();
|
||||||
|
|
@ -100,7 +100,7 @@ void PopupAnchor::setItem(QQuickItem* item) {
|
||||||
|
|
||||||
void PopupAnchor::onWindowDestroyed() {
|
void PopupAnchor::onWindowDestroyed() {
|
||||||
this->mWindow = nullptr;
|
this->mWindow = nullptr;
|
||||||
this->mProxyWindow = nullptr;
|
this->bProxyWindow = nullptr;
|
||||||
emit this->windowChanged();
|
emit this->windowChanged();
|
||||||
emit this->backingWindowVisibilityChanged();
|
emit this->backingWindowVisibilityChanged();
|
||||||
}
|
}
|
||||||
|
|
@ -186,11 +186,11 @@ void PopupAnchor::updatePlacement(const QPoint& anchorpoint, const QSize& size)
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupAnchor::updateAnchor() {
|
void PopupAnchor::updateAnchor() {
|
||||||
if (this->mItem && this->mProxyWindow) {
|
if (this->mItem && this->bProxyWindow) {
|
||||||
auto baseRect =
|
auto baseRect =
|
||||||
this->mUserRect.isEmpty() ? this->mItem->boundingRect() : this->mUserRect.qrect();
|
this->mUserRect.isEmpty() ? this->mItem->boundingRect() : this->mUserRect.qrect();
|
||||||
|
|
||||||
auto rect = this->mProxyWindow->contentItem()->mapFromItem(
|
auto rect = this->bProxyWindow->contentItem()->mapFromItem(
|
||||||
this->mItem,
|
this->mItem,
|
||||||
baseRect.marginsRemoved(this->mMargins.qmargins())
|
baseRect.marginsRemoved(this->mMargins.qmargins())
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <qnamespace.h>
|
#include <qnamespace.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qpoint.h>
|
#include <qpoint.h>
|
||||||
|
#include <qproperty.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qquickitem.h>
|
#include <qquickitem.h>
|
||||||
#include <qsize.h>
|
#include <qsize.h>
|
||||||
|
|
@ -139,7 +140,9 @@ public:
|
||||||
void markDirty();
|
void markDirty();
|
||||||
|
|
||||||
[[nodiscard]] QObject* window() const { return this->mWindow; }
|
[[nodiscard]] QObject* window() const { return this->mWindow; }
|
||||||
[[nodiscard]] ProxyWindowBase* proxyWindow() const { return this->mProxyWindow; }
|
[[nodiscard]] QBindable<ProxyWindowBase*> bindableProxyWindow() const {
|
||||||
|
return &this->bProxyWindow;
|
||||||
|
}
|
||||||
[[nodiscard]] QWindow* backingWindow() const;
|
[[nodiscard]] QWindow* backingWindow() const;
|
||||||
void setWindowInternal(QObject* window);
|
void setWindowInternal(QObject* window);
|
||||||
void setWindow(QObject* window);
|
void setWindow(QObject* window);
|
||||||
|
|
@ -193,11 +196,12 @@ private slots:
|
||||||
private:
|
private:
|
||||||
QObject* mWindow = nullptr;
|
QObject* mWindow = nullptr;
|
||||||
QQuickItem* mItem = nullptr;
|
QQuickItem* mItem = nullptr;
|
||||||
ProxyWindowBase* mProxyWindow = nullptr;
|
|
||||||
PopupAnchorState state;
|
PopupAnchorState state;
|
||||||
Box mUserRect;
|
Box mUserRect;
|
||||||
Margins mMargins;
|
Margins mMargins;
|
||||||
std::optional<PopupAnchorState> lastState;
|
std::optional<PopupAnchorState> lastState;
|
||||||
|
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(PopupAnchor, ProxyWindowBase*, bProxyWindow);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PopupPositioner {
|
class PopupPositioner {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ using XdgPositioner = QtWayland::xdg_positioner;
|
||||||
using qs::wayland::xdg_shell::XdgWmBase;
|
using qs::wayland::xdg_shell::XdgWmBase;
|
||||||
|
|
||||||
void WaylandPopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool onlyIfDirty) {
|
void WaylandPopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool onlyIfDirty) {
|
||||||
|
|
||||||
auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle());
|
auto* waylandWindow = dynamic_cast<QWaylandWindow*>(window->handle());
|
||||||
auto* popupRole = waylandWindow ? waylandWindow->surfaceRole<::xdg_popup>() : nullptr;
|
auto* popupRole = waylandWindow ? waylandWindow->surfaceRole<::xdg_popup>() : nullptr;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,29 +12,74 @@
|
||||||
|
|
||||||
ProxyPopupWindow::ProxyPopupWindow(QObject* parent): ProxyWindowBase(parent) {
|
ProxyPopupWindow::ProxyPopupWindow(QObject* parent): ProxyWindowBase(parent) {
|
||||||
this->mVisible = false;
|
this->mVisible = false;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
QObject::connect(&this->mAnchor, &PopupAnchor::windowChanged, this, &ProxyPopupWindow::parentWindowChanged);
|
QObject::connect(&this->mAnchor, &PopupAnchor::windowChanged, this, &ProxyPopupWindow::onParentWindowChanged);
|
||||||
QObject::connect(&this->mAnchor, &PopupAnchor::windowRectChanged, this, &ProxyPopupWindow::reposition);
|
QObject::connect(&this->mAnchor, &PopupAnchor::windowRectChanged, this, &ProxyPopupWindow::reposition);
|
||||||
QObject::connect(&this->mAnchor, &PopupAnchor::edgesChanged, this, &ProxyPopupWindow::reposition);
|
QObject::connect(&this->mAnchor, &PopupAnchor::edgesChanged, this, &ProxyPopupWindow::reposition);
|
||||||
QObject::connect(&this->mAnchor, &PopupAnchor::gravityChanged, this, &ProxyPopupWindow::reposition);
|
QObject::connect(&this->mAnchor, &PopupAnchor::gravityChanged, this, &ProxyPopupWindow::reposition);
|
||||||
QObject::connect(&this->mAnchor, &PopupAnchor::adjustmentChanged, this, &ProxyPopupWindow::reposition);
|
QObject::connect(&this->mAnchor, &PopupAnchor::adjustmentChanged, this, &ProxyPopupWindow::reposition);
|
||||||
QObject::connect(&this->mAnchor, &PopupAnchor::backingWindowVisibilityChanged, this, &ProxyPopupWindow::onParentUpdated);
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
this->bTargetVisible.setBinding([this] {
|
||||||
|
auto* window = this->mAnchor.bindableProxyWindow().value();
|
||||||
|
|
||||||
|
if (window == this) {
|
||||||
|
qmlWarning(this) << "Anchor assigned to current window";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window) return false;
|
||||||
|
|
||||||
|
if (!this->bWantsVisible) return false;
|
||||||
|
return window->bindableBackerVisibility().value();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyPopupWindow::targetVisibleChanged() {
|
||||||
|
this->ProxyWindowBase::setVisible(this->bTargetVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyPopupWindow::completeWindow() {
|
void ProxyPopupWindow::completeWindow() {
|
||||||
this->ProxyWindowBase::completeWindow();
|
this->ProxyWindowBase::completeWindow();
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
QObject::connect(this->window, &QWindow::visibleChanged, this, &ProxyPopupWindow::onVisibleChanged);
|
QObject::connect(this, &ProxyWindowBase::closed, this, &ProxyPopupWindow::onClosed);
|
||||||
QObject::connect(this->window, &QWindow::widthChanged, this, &ProxyPopupWindow::reposition);
|
QObject::connect(this->window, &QWindow::widthChanged, this, &ProxyPopupWindow::reposition);
|
||||||
QObject::connect(this->window, &QWindow::heightChanged, this, &ProxyPopupWindow::reposition);
|
QObject::connect(this->window, &QWindow::heightChanged, this, &ProxyPopupWindow::reposition);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
auto* bw = this->mAnchor.backingWindow();
|
||||||
|
|
||||||
|
if (bw && PopupPositioner::instance()->shouldRepositionOnMove()) {
|
||||||
|
QObject::connect(bw, &QWindow::xChanged, this, &ProxyPopupWindow::reposition);
|
||||||
|
QObject::connect(bw, &QWindow::yChanged, this, &ProxyPopupWindow::reposition);
|
||||||
|
QObject::connect(bw, &QWindow::widthChanged, this, &ProxyPopupWindow::reposition);
|
||||||
|
QObject::connect(bw, &QWindow::heightChanged, this, &ProxyPopupWindow::reposition);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->window->setTransientParent(bw);
|
||||||
this->window->setFlag(Qt::ToolTip);
|
this->window->setFlag(Qt::ToolTip);
|
||||||
|
|
||||||
|
this->mAnchor.markDirty();
|
||||||
|
PopupPositioner::instance()->reposition(&this->mAnchor, this->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyPopupWindow::postCompleteWindow() { this->updateTransientParent(); }
|
void ProxyPopupWindow::postCompleteWindow() {
|
||||||
|
this->ProxyWindowBase::setVisible(this->bTargetVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyPopupWindow::onClosed() { this->bWantsVisible = false; }
|
||||||
|
|
||||||
|
void ProxyPopupWindow::onParentWindowChanged() {
|
||||||
|
// recreate for new parent
|
||||||
|
if (this->bTargetVisible && this->isVisibleDirect()) {
|
||||||
|
this->ProxyWindowBase::setVisibleDirect(false);
|
||||||
|
this->ProxyWindowBase::setVisibleDirect(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit this->parentWindowChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void ProxyPopupWindow::setParentWindow(QObject* parent) {
|
void ProxyPopupWindow::setParentWindow(QObject* parent) {
|
||||||
qmlWarning(this) << "PopupWindow.parentWindow is deprecated. Use PopupWindow.anchor.window.";
|
qmlWarning(this) << "PopupWindow.parentWindow is deprecated. Use PopupWindow.anchor.window.";
|
||||||
|
|
@ -43,60 +88,13 @@ void ProxyPopupWindow::setParentWindow(QObject* parent) {
|
||||||
|
|
||||||
QObject* ProxyPopupWindow::parentWindow() const { return this->mAnchor.window(); }
|
QObject* ProxyPopupWindow::parentWindow() const { return this->mAnchor.window(); }
|
||||||
|
|
||||||
void ProxyPopupWindow::updateTransientParent() {
|
|
||||||
auto* bw = this->mAnchor.backingWindow();
|
|
||||||
|
|
||||||
if (this->window != nullptr && bw != this->window->transientParent()) {
|
|
||||||
if (this->window->transientParent()) {
|
|
||||||
QObject::disconnect(this->window->transientParent(), nullptr, this, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bw && PopupPositioner::instance()->shouldRepositionOnMove()) {
|
|
||||||
QObject::connect(bw, &QWindow::xChanged, this, &ProxyPopupWindow::reposition);
|
|
||||||
QObject::connect(bw, &QWindow::yChanged, this, &ProxyPopupWindow::reposition);
|
|
||||||
QObject::connect(bw, &QWindow::widthChanged, this, &ProxyPopupWindow::reposition);
|
|
||||||
QObject::connect(bw, &QWindow::heightChanged, this, &ProxyPopupWindow::reposition);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->window->setTransientParent(bw);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->updateVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyPopupWindow::onParentUpdated() { this->updateTransientParent(); }
|
|
||||||
|
|
||||||
void ProxyPopupWindow::setScreen(QuickshellScreenInfo* /*unused*/) {
|
void ProxyPopupWindow::setScreen(QuickshellScreenInfo* /*unused*/) {
|
||||||
qmlWarning(
|
qmlWarning(
|
||||||
this
|
this
|
||||||
) << "Cannot set screen of popup window, as that is controlled by the parent window";
|
) << "Cannot set screen of popup window, as that is controlled by the parent window";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyPopupWindow::setVisible(bool visible) {
|
void ProxyPopupWindow::setVisible(bool visible) { this->bWantsVisible = visible; }
|
||||||
if (visible == this->wantsVisible) return;
|
|
||||||
this->wantsVisible = visible;
|
|
||||||
this->updateVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyPopupWindow::updateVisible() {
|
|
||||||
auto target = this->wantsVisible && this->mAnchor.window() != nullptr
|
|
||||||
&& this->mAnchor.proxyWindow()->isVisibleDirect();
|
|
||||||
|
|
||||||
if (target && this->window != nullptr && !this->window->isVisible()) {
|
|
||||||
PopupPositioner::instance()->reposition(&this->mAnchor, this->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->ProxyWindowBase::setVisible(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyPopupWindow::onVisibleChanged() {
|
|
||||||
// If the window was made invisible without its parent becoming invisible
|
|
||||||
// the compositor probably destroyed it. Without this the window won't ever
|
|
||||||
// be able to become visible again.
|
|
||||||
if (this->window->transientParent() && this->window->transientParent()->isVisible()) {
|
|
||||||
this->wantsVisible = this->window->isVisible();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProxyPopupWindow::setRelativeX(qint32 x) {
|
void ProxyPopupWindow::setRelativeX(qint32 x) {
|
||||||
qmlWarning(this) << "PopupWindow.relativeX is deprecated. Use PopupWindow.anchor.rect.x.";
|
qmlWarning(this) << "PopupWindow.relativeX is deprecated. Use PopupWindow.anchor.rect.x.";
|
||||||
|
|
@ -144,3 +142,5 @@ void ProxyPopupWindow::onPolished() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProxyPopupWindow::deleteOnInvisible() const { return true; }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
|
#include <qproperty.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qquickwindow.h>
|
#include <qquickwindow.h>
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
@ -88,6 +89,7 @@ public:
|
||||||
void completeWindow() override;
|
void completeWindow() override;
|
||||||
void postCompleteWindow() override;
|
void postCompleteWindow() override;
|
||||||
void onPolished() override;
|
void onPolished() override;
|
||||||
|
bool deleteOnInvisible() const override;
|
||||||
|
|
||||||
void setScreen(QuickshellScreenInfo* screen) override;
|
void setScreen(QuickshellScreenInfo* screen) override;
|
||||||
void setVisible(bool visible) override;
|
void setVisible(bool visible) override;
|
||||||
|
|
@ -109,16 +111,24 @@ signals:
|
||||||
void relativeYChanged();
|
void relativeYChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onVisibleChanged();
|
void onParentWindowChanged();
|
||||||
void onParentUpdated();
|
void onClosed();
|
||||||
void reposition();
|
void reposition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void targetVisibleChanged();
|
||||||
|
|
||||||
QQuickWindow* parentBackingWindow();
|
QQuickWindow* parentBackingWindow();
|
||||||
void updateTransientParent();
|
|
||||||
void updateVisible();
|
|
||||||
|
|
||||||
PopupAnchor mAnchor {this};
|
PopupAnchor mAnchor {this};
|
||||||
bool wantsVisible = false;
|
|
||||||
bool pendingReposition = false;
|
bool pendingReposition = false;
|
||||||
|
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(ProxyPopupWindow, bool, bWantsVisible);
|
||||||
|
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(
|
||||||
|
ProxyPopupWindow,
|
||||||
|
bool,
|
||||||
|
bTargetVisible,
|
||||||
|
&ProxyPopupWindow::targetVisibleChanged
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,10 @@ ProxyWindowBase::ProxyWindowBase(QObject* parent)
|
||||||
ProxyWindowBase::~ProxyWindowBase() { this->deleteWindow(true); }
|
ProxyWindowBase::~ProxyWindowBase() { this->deleteWindow(true); }
|
||||||
|
|
||||||
void ProxyWindowBase::onReload(QObject* oldInstance) {
|
void ProxyWindowBase::onReload(QObject* oldInstance) {
|
||||||
this->window = this->retrieveWindow(oldInstance);
|
if (this->mVisible) this->window = this->retrieveWindow(oldInstance);
|
||||||
auto wasVisible = this->window != nullptr && this->window->isVisible();
|
auto wasVisible = this->window != nullptr && this->window->isVisible();
|
||||||
this->ensureQWindow();
|
|
||||||
|
if (this->mVisible) this->ensureQWindow();
|
||||||
|
|
||||||
// The qml engine will leave the WindowInterface as owner of everything
|
// The qml engine will leave the WindowInterface as owner of everything
|
||||||
// nested in an item, so we have to make sure the interface's children
|
// nested in an item, so we have to make sure the interface's children
|
||||||
|
|
@ -76,17 +77,21 @@ void ProxyWindowBase::onReload(QObject* oldInstance) {
|
||||||
|
|
||||||
Reloadable::reloadChildrenRecursive(this, oldInstance);
|
Reloadable::reloadChildrenRecursive(this, oldInstance);
|
||||||
|
|
||||||
this->connectWindow();
|
if (this->mVisible) {
|
||||||
this->completeWindow();
|
this->connectWindow();
|
||||||
|
this->completeWindow();
|
||||||
|
}
|
||||||
|
|
||||||
this->reloadComplete = true;
|
this->reloadComplete = true;
|
||||||
|
|
||||||
emit this->windowConnected();
|
if (this->mVisible) {
|
||||||
this->postCompleteWindow();
|
emit this->windowConnected();
|
||||||
|
this->postCompleteWindow();
|
||||||
|
|
||||||
if (wasVisible && this->isVisibleDirect()) {
|
if (wasVisible && this->isVisibleDirect()) {
|
||||||
emit this->backerVisibilityChanged();
|
this->bBackerVisibility = true;
|
||||||
this->onExposed();
|
this->onExposed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,24 +277,21 @@ void ProxyWindowBase::setVisible(bool visible) {
|
||||||
|
|
||||||
void ProxyWindowBase::setVisibleDirect(bool visible) {
|
void ProxyWindowBase::setVisibleDirect(bool visible) {
|
||||||
if (this->deleteOnInvisible()) {
|
if (this->deleteOnInvisible()) {
|
||||||
if (visible == this->isVisibleDirect()) return;
|
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
if (visible == this->isVisibleDirect()) return;
|
||||||
this->createWindow();
|
this->createWindow();
|
||||||
this->polishItems();
|
this->polishItems();
|
||||||
this->window->setVisible(true);
|
this->window->setVisible(true);
|
||||||
emit this->backerVisibilityChanged();
|
this->bBackerVisibility = true;
|
||||||
} else {
|
} else {
|
||||||
if (this->window != nullptr) {
|
if (this->window != nullptr) this->window->setVisible(false);
|
||||||
this->window->setVisible(false);
|
this->bBackerVisibility = false;
|
||||||
emit this->backerVisibilityChanged();
|
this->deleteWindow();
|
||||||
this->deleteWindow();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (this->window != nullptr) {
|
} else if (this->window != nullptr) {
|
||||||
if (visible) this->polishItems();
|
if (visible) this->polishItems();
|
||||||
this->window->setVisible(visible);
|
this->window->setVisible(visible);
|
||||||
emit this->backerVisibilityChanged();
|
this->bBackerVisibility = visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,10 @@ public:
|
||||||
virtual void setVisible(bool visible);
|
virtual void setVisible(bool visible);
|
||||||
virtual void setVisibleDirect(bool visible);
|
virtual void setVisibleDirect(bool visible);
|
||||||
|
|
||||||
|
[[nodiscard]] QBindable<bool> bindableBackerVisibility() const {
|
||||||
|
return &this->bBackerVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
void schedulePolish();
|
void schedulePolish();
|
||||||
|
|
||||||
[[nodiscard]] virtual qint32 x() const;
|
[[nodiscard]] virtual qint32 x() const;
|
||||||
|
|
@ -206,6 +210,13 @@ protected:
|
||||||
&ProxyWindowBase::implicitHeightChanged
|
&ProxyWindowBase::implicitHeightChanged
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Q_OBJECT_BINDABLE_PROPERTY(
|
||||||
|
ProxyWindowBase,
|
||||||
|
bool,
|
||||||
|
bBackerVisibility,
|
||||||
|
&ProxyWindowBase::backerVisibilityChanged
|
||||||
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void polishItems();
|
void polishItems();
|
||||||
void updateMask();
|
void updateMask();
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ void TestPopupWindow::initiallyVisible() { // NOLINT
|
||||||
auto parent = ProxyWindowBase();
|
auto parent = ProxyWindowBase();
|
||||||
auto popup = ProxyPopupWindow();
|
auto popup = ProxyPopupWindow();
|
||||||
|
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
|
|
||||||
parent.reload();
|
parent.reload();
|
||||||
|
|
@ -33,7 +33,7 @@ void TestPopupWindow::reloadReparent() { // NOLINT
|
||||||
win2->setVisible(true);
|
win2->setVisible(true);
|
||||||
|
|
||||||
parent.setVisible(true);
|
parent.setVisible(true);
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
|
|
||||||
parent.reload();
|
parent.reload();
|
||||||
|
|
@ -43,7 +43,7 @@ void TestPopupWindow::reloadReparent() { // NOLINT
|
||||||
auto newParent = ProxyWindowBase();
|
auto newParent = ProxyWindowBase();
|
||||||
auto newPopup = ProxyPopupWindow();
|
auto newPopup = ProxyPopupWindow();
|
||||||
|
|
||||||
newPopup.setParentWindow(&newParent);
|
newPopup.anchor()->setWindow(&newParent);
|
||||||
newPopup.setVisible(true);
|
newPopup.setVisible(true);
|
||||||
|
|
||||||
auto* oldWindow = popup.backingWindow();
|
auto* oldWindow = popup.backingWindow();
|
||||||
|
|
@ -66,7 +66,7 @@ void TestPopupWindow::reloadUnparent() { // NOLINT
|
||||||
auto parent = ProxyWindowBase();
|
auto parent = ProxyWindowBase();
|
||||||
auto popup = ProxyPopupWindow();
|
auto popup = ProxyPopupWindow();
|
||||||
|
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
|
|
||||||
parent.reload();
|
parent.reload();
|
||||||
|
|
@ -80,8 +80,7 @@ void TestPopupWindow::reloadUnparent() { // NOLINT
|
||||||
newPopup.reload(&popup);
|
newPopup.reload(&popup);
|
||||||
|
|
||||||
QVERIFY(!newPopup.isVisible());
|
QVERIFY(!newPopup.isVisible());
|
||||||
QVERIFY(!newPopup.backingWindow()->isVisible());
|
QVERIFY(!newPopup.backingWindow() || !newPopup.backingWindow()->isVisible());
|
||||||
QCOMPARE(newPopup.backingWindow()->transientParent(), nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestPopupWindow::invisibleWithoutParent() { // NOLINT
|
void TestPopupWindow::invisibleWithoutParent() { // NOLINT
|
||||||
|
|
@ -97,9 +96,11 @@ void TestPopupWindow::moveWithParent() { // NOLINT
|
||||||
auto parent = ProxyWindowBase();
|
auto parent = ProxyWindowBase();
|
||||||
auto popup = ProxyPopupWindow();
|
auto popup = ProxyPopupWindow();
|
||||||
|
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
popup.setRelativeX(10);
|
auto rect = popup.anchor()->rect();
|
||||||
popup.setRelativeY(10);
|
rect.x = 10;
|
||||||
|
rect.y = 10;
|
||||||
|
popup.anchor()->setRect(rect);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
|
|
||||||
parent.reload();
|
parent.reload();
|
||||||
|
|
@ -126,7 +127,7 @@ void TestPopupWindow::attachParentLate() { // NOLINT
|
||||||
|
|
||||||
QVERIFY(!popup.isVisible());
|
QVERIFY(!popup.isVisible());
|
||||||
|
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
QVERIFY(popup.isVisible());
|
QVERIFY(popup.isVisible());
|
||||||
QVERIFY(popup.backingWindow()->isVisible());
|
QVERIFY(popup.backingWindow()->isVisible());
|
||||||
QCOMPARE(popup.backingWindow()->transientParent(), parent.backingWindow());
|
QCOMPARE(popup.backingWindow()->transientParent(), parent.backingWindow());
|
||||||
|
|
@ -136,7 +137,7 @@ void TestPopupWindow::reparentLate() { // NOLINT
|
||||||
auto parent = ProxyWindowBase();
|
auto parent = ProxyWindowBase();
|
||||||
auto popup = ProxyPopupWindow();
|
auto popup = ProxyPopupWindow();
|
||||||
|
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
|
|
||||||
parent.reload();
|
parent.reload();
|
||||||
|
|
@ -151,7 +152,7 @@ void TestPopupWindow::reparentLate() { // NOLINT
|
||||||
parent2.backingWindow()->setX(10);
|
parent2.backingWindow()->setX(10);
|
||||||
parent2.backingWindow()->setY(10);
|
parent2.backingWindow()->setY(10);
|
||||||
|
|
||||||
popup.setParentWindow(&parent2);
|
popup.anchor()->setWindow(&parent2);
|
||||||
QVERIFY(popup.isVisible());
|
QVERIFY(popup.isVisible());
|
||||||
QVERIFY(popup.backingWindow()->isVisible());
|
QVERIFY(popup.backingWindow()->isVisible());
|
||||||
QCOMPARE(popup.backingWindow()->transientParent(), parent2.backingWindow());
|
QCOMPARE(popup.backingWindow()->transientParent(), parent2.backingWindow());
|
||||||
|
|
@ -163,7 +164,7 @@ void TestPopupWindow::xMigrationFix() { // NOLINT
|
||||||
auto parent = ProxyWindowBase();
|
auto parent = ProxyWindowBase();
|
||||||
auto popup = ProxyPopupWindow();
|
auto popup = ProxyPopupWindow();
|
||||||
|
|
||||||
popup.setParentWindow(&parent);
|
popup.anchor()->setWindow(&parent);
|
||||||
popup.setVisible(true);
|
popup.setVisible(true);
|
||||||
|
|
||||||
parent.reload();
|
parent.reload();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue