hyprland/ipc: re-request monitors and workspaces on fail

This commit is contained in:
outfoxxed 2024-06-06 00:46:38 -07:00
parent d14ca70984
commit ef1a4134f0
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
2 changed files with 93 additions and 78 deletions

View file

@ -377,59 +377,66 @@ HyprlandIpc::findWorkspaceByName(const QString& name, bool createIfMissing, qint
} }
} }
void HyprlandIpc::refreshWorkspaces(bool canCreate) { void HyprlandIpc::refreshWorkspaces(bool canCreate, bool tryAgain) {
if (this->requestingWorkspaces) return; if (this->requestingWorkspaces) return;
this->requestingWorkspaces = true; this->requestingWorkspaces = true;
this->makeRequest("j/workspaces", [this, canCreate](bool success, const QByteArray& resp) { this->makeRequest(
this->requestingWorkspaces = false; "j/workspaces",
if (!success) return; [this, canCreate, tryAgain](bool success, const QByteArray& resp) {
this->requestingWorkspaces = false;
if (!success) {
// sometimes fails randomly, so we give it another shot.
if (tryAgain) this->refreshWorkspaces(canCreate, false);
return;
}
qCDebug(logHyprlandIpc) << "parsing workspaces response"; qCDebug(logHyprlandIpc) << "parsing workspaces response";
auto json = QJsonDocument::fromJson(resp).array(); auto json = QJsonDocument::fromJson(resp).array();
const auto& mList = this->mWorkspaces.valueList(); const auto& mList = this->mWorkspaces.valueList();
auto names = QVector<QString>(); auto names = QVector<QString>();
for (auto entry: json) { for (auto entry: json) {
auto object = entry.toObject().toVariantMap(); auto object = entry.toObject().toVariantMap();
auto name = object.value("name").toString(); auto name = object.value("name").toString();
auto workspaceIter = auto workspaceIter =
std::find_if(mList.begin(), mList.end(), [name](const HyprlandWorkspace* m) { std::find_if(mList.begin(), mList.end(), [name](const HyprlandWorkspace* m) {
return m->name() == name; return m->name() == name;
}); });
auto* workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter; auto* workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter;
auto existed = workspace != nullptr; auto existed = workspace != nullptr;
if (workspace == nullptr) { if (workspace == nullptr) {
if (!canCreate) continue; if (!canCreate) continue;
workspace = new HyprlandWorkspace(this); workspace = new HyprlandWorkspace(this);
} }
workspace->updateFromObject(object); workspace->updateFromObject(object);
if (!existed) { if (!existed) {
this->mWorkspaces.insertObject(workspace); this->mWorkspaces.insertObject(workspace);
} }
names.push_back(name); names.push_back(name);
} }
auto removedWorkspaces = QVector<HyprlandWorkspace*>(); auto removedWorkspaces = QVector<HyprlandWorkspace*>();
for (auto* workspace: mList) { for (auto* workspace: mList) {
if (!names.contains(workspace->name())) { if (!names.contains(workspace->name())) {
removedWorkspaces.push_back(workspace); removedWorkspaces.push_back(workspace);
} }
} }
for (auto* workspace: removedWorkspaces) { for (auto* workspace: removedWorkspaces) {
this->mWorkspaces.removeObject(workspace); this->mWorkspaces.removeObject(workspace);
delete workspace; delete workspace;
} }
}); }
);
} }
HyprlandMonitor* HyprlandMonitor*
@ -484,59 +491,67 @@ void HyprlandIpc::onFocusedMonitorDestroyed() {
emit this->focusedMonitorChanged(); emit this->focusedMonitorChanged();
} }
void HyprlandIpc::refreshMonitors(bool canCreate) { void HyprlandIpc::refreshMonitors(bool canCreate, bool tryAgain) {
if (this->requestingMonitors) return; if (this->requestingMonitors) return;
this->requestingMonitors = true; this->requestingMonitors = true;
this->makeRequest("j/monitors", [this, canCreate](bool success, const QByteArray& resp) { this->makeRequest(
this->requestingMonitors = false; "j/monitors",
if (!success) return; [this, canCreate, tryAgain](bool success, const QByteArray& resp) {
this->requestingMonitors = false;
if (!success) {
// sometimes fails randomly, so we give it another shot.
if (tryAgain) this->refreshMonitors(canCreate, false);
return;
}
qCDebug(logHyprlandIpc) << "parsing monitors response"; qCDebug(logHyprlandIpc) << "parsing monitors response";
auto json = QJsonDocument::fromJson(resp).array(); auto json = QJsonDocument::fromJson(resp).array();
const auto& mList = this->mMonitors.valueList(); const auto& mList = this->mMonitors.valueList();
auto ids = QVector<qint32>(); auto ids = QVector<qint32>();
for (auto entry: json) { for (auto entry: json) {
auto object = entry.toObject().toVariantMap(); auto object = entry.toObject().toVariantMap();
auto id = object.value("id").toInt(); auto id = object.value("id").toInt();
auto monitorIter = std::find_if(mList.begin(), mList.end(), [id](const HyprlandMonitor* m) { auto monitorIter =
return m->id() == id; std::find_if(mList.begin(), mList.end(), [id](const HyprlandMonitor* m) {
}); return m->id() == id;
});
auto* monitor = monitorIter == mList.end() ? nullptr : *monitorIter; auto* monitor = monitorIter == mList.end() ? nullptr : *monitorIter;
auto existed = monitor != nullptr; auto existed = monitor != nullptr;
if (monitor == nullptr) { if (monitor == nullptr) {
if (!canCreate) continue; if (!canCreate) continue;
monitor = new HyprlandMonitor(this); monitor = new HyprlandMonitor(this);
} }
monitor->updateFromObject(object); monitor->updateFromObject(object);
if (!existed) { if (!existed) {
this->mMonitors.insertObject(monitor); this->mMonitors.insertObject(monitor);
} }
ids.push_back(id); ids.push_back(id);
} }
auto removedMonitors = QVector<HyprlandMonitor*>(); auto removedMonitors = QVector<HyprlandMonitor*>();
for (auto* monitor: mList) { for (auto* monitor: mList) {
if (!ids.contains(monitor->id())) { if (!ids.contains(monitor->id())) {
removedMonitors.push_back(monitor); removedMonitors.push_back(monitor);
} }
} }
for (auto* monitor: removedMonitors) { for (auto* monitor: removedMonitors) {
this->mMonitors.removeObject(monitor); this->mMonitors.removeObject(monitor);
// see comment in onEvent // see comment in onEvent
monitor->deleteLater(); monitor->deleteLater();
} }
}); }
);
} }
} // namespace qs::hyprland::ipc } // namespace qs::hyprland::ipc

View file

@ -81,8 +81,8 @@ public:
HyprlandMonitor* findMonitorByName(const QString& name, bool createIfMissing, qint32 id = -1); HyprlandMonitor* findMonitorByName(const QString& name, bool createIfMissing, qint32 id = -1);
// canCreate avoids making ghost workspaces when the connection races // canCreate avoids making ghost workspaces when the connection races
void refreshWorkspaces(bool canCreate); void refreshWorkspaces(bool canCreate, bool tryAgain = true);
void refreshMonitors(bool canCreate); void refreshMonitors(bool canCreate, bool tryAgain = true);
// The last argument may contain commas, so the count is required. // The last argument may contain commas, so the count is required.
[[nodiscard]] static QVector<QByteArrayView> parseEventArgs(QByteArrayView event, quint16 count); [[nodiscard]] static QVector<QByteArrayView> parseEventArgs(QByteArrayView event, quint16 count);