#include "floatingwindow.hpp" #include #include #include #include #include #include #include #include "proxywindow.hpp" #include "windowinterface.hpp" ProxyFloatingWindow::ProxyFloatingWindow(QObject* parent): ProxyWindowBase(parent) { this->bTargetVisible.setBinding([this] { if (!this->bWantsVisible) return false; auto* parent = this->bParentProxyWindow.value(); if (!parent) return true; return parent->bindableBackerVisibility().value(); }); } void ProxyFloatingWindow::targetVisibleChanged() { if (this->window && this->bParentProxyWindow) { auto* bw = this->bParentProxyWindow.value()->backingWindow(); if (bw != this->window->transientParent()) { this->window->setTransientParent(bw); } } this->ProxyWindowBase::setVisible(this->bTargetVisible); } void ProxyFloatingWindow::connectWindow() { this->ProxyWindowBase::connectWindow(); this->window->setTitle(this->bTitle); this->window->setMinimumSize(this->bMinimumSize); this->window->setMaximumSize(this->bMaximumSize); } void ProxyFloatingWindow::completeWindow() { this->ProxyWindowBase::completeWindow(); auto* parent = this->bParentProxyWindow.value(); this->window->setTransientParent(parent ? parent->backingWindow() : nullptr); } void ProxyFloatingWindow::postCompleteWindow() { this->ProxyWindowBase::setVisible(this->bTargetVisible); } void ProxyFloatingWindow::onParentDestroyed() { this->mParentWindow = nullptr; this->bParentProxyWindow = nullptr; emit this->parentWindowChanged(); } void ProxyFloatingWindow::setVisible(bool visible) { this->bWantsVisible = visible; } void ProxyFloatingWindow::trySetWidth(qint32 implicitWidth) { if (!this->window->isVisible()) { this->ProxyWindowBase::trySetWidth(implicitWidth); } } void ProxyFloatingWindow::trySetHeight(qint32 implicitHeight) { if (!this->window->isVisible()) { this->ProxyWindowBase::trySetHeight(implicitHeight); } } void ProxyFloatingWindow::onTitleChanged() { if (this->window) this->window->setTitle(this->bTitle); emit this->titleChanged(); } void ProxyFloatingWindow::onMinimumSizeChanged() { if (this->window) this->window->setMinimumSize(this->bMinimumSize); emit this->minimumSizeChanged(); } void ProxyFloatingWindow::onMaximumSizeChanged() { if (this->window) this->window->setMaximumSize(this->bMaximumSize); emit this->maximumSizeChanged(); } QObject* ProxyFloatingWindow::parentWindow() const { return this->mParentWindow; } void ProxyFloatingWindow::setParentWindow(QObject* window) { if (window == this->mParentWindow) return; if (this->window && this->window->isVisible()) { qmlWarning(this) << "parentWindow cannot be changed after the window is visible."; return; } if (this->bParentProxyWindow) { QObject::disconnect(this->bParentProxyWindow, nullptr, this, nullptr); } if (this->mParentWindow) { QObject::disconnect(this->mParentWindow, nullptr, this, nullptr); } this->mParentWindow = nullptr; this->bParentProxyWindow = nullptr; if (auto* proxy = ProxyWindowBase::forObject(window)) { this->mParentWindow = window; this->bParentProxyWindow = proxy; QObject::connect( this->mParentWindow, &QObject::destroyed, this, &ProxyFloatingWindow::onParentDestroyed ); } emit this->parentWindowChanged(); } // FloatingWindowInterface FloatingWindowInterface::FloatingWindowInterface(QObject* parent) : WindowInterface(parent) , window(new ProxyFloatingWindow(this)) { this->connectSignals(); // clang-format off QObject::connect(this->window, &ProxyFloatingWindow::titleChanged, this, &FloatingWindowInterface::titleChanged); QObject::connect(this->window, &ProxyFloatingWindow::minimumSizeChanged, this, &FloatingWindowInterface::minimumSizeChanged); QObject::connect(this->window, &ProxyFloatingWindow::maximumSizeChanged, this, &FloatingWindowInterface::maximumSizeChanged); QObject::connect(this->window, &ProxyFloatingWindow::parentWindowChanged, this, &FloatingWindowInterface::parentWindowChanged); QObject::connect(this->window, &ProxyWindowBase::windowConnected, this, &FloatingWindowInterface::onWindowConnected); // clang-format on } void FloatingWindowInterface::onReload(QObject* oldInstance) { QQmlEngine::setContextForObject(this->window, QQmlEngine::contextForObject(this)); auto* old = qobject_cast(oldInstance); this->window->reload(old != nullptr ? old->window : nullptr); } ProxyWindowBase* FloatingWindowInterface::proxyWindow() const { return this->window; } void FloatingWindowInterface::onWindowConnected() { auto* qw = this->window->backingWindow(); if (qw) { QObject::connect( qw, &QWindow::windowStateChanged, this, &FloatingWindowInterface::onWindowStateChanged ); this->setMinimized(this->mMinimized); this->setMaximized(this->mMaximized); this->setFullscreen(this->mFullscreen); this->onWindowStateChanged(); } } void FloatingWindowInterface::onWindowStateChanged() { auto* qw = this->window->backingWindow(); auto states = qw ? qw->windowStates() : Qt::WindowStates(); auto minimized = states.testFlag(Qt::WindowMinimized); auto maximized = states.testFlag(Qt::WindowMaximized); auto fullscreen = states.testFlag(Qt::WindowFullScreen); if (minimized != this->mWasMinimized) { this->mWasMinimized = minimized; emit this->minimizedChanged(); } if (maximized != this->mWasMaximized) { this->mWasMaximized = maximized; emit this->maximizedChanged(); } if (fullscreen != this->mWasFullscreen) { this->mWasFullscreen = fullscreen; emit this->fullscreenChanged(); } } bool FloatingWindowInterface::isMinimized() const { auto* qw = this->window->backingWindow(); if (!qw) return this->mWasMinimized; return qw->windowStates().testFlag(Qt::WindowMinimized); } void FloatingWindowInterface::setMinimized(bool minimized) { this->mMinimized = minimized; if (auto* qw = this->window->backingWindow()) { auto states = qw->windowStates(); states.setFlag(Qt::WindowMinimized, minimized); qw->setWindowStates(states); } } bool FloatingWindowInterface::isMaximized() const { auto* qw = this->window->backingWindow(); if (!qw) return this->mWasMaximized; return qw->windowStates().testFlag(Qt::WindowMaximized); } void FloatingWindowInterface::setMaximized(bool maximized) { this->mMaximized = maximized; if (auto* qw = this->window->backingWindow()) { auto states = qw->windowStates(); states.setFlag(Qt::WindowMaximized, maximized); qw->setWindowStates(states); } } bool FloatingWindowInterface::isFullscreen() const { auto* qw = this->window->backingWindow(); if (!qw) return this->mWasFullscreen; return qw->windowStates().testFlag(Qt::WindowFullScreen); } void FloatingWindowInterface::setFullscreen(bool fullscreen) { this->mFullscreen = fullscreen; if (auto* qw = this->window->backingWindow()) { auto states = qw->windowStates(); states.setFlag(Qt::WindowFullScreen, fullscreen); qw->setWindowStates(states); } } bool FloatingWindowInterface::startSystemMove() const { auto* qw = this->window->backingWindow(); if (!qw) return false; return qw->startSystemMove(); } bool FloatingWindowInterface::startSystemResize(Qt::Edges edges) const { auto* qw = this->window->backingWindow(); if (!qw) return false; return qw->startSystemResize(edges); } QObject* FloatingWindowInterface::parentWindow() const { return this->window->parentWindow(); } void FloatingWindowInterface::setParentWindow(QObject* window) { this->window->setParentWindow(window); }