From ef1a4134f052998c15369e03cb3b2cb18adfb553 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Thu, 6 Jun 2024 00:46:38 -0700 Subject: [PATCH] hyprland/ipc: re-request monitors and workspaces on fail --- src/wayland/hyprland/ipc/connection.cpp | 167 +++++++++++++----------- src/wayland/hyprland/ipc/connection.hpp | 4 +- 2 files changed, 93 insertions(+), 78 deletions(-) diff --git a/src/wayland/hyprland/ipc/connection.cpp b/src/wayland/hyprland/ipc/connection.cpp index e7265c7..dcb5765 100644 --- a/src/wayland/hyprland/ipc/connection.cpp +++ b/src/wayland/hyprland/ipc/connection.cpp @@ -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; this->requestingWorkspaces = true; - this->makeRequest("j/workspaces", [this, canCreate](bool success, const QByteArray& resp) { - this->requestingWorkspaces = false; - if (!success) return; + this->makeRequest( + "j/workspaces", + [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"; - auto json = QJsonDocument::fromJson(resp).array(); + qCDebug(logHyprlandIpc) << "parsing workspaces response"; + auto json = QJsonDocument::fromJson(resp).array(); - const auto& mList = this->mWorkspaces.valueList(); - auto names = QVector(); + const auto& mList = this->mWorkspaces.valueList(); + auto names = QVector(); - for (auto entry: json) { - auto object = entry.toObject().toVariantMap(); - auto name = object.value("name").toString(); + for (auto entry: json) { + auto object = entry.toObject().toVariantMap(); + auto name = object.value("name").toString(); - auto workspaceIter = - std::find_if(mList.begin(), mList.end(), [name](const HyprlandWorkspace* m) { - return m->name() == name; - }); + auto workspaceIter = + std::find_if(mList.begin(), mList.end(), [name](const HyprlandWorkspace* m) { + return m->name() == name; + }); - auto* workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter; - auto existed = workspace != nullptr; + auto* workspace = workspaceIter == mList.end() ? nullptr : *workspaceIter; + auto existed = workspace != nullptr; - if (workspace == nullptr) { - if (!canCreate) continue; - workspace = new HyprlandWorkspace(this); - } + if (workspace == nullptr) { + if (!canCreate) continue; + workspace = new HyprlandWorkspace(this); + } - workspace->updateFromObject(object); + workspace->updateFromObject(object); - if (!existed) { - this->mWorkspaces.insertObject(workspace); - } + if (!existed) { + this->mWorkspaces.insertObject(workspace); + } - names.push_back(name); - } + names.push_back(name); + } - auto removedWorkspaces = QVector(); + auto removedWorkspaces = QVector(); - for (auto* workspace: mList) { - if (!names.contains(workspace->name())) { - removedWorkspaces.push_back(workspace); - } - } + for (auto* workspace: mList) { + if (!names.contains(workspace->name())) { + removedWorkspaces.push_back(workspace); + } + } - for (auto* workspace: removedWorkspaces) { - this->mWorkspaces.removeObject(workspace); - delete workspace; - } - }); + for (auto* workspace: removedWorkspaces) { + this->mWorkspaces.removeObject(workspace); + delete workspace; + } + } + ); } HyprlandMonitor* @@ -484,59 +491,67 @@ void HyprlandIpc::onFocusedMonitorDestroyed() { emit this->focusedMonitorChanged(); } -void HyprlandIpc::refreshMonitors(bool canCreate) { +void HyprlandIpc::refreshMonitors(bool canCreate, bool tryAgain) { if (this->requestingMonitors) return; this->requestingMonitors = true; - this->makeRequest("j/monitors", [this, canCreate](bool success, const QByteArray& resp) { - this->requestingMonitors = false; - if (!success) return; + this->makeRequest( + "j/monitors", + [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"; - auto json = QJsonDocument::fromJson(resp).array(); + qCDebug(logHyprlandIpc) << "parsing monitors response"; + auto json = QJsonDocument::fromJson(resp).array(); - const auto& mList = this->mMonitors.valueList(); - auto ids = QVector(); + const auto& mList = this->mMonitors.valueList(); + auto ids = QVector(); - for (auto entry: json) { - auto object = entry.toObject().toVariantMap(); - auto id = object.value("id").toInt(); + for (auto entry: json) { + auto object = entry.toObject().toVariantMap(); + auto id = object.value("id").toInt(); - auto monitorIter = std::find_if(mList.begin(), mList.end(), [id](const HyprlandMonitor* m) { - return m->id() == id; - }); + auto monitorIter = + std::find_if(mList.begin(), mList.end(), [id](const HyprlandMonitor* m) { + return m->id() == id; + }); - auto* monitor = monitorIter == mList.end() ? nullptr : *monitorIter; - auto existed = monitor != nullptr; + auto* monitor = monitorIter == mList.end() ? nullptr : *monitorIter; + auto existed = monitor != nullptr; - if (monitor == nullptr) { - if (!canCreate) continue; - monitor = new HyprlandMonitor(this); - } + if (monitor == nullptr) { + if (!canCreate) continue; + monitor = new HyprlandMonitor(this); + } - monitor->updateFromObject(object); + monitor->updateFromObject(object); - if (!existed) { - this->mMonitors.insertObject(monitor); - } + if (!existed) { + this->mMonitors.insertObject(monitor); + } - ids.push_back(id); - } + ids.push_back(id); + } - auto removedMonitors = QVector(); + auto removedMonitors = QVector(); - for (auto* monitor: mList) { - if (!ids.contains(monitor->id())) { - removedMonitors.push_back(monitor); - } - } + for (auto* monitor: mList) { + if (!ids.contains(monitor->id())) { + removedMonitors.push_back(monitor); + } + } - for (auto* monitor: removedMonitors) { - this->mMonitors.removeObject(monitor); - // see comment in onEvent - monitor->deleteLater(); - } - }); + for (auto* monitor: removedMonitors) { + this->mMonitors.removeObject(monitor); + // see comment in onEvent + monitor->deleteLater(); + } + } + ); } } // namespace qs::hyprland::ipc diff --git a/src/wayland/hyprland/ipc/connection.hpp b/src/wayland/hyprland/ipc/connection.hpp index d566a86..0144ab4 100644 --- a/src/wayland/hyprland/ipc/connection.hpp +++ b/src/wayland/hyprland/ipc/connection.hpp @@ -81,8 +81,8 @@ public: HyprlandMonitor* findMonitorByName(const QString& name, bool createIfMissing, qint32 id = -1); // canCreate avoids making ghost workspaces when the connection races - void refreshWorkspaces(bool canCreate); - void refreshMonitors(bool canCreate); + void refreshWorkspaces(bool canCreate, bool tryAgain = true); + void refreshMonitors(bool canCreate, bool tryAgain = true); // The last argument may contain commas, so the count is required. [[nodiscard]] static QVector parseEventArgs(QByteArrayView event, quint16 count);