From 3b2d84caf0d4494b276de2e86a2593a728318ab5 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 21 Mar 2025 02:46:09 -0700 Subject: [PATCH] hyprland/ipc: convert to bindable properties --- src/wayland/hyprland/ipc/connection.cpp | 59 +++++++++------- src/wayland/hyprland/ipc/monitor.cpp | 91 ++++++------------------- src/wayland/hyprland/ipc/monitor.hpp | 56 ++++++++------- src/wayland/hyprland/ipc/workspace.cpp | 39 +++-------- src/wayland/hyprland/ipc/workspace.hpp | 20 +++--- 5 files changed, 105 insertions(+), 160 deletions(-) diff --git a/src/wayland/hyprland/ipc/connection.cpp b/src/wayland/hyprland/ipc/connection.cpp index 36359a0e..fb1cbc9f 100644 --- a/src/wayland/hyprland/ipc/connection.cpp +++ b/src/wayland/hyprland/ipc/connection.cpp @@ -243,8 +243,9 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) { const auto& mList = this->mMonitors.valueList(); auto name = QString::fromUtf8(event->data); - auto monitorIter = - std::ranges::find_if(mList, [name](const HyprlandMonitor* m) { return m->name() == name; }); + auto monitorIter = std::ranges::find_if(mList, [name](HyprlandMonitor* m) { + return m->bindableName().value() == name; + }); if (monitorIter == mList.end()) { qCWarning(logHyprlandIpc) << "Got removal for monitor" << name @@ -255,8 +256,8 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) { auto index = monitorIter - mList.begin(); auto* monitor = *monitorIter; - qCDebug(logHyprlandIpc) << "Monitor removed with id" << monitor->id() << "name" - << monitor->name(); + qCDebug(logHyprlandIpc) << "Monitor removed with id" << monitor->bindableId().value() << "name" + << monitor->bindableName().value(); this->mMonitors.removeAt(index); // delete the monitor object in the next event loop cycle so it's likely to @@ -293,8 +294,9 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) { const auto& mList = this->mWorkspaces.valueList(); - auto workspaceIter = - std::ranges::find_if(mList, [id](const HyprlandWorkspace* m) { return m->id() == id; }); + auto workspaceIter = std::ranges::find_if(mList, [id](HyprlandWorkspace* m) { + return m->bindableId().value() == id; + }); if (workspaceIter == mList.end()) { qCWarning(logHyprlandIpc) << "Got removal for workspace id" << id << "name" << name @@ -334,7 +336,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) { this->setFocusedMonitor(monitor); monitor->setActiveWorkspace(workspace); qCDebug(logHyprlandIpc) << "Monitor" << name << "focused with workspace" - << (workspace ? workspace->id() : -1); + << (workspace ? workspace->bindableId().value() : -1); } else if (event->name == "workspacev2") { auto args = event->parseView(2); auto id = args.at(0).toInt(); @@ -344,7 +346,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) { auto* workspace = this->findWorkspaceByName(name, true, id); this->mFocusedMonitor->setActiveWorkspace(workspace); qCDebug(logHyprlandIpc) << "Workspace" << id << "activated on" - << this->mFocusedMonitor->name(); + << this->mFocusedMonitor->bindableName().value(); } } else if (event->name == "moveworkspacev2") { auto args = event->parseView(3); @@ -364,15 +366,16 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) { const auto& mList = this->mWorkspaces.valueList(); - auto workspaceIter = - std::ranges::find_if(mList, [id](const HyprlandWorkspace* m) { return m->id() == id; }); + auto workspaceIter = std::ranges::find_if(mList, [id](HyprlandWorkspace* m) { + return m->bindableId().value() == id; + }); if (workspaceIter == mList.end()) return; qCDebug(logHyprlandIpc) << "Workspace with id" << id << "renamed from" - << (*workspaceIter)->name() << "to" << name; + << (*workspaceIter)->bindableName().value() << "to" << name; - (*workspaceIter)->setName(name); + (*workspaceIter)->bindableName().setValue(name); } } @@ -382,15 +385,17 @@ HyprlandIpc::findWorkspaceByName(const QString& name, bool createIfMissing, qint HyprlandWorkspace* workspace = nullptr; if (id != -1) { - auto workspaceIter = - std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) { return m->id() == id; }); + auto workspaceIter = std::ranges::find_if(mList, [&](HyprlandWorkspace* m) { + return m->bindableId().value() == id; + }); workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter; } if (!workspace) { - auto workspaceIter = - std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) { return m->name() == name; }); + auto workspaceIter = std::ranges::find_if(mList, [&](HyprlandWorkspace* m) { + return m->bindableName().value() == name; + }); workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter; } @@ -429,16 +434,17 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) { auto id = object.value("id").toInt(); - auto workspaceIter = - std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) { return m->id() == id; }); + auto workspaceIter = std::ranges::find_if(mList, [&](HyprlandWorkspace* m) { + return m->bindableId().value() == id; + }); // Only fall back to name-based filtering as a last resort, for workspaces where // no ID has been determined yet. if (workspaceIter == mList.end()) { auto name = object.value("name").toString(); - workspaceIter = std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) { - return m->id() == -1 && m->name() == name; + workspaceIter = std::ranges::find_if(mList, [&](HyprlandWorkspace* m) { + return m->bindableId().value() == -1 && m->bindableName().value() == name; }); } @@ -463,7 +469,7 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) { auto removedWorkspaces = QVector(); for (auto* workspace: mList) { - if (!ids.contains(workspace->id())) { + if (!ids.contains(workspace->bindableId().value())) { removedWorkspaces.push_back(workspace); } } @@ -480,8 +486,9 @@ HyprlandMonitor* HyprlandIpc::findMonitorByName(const QString& name, bool createIfMissing, qint32 id) { const auto& mList = this->mMonitors.valueList(); - auto monitorIter = - std::ranges::find_if(mList, [name](const HyprlandMonitor* m) { return m->name() == name; }); + auto monitorIter = std::ranges::find_if(mList, [name](HyprlandMonitor* m) { + return m->bindableName().value() == name; + }); if (monitorIter != mList.end()) { return *monitorIter; @@ -549,8 +556,8 @@ void HyprlandIpc::refreshMonitors(bool canCreate) { auto object = entry.toObject().toVariantMap(); auto name = object.value("name").toString(); - auto monitorIter = std::ranges::find_if(mList, [name](const HyprlandMonitor* m) { - return m->name() == name; + auto monitorIter = std::ranges::find_if(mList, [name](HyprlandMonitor* m) { + return m->bindableName().value() == name; }); auto* monitor = monitorIter == mList.end() ? nullptr : *monitorIter; @@ -573,7 +580,7 @@ void HyprlandIpc::refreshMonitors(bool canCreate) { auto removedMonitors = QVector(); for (auto* monitor: mList) { - if (!names.contains(monitor->name())) { + if (!names.contains(monitor->bindableName().value())) { removedMonitors.push_back(monitor); } } diff --git a/src/wayland/hyprland/ipc/monitor.cpp b/src/wayland/hyprland/ipc/monitor.cpp index 190ab668..68312674 100644 --- a/src/wayland/hyprland/ipc/monitor.cpp +++ b/src/wayland/hyprland/ipc/monitor.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -10,88 +11,36 @@ namespace qs::hyprland::ipc { -qint32 HyprlandMonitor::id() const { return this->mId; } -QString HyprlandMonitor::name() const { return this->mName; } -QString HyprlandMonitor::description() const { return this->mDescription; } -qint32 HyprlandMonitor::x() const { return this->mX; } -qint32 HyprlandMonitor::y() const { return this->mY; } -qint32 HyprlandMonitor::width() const { return this->mWidth; } -qint32 HyprlandMonitor::height() const { return this->mHeight; } -qreal HyprlandMonitor::scale() const { return this->mScale; } QVariantMap HyprlandMonitor::lastIpcObject() const { return this->mLastIpcObject; } -void HyprlandMonitor::updateInitial(qint32 id, QString name, QString description) { - if (id != this->mId) { - this->mId = id; - emit this->idChanged(); - } - - if (name != this->mName) { - this->mName = std::move(name); - emit this->nameChanged(); - } - - if (description != this->mDescription) { - this->mDescription = std::move(description); - emit this->descriptionChanged(); - } +void HyprlandMonitor::updateInitial(qint32 id, const QString& name, const QString& description) { + Qt::beginPropertyUpdateGroup(); + this->bId = id; + this->bName = name; + this->bDescription = description; + Qt::endPropertyUpdateGroup(); } void HyprlandMonitor::updateFromObject(QVariantMap object) { - auto id = object.value("id").value(); - auto name = object.value("name").value(); - auto description = object.value("description").value(); - auto x = object.value("x").value(); - auto y = object.value("y").value(); - auto width = object.value("width").value(); - auto height = object.value("height").value(); - auto scale = object.value("height").value(); auto activeWorkspaceObj = object.value("activeWorkspace").value(); auto activeWorkspaceId = activeWorkspaceObj.value("id").value(); auto activeWorkspaceName = activeWorkspaceObj.value("name").value(); auto focused = object.value("focused").value(); - if (id != this->mId) { - this->mId = id; - emit this->idChanged(); - } + Qt::beginPropertyUpdateGroup(); + this->bId = object.value("id").value(); + this->bName = object.value("name").value(); + this->bDescription = object.value("description").value(); + this->bX = object.value("x").value(); + this->bY = object.value("y").value(); + this->bWidth = object.value("width").value(); + this->bHeight = object.value("height").value(); + this->bScale = object.value("scale").value(); + Qt::endPropertyUpdateGroup(); - if (name != this->mName) { - this->mName = std::move(name); - emit this->nameChanged(); - } - - if (description != this->mDescription) { - this->mDescription = std::move(description); - emit this->descriptionChanged(); - } - - if (x != this->mX) { - this->mX = x; - emit this->xChanged(); - } - - if (y != this->mY) { - this->mY = y; - emit this->yChanged(); - } - - if (width != this->mWidth) { - this->mWidth = width; - emit this->widthChanged(); - } - - if (height != this->mHeight) { - this->mHeight = height; - emit this->heightChanged(); - } - - if (scale != this->mScale) { - this->mScale = scale; - emit this->scaleChanged(); - } - - if (this->mActiveWorkspace == nullptr || this->mActiveWorkspace->name() != activeWorkspaceName) { + if (this->mActiveWorkspace == nullptr + || this->mActiveWorkspace->bindableName().value() != activeWorkspaceName) + { auto* workspace = this->ipc->findWorkspaceByName(activeWorkspaceName, true, activeWorkspaceId); workspace->setMonitor(this); this->setActiveWorkspace(workspace); diff --git a/src/wayland/hyprland/ipc/monitor.hpp b/src/wayland/hyprland/ipc/monitor.hpp index c16777c7..974fcbfc 100644 --- a/src/wayland/hyprland/ipc/monitor.hpp +++ b/src/wayland/hyprland/ipc/monitor.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -14,14 +15,14 @@ namespace qs::hyprland::ipc { class HyprlandMonitor: public QObject { Q_OBJECT; // clang-format off - Q_PROPERTY(qint32 id READ id NOTIFY idChanged); - Q_PROPERTY(QString name READ name NOTIFY nameChanged); - Q_PROPERTY(QString description READ description NOTIFY descriptionChanged); - Q_PROPERTY(qint32 x READ x NOTIFY xChanged); - Q_PROPERTY(qint32 y READ y NOTIFY yChanged); - Q_PROPERTY(qint32 width READ width NOTIFY widthChanged); - Q_PROPERTY(qint32 height READ height NOTIFY heightChanged); - Q_PROPERTY(qreal scale READ scale NOTIFY scaleChanged); + Q_PROPERTY(qint32 id READ default NOTIFY idChanged BINDABLE bindableId); + Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName); + Q_PROPERTY(QString description READ default NOTIFY descriptionChanged BINDABLE bindableDescription); + Q_PROPERTY(qint32 x READ default NOTIFY xChanged BINDABLE bindableX); + Q_PROPERTY(qint32 y READ default NOTIFY yChanged BINDABLE bindableY); + Q_PROPERTY(qint32 width READ default NOTIFY widthChanged BINDABLE bindableWidth); + Q_PROPERTY(qint32 height READ default NOTIFY heightChanged BINDABLE bindableHeight); + Q_PROPERTY(qreal scale READ default NOTIFY scaleChanged BINDABLE bindableScale); /// Last json returned for this monitor, as a javascript object. /// /// > [!WARNING] This is *not* updated unless the monitor object is fetched again from @@ -37,17 +38,18 @@ class HyprlandMonitor: public QObject { public: explicit HyprlandMonitor(HyprlandIpc* ipc): QObject(ipc), ipc(ipc) {} - void updateInitial(qint32 id, QString name, QString description); + void updateInitial(qint32 id, const QString& name, const QString& description); void updateFromObject(QVariantMap object); - [[nodiscard]] qint32 id() const; - [[nodiscard]] QString name() const; - [[nodiscard]] QString description() const; - [[nodiscard]] qint32 x() const; - [[nodiscard]] qint32 y() const; - [[nodiscard]] qint32 width() const; - [[nodiscard]] qint32 height() const; - [[nodiscard]] qreal scale() const; + [[nodiscard]] QBindable bindableId() { return &this->bId; } + [[nodiscard]] QBindable bindableName() { return &this->bName; } + [[nodiscard]] QBindable bindableDescription() { return &this->bDescription; } + [[nodiscard]] QBindable bindableX() { return &this->bX; } + [[nodiscard]] QBindable bindableY() { return &this->bY; } + [[nodiscard]] QBindable bindableWidth() { return &this->bWidth; } + [[nodiscard]] QBindable bindableHeight() { return &this->bHeight; } + [[nodiscard]] QBindable bindableScale() { return &this->bScale; } + [[nodiscard]] QVariantMap lastIpcObject() const; void setActiveWorkspace(HyprlandWorkspace* workspace); @@ -71,17 +73,19 @@ private slots: private: HyprlandIpc* ipc; - qint32 mId = -1; - QString mName; - QString mDescription; - qint32 mX = 0; - qint32 mY = 0; - qint32 mWidth = 0; - qint32 mHeight = 0; - qreal mScale = 0; QVariantMap mLastIpcObject; - HyprlandWorkspace* mActiveWorkspace = nullptr; + + // clang-format off + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(HyprlandMonitor, qint32, bId, -1, &HyprlandMonitor::idChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, QString, bName, &HyprlandMonitor::nameChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, QString, bDescription, &HyprlandMonitor::descriptionChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qint32, bX, &HyprlandMonitor::xChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qint32, bY, &HyprlandMonitor::yChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qint32, bWidth, &HyprlandMonitor::widthChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qint32, bHeight, &HyprlandMonitor::heightChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qreal, bScale, &HyprlandMonitor::scaleChanged); + // clang-format on }; } // namespace qs::hyprland::ipc diff --git a/src/wayland/hyprland/ipc/workspace.cpp b/src/wayland/hyprland/ipc/workspace.cpp index 428edd6b..f0cda668 100644 --- a/src/wayland/hyprland/ipc/workspace.cpp +++ b/src/wayland/hyprland/ipc/workspace.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -10,52 +11,34 @@ namespace qs::hyprland::ipc { -qint32 HyprlandWorkspace::id() const { return this->mId; } - -QString HyprlandWorkspace::name() const { return this->mName; } - -void HyprlandWorkspace::setName(QString name) { - if (name == this->mName) return; - this->mName = std::move(name); - emit this->nameChanged(); -} - QVariantMap HyprlandWorkspace::lastIpcObject() const { return this->mLastIpcObject; } -void HyprlandWorkspace::updateInitial(qint32 id, QString name) { - if (id != this->mId) { - this->mId = id; - emit this->idChanged(); - } - - if (name != this->mName) { - this->mName = std::move(name); - emit this->nameChanged(); - } +void HyprlandWorkspace::updateInitial(qint32 id, const QString& name) { + Qt::beginPropertyUpdateGroup(); + this->bId = id; + this->bName = name; + Qt::endPropertyUpdateGroup(); } void HyprlandWorkspace::updateFromObject(QVariantMap object) { - auto name = object.value("name").value(); auto monitorId = object.value("monitorID").value(); auto monitorName = object.value("monitor").value(); - auto initial = this->mId = -1; + auto initial = this->bId == -1; // ID cannot be updated after creation if (initial) { - this->mId = object.value("id").value(); - emit this->idChanged(); + this->bId = object.value("id").value(); } // No events we currently handle give a workspace id but not a name, // so we shouldn't set this if it isn't an initial query - if (initial && name != this->mName) { - this->mName = name; - emit this->nameChanged(); + if (initial) { + this->bName = object.value("name").value(); } if (!monitorName.isEmpty() - && (this->mMonitor == nullptr || this->mMonitor->name() != monitorName)) + && (this->mMonitor == nullptr || this->mMonitor->bindableName().value() != monitorName)) { auto* monitor = this->ipc->findMonitorByName(monitorName, true, monitorId); this->setMonitor(monitor); diff --git a/src/wayland/hyprland/ipc/workspace.hpp b/src/wayland/hyprland/ipc/workspace.hpp index 5eedfe22..51afcad1 100644 --- a/src/wayland/hyprland/ipc/workspace.hpp +++ b/src/wayland/hyprland/ipc/workspace.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -13,8 +14,8 @@ namespace qs::hyprland::ipc { class HyprlandWorkspace: public QObject { Q_OBJECT; - Q_PROPERTY(qint32 id READ id NOTIFY idChanged); - Q_PROPERTY(QString name READ name NOTIFY nameChanged); + Q_PROPERTY(qint32 id READ default NOTIFY idChanged BINDABLE bindableId); + Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName); /// Last json returned for this workspace, as a javascript object. /// /// > [!WARNING] This is *not* updated unless the workspace object is fetched again from @@ -28,13 +29,11 @@ class HyprlandWorkspace: public QObject { public: explicit HyprlandWorkspace(HyprlandIpc* ipc): QObject(ipc), ipc(ipc) {} - void updateInitial(qint32 id, QString name); + void updateInitial(qint32 id, const QString& name); void updateFromObject(QVariantMap object); - [[nodiscard]] qint32 id() const; - - [[nodiscard]] QString name() const; - void setName(QString name); + [[nodiscard]] QBindable bindableId() { return &this->bId; } + [[nodiscard]] QBindable bindableName() { return &this->bName; } [[nodiscard]] QVariantMap lastIpcObject() const; @@ -53,10 +52,13 @@ private slots: private: HyprlandIpc* ipc; - qint32 mId = -1; - QString mName; QVariantMap mLastIpcObject; HyprlandMonitor* mMonitor = nullptr; + + // clang-format off + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(HyprlandWorkspace, qint32, bId, -1, &HyprlandWorkspace::idChanged); + Q_OBJECT_BINDABLE_PROPERTY(HyprlandWorkspace, QString, bName, &HyprlandWorkspace::nameChanged); + // clang-format on }; } // namespace qs::hyprland::ipc