diff --git a/src/x11/i3/ipc/connection.cpp b/src/x11/i3/ipc/connection.cpp index d737f77..9193cd9 100644 --- a/src/x11/i3/ipc/connection.cpp +++ b/src/x11/i3/ipc/connection.cpp @@ -190,7 +190,7 @@ void I3Ipc::setFocusedWorkspace(I3Workspace* workspace) { if (workspace == this->mFocusedWorkspace) return; if (this->mFocusedWorkspace != nullptr) { - this->mFocusedWorkspace->setFocus(false); + this->mFocusedWorkspace->bindableFocused().setValue(false); QObject::disconnect(this->mFocusedWorkspace, nullptr, this, nullptr); } @@ -202,7 +202,7 @@ void I3Ipc::setFocusedWorkspace(I3Workspace* workspace) { } QObject::connect(workspace, &QObject::destroyed, this, &I3Ipc::onFocusedWorkspaceDestroyed); - workspace->setFocus(true); + workspace->bindableFocused().setValue(true); this->setFocusedMonitor(workspace->monitor()); } @@ -213,14 +213,14 @@ void I3Ipc::setFocusedMonitor(I3Monitor* monitor) { if (monitor == this->mFocusedMonitor) return; if (this->mFocusedMonitor != nullptr) { - this->mFocusedMonitor->setFocus(false); + this->mFocusedMonitor->bindableFocused().setValue(false); QObject::disconnect(this->mFocusedMonitor, nullptr, this, nullptr); } this->mFocusedMonitor = monitor; if (monitor != nullptr) { - monitor->setFocus(true); + monitor->bindableFocused().setValue(true); QObject::connect(monitor, &QObject::destroyed, this, &I3Ipc::onFocusedMonitorDestroyed); } @@ -264,8 +264,9 @@ void I3Ipc::handleGetWorkspacesEvent(I3IpcEvent* event) { auto object = entry.toObject().toVariantMap(); auto name = object["name"].toString(); - auto workspaceIter = - std::ranges::find_if(mList, [name](const I3Workspace* m) { return m->name() == name; }); + auto workspaceIter = std::ranges::find_if(mList, [name](I3Workspace* m) { + return m->bindableName().value() == name; + }); auto* workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter; auto existed = workspace != nullptr; @@ -276,7 +277,7 @@ void I3Ipc::handleGetWorkspacesEvent(I3IpcEvent* event) { workspace->updateFromObject(object); - if (workspace->focused()) { + if (workspace->bindableFocused().value()) { this->setFocusedWorkspace(workspace); } @@ -290,7 +291,7 @@ void I3Ipc::handleGetWorkspacesEvent(I3IpcEvent* event) { auto removedWorkspaces = QVector<I3Workspace*>(); for (auto* workspace: mList) { - if (!names.contains(workspace->name())) { + if (!names.contains(workspace->bindableName().value())) { removedWorkspaces.push_back(workspace); } } @@ -320,8 +321,9 @@ void I3Ipc::handleGetOutputsEvent(I3IpcEvent* event) { auto object = elem.toObject().toVariantMap(); auto name = object["name"].toString(); - auto monitorIter = - std::ranges::find_if(mList, [name](const I3Monitor* m) { return m->name() == name; }); + auto monitorIter = std::ranges::find_if(mList, [name](I3Monitor* m) { + return m->bindableName().value() == name; + }); auto* monitor = monitorIter == mList.end() ? nullptr : *monitorIter; auto existed = monitor != nullptr; @@ -332,7 +334,7 @@ void I3Ipc::handleGetOutputsEvent(I3IpcEvent* event) { monitor->updateFromObject(object); - if (monitor->focused()) { + if (monitor->bindableFocused().value()) { this->setFocusedMonitor(monitor); } @@ -346,7 +348,7 @@ void I3Ipc::handleGetOutputsEvent(I3IpcEvent* event) { auto removedMonitors = QVector<I3Monitor*>(); for (auto* monitor: mList) { - if (!names.contains(monitor->name())) { + if (!names.contains(monitor->bindableName().value())) { removedMonitors.push_back(monitor); } } @@ -413,7 +415,7 @@ void I3Ipc::handleWorkspaceEvent(I3IpcEvent* event) { if (!existed) { this->mWorkspaces.insertObject(workspace); - qCInfo(logI3Ipc) << "Added workspace" << workspace->name() << "to list"; + qCInfo(logI3Ipc) << "Added workspace" << workspace->bindableName().value() << "to list"; } } else if (change == "focus") { auto oldData = event->mData["old"]; @@ -441,7 +443,7 @@ void I3Ipc::handleWorkspaceEvent(I3IpcEvent* event) { auto* oldWorkspace = this->findWorkspaceByName(name); if (oldWorkspace != nullptr) { - qCInfo(logI3Ipc) << "Deleting" << oldWorkspace->id() << name; + qCInfo(logI3Ipc) << "Deleting" << oldWorkspace->bindableId().value() << name; if (this->mFocusedWorkspace == oldWorkspace) { this->setFocusedWorkspace(nullptr); @@ -480,23 +482,25 @@ I3Monitor* I3Ipc::monitorFor(QuickshellScreenInfo* screen) { I3Workspace* I3Ipc::findWorkspaceByID(qint32 id) { auto list = this->mWorkspaces.valueList(); auto workspaceIter = - std::ranges::find_if(list, [id](const I3Workspace* m) { return m->id() == id; }); + std::ranges::find_if(list, [id](I3Workspace* m) { return m->bindableId().value() == id; }); return workspaceIter == list.end() ? nullptr : *workspaceIter; } I3Workspace* I3Ipc::findWorkspaceByName(const QString& name) { auto list = this->mWorkspaces.valueList(); - auto workspaceIter = - std::ranges::find_if(list, [name](const I3Workspace* m) { return m->name() == name; }); + auto workspaceIter = std::ranges::find_if(list, [name](I3Workspace* m) { + return m->bindableName().value() == name; + }); return workspaceIter == list.end() ? nullptr : *workspaceIter; } I3Monitor* I3Ipc::findMonitorByName(const QString& name) { auto list = this->mMonitors.valueList(); - auto monitorIter = - std::ranges::find_if(list, [name](const I3Monitor* m) { return m->name() == name; }); + auto monitorIter = std::ranges::find_if(list, [name](I3Monitor* m) { + return m->bindableName().value() == name; + }); return monitorIter == list.end() ? nullptr : *monitorIter; } diff --git a/src/x11/i3/ipc/monitor.cpp b/src/x11/i3/ipc/monitor.cpp index de54e0c..528d695 100644 --- a/src/x11/i3/ipc/monitor.cpp +++ b/src/x11/i3/ipc/monitor.cpp @@ -1,6 +1,7 @@ #include "monitor.hpp" #include <qcontainerfwd.h> +#include <qproperty.h> #include <qstring.h> #include <qtmetamacros.h> #include <qtypes.h> @@ -9,45 +10,24 @@ namespace qs::i3::ipc { -qint32 I3Monitor::id() const { return this->mId; }; -QString I3Monitor::name() const { return this->mName; }; -bool I3Monitor::power() const { return this->mPower; }; I3Workspace* I3Monitor::focusedWorkspace() const { return this->mFocusedWorkspace; }; -qint32 I3Monitor::x() const { return this->mX; }; -qint32 I3Monitor::y() const { return this->mY; }; -qint32 I3Monitor::width() const { return this->mWidth; }; -qint32 I3Monitor::height() const { return this->mHeight; }; -qreal I3Monitor::scale() const { return this->mScale; }; -bool I3Monitor::focused() const { return this->mFocused; }; QVariantMap I3Monitor::lastIpcObject() const { return this->mLastIpcObject; }; void I3Monitor::updateFromObject(const QVariantMap& obj) { - auto id = obj.value("id").value<qint32>(); - auto name = obj.value("name").value<QString>(); - auto power = obj.value("power").value<bool>(); auto activeWorkspaceId = obj.value("current_workspace").value<QString>(); auto rect = obj.value("rect").toMap(); - auto x = rect.value("x").value<qint32>(); - auto y = rect.value("y").value<qint32>(); - auto width = rect.value("width").value<qint32>(); - auto height = rect.value("height").value<qint32>(); - auto scale = obj.value("scale").value<qreal>(); - auto focused = obj.value("focused").value<bool>(); - if (id != this->mId) { - this->mId = id; - emit this->idChanged(); - } - - if (name != this->mName) { - this->mName = name; - emit this->nameChanged(); - } - - if (power != this->mPower) { - this->mPower = power; - this->powerChanged(); - } + Qt::beginPropertyUpdateGroup(); + this->bId = obj.value("id").value<qint32>(); + this->bName = obj.value("name").value<QString>(); + this->bPower = obj.value("power").value<bool>(); + this->bX = rect.value("x").value<qint32>(); + this->bY = rect.value("y").value<qint32>(); + this->bWidth = rect.value("width").value<qint32>(); + this->bHeight = rect.value("height").value<qint32>(); + this->bScale = obj.value("scale").value<qreal>(); + this->bFocused = obj.value("focused").value<bool>(); + Qt::endPropertyUpdateGroup(); if (activeWorkspaceId != this->mFocusedWorkspaceName) { auto* workspace = this->ipc->findWorkspaceByName(activeWorkspaceId); @@ -61,50 +41,15 @@ void I3Monitor::updateFromObject(const QVariantMap& obj) { emit this->focusedWorkspaceChanged(); }; - 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 (focused != this->mFocused) { - this->mFocused = focused; - emit this->focusedChanged(); - } - if (obj != this->mLastIpcObject) { this->mLastIpcObject = obj; emit this->lastIpcObjectChanged(); } } -void I3Monitor::setFocus(bool focused) { - this->mFocused = focused; - emit this->focusedChanged(); -} - void I3Monitor::setFocusedWorkspace(I3Workspace* workspace) { this->mFocusedWorkspace = workspace; - this->mFocusedWorkspaceName = workspace->name(); + this->mFocusedWorkspaceName = workspace->bindableName().value(); emit this->focusedWorkspaceChanged(); }; diff --git a/src/x11/i3/ipc/monitor.hpp b/src/x11/i3/ipc/monitor.hpp index 2ca8913..d0c4bd1 100644 --- a/src/x11/i3/ipc/monitor.hpp +++ b/src/x11/i3/ipc/monitor.hpp @@ -1,6 +1,7 @@ #pragma once #include <qobject.h> +#include <qproperty.h> #include "connection.hpp" @@ -11,25 +12,25 @@ class I3Monitor: public QObject { Q_OBJECT; // clang-format off /// The ID of this monitor - Q_PROPERTY(qint32 id READ id NOTIFY idChanged); + Q_PROPERTY(qint32 id READ default NOTIFY idChanged BINDABLE bindableId); /// The name of this monitor - Q_PROPERTY(QString name READ name NOTIFY nameChanged); + Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName); /// Wether this monitor is turned on or not - Q_PROPERTY(bool power READ power NOTIFY powerChanged); + Q_PROPERTY(bool power READ default NOTIFY powerChanged BINDABLE bindablePower); /// The current workspace Q_PROPERTY(qs::i3::ipc::I3Workspace* focusedWorkspace READ focusedWorkspace NOTIFY focusedWorkspaceChanged); /// The X coordinate of this monitor inside the monitor layout - Q_PROPERTY(qint32 x READ x NOTIFY xChanged); + Q_PROPERTY(qint32 x READ default NOTIFY xChanged BINDABLE bindableX); /// The Y coordinate of this monitor inside the monitor layout - Q_PROPERTY(qint32 y READ y NOTIFY yChanged); + Q_PROPERTY(qint32 y READ default NOTIFY yChanged BINDABLE bindableY); /// The width in pixels of this monitor - Q_PROPERTY(qint32 width READ width NOTIFY widthChanged); + Q_PROPERTY(qint32 width READ default NOTIFY widthChanged BINDABLE bindableWidth); /// The height in pixels of this monitor - Q_PROPERTY(qint32 height READ height NOTIFY heightChanged); + Q_PROPERTY(qint32 height READ default NOTIFY heightChanged BINDABLE bindableHeight); /// The scaling factor of this monitor, 1 means it runs at native resolution - Q_PROPERTY(qreal scale READ scale NOTIFY scaleChanged); + Q_PROPERTY(qreal scale READ default NOTIFY scaleChanged BINDABLE bindableScale); /// Whether this monitor is currently in focus - Q_PROPERTY(bool focused READ focused NOTIFY focusedChanged); + Q_PROPERTY(bool focused READ default NOTIFY focusedChanged BINDABLE bindableFocused); /// Last JSON returned for this monitor, as a JavaScript object. /// /// This updates every time Quickshell receives an `output` event from i3/Sway @@ -41,22 +42,23 @@ class I3Monitor: public QObject { public: explicit I3Monitor(I3Ipc* ipc): QObject(ipc), ipc(ipc) {} - [[nodiscard]] qint32 id() const; - [[nodiscard]] QString name() const; - [[nodiscard]] bool power() const; + [[nodiscard]] QBindable<qint32> bindableId() { return &this->bId; } + [[nodiscard]] QBindable<QString> bindableName() { return &this->bName; } + [[nodiscard]] QBindable<bool> bindablePower() { return &this->bPower; } + [[nodiscard]] QBindable<qint32> bindableX() { return &this->bX; } + [[nodiscard]] QBindable<qint32> bindableY() { return &this->bY; } + [[nodiscard]] QBindable<qint32> bindableWidth() { return &this->bWidth; } + [[nodiscard]] QBindable<qint32> bindableHeight() { return &this->bHeight; } + [[nodiscard]] QBindable<qreal> bindableScale() { return &this->bScale; } + [[nodiscard]] QBindable<bool> bindableFocused() { return &this->bFocused; } + [[nodiscard]] I3Workspace* focusedWorkspace() const; - [[nodiscard]] qint32 x() const; - [[nodiscard]] qint32 y() const; - [[nodiscard]] qint32 width() const; - [[nodiscard]] qint32 height() const; - [[nodiscard]] qreal scale() const; - [[nodiscard]] bool focused() const; [[nodiscard]] QVariantMap lastIpcObject() const; void updateFromObject(const QVariantMap& obj); void setFocusedWorkspace(I3Workspace* workspace); - void setFocus(bool focus); + signals: void idChanged(); void nameChanged(); @@ -73,19 +75,19 @@ signals: private: I3Ipc* ipc; - qint32 mId = -1; - QString mName; - bool mPower = false; - qint32 mX = 0; - qint32 mY = 0; - qint32 mWidth = 0; - qint32 mHeight = 0; - qreal mScale = 1; - bool mFocused = false; QVariantMap mLastIpcObject; - I3Workspace* mFocusedWorkspace = nullptr; QString mFocusedWorkspaceName; // use for faster change detection + + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(I3Monitor, qint32, bId, -1, &I3Monitor::idChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, QString, bName, &I3Monitor::nameChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, bool, bPower, &I3Monitor::powerChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, qint32, bX, &I3Monitor::xChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, qint32, bY, &I3Monitor::yChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, qint32, bWidth, &I3Monitor::widthChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, qint32, bHeight, &I3Monitor::heightChanged); + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(I3Monitor, qreal, bScale, 1, &I3Monitor::scaleChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, bool, bFocused, &I3Monitor::focusedChanged); }; } // namespace qs::i3::ipc diff --git a/src/x11/i3/ipc/workspace.cpp b/src/x11/i3/ipc/workspace.cpp index 19c9edf..b1171e2 100644 --- a/src/x11/i3/ipc/workspace.cpp +++ b/src/x11/i3/ipc/workspace.cpp @@ -1,6 +1,7 @@ #include "workspace.hpp" #include <qcontainerfwd.h> +#include <qproperty.h> #include <qstring.h> #include <qtmetamacros.h> #include <qtypes.h> @@ -9,47 +10,20 @@ namespace qs::i3::ipc { -qint32 I3Workspace ::id() const { return this->mId; } -QString I3Workspace::name() const { return this->mName; } -qint32 I3Workspace ::num() const { return this->mNum; } -bool I3Workspace ::urgent() const { return this->mUrgent; } -bool I3Workspace::focused() const { return this->mFocused; } I3Monitor* I3Workspace::monitor() const { return this->mMonitor; } QVariantMap I3Workspace::lastIpcObject() const { return this->mLastIpcObject; } void I3Workspace::updateFromObject(const QVariantMap& obj) { - auto id = obj.value("id").value<qint32>(); - auto name = obj.value("name").value<QString>(); - auto num = obj.value("num").value<qint32>(); - auto urgent = obj.value("urgent").value<bool>(); - auto focused = obj.value("focused").value<bool>(); + Qt::beginPropertyUpdateGroup(); + this->bId = obj.value("id").value<qint32>(); + this->bName = obj.value("name").value<QString>(); + this->bNum = obj.value("num").value<qint32>(); + this->bUrgent = obj.value("urgent").value<bool>(); + this->bFocused = obj.value("focused").value<bool>(); + Qt::endPropertyUpdateGroup(); + auto monitorName = obj.value("output").value<QString>(); - if (id != this->mId) { - this->mId = id; - emit this->idChanged(); - } - - if (name != this->mName) { - this->mName = name; - emit this->nameChanged(); - } - - if (num != this->mNum) { - this->mNum = num; - emit this->numChanged(); - } - - if (urgent != this->mUrgent) { - this->mUrgent = urgent; - emit this->urgentChanged(); - } - - if (focused != this->mFocused) { - this->mFocused = focused; - emit this->focusedChanged(); - } - if (obj != this->mLastIpcObject) { this->mLastIpcObject = obj; emit this->lastIpcObjectChanged(); @@ -68,6 +42,4 @@ void I3Workspace::updateFromObject(const QVariantMap& obj) { } } -void I3Workspace::setFocus(bool focus) { this->mFocused = focus; } - } // namespace qs::i3::ipc diff --git a/src/x11/i3/ipc/workspace.hpp b/src/x11/i3/ipc/workspace.hpp index 6df8c8b..68b0ec4 100644 --- a/src/x11/i3/ipc/workspace.hpp +++ b/src/x11/i3/ipc/workspace.hpp @@ -1,5 +1,9 @@ #pragma once +#include <qcontainerfwd.h> +#include <qproperty.h> +#include <qtypes.h> + #include "connection.hpp" namespace qs::i3::ipc { @@ -9,19 +13,19 @@ class I3Workspace: public QObject { Q_OBJECT; /// The ID of this workspace, it is unique for i3/Sway launch - Q_PROPERTY(qint32 id READ id NOTIFY idChanged); + Q_PROPERTY(qint32 id READ default NOTIFY idChanged BINDABLE bindableId); /// The name of this workspace - Q_PROPERTY(QString name READ name NOTIFY nameChanged); + Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName); /// The number of this workspace - Q_PROPERTY(qint32 num READ num NOTIFY numChanged); + Q_PROPERTY(qint32 num READ default NOTIFY numChanged BINDABLE bindableNum); /// If a window in this workspace has an urgent notification - Q_PROPERTY(bool urgent READ urgent NOTIFY urgentChanged); + Q_PROPERTY(bool urgent READ default NOTIFY urgentChanged BINDABLE bindableUrgent); /// If this workspace is the one currently in focus - Q_PROPERTY(bool focused READ focused NOTIFY focusedChanged); + Q_PROPERTY(bool focused READ default NOTIFY focusedChanged BINDABLE bindableFocused); /// The monitor this workspace is being displayed on Q_PROPERTY(qs::i3::ipc::I3Monitor* monitor READ monitor NOTIFY monitorChanged); @@ -37,16 +41,15 @@ class I3Workspace: public QObject { public: I3Workspace(qs::i3::ipc::I3Ipc* ipc): QObject(ipc), ipc(ipc) {} - [[nodiscard]] qint32 id() const; - [[nodiscard]] QString name() const; - [[nodiscard]] qint32 num() const; - [[nodiscard]] bool urgent() const; - [[nodiscard]] bool focused() const; + [[nodiscard]] QBindable<qint32> bindableId() { return &this->bId; } + [[nodiscard]] QBindable<QString> bindableName() { return &this->bName; } + [[nodiscard]] QBindable<qint32> bindableNum() { return &this->bNum; } + [[nodiscard]] QBindable<bool> bindableFocused() { return &this->bFocused; } + [[nodiscard]] QBindable<bool> bindableUrgent() { return &this->bUrgent; } [[nodiscard]] I3Monitor* monitor() const; [[nodiscard]] QVariantMap lastIpcObject() const; void updateFromObject(const QVariantMap& obj); - void setFocus(bool focus); signals: void idChanged(); @@ -60,14 +63,14 @@ signals: private: I3Ipc* ipc; - qint32 mId = -1; - QString mName; - qint32 mNum = -1; - bool mFocused = false; - bool mUrgent = false; - QVariantMap mLastIpcObject; I3Monitor* mMonitor = nullptr; QString mMonitorName; + + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(I3Workspace, qint32, bId, -1, &I3Workspace::idChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, QString, bName, &I3Workspace::nameChanged); + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(I3Workspace, qint32, bNum, -1, &I3Workspace::numChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, bool, bFocused, &I3Workspace::focusedChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, bool, bUrgent, &I3Workspace::urgentChanged); }; } // namespace qs::i3::ipc