hyprland/ipc: convert to bindable properties

This commit is contained in:
outfoxxed 2025-03-21 02:46:09 -07:00
parent eabf79ebb6
commit 3b2d84caf0
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
5 changed files with 105 additions and 160 deletions

View file

@ -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<HyprlandWorkspace*>();
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<HyprlandMonitor*>();
for (auto* monitor: mList) {
if (!names.contains(monitor->name())) {
if (!names.contains(monitor->bindableName().value())) {
removedMonitors.push_back(monitor);
}
}

View file

@ -3,6 +3,7 @@
#include <qcontainerfwd.h>
#include <qobject.h>
#include <qproperty.h>
#include <qtmetamacros.h>
#include <qtypes.h>
@ -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<qint32>();
auto name = object.value("name").value<QString>();
auto description = object.value("description").value<QString>();
auto x = object.value("x").value<qint32>();
auto y = object.value("y").value<qint32>();
auto width = object.value("width").value<qint32>();
auto height = object.value("height").value<qint32>();
auto scale = object.value("height").value<qint32>();
auto activeWorkspaceObj = object.value("activeWorkspace").value<QVariantMap>();
auto activeWorkspaceId = activeWorkspaceObj.value("id").value<qint32>();
auto activeWorkspaceName = activeWorkspaceObj.value("name").value<QString>();
auto focused = object.value("focused").value<bool>();
if (id != this->mId) {
this->mId = id;
emit this->idChanged();
}
Qt::beginPropertyUpdateGroup();
this->bId = object.value("id").value<qint32>();
this->bName = object.value("name").value<QString>();
this->bDescription = object.value("description").value<QString>();
this->bX = object.value("x").value<qint32>();
this->bY = object.value("y").value<qint32>();
this->bWidth = object.value("width").value<qint32>();
this->bHeight = object.value("height").value<qint32>();
this->bScale = object.value("scale").value<qreal>();
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);

View file

@ -3,6 +3,7 @@
#include <qbytearrayview.h>
#include <qcontainerfwd.h>
#include <qobject.h>
#include <qproperty.h>
#include <qqmlintegration.h>
#include <qtmetamacros.h>
#include <qtypes.h>
@ -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<qint32> bindableId() { return &this->bId; }
[[nodiscard]] QBindable<QString> bindableName() { return &this->bName; }
[[nodiscard]] QBindable<QString> bindableDescription() { return &this->bDescription; }
[[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]] 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

View file

@ -3,6 +3,7 @@
#include <qcontainerfwd.h>
#include <qobject.h>
#include <qproperty.h>
#include <qtmetamacros.h>
#include <qtypes.h>
@ -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<QString>();
auto monitorId = object.value("monitorID").value<qint32>();
auto monitorName = object.value("monitor").value<QString>();
auto initial = this->mId = -1;
auto initial = this->bId == -1;
// ID cannot be updated after creation
if (initial) {
this->mId = object.value("id").value<qint32>();
emit this->idChanged();
this->bId = object.value("id").value<qint32>();
}
// 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<QString>();
}
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);

View file

@ -3,6 +3,7 @@
#include <qbytearrayview.h>
#include <qjsonobject.h>
#include <qobject.h>
#include <qproperty.h>
#include <qqmlintegration.h>
#include <qtmetamacros.h>
#include <qtypes.h>
@ -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<qint32> bindableId() { return &this->bId; }
[[nodiscard]] QBindable<QString> 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