diff --git a/src/LayoutSaver.cpp b/src/LayoutSaver.cpp index 340495f9..7576e0e8 100644 --- a/src/LayoutSaver.cpp +++ b/src/LayoutSaver.cpp @@ -30,6 +30,7 @@ #include "private/LayoutWidget_p.h" #include "private/Logging_p.h" #include "private/Position_p.h" +#include "private/Utils_p.h" #include #include @@ -339,10 +340,17 @@ void LayoutSaver::Private::deserializeWindowGeometry(const T &saved, QWidgetOrQu // Not simply calling QWidget::setGeometry() here. // For QtQuick we need to modify the QWindow's geometry. + QRect geometry = saved.geometry; + if (!isNormalWindowState(saved.windowState)) { + // The window will be maximized. We first set its geometry to normal + // Later it's maximized and will remember this value + geometry = saved.normalGeometry; + } + if (topLevel->isWindow()) { - topLevel->setGeometry(saved.geometry); + topLevel->setGeometry(geometry); } else { - KDDockWidgets::Private::setTopLevelGeometry(saved.geometry, topLevel); + KDDockWidgets::Private::setTopLevelGeometry(geometry, topLevel); } topLevel->setVisible(saved.isVisible); @@ -848,6 +856,7 @@ QVariantMap LayoutSaver::MainWindow::toVariantMap() const map.insert(QStringLiteral("multiSplitterLayout"), multiSplitterLayout.toVariantMap()); map.insert(QStringLiteral("uniqueName"), uniqueName); map.insert(QStringLiteral("geometry"), Layouting::rectToMap(geometry)); + map.insert(QStringLiteral("normalGeometry"), Layouting::rectToMap(normalGeometry)); map.insert(QStringLiteral("screenIndex"), screenIndex); map.insert(QStringLiteral("screenSize"), Layouting::sizeToMap(screenSize)); map.insert(QStringLiteral("isVisible"), isVisible); @@ -869,6 +878,7 @@ void LayoutSaver::MainWindow::fromVariantMap(const QVariantMap &map) multiSplitterLayout.fromVariantMap(map.value(QStringLiteral("multiSplitterLayout")).toMap()); uniqueName = map.value(QStringLiteral("uniqueName")).toString(); geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap()); + normalGeometry = Layouting::mapToRect(map.value(QStringLiteral("normalGeometry")).toMap()); screenIndex = map.value(QStringLiteral("screenIndex")).toInt(); screenSize = Layouting::mapToSize(map.value(QStringLiteral("screenSize")).toMap()); isVisible = map.value(QStringLiteral("isVisible")).toBool(); diff --git a/src/MainWindowBase.cpp b/src/MainWindowBase.cpp index 7b446416..fdd4b51f 100644 --- a/src/MainWindowBase.cpp +++ b/src/MainWindowBase.cpp @@ -739,6 +739,7 @@ LayoutSaver::MainWindow MainWindowBase::serialize() const m.options = options(); m.geometry = windowGeometry(); + m.normalGeometry = normalGeometry(); m.isVisible = isVisible(); m.uniqueName = uniqueName(); m.screenIndex = screenNumberForWidget(this); diff --git a/src/private/FloatingWindow.cpp b/src/private/FloatingWindow.cpp index 8396715a..267240b5 100644 --- a/src/private/FloatingWindow.cpp +++ b/src/private/FloatingWindow.cpp @@ -459,12 +459,6 @@ bool FloatingWindow::deserialize(const LayoutSaver::FloatingWindow &fw) if (dropArea()->deserialize(fw.multiSplitterLayout)) { updateTitleBarVisibility(); - if (fw.normalGeometry.isValid() && !isNormalWindowState(fw.windowState)) { - // Restore QWidgetPrivate's normalGeometry (no public API in QWidget) - setNormalGeometry(fw.normalGeometry); - } - - // And show it: if (fw.windowState & Qt::WindowMaximized) { showMaximized(); } else if (fw.windowState & Qt::WindowMinimized) { diff --git a/src/private/LayoutSaver_p.h b/src/private/LayoutSaver_p.h index 369761fa..99b59eff 100644 --- a/src/private/LayoutSaver_p.h +++ b/src/private/LayoutSaver_p.h @@ -284,6 +284,7 @@ public: QString uniqueName; QStringList affinities; QRect geometry; + QRect normalGeometry; int screenIndex; QSize screenSize; // for relative-size restoring bool isVisible; diff --git a/src/private/quick/QWidgetAdapter_quick.cpp b/src/private/quick/QWidgetAdapter_quick.cpp index fa38ce0d..e35557b4 100644 --- a/src/private/quick/QWidgetAdapter_quick.cpp +++ b/src/private/quick/QWidgetAdapter_quick.cpp @@ -138,6 +138,8 @@ QWidgetAdapter::QWidgetAdapter(QQuickItem *parent, Qt::WindowFlags flags) } }); + qApp->installEventFilter(this); + setSize(QSize(800, 800)); } @@ -178,6 +180,55 @@ void QWidgetAdapter::onMouseRelease() void QWidgetAdapter::onCloseEvent(QCloseEvent *) { } +void QWidgetAdapter::onResizeEvent(QResizeEvent *event) +{ + QWindow* window = windowHandle(); + if (!window) { + return; + } + + if (isNormalWindowState(m_oldWindowState)) { + QRect geo = normalGeometry(); + + auto curState = window->windowState(); + if (isNormalWindowState(curState)) { + geo.setSize(event->size()); + } else { + geo.setSize(event->oldSize()); + } + + setNormalGeometry(geo); + } +} +void QWidgetAdapter::onMoveEvent(QMoveEvent *event) +{ + QWindow* window = windowHandle(); + if (!window) { + return; + } + + if (isNormalWindowState(m_oldWindowState)) { + QRect geo = normalGeometry(); + + auto windowCurrentState = window->windowState(); + if (isNormalWindowState(windowCurrentState)) { + geo.moveTopLeft(event->pos()); + } else { + geo.moveTopLeft(event->oldPos()); + } + + setNormalGeometry(geo); + } +} +void QWidgetAdapter::onWindowStateChangeEvent(QWindowStateChangeEvent *) +{ + QWindow* window = windowHandle(); + if (!window) { + return; + } + + m_oldWindowState = window->windowState(); +} void QWidgetAdapter::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) { @@ -300,23 +351,12 @@ QRect QWidgetAdapter::geometry() const QRect QWidgetAdapter::normalGeometry() const { - // TODO: There's no such concept in QWindow, do we need to workaround for QtQuick ? - return QWidgetAdapter::geometry(); + return m_normalGeometry; } void QWidgetAdapter::setNormalGeometry(QRect geo) { - if (!isTopLevel()) - return; - - if (QWindow *w = windowHandle()) { - if (isNormalWindowState(w->windowStates())) { - w->setGeometry(geo); - } else { - // Nothing better at this point, as QWindow doesn't have this concept - qDebug() << Q_FUNC_INFO << "TODO"; - } - } + m_normalGeometry = geo; } QRect QWidgetAdapter::rect() const @@ -749,6 +789,14 @@ bool QWidgetAdapter::eventFilter(QObject *watched, QEvent *ev) break; } } + + if (ev->type() == QEvent::Resize) { + onResizeEvent(static_cast(ev)); + } else if (ev->type() == QEvent::Move) { + onMoveEvent(static_cast(ev)); + } else if (ev->type() == QEvent::WindowStateChange) { + onWindowStateChangeEvent(static_cast(ev)); + } } return QQuickItem::eventFilter(watched, ev); diff --git a/src/private/quick/QWidgetAdapter_quick_p.h b/src/private/quick/QWidgetAdapter_quick_p.h index e0c5c767..74dcb5d2 100644 --- a/src/private/quick/QWidgetAdapter_quick_p.h +++ b/src/private/quick/QWidgetAdapter_quick_p.h @@ -251,6 +251,9 @@ protected: virtual void onMouseMove(QPoint globalPos); virtual void onMouseRelease(); virtual void onCloseEvent(QCloseEvent *); + virtual void onResizeEvent(QResizeEvent *); + virtual void onMoveEvent(QMoveEvent *); + virtual void onWindowStateChangeEvent(QWindowStateChangeEvent *); void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &) override; private: @@ -265,6 +268,8 @@ private: bool m_isWrapper = false; bool m_inSetParent = false; MouseEventRedirector *m_mouseEventRedirector = nullptr; + QRect m_normalGeometry; + Qt::WindowStates m_oldWindowState = Qt::WindowState::WindowNoState; }; inline qreal logicalDpiFactor(const QQuickItem *item) diff --git a/src/private/widgets/QWidgetAdapter_widgets.cpp b/src/private/widgets/QWidgetAdapter_widgets.cpp index 18d5acff..17722b11 100644 --- a/src/private/widgets/QWidgetAdapter_widgets.cpp +++ b/src/private/widgets/QWidgetAdapter_widgets.cpp @@ -133,15 +133,11 @@ QWidget *KDDockWidgets::Private::widgetForWindow(QWindow *window) void QWidgetAdapter::setNormalGeometry(QRect geo) { - if (isNormalWindowState(windowState())) { - setGeometry(geo); + QWidgetPrivate *priv = QWidgetPrivate::get(this); + if (priv->extra && priv->extra->topextra) { + priv->topData()->normalGeometry = geo; } else { - QWidgetPrivate *priv = QWidgetPrivate::get(this); - if (priv->extra && priv->extra->topextra) { - priv->topData()->normalGeometry = geo; - } else { - qWarning() << Q_FUNC_INFO << "Failing to set normal geometry"; - } + qWarning() << Q_FUNC_INFO << "Failing to set normal geometry"; } }