diff --git a/CMakeLists.txt b/CMakeLists.txt index 8293f23..966e8c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,6 @@ project(quickshell VERSION "0.2.1" LANGUAGES CXX C) set(UNRELEASED_FEATURES "network.2" "colorquant-imagerect" - "window-parent" ) set(QT_MIN_VERSION "6.6.0") diff --git a/changelog/next.md b/changelog/next.md index 86687eb..8b22d07 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -30,7 +30,6 @@ set shell id. - Added ext-background-effect window blur support. - Added per-corner radius support to Region. - Added ColorQuantizer region selection. -- Added dialog window support to FloatingWindow. ## Other Changes @@ -67,9 +66,6 @@ set shell id. - Worked around Qt bug causing crashes when plugging and unplugging monitors. - Fixed HyprlandFocusGrab crashing if windows were destroyed after being passed to it. - Fixed ScreencopyView pixelation when scaled. -- Fixed JsonAdapter crashing and providing bad data on read when using JsonObject. -- Fixed JsonAdapter sending unnecessary property changes for primitive values. -- Fixed JsonAdapter serialization for lists. ## Packaging Changes diff --git a/src/io/jsonadapter.cpp b/src/io/jsonadapter.cpp index 369ccbe..e80c6f2 100644 --- a/src/io/jsonadapter.cpp +++ b/src/io/jsonadapter.cpp @@ -1,13 +1,11 @@ #include "jsonadapter.hpp" -#include #include #include #include #include #include #include -#include #include #include #include @@ -16,7 +14,6 @@ #include #include #include -#include #include #include @@ -134,22 +131,13 @@ QJsonObject JsonAdapter::serializeRec(const QObject* obj, const QMetaObject* bas } json.insert(prop.name(), array); + } else if (val.canConvert()) { + auto variant = val.value().toVariant(); + auto jv = QJsonValue::fromVariant(variant); + json.insert(prop.name(), jv); } else { - if (val.canConvert()) val = val.value().toVariant(); - - auto jsonVal = QJsonValue::fromVariant(val); - - if (jsonVal.isNull() && !val.isNull() && val.isValid()) { - if (val.canConvert()) { - val.convert(QMetaType::fromType()); - } else if (val.canConvert()) { - val.convert(QMetaType::fromType()); - } - - jsonVal = QJsonValue::fromVariant(val); - } - - json.insert(prop.name(), jsonVal); + auto jv = QJsonValue::fromVariant(val); + json.insert(prop.name(), jv); } } } @@ -166,16 +154,14 @@ void JsonAdapter::deserializeRec(const QJsonObject& json, QObject* obj, const QM auto jval = json.value(prop.name()); if (prop.metaType() == QMetaType::fromType()) { - auto newVariant = jval.toVariant(); - auto oldValue = prop.read(obj); - auto oldVariant = - oldValue.canConvert() ? oldValue.value().toVariant() : oldValue; + auto variant = jval.toVariant(); + auto oldValue = prop.read(this).value(); // Calling prop.write with a new QJSValue will cause a property update // even if content is identical. - if (newVariant != oldVariant) { - auto jsValue = qmlEngine(this)->fromVariant(newVariant); - prop.write(obj, QVariant::fromValue(jsValue)); + if (jval.toVariant() != oldValue.toVariant()) { + auto jsValue = qmlEngine(this)->fromVariant(jval.toVariant()); + prop.write(this, QVariant::fromValue(jsValue)); } } else if (QMetaType::canView(prop.metaType(), QMetaType::fromType())) { // FIXME: This doesn't support creating descendants of JsonObject, as QMetaType.metaObject() @@ -210,7 +196,7 @@ void JsonAdapter::deserializeRec(const QJsonObject& json, QObject* obj, const QM QMetaType::fromType>() )) { - auto pval = prop.read(obj); + auto pval = prop.read(this); if (pval.canConvert>()) { auto lp = pval.value>(); @@ -261,35 +247,12 @@ void JsonAdapter::deserializeRec(const QJsonObject& json, QObject* obj, const QM } } else { auto variant = jval.toVariant(); - auto convVariant = variant; - if (convVariant.convert(prop.metaType())) { - prop.write(obj, convVariant); + if (variant.convert(prop.metaType())) { + prop.write(obj, variant); } else { - auto pval = prop.read(obj); - if (variant.canConvert() && pval.canView()) { - auto targetv = QVariant(pval.metaType()); - auto target = targetv.view().metaContainer(); - auto valueType = target.valueMetaType(); - auto i = 0; - - for (QVariant item: variant.value()) { - if (item.convert(valueType)) { - target.addValueAtEnd(targetv.data(), item.constData()); - } else { - qmlWarning(this) << "Failed to deserialize list member " << i << " of property " - << prop.name() << ": expected " << valueType.name() << " but got " - << item.typeName(); - } - - ++i; - } - prop.write(obj, targetv); - } else { - qmlWarning(this) << "Failed to deserialize property " << prop.name() << ": expected " - << prop.metaType().name() << " but got " - << jval.toVariant().typeName(); - } + qmlWarning(this) << "Failed to deserialize property " << prop.name() << ": expected " + << prop.metaType().name() << " but got " << jval.toVariant().typeName(); } } } diff --git a/src/window/floatingwindow.cpp b/src/window/floatingwindow.cpp index 7a46bbf..a0c9fdd 100644 --- a/src/window/floatingwindow.cpp +++ b/src/window/floatingwindow.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -11,27 +11,6 @@ #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(); @@ -40,25 +19,6 @@ void ProxyFloatingWindow::connectWindow() { 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); @@ -86,42 +46,6 @@ void ProxyFloatingWindow::onMaximumSizeChanged() { 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) @@ -133,7 +57,6 @@ 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, &ProxyFloatingWindow::parentWindowChanged, this, &FloatingWindowInterface::parentWindowChanged); QObject::connect(this->window, &ProxyWindowBase::windowConnected, this, &FloatingWindowInterface::onWindowConnected); // clang-format on } @@ -246,9 +169,3 @@ bool FloatingWindowInterface::startSystemResize(Qt::Edges edges) const { 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); -} diff --git a/src/window/floatingwindow.hpp b/src/window/floatingwindow.hpp index e9e536a..06b5b9e 100644 --- a/src/window/floatingwindow.hpp +++ b/src/window/floatingwindow.hpp @@ -16,15 +16,9 @@ class ProxyFloatingWindow: public ProxyWindowBase { Q_OBJECT; public: - explicit ProxyFloatingWindow(QObject* parent = nullptr); + explicit ProxyFloatingWindow(QObject* parent = nullptr): ProxyWindowBase(parent) {} void connectWindow() override; - void completeWindow() override; - void postCompleteWindow() override; - void setVisible(bool visible) override; - - [[nodiscard]] QObject* parentWindow() const; - void setParentWindow(QObject* window); // Setting geometry while the window is visible makes the content item shrink but not the window // which is awful so we disable it for floating windows. @@ -35,28 +29,11 @@ signals: void minimumSizeChanged(); void maximumSizeChanged(); void titleChanged(); - void parentWindowChanged(); - -private slots: - void onParentDestroyed(); private: void onMinimumSizeChanged(); void onMaximumSizeChanged(); void onTitleChanged(); - void targetVisibleChanged(); - - QObject* mParentWindow = nullptr; - - Q_OBJECT_BINDABLE_PROPERTY(ProxyFloatingWindow, ProxyWindowBase*, bParentProxyWindow); - Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(ProxyFloatingWindow, bool, bWantsVisible, true); - - Q_OBJECT_BINDABLE_PROPERTY( - ProxyFloatingWindow, - bool, - bTargetVisible, - &ProxyFloatingWindow::targetVisibleChanged - ); public: Q_OBJECT_BINDABLE_PROPERTY( @@ -98,11 +75,6 @@ class FloatingWindowInterface: public WindowInterface { Q_PROPERTY(bool maximized READ isMaximized WRITE setMaximized NOTIFY maximizedChanged); /// Whether the window is currently fullscreen. Q_PROPERTY(bool fullscreen READ isFullscreen WRITE setFullscreen NOTIFY fullscreenChanged); - /// The parent window of this window. Setting this makes the window a child of the parent, - /// which affects window stacking behavior. - /// - /// > [!NOTE] This property cannot be changed after the window is visible. - Q_PROPERTY(QObject* parentWindow READ parentWindow WRITE setParentWindow NOTIFY parentWindowChanged); // clang-format on QML_NAMED_ELEMENT(FloatingWindow); @@ -129,9 +101,6 @@ public: /// Start a system resize operation. Must be called during a pointer press/drag. Q_INVOKABLE [[nodiscard]] bool startSystemResize(Qt::Edges edges) const; - [[nodiscard]] QObject* parentWindow() const; - void setParentWindow(QObject* window); - signals: void minimumSizeChanged(); void maximumSizeChanged(); @@ -139,7 +108,6 @@ signals: void minimizedChanged(); void maximizedChanged(); void fullscreenChanged(); - void parentWindowChanged(); private slots: void onWindowConnected(); diff --git a/src/window/test/manual/parentwindow.qml b/src/window/test/manual/parentwindow.qml deleted file mode 100644 index 214ee25..0000000 --- a/src/window/test/manual/parentwindow.qml +++ /dev/null @@ -1,42 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls.Fusion -import Quickshell - -Scope { - FloatingWindow { - id: control - color: contentItem.palette.window - ColumnLayout { - CheckBox { - id: parentCb - text: "Show parent" - } - - CheckBox { - id: dialogCb - text: "Show dialog" - } - } - } - - FloatingWindow { - id: parentw - Text { - text: "parent" - } - visible: parentCb.checked - color: contentItem.palette.window - - FloatingWindow { - id: dialog - parentWindow: parentw - visible: dialogCb.checked - color: contentItem.palette.window - - Text { - text: "dialog" - } - } - } -} diff --git a/src/windowmanager/windowmanager.cpp b/src/windowmanager/windowmanager.cpp index 511e8ec..6b51db1 100644 --- a/src/windowmanager/windowmanager.cpp +++ b/src/windowmanager/windowmanager.cpp @@ -21,8 +21,6 @@ WindowManager* WindowManager::instance() { } ScreenProjection* WindowManager::screenProjection(QuickshellScreenInfo* screen) { - if (!screen) return nullptr; - auto* qscreen = screen->screen; auto it = this->mScreenProjections.find(qscreen); if (it != this->mScreenProjections.end()) {