Skip to content

Commit d3b1a65

Browse files
committed
hyprland/ipc: reduce impact of racing workspace queries
1 parent 9506c1b commit d3b1a65

File tree

3 files changed

+42
-21
lines changed

3 files changed

+42
-21
lines changed

src/wayland/hyprland/ipc/connection.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
333333
auto* monitor = this->findMonitorByName(name, true);
334334
this->setFocusedMonitor(monitor);
335335
monitor->setActiveWorkspace(workspace);
336+
qCDebug(logHyprlandIpc) << "Monitor" << name << "focused with workspace" << workspace->id();
336337
} else if (event->name == "workspacev2") {
337338
auto args = event->parseView(2);
338339
auto id = args.at(0).toInt();
@@ -341,6 +342,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
341342
if (this->mFocusedMonitor != nullptr) {
342343
auto* workspace = this->findWorkspaceByName(name, true, id);
343344
this->mFocusedMonitor->setActiveWorkspace(workspace);
345+
qCDebug(logHyprlandIpc) << "Workspace" << id << "activated on" << this->mFocusedMonitor->name();
344346
}
345347
} else if (event->name == "moveworkspacev2") {
346348
auto args = event->parseView(3);
@@ -351,6 +353,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
351353
auto* workspace = this->findWorkspaceByName(name, true, id);
352354
auto* monitor = this->findMonitorByName(monitorName, true);
353355

356+
qCDebug(logHyprlandIpc) << "Workspace" << id << "moved to monitor" << monitorName;
354357
workspace->setMonitor(monitor);
355358
} else if (event->name == "renameworkspace") {
356359
auto args = event->parseView(2);
@@ -400,24 +403,35 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) {
400403
this->requestingWorkspaces = false;
401404
if (!success) return;
402405

403-
qCDebug(logHyprlandIpc) << "parsing workspaces response";
406+
qCDebug(logHyprlandIpc) << "Parsing workspaces response";
404407
auto json = QJsonDocument::fromJson(resp).array();
405408

406409
const auto& mList = this->mWorkspaces.valueList();
407-
auto names = QVector<QString>();
410+
auto ids = QVector<quint32>();
408411

409412
for (auto entry: json) {
410413
auto object = entry.toObject().toVariantMap();
411-
auto name = object.value("name").toString();
412414

413-
auto workspaceIter = std::ranges::find_if(mList, [name](const HyprlandWorkspace* m) {
414-
return m->name() == name;
415+
auto id = object.value("id").toInt();
416+
417+
auto workspaceIter = std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) {
418+
return m->id() == id;
415419
});
416420

421+
// Only fall back to name-based filtering as a last resort, for workspaces where
422+
// no ID has been determined yet.
423+
if (workspaceIter == mList.end()) {
424+
auto name = object.value("name").toString();
425+
426+
workspaceIter = std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) {
427+
return m->id() == -1 && m->name() == name;
428+
});
429+
}
430+
417431
auto* workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter;
418432
auto existed = workspace != nullptr;
419433

420-
if (workspace == nullptr) {
434+
if (!existed) {
421435
if (!canCreate) continue;
422436
workspace = new HyprlandWorkspace(this);
423437
}
@@ -428,20 +442,22 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) {
428442
this->mWorkspaces.insertObject(workspace);
429443
}
430444

431-
names.push_back(name);
445+
ids.push_back(id);
432446
}
433447

434-
auto removedWorkspaces = QVector<HyprlandWorkspace*>();
448+
if (canCreate) {
449+
auto removedWorkspaces = QVector<HyprlandWorkspace*>();
435450

436-
for (auto* workspace: mList) {
437-
if (!names.contains(workspace->name())) {
438-
removedWorkspaces.push_back(workspace);
451+
for (auto* workspace: mList) {
452+
if (!ids.contains(workspace->id())) {
453+
removedWorkspaces.push_back(workspace);
454+
}
439455
}
440-
}
441456

442-
for (auto* workspace: removedWorkspaces) {
443-
this->mWorkspaces.removeObject(workspace);
444-
delete workspace;
457+
for (auto* workspace: removedWorkspaces) {
458+
this->mWorkspaces.removeObject(workspace);
459+
delete workspace;
460+
}
445461
}
446462
});
447463
}

src/wayland/hyprland/ipc/monitor.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ void HyprlandMonitor::setActiveWorkspace(HyprlandWorkspace* workspace) {
117117
this->mActiveWorkspace = workspace;
118118

119119
if (workspace != nullptr) {
120+
workspace->setMonitor(this);
121+
120122
QObject::connect(
121123
workspace,
122124
&QObject::destroyed,

src/wayland/hyprland/ipc/workspace.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,21 @@ void HyprlandWorkspace::updateInitial(qint32 id, QString name) {
3535
}
3636

3737
void HyprlandWorkspace::updateFromObject(QVariantMap object) {
38-
auto id = object.value("id").value<qint32>();
39-
auto name = object.value("name").value<QString>();
4038
auto monitorId = object.value("monitorID").value<qint32>();
4139
auto monitorName = object.value("monitor").value<QString>();
4240

43-
if (id != this->mId) {
44-
this->mId = id;
41+
auto initial = this->mId = -1;
42+
43+
// ID cannot be updated after creation
44+
if (initial) {
45+
this->mId = object.value("id").value<qint32>();
4546
emit this->idChanged();
4647
}
4748

48-
if (name != this->mName) {
49-
this->mName = std::move(name);
49+
// No events we currently handle give a workspace id but not a name,
50+
// so we shouldn't set this if it isn't an initial query
51+
if (initial) {
52+
this->mName = object.value("name").value<QString>();
5053
emit this->nameChanged();
5154
}
5255

0 commit comments

Comments
 (0)