diff --git a/src/x11/i3/ipc/connection.cpp b/src/x11/i3/ipc/connection.cpp index 9193cd9f..1939fb5b 100644 --- a/src/x11/i3/ipc/connection.cpp +++ b/src/x11/i3/ipc/connection.cpp @@ -73,6 +73,11 @@ I3Ipc::I3Ipc() { } } + this->bFocusedWorkspace.setBinding([this]() -> I3Workspace* { + if (!this->bFocusedMonitor) return nullptr; + return this->bFocusedMonitor->bindableActiveWorkspace().value(); + }); + this->mSocketPath = sock; // clang-format off @@ -183,59 +188,23 @@ void I3Ipc::eventSocketStateChanged(QLocalSocket::LocalSocketState state) { } QString I3Ipc::socketPath() const { return this->mSocketPath; } -I3Workspace* I3Ipc::focusedWorkspace() const { return this->mFocusedWorkspace; } -I3Monitor* I3Ipc::focusedMonitor() const { return this->mFocusedMonitor; } - -void I3Ipc::setFocusedWorkspace(I3Workspace* workspace) { - if (workspace == this->mFocusedWorkspace) return; - - if (this->mFocusedWorkspace != nullptr) { - this->mFocusedWorkspace->bindableFocused().setValue(false); - QObject::disconnect(this->mFocusedWorkspace, nullptr, this, nullptr); - } - - this->mFocusedWorkspace = workspace; - - if (workspace != nullptr) { - if (auto* monitor = this->mFocusedWorkspace->monitor()) { - monitor->setFocusedWorkspace(this->mFocusedWorkspace); - } - - QObject::connect(workspace, &QObject::destroyed, this, &I3Ipc::onFocusedWorkspaceDestroyed); - workspace->bindableFocused().setValue(true); - this->setFocusedMonitor(workspace->monitor()); - } - - emit this->focusedWorkspaceChanged(); -} void I3Ipc::setFocusedMonitor(I3Monitor* monitor) { - if (monitor == this->mFocusedMonitor) return; + auto* oldMonitor = this->bFocusedMonitor.value(); + if (monitor == oldMonitor) return; - if (this->mFocusedMonitor != nullptr) { - this->mFocusedMonitor->bindableFocused().setValue(false); - QObject::disconnect(this->mFocusedMonitor, nullptr, this, nullptr); + if (oldMonitor != nullptr) { + QObject::disconnect(oldMonitor, nullptr, this, nullptr); } - this->mFocusedMonitor = monitor; - if (monitor != nullptr) { - monitor->bindableFocused().setValue(true); QObject::connect(monitor, &QObject::destroyed, this, &I3Ipc::onFocusedMonitorDestroyed); } - emit this->focusedMonitorChanged(); + this->bFocusedMonitor = monitor; } -void I3Ipc::onFocusedWorkspaceDestroyed() { - this->mFocusedWorkspace = nullptr; - emit this->focusedWorkspaceChanged(); -} - -void I3Ipc::onFocusedMonitorDestroyed() { - this->mFocusedMonitor = nullptr; - emit this->focusedMonitorChanged(); -} +void I3Ipc::onFocusedMonitorDestroyed() { this->bFocusedMonitor = nullptr; } I3Ipc* I3Ipc::instance() { static I3Ipc* instance = nullptr; // NOLINT @@ -277,10 +246,6 @@ void I3Ipc::handleGetWorkspacesEvent(I3IpcEvent* event) { workspace->updateFromObject(object); - if (workspace->bindableFocused().value()) { - this->setFocusedWorkspace(workspace); - } - if (!existed) { this->mWorkspaces.insertObject(workspace); } @@ -436,7 +401,12 @@ void I3Ipc::handleWorkspaceEvent(I3IpcEvent* event) { } newWorkspace->updateFromObject(newData.toObject().toVariantMap()); - this->setFocusedWorkspace(newWorkspace); + + if (newWorkspace->bindableMonitor().value()) { + auto* monitor = newWorkspace->bindableMonitor().value(); + monitor->setFocusedWorkspace(newWorkspace); + this->bFocusedMonitor = monitor; + } } else if (change == "empty") { auto name = event->mData["current"]["name"].toString(); @@ -445,8 +415,8 @@ void I3Ipc::handleWorkspaceEvent(I3IpcEvent* event) { if (oldWorkspace != nullptr) { qCInfo(logI3Ipc) << "Deleting" << oldWorkspace->bindableId().value() << name; - if (this->mFocusedWorkspace == oldWorkspace) { - this->setFocusedWorkspace(nullptr); + if (this->bFocusedWorkspace == oldWorkspace) { + this->bFocusedMonitor->setFocusedWorkspace(nullptr); } this->workspaces()->removeObject(oldWorkspace); diff --git a/src/x11/i3/ipc/connection.hpp b/src/x11/i3/ipc/connection.hpp index 04cccc2c..c8f61661 100644 --- a/src/x11/i3/ipc/connection.hpp +++ b/src/x11/i3/ipc/connection.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -91,7 +92,6 @@ public: I3Monitor* findMonitorByName(const QString& name); I3Workspace* findWorkspaceByID(qint32 id); - void setFocusedWorkspace(I3Workspace* workspace); void setFocusedMonitor(I3Monitor* monitor); void refreshWorkspaces(); @@ -99,8 +99,14 @@ public: I3Monitor* monitorFor(QuickshellScreenInfo* screen); - [[nodiscard]] I3Monitor* focusedMonitor() const; - [[nodiscard]] I3Workspace* focusedWorkspace() const; + [[nodiscard]] QBindable bindableFocusedMonitor() const { + return &this->bFocusedMonitor; + }; + + [[nodiscard]] QBindable bindableFocusedWorkspace() const { + return &this->bFocusedWorkspace; + }; + [[nodiscard]] ObjectModel* monitors(); [[nodiscard]] ObjectModel* workspaces(); signals: @@ -115,7 +121,6 @@ private slots: void eventSocketReady(); void subscribe(); - void onFocusedWorkspaceDestroyed(); void onFocusedMonitorDestroyed(); private: @@ -144,8 +149,14 @@ private: I3IpcEvent event {this}; - I3Workspace* mFocusedWorkspace = nullptr; - I3Monitor* mFocusedMonitor = nullptr; + Q_OBJECT_BINDABLE_PROPERTY(I3Ipc, I3Monitor*, bFocusedMonitor, &I3Ipc::focusedMonitorChanged); + + Q_OBJECT_BINDABLE_PROPERTY( + I3Ipc, + I3Workspace*, + bFocusedWorkspace, + &I3Ipc::focusedWorkspaceChanged + ); }; } // namespace qs::i3::ipc diff --git a/src/x11/i3/ipc/monitor.cpp b/src/x11/i3/ipc/monitor.cpp index 528d6951..0098f63a 100644 --- a/src/x11/i3/ipc/monitor.cpp +++ b/src/x11/i3/ipc/monitor.cpp @@ -1,23 +1,36 @@ #include "monitor.hpp" #include +#include #include #include #include #include +#include "connection.hpp" #include "workspace.hpp" namespace qs::i3::ipc { -I3Workspace* I3Monitor::focusedWorkspace() const { return this->mFocusedWorkspace; }; +I3Monitor::I3Monitor(I3Ipc* ipc): QObject(ipc), ipc(ipc) { + // clang-format off + this->bFocused.setBinding([this]() { return this->ipc->bindableFocusedMonitor().value() == this; }); + // clang-format on +} + QVariantMap I3Monitor::lastIpcObject() const { return this->mLastIpcObject; }; void I3Monitor::updateFromObject(const QVariantMap& obj) { - auto activeWorkspaceId = obj.value("current_workspace").value(); + if (obj != this->mLastIpcObject) { + this->mLastIpcObject = obj; + emit this->lastIpcObjectChanged(); + } + + auto activeWorkspaceName = obj.value("current_workspace").value(); auto rect = obj.value("rect").toMap(); Qt::beginPropertyUpdateGroup(); + this->bId = obj.value("id").value(); this->bName = obj.value("name").value(); this->bPower = obj.value("power").value(); @@ -26,31 +39,21 @@ void I3Monitor::updateFromObject(const QVariantMap& obj) { this->bWidth = rect.value("width").value(); this->bHeight = rect.value("height").value(); this->bScale = obj.value("scale").value(); - this->bFocused = obj.value("focused").value(); - Qt::endPropertyUpdateGroup(); - if (activeWorkspaceId != this->mFocusedWorkspaceName) { - auto* workspace = this->ipc->findWorkspaceByName(activeWorkspaceId); - if (activeWorkspaceId.isEmpty() || workspace == nullptr) { // is null when output is disabled - this->mFocusedWorkspace = nullptr; - this->mFocusedWorkspaceName = ""; + if (!this->bActiveWorkspace + || activeWorkspaceName != this->bActiveWorkspace->bindableName().value()) + { + auto* workspace = this->ipc->findWorkspaceByName(activeWorkspaceName); + if (activeWorkspaceName.isEmpty() || workspace == nullptr) { // is null when output is disabled + this->bActiveWorkspace = nullptr; } else { - this->mFocusedWorkspaceName = activeWorkspaceId; - this->mFocusedWorkspace = workspace; + this->bActiveWorkspace = workspace; } - emit this->focusedWorkspaceChanged(); }; - if (obj != this->mLastIpcObject) { - this->mLastIpcObject = obj; - emit this->lastIpcObjectChanged(); - } + Qt::endPropertyUpdateGroup(); } -void I3Monitor::setFocusedWorkspace(I3Workspace* workspace) { - this->mFocusedWorkspace = workspace; - this->mFocusedWorkspaceName = workspace->bindableName().value(); - emit this->focusedWorkspaceChanged(); -}; +void I3Monitor::setFocusedWorkspace(I3Workspace* workspace) { this->bActiveWorkspace = workspace; }; } // namespace qs::i3::ipc diff --git a/src/x11/i3/ipc/monitor.hpp b/src/x11/i3/ipc/monitor.hpp index d0c4bd19..d184235f 100644 --- a/src/x11/i3/ipc/monitor.hpp +++ b/src/x11/i3/ipc/monitor.hpp @@ -17,8 +17,10 @@ class I3Monitor: public QObject { Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName); /// Wether this monitor is turned on or not 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 currently active workspace on this monitor, May be null. + Q_PROPERTY(qs::i3::ipc::I3Workspace* activeWorkspace READ default NOTIFY activeWorkspaceChanged BINDABLE bindableActiveWorkspace); + /// Deprecated: See @@activeWorkspace. + Q_PROPERTY(qs::i3::ipc::I3Workspace* focusedWorkspace READ default NOTIFY activeWorkspaceChanged BINDABLE bindableActiveWorkspace); /// The X coordinate of this monitor inside the monitor layout Q_PROPERTY(qint32 x READ default NOTIFY xChanged BINDABLE bindableX); /// The Y coordinate of this monitor inside the monitor layout @@ -40,7 +42,7 @@ class I3Monitor: public QObject { QML_UNCREATABLE("I3Monitors must be retrieved from the I3Ipc object."); public: - explicit I3Monitor(I3Ipc* ipc): QObject(ipc), ipc(ipc) {} + explicit I3Monitor(I3Ipc* ipc); [[nodiscard]] QBindable bindableId() { return &this->bId; } [[nodiscard]] QBindable bindableName() { return &this->bName; } @@ -52,7 +54,10 @@ public: [[nodiscard]] QBindable bindableScale() { return &this->bScale; } [[nodiscard]] QBindable bindableFocused() { return &this->bFocused; } - [[nodiscard]] I3Workspace* focusedWorkspace() const; + [[nodiscard]] QBindable bindableActiveWorkspace() { + return &this->bActiveWorkspace; + } + [[nodiscard]] QVariantMap lastIpcObject() const; void updateFromObject(const QVariantMap& obj); @@ -63,7 +68,7 @@ signals: void idChanged(); void nameChanged(); void powerChanged(); - void focusedWorkspaceChanged(); + void activeWorkspaceChanged(); void xChanged(); void yChanged(); void widthChanged(); @@ -76,9 +81,8 @@ private: I3Ipc* ipc; QVariantMap mLastIpcObject; - I3Workspace* mFocusedWorkspace = nullptr; - QString mFocusedWorkspaceName; // use for faster change detection + // clang-format off 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); @@ -88,6 +92,8 @@ private: 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); + Q_OBJECT_BINDABLE_PROPERTY(I3Monitor, I3Workspace*, bActiveWorkspace, &I3Monitor::activeWorkspaceChanged); + // clang-format on }; } // namespace qs::i3::ipc diff --git a/src/x11/i3/ipc/qml.cpp b/src/x11/i3/ipc/qml.cpp index d47cd8ee..28041612 100644 --- a/src/x11/i3/ipc/qml.cpp +++ b/src/x11/i3/ipc/qml.cpp @@ -1,6 +1,7 @@ #include "qml.hpp" #include +#include #include #include "../../../core/model.hpp" @@ -13,32 +14,28 @@ namespace qs::i3::ipc { I3IpcQml::I3IpcQml() { auto* instance = I3Ipc::instance(); + // clang-format off QObject::connect(instance, &I3Ipc::rawEvent, this, &I3IpcQml::rawEvent); QObject::connect(instance, &I3Ipc::connected, this, &I3IpcQml::connected); - QObject::connect( - instance, - &I3Ipc::focusedWorkspaceChanged, - this, - &I3IpcQml::focusedWorkspaceChanged - ); + QObject::connect(instance, &I3Ipc::focusedWorkspaceChanged, this, &I3IpcQml::focusedWorkspaceChanged); QObject::connect(instance, &I3Ipc::focusedMonitorChanged, this, &I3IpcQml::focusedMonitorChanged); + // clang-format on } void I3IpcQml::dispatch(const QString& request) { I3Ipc::instance()->dispatch(request); } - void I3IpcQml::refreshMonitors() { I3Ipc::instance()->refreshMonitors(); } - void I3IpcQml::refreshWorkspaces() { I3Ipc::instance()->refreshWorkspaces(); } - QString I3IpcQml::socketPath() { return I3Ipc::instance()->socketPath(); } - ObjectModel* I3IpcQml::monitors() { return I3Ipc::instance()->monitors(); } - ObjectModel* I3IpcQml::workspaces() { return I3Ipc::instance()->workspaces(); } -I3Workspace* I3IpcQml::focusedWorkspace() { return I3Ipc::instance()->focusedWorkspace(); } +QBindable I3IpcQml::bindableFocusedWorkspace() { + return I3Ipc::instance()->bindableFocusedWorkspace(); +} -I3Monitor* I3IpcQml::focusedMonitor() { return I3Ipc::instance()->focusedMonitor(); } +QBindable I3IpcQml::bindableFocusedMonitor() { + return I3Ipc::instance()->bindableFocusedMonitor(); +} I3Workspace* I3IpcQml::findWorkspaceByName(const QString& name) { return I3Ipc::instance()->findWorkspaceByName(name); diff --git a/src/x11/i3/ipc/qml.hpp b/src/x11/i3/ipc/qml.hpp index 732c829a..804e42a0 100644 --- a/src/x11/i3/ipc/qml.hpp +++ b/src/x11/i3/ipc/qml.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "../../../core/doc.hpp" #include "../../../core/qmlscreen.hpp" @@ -16,8 +17,8 @@ class I3IpcQml: public QObject { /// Path to the I3 socket Q_PROPERTY(QString socketPath READ socketPath CONSTANT); - Q_PROPERTY(qs::i3::ipc::I3Workspace* focusedWorkspace READ focusedWorkspace NOTIFY focusedWorkspaceChanged); - Q_PROPERTY(qs::i3::ipc::I3Monitor* focusedMonitor READ focusedMonitor NOTIFY focusedMonitorChanged); + Q_PROPERTY(qs::i3::ipc::I3Workspace* focusedWorkspace READ default NOTIFY focusedWorkspaceChanged BINDABLE bindableFocusedWorkspace); + Q_PROPERTY(qs::i3::ipc::I3Monitor* focusedMonitor READ default NOTIFY focusedMonitorChanged BINDABLE bindableFocusedMonitor); /// All I3 monitors. QSDOC_TYPE_OVERRIDE(ObjectModel*); Q_PROPERTY(UntypedObjectModel* monitors READ monitors CONSTANT); @@ -59,10 +60,10 @@ public: [[nodiscard]] static ObjectModel* workspaces(); /// The currently focused Workspace - [[nodiscard]] static I3Workspace* focusedWorkspace(); + [[nodiscard]] static QBindable bindableFocusedWorkspace(); /// The currently focused Monitor - [[nodiscard]] static I3Monitor* focusedMonitor(); + [[nodiscard]] static QBindable bindableFocusedMonitor(); signals: void rawEvent(I3IpcEvent* event); diff --git a/src/x11/i3/ipc/workspace.cpp b/src/x11/i3/ipc/workspace.cpp index b1171e2a..28fc0912 100644 --- a/src/x11/i3/ipc/workspace.cpp +++ b/src/x11/i3/ipc/workspace.cpp @@ -1,45 +1,62 @@ #include "workspace.hpp" #include +#include #include #include #include #include +#include "connection.hpp" #include "monitor.hpp" namespace qs::i3::ipc { -I3Monitor* I3Workspace::monitor() const { return this->mMonitor; } +I3Workspace::I3Workspace(I3Ipc* ipc): QObject(ipc), ipc(ipc) { + Qt::beginPropertyUpdateGroup(); + + this->bActive.setBinding([this]() { + return this->bMonitor.value() && this->bMonitor->bindableActiveWorkspace().value() == this; + }); + + this->bFocused.setBinding([this]() { + return this->ipc->bindableFocusedWorkspace().value() == this; + }); + + Qt::endPropertyUpdateGroup(); +} + QVariantMap I3Workspace::lastIpcObject() const { return this->mLastIpcObject; } void I3Workspace::updateFromObject(const QVariantMap& obj) { - Qt::beginPropertyUpdateGroup(); - this->bId = obj.value("id").value(); - this->bName = obj.value("name").value(); - this->bNum = obj.value("num").value(); - this->bUrgent = obj.value("urgent").value(); - this->bFocused = obj.value("focused").value(); - Qt::endPropertyUpdateGroup(); - - auto monitorName = obj.value("output").value(); - if (obj != this->mLastIpcObject) { this->mLastIpcObject = obj; emit this->lastIpcObjectChanged(); } - if (monitorName != this->mMonitorName) { + Qt::beginPropertyUpdateGroup(); + + this->bId = obj.value("id").value(); + this->bName = obj.value("name").value(); + this->bNumber = obj.value("num").value(); + this->bUrgent = obj.value("urgent").value(); + + auto monitorName = obj.value("output").value(); + + if (!this->bMonitor || monitorName != this->bMonitor->bindableName().value()) { auto* monitor = this->ipc->findMonitorByName(monitorName); if (monitorName.isEmpty() || monitor == nullptr) { // is null when output is disabled - this->mMonitor = nullptr; - this->mMonitorName = ""; + this->bMonitor = nullptr; } else { - this->mMonitorName = monitorName; - this->mMonitor = monitor; + this->bMonitor = monitor; } - emit this->monitorChanged(); } + + Qt::endPropertyUpdateGroup(); +} + +void I3Workspace::activate() { + this->ipc->dispatch(QString("workspace number %1").arg(this->bNumber.value())); } } // namespace qs::i3::ipc diff --git a/src/x11/i3/ipc/workspace.hpp b/src/x11/i3/ipc/workspace.hpp index 68b0ec45..c9cd0298 100644 --- a/src/x11/i3/ipc/workspace.hpp +++ b/src/x11/i3/ipc/workspace.hpp @@ -8,45 +8,55 @@ namespace qs::i3::ipc { +class I3Monitor; + ///! I3/Sway workspaces class I3Workspace: public QObject { Q_OBJECT; - + // clang-format off /// The ID of this workspace, it is unique for i3/Sway launch Q_PROPERTY(qint32 id READ default NOTIFY idChanged BINDABLE bindableId); - /// The name of this workspace Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName); - /// The number of this workspace - Q_PROPERTY(qint32 num READ default NOTIFY numChanged BINDABLE bindableNum); - + Q_PROPERTY(qint32 number READ default NOTIFY numberChanged BINDABLE bindableNumber); + /// Deprecated: use @@number + Q_PROPERTY(qint32 num READ default NOTIFY numberChanged BINDABLE bindableNumber); /// If a window in this workspace has an urgent notification Q_PROPERTY(bool urgent READ default NOTIFY urgentChanged BINDABLE bindableUrgent); - - /// If this workspace is the one currently in focus + /// If this workspace is currently active on its monitor. See also @@focused. + Q_PROPERTY(bool active READ default NOTIFY activeChanged BINDABLE bindableActive); + /// If this workspace is currently active on a monitor and that monitor is currently + /// focused. See also @@active. 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); - + Q_PROPERTY(qs::i3::ipc::I3Monitor* monitor READ default NOTIFY monitorChanged BINDABLE bindableMonitor); /// Last JSON returned for this workspace, as a JavaScript object. /// /// This updates every time we receive a `workspace` event from i3/Sway Q_PROPERTY(QVariantMap lastIpcObject READ lastIpcObject NOTIFY lastIpcObjectChanged); - + // clang-format on QML_ELEMENT; QML_UNCREATABLE("I3Workspaces must be retrieved from the I3 object."); public: - I3Workspace(qs::i3::ipc::I3Ipc* ipc): QObject(ipc), ipc(ipc) {} + I3Workspace(I3Ipc* ipc); + + /// Activate the workspace. + /// + /// > [!NOTE] This is equivalent to running + /// > ```qml + /// > I3.dispatch(`workspace number ${workspace.number}`); + /// > ``` + Q_INVOKABLE void activate(); [[nodiscard]] QBindable bindableId() { return &this->bId; } [[nodiscard]] QBindable bindableName() { return &this->bName; } - [[nodiscard]] QBindable bindableNum() { return &this->bNum; } + [[nodiscard]] QBindable bindableNumber() { return &this->bNumber; } + [[nodiscard]] QBindable bindableActive() { return &this->bActive; } [[nodiscard]] QBindable bindableFocused() { return &this->bFocused; } [[nodiscard]] QBindable bindableUrgent() { return &this->bUrgent; } - [[nodiscard]] I3Monitor* monitor() const; + [[nodiscard]] QBindable bindableMonitor() { return &this->bMonitor; } [[nodiscard]] QVariantMap lastIpcObject() const; void updateFromObject(const QVariantMap& obj); @@ -55,8 +65,9 @@ signals: void idChanged(); void nameChanged(); void urgentChanged(); + void activeChanged(); void focusedChanged(); - void numChanged(); + void numberChanged(); void monitorChanged(); void lastIpcObjectChanged(); @@ -64,13 +75,15 @@ private: I3Ipc* ipc; QVariantMap mLastIpcObject; - I3Monitor* mMonitor = nullptr; - QString mMonitorName; + // clang-format off 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_WITH_ARGS(I3Workspace, qint32, bNumber, -1, &I3Workspace::numberChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, bool, bActive, &I3Workspace::activeChanged); Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, bool, bFocused, &I3Workspace::focusedChanged); Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, bool, bUrgent, &I3Workspace::urgentChanged); + Q_OBJECT_BINDABLE_PROPERTY(I3Workspace, I3Monitor*, bMonitor, &I3Workspace::monitorChanged); + // clang-format on }; } // namespace qs::i3::ipc