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