From 09b3822764ae057d0fa2361ed9eda1c3eeb7d262 Mon Sep 17 00:00:00 2001 From: bbedward Date: Wed, 26 Nov 2025 09:54:32 -0500 Subject: [PATCH 1/4] core/window: add startSystemMove, startSystemResize, maximize, and fullscreen to FloatingWindow --- src/window/floatingwindow.cpp | 51 +++++++++++++++++++++++++++++++++++ src/window/floatingwindow.hpp | 35 +++++++++++++++++++++--- src/window/proxywindow.cpp | 1 + src/window/proxywindow.hpp | 1 + 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/src/window/floatingwindow.cpp b/src/window/floatingwindow.cpp index 0b9e9b1c..47f6eac4 100644 --- a/src/window/floatingwindow.cpp +++ b/src/window/floatingwindow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "proxywindow.hpp" #include "windowinterface.hpp" @@ -55,6 +56,7 @@ FloatingWindowInterface::FloatingWindowInterface(QObject* parent) 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, &ProxyWindowBase::windowVisibilityChanged, this, &FloatingWindowInterface::onVisibilityChanged); // clang-format on } @@ -66,3 +68,52 @@ void FloatingWindowInterface::onReload(QObject* oldInstance) { } ProxyWindowBase* FloatingWindowInterface::proxyWindow() const { return this->window; } + +void FloatingWindowInterface::onVisibilityChanged() { + auto* qw = this->window->backingWindow(); + auto visibility = qw ? qw->visibility() : QWindow::Hidden; + + auto maximized = visibility == QWindow::Maximized; + auto fullscreen = visibility == QWindow::FullScreen; + + if (maximized != this->mMaximized) { + this->mMaximized = maximized; + emit this->maximizedChanged(); + } + + if (fullscreen != this->mFullscreen) { + this->mFullscreen = fullscreen; + emit this->fullscreenChanged(); + } +} + +bool FloatingWindowInterface::maximized() const { return this->mMaximized; } +bool FloatingWindowInterface::fullscreen() const { return this->mFullscreen; } + +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); +} + +void FloatingWindowInterface::showNormal() const { + if (auto* qw = this->window->backingWindow()) qw->showNormal(); +} + +void FloatingWindowInterface::showMaximized() const { + if (auto* qw = this->window->backingWindow()) qw->showMaximized(); +} + +void FloatingWindowInterface::showMinimized() const { + if (auto* qw = this->window->backingWindow()) qw->showMinimized(); +} + +void FloatingWindowInterface::showFullScreen() const { + if (auto* qw = this->window->backingWindow()) qw->showFullScreen(); +} diff --git a/src/window/floatingwindow.hpp b/src/window/floatingwindow.hpp index f9cd5ced..bf5b33a9 100644 --- a/src/window/floatingwindow.hpp +++ b/src/window/floatingwindow.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -68,6 +69,10 @@ 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); + /// Whether the window is currently maximized. + Q_PROPERTY(bool maximized READ maximized NOTIFY maximizedChanged); + /// Whether the window is currently fullscreen. + Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged); // clang-format on QML_NAMED_ELEMENT(FloatingWindow); @@ -78,15 +83,39 @@ class FloatingWindowInterface: public WindowInterface { [[nodiscard]] ProxyWindowBase* proxyWindow() const override; - QBindable bindableMinimumSize() { return &this->window->bMinimumSize; } - QBindable bindableMaximumSize() { return &this->window->bMaximumSize; } - QBindable bindableTitle() { return &this->window->bTitle; } + [[nodiscard]] QBindable bindableMinimumSize() { return &this->window->bMinimumSize; } + [[nodiscard]] QBindable bindableMaximumSize() { return &this->window->bMaximumSize; } + [[nodiscard]] QBindable bindableTitle() { return &this->window->bTitle; } + + [[nodiscard]] bool maximized() const; + [[nodiscard]] bool fullscreen() const; + + /// Start a system move operation. Must be called during a pointer press/drag. + Q_INVOKABLE [[nodiscard]] bool startSystemMove() const; + /// Start a system resize operation. Must be called during a pointer press/drag. + Q_INVOKABLE [[nodiscard]] bool startSystemResize(Qt::Edges edges) const; + + /// Show the window in normal (restored) state. + Q_INVOKABLE void showNormal() const; + /// Show the window maximized. + Q_INVOKABLE void showMaximized() const; + /// Show the window minimized. + Q_INVOKABLE void showMinimized() const; + /// Show the window fullscreen. + Q_INVOKABLE void showFullScreen() const; signals: void minimumSizeChanged(); void maximumSizeChanged(); void titleChanged(); + void maximizedChanged(); + void fullscreenChanged(); + +private slots: + void onVisibilityChanged(); private: ProxyFloatingWindow* window; + bool mMaximized = false; + bool mFullscreen = false; }; diff --git a/src/window/proxywindow.cpp b/src/window/proxywindow.cpp index ea2904bb..670ea013 100644 --- a/src/window/proxywindow.cpp +++ b/src/window/proxywindow.cpp @@ -248,6 +248,7 @@ void ProxyWindowBase::onVisibleChanged() { } emit this->visibleChanged(); + emit this->windowVisibilityChanged(); } bool ProxyWindowBase::deleteOnInvisible() const { return false; } diff --git a/src/window/proxywindow.hpp b/src/window/proxywindow.hpp index 025b970a..88a01a3b 100644 --- a/src/window/proxywindow.hpp +++ b/src/window/proxywindow.hpp @@ -147,6 +147,7 @@ class ProxyWindowBase: public Reloadable { void windowDestroyed(); void visibleChanged(); void backerVisibilityChanged(); + void windowVisibilityChanged(); void xChanged(); void yChanged(); void implicitWidthChanged(); From 1e9249656bc65b031293b8a11b1a2fd990f07e9f Mon Sep 17 00:00:00 2001 From: bbedward Date: Wed, 26 Nov 2025 10:44:50 -0500 Subject: [PATCH 2/4] core/window: fix lints --- src/window/floatingwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/window/floatingwindow.cpp b/src/window/floatingwindow.cpp index 47f6eac4..55612e61 100644 --- a/src/window/floatingwindow.cpp +++ b/src/window/floatingwindow.cpp @@ -1,5 +1,6 @@ #include "floatingwindow.hpp" +#include #include #include #include From 71b68d598c4223b48eba4741478f3eb01bef47a7 Mon Sep 17 00:00:00 2001 From: bbedward Date: Sun, 30 Nov 2025 10:30:08 -0500 Subject: [PATCH 3/4] core/window: add minimize, use windowStates --- src/window/floatingwindow.cpp | 38 ++++++++++++++++++++++++++--------- src/window/floatingwindow.hpp | 25 ++++++++++++++--------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/window/floatingwindow.cpp b/src/window/floatingwindow.cpp index 55612e61..4fc4d3fa 100644 --- a/src/window/floatingwindow.cpp +++ b/src/window/floatingwindow.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include "proxywindow.hpp" #include "windowinterface.hpp" @@ -72,10 +71,16 @@ ProxyWindowBase* FloatingWindowInterface::proxyWindow() const { return this->win void FloatingWindowInterface::onVisibilityChanged() { auto* qw = this->window->backingWindow(); - auto visibility = qw ? qw->visibility() : QWindow::Hidden; + auto states = qw ? qw->windowStates() : Qt::WindowStates(); - auto maximized = visibility == QWindow::Maximized; - auto fullscreen = visibility == QWindow::FullScreen; + auto minimized = states.testFlag(Qt::WindowMinimized); + auto maximized = states.testFlag(Qt::WindowMaximized); + auto fullscreen = states.testFlag(Qt::WindowFullScreen); + + if (minimized != this->mMinimized) { + this->mMinimized = minimized; + emit this->minimizedChanged(); + } if (maximized != this->mMaximized) { this->mMaximized = maximized; @@ -88,8 +93,23 @@ void FloatingWindowInterface::onVisibilityChanged() { } } -bool FloatingWindowInterface::maximized() const { return this->mMaximized; } -bool FloatingWindowInterface::fullscreen() const { return this->mFullscreen; } +bool FloatingWindowInterface::isMinimized() const { + auto* qw = this->window->backingWindow(); + if (!qw) return this->mMinimized; + return qw->windowStates().testFlag(Qt::WindowMinimized); +} + +bool FloatingWindowInterface::isMaximized() const { + auto* qw = this->window->backingWindow(); + if (!qw) return this->mMaximized; + return qw->windowStates().testFlag(Qt::WindowMaximized); +} + +bool FloatingWindowInterface::isFullscreen() const { + auto* qw = this->window->backingWindow(); + if (!qw) return this->mFullscreen; + return qw->windowStates().testFlag(Qt::WindowFullScreen); +} bool FloatingWindowInterface::startSystemMove() const { auto* qw = this->window->backingWindow(); @@ -107,14 +127,14 @@ void FloatingWindowInterface::showNormal() const { if (auto* qw = this->window->backingWindow()) qw->showNormal(); } -void FloatingWindowInterface::showMaximized() const { +void FloatingWindowInterface::maximize() const { if (auto* qw = this->window->backingWindow()) qw->showMaximized(); } -void FloatingWindowInterface::showMinimized() const { +void FloatingWindowInterface::minimize() const { if (auto* qw = this->window->backingWindow()) qw->showMinimized(); } -void FloatingWindowInterface::showFullScreen() const { +void FloatingWindowInterface::fullscreen() const { if (auto* qw = this->window->backingWindow()) qw->showFullScreen(); } diff --git a/src/window/floatingwindow.hpp b/src/window/floatingwindow.hpp index bf5b33a9..1b20b053 100644 --- a/src/window/floatingwindow.hpp +++ b/src/window/floatingwindow.hpp @@ -69,10 +69,12 @@ 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); + /// Whether the window is currently minimized. + Q_PROPERTY(bool minimized READ isMinimized NOTIFY minimizedChanged); /// Whether the window is currently maximized. - Q_PROPERTY(bool maximized READ maximized NOTIFY maximizedChanged); + Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged); /// Whether the window is currently fullscreen. - Q_PROPERTY(bool fullscreen READ fullscreen NOTIFY fullscreenChanged); + Q_PROPERTY(bool fullscreen READ isFullscreen NOTIFY fullscreenChanged); // clang-format on QML_NAMED_ELEMENT(FloatingWindow); @@ -87,8 +89,9 @@ class FloatingWindowInterface: public WindowInterface { [[nodiscard]] QBindable bindableMaximumSize() { return &this->window->bMaximumSize; } [[nodiscard]] QBindable bindableTitle() { return &this->window->bTitle; } - [[nodiscard]] bool maximized() const; - [[nodiscard]] bool fullscreen() const; + [[nodiscard]] bool isMinimized() const; + [[nodiscard]] bool isMaximized() const; + [[nodiscard]] bool isFullscreen() const; /// Start a system move operation. Must be called during a pointer press/drag. Q_INVOKABLE [[nodiscard]] bool startSystemMove() const; @@ -97,17 +100,18 @@ class FloatingWindowInterface: public WindowInterface { /// Show the window in normal (restored) state. Q_INVOKABLE void showNormal() const; - /// Show the window maximized. - Q_INVOKABLE void showMaximized() const; - /// Show the window minimized. - Q_INVOKABLE void showMinimized() const; - /// Show the window fullscreen. - Q_INVOKABLE void showFullScreen() const; + /// Maximize the window. + Q_INVOKABLE void maximize() const; + /// Minimize the window. + Q_INVOKABLE void minimize() const; + /// Fullscreen the window. + Q_INVOKABLE void fullscreen() const; signals: void minimumSizeChanged(); void maximumSizeChanged(); void titleChanged(); + void minimizedChanged(); void maximizedChanged(); void fullscreenChanged(); @@ -116,6 +120,7 @@ private slots: private: ProxyFloatingWindow* window; + bool mMinimized = false; bool mMaximized = false; bool mFullscreen = false; }; From 4c3f368bd763b058ae56624d3074f5086f9b0d20 Mon Sep 17 00:00:00 2001 From: bbedward Date: Sun, 30 Nov 2025 10:37:22 -0500 Subject: [PATCH 4/4] core/window: connect to windowStateChanged --- src/window/floatingwindow.cpp | 17 +++++++++++++++-- src/window/floatingwindow.hpp | 3 ++- src/window/proxywindow.cpp | 1 - src/window/proxywindow.hpp | 1 - 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/window/floatingwindow.cpp b/src/window/floatingwindow.cpp index 4fc4d3fa..aa4aebe1 100644 --- a/src/window/floatingwindow.cpp +++ b/src/window/floatingwindow.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "proxywindow.hpp" #include "windowinterface.hpp" @@ -56,7 +57,7 @@ FloatingWindowInterface::FloatingWindowInterface(QObject* parent) 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, &ProxyWindowBase::windowVisibilityChanged, this, &FloatingWindowInterface::onVisibilityChanged); + QObject::connect(this->window, &ProxyWindowBase::windowConnected, this, &FloatingWindowInterface::onWindowConnected); // clang-format on } @@ -69,7 +70,19 @@ void FloatingWindowInterface::onReload(QObject* oldInstance) { ProxyWindowBase* FloatingWindowInterface::proxyWindow() const { return this->window; } -void FloatingWindowInterface::onVisibilityChanged() { +void FloatingWindowInterface::onWindowConnected() { + auto* qw = this->window->backingWindow(); + if (qw) { + QObject::connect( + qw, + &QWindow::windowStateChanged, + this, + &FloatingWindowInterface::onWindowStateChanged + ); + } +} + +void FloatingWindowInterface::onWindowStateChanged() { auto* qw = this->window->backingWindow(); auto states = qw ? qw->windowStates() : Qt::WindowStates(); diff --git a/src/window/floatingwindow.hpp b/src/window/floatingwindow.hpp index 1b20b053..37f4c945 100644 --- a/src/window/floatingwindow.hpp +++ b/src/window/floatingwindow.hpp @@ -116,7 +116,8 @@ class FloatingWindowInterface: public WindowInterface { void fullscreenChanged(); private slots: - void onVisibilityChanged(); + void onWindowConnected(); + void onWindowStateChanged(); private: ProxyFloatingWindow* window; diff --git a/src/window/proxywindow.cpp b/src/window/proxywindow.cpp index 670ea013..ea2904bb 100644 --- a/src/window/proxywindow.cpp +++ b/src/window/proxywindow.cpp @@ -248,7 +248,6 @@ void ProxyWindowBase::onVisibleChanged() { } emit this->visibleChanged(); - emit this->windowVisibilityChanged(); } bool ProxyWindowBase::deleteOnInvisible() const { return false; } diff --git a/src/window/proxywindow.hpp b/src/window/proxywindow.hpp index 88a01a3b..025b970a 100644 --- a/src/window/proxywindow.hpp +++ b/src/window/proxywindow.hpp @@ -147,7 +147,6 @@ class ProxyWindowBase: public Reloadable { void windowDestroyed(); void visibleChanged(); void backerVisibilityChanged(); - void windowVisibilityChanged(); void xChanged(); void yChanged(); void implicitWidthChanged();