i3/ipc: convert to bindable properties

This commit is contained in:
outfoxxed 2025-03-21 02:46:47 -07:00
parent 3b2d84caf0
commit 1a20c39fba
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
5 changed files with 96 additions and 170 deletions

View file

@ -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;
}

View file

@ -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();
};

View file

@ -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

View file

@ -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

View file

@ -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