forked from quickshell/quickshell
		
	hyprland/ipc: re-request monitors and workspaces on fail
This commit is contained in:
		
							parent
							
								
									d14ca70984
								
							
						
					
					
						commit
						ef1a4134f0
					
				
					 2 changed files with 93 additions and 78 deletions
				
			
		| 
						 | 
				
			
			@ -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<QString>();
 | 
			
		||||
		    const auto& mList = this->mWorkspaces.valueList();
 | 
			
		||||
		    auto names = QVector<QString>();
 | 
			
		||||
 | 
			
		||||
		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<HyprlandWorkspace*>();
 | 
			
		||||
		    auto removedWorkspaces = QVector<HyprlandWorkspace*>();
 | 
			
		||||
 | 
			
		||||
		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<qint32>();
 | 
			
		||||
		    const auto& mList = this->mMonitors.valueList();
 | 
			
		||||
		    auto ids = QVector<qint32>();
 | 
			
		||||
 | 
			
		||||
		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<HyprlandMonitor*>();
 | 
			
		||||
		    auto removedMonitors = QVector<HyprlandMonitor*>();
 | 
			
		||||
 | 
			
		||||
		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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<QByteArrayView> parseEventArgs(QByteArrayView event, quint16 count);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue