forked from quickshell/quickshell
		
	hyprland/ipc: reduce impact of racing workspace queries
This commit is contained in:
		
							parent
							
								
									9506c1bb62
								
							
						
					
					
						commit
						d3b1a65911
					
				
					 3 changed files with 42 additions and 21 deletions
				
			
		| 
						 | 
					@ -333,6 +333,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
 | 
				
			||||||
		auto* monitor = this->findMonitorByName(name, true);
 | 
							auto* monitor = this->findMonitorByName(name, true);
 | 
				
			||||||
		this->setFocusedMonitor(monitor);
 | 
							this->setFocusedMonitor(monitor);
 | 
				
			||||||
		monitor->setActiveWorkspace(workspace);
 | 
							monitor->setActiveWorkspace(workspace);
 | 
				
			||||||
 | 
							qCDebug(logHyprlandIpc) << "Monitor" << name << "focused with workspace" << workspace->id();
 | 
				
			||||||
	} else if (event->name == "workspacev2") {
 | 
						} else if (event->name == "workspacev2") {
 | 
				
			||||||
		auto args = event->parseView(2);
 | 
							auto args = event->parseView(2);
 | 
				
			||||||
		auto id = args.at(0).toInt();
 | 
							auto id = args.at(0).toInt();
 | 
				
			||||||
| 
						 | 
					@ -341,6 +342,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
 | 
				
			||||||
		if (this->mFocusedMonitor != nullptr) {
 | 
							if (this->mFocusedMonitor != nullptr) {
 | 
				
			||||||
			auto* workspace = this->findWorkspaceByName(name, true, id);
 | 
								auto* workspace = this->findWorkspaceByName(name, true, id);
 | 
				
			||||||
			this->mFocusedMonitor->setActiveWorkspace(workspace);
 | 
								this->mFocusedMonitor->setActiveWorkspace(workspace);
 | 
				
			||||||
 | 
								qCDebug(logHyprlandIpc) << "Workspace" << id << "activated on" << this->mFocusedMonitor->name();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (event->name == "moveworkspacev2") {
 | 
						} else if (event->name == "moveworkspacev2") {
 | 
				
			||||||
		auto args = event->parseView(3);
 | 
							auto args = event->parseView(3);
 | 
				
			||||||
| 
						 | 
					@ -351,6 +353,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
 | 
				
			||||||
		auto* workspace = this->findWorkspaceByName(name, true, id);
 | 
							auto* workspace = this->findWorkspaceByName(name, true, id);
 | 
				
			||||||
		auto* monitor = this->findMonitorByName(monitorName, true);
 | 
							auto* monitor = this->findMonitorByName(monitorName, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							qCDebug(logHyprlandIpc) << "Workspace" << id << "moved to monitor" << monitorName;
 | 
				
			||||||
		workspace->setMonitor(monitor);
 | 
							workspace->setMonitor(monitor);
 | 
				
			||||||
	} else if (event->name == "renameworkspace") {
 | 
						} else if (event->name == "renameworkspace") {
 | 
				
			||||||
		auto args = event->parseView(2);
 | 
							auto args = event->parseView(2);
 | 
				
			||||||
| 
						 | 
					@ -400,24 +403,35 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) {
 | 
				
			||||||
		this->requestingWorkspaces = false;
 | 
							this->requestingWorkspaces = false;
 | 
				
			||||||
		if (!success) return;
 | 
							if (!success) 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 ids = QVector<quint32>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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 workspaceIter = std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) {
 | 
				
			||||||
 | 
									return m->id() == 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();
 | 
									auto name = object.value("name").toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto workspaceIter = std::ranges::find_if(mList, [name](const HyprlandWorkspace* m) {
 | 
									workspaceIter = std::ranges::find_if(mList, [&](const HyprlandWorkspace* m) {
 | 
				
			||||||
				return m->name() == name;
 | 
										return m->id() == -1 && 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 (!existed) {
 | 
				
			||||||
				if (!canCreate) continue;
 | 
									if (!canCreate) continue;
 | 
				
			||||||
				workspace = new HyprlandWorkspace(this);
 | 
									workspace = new HyprlandWorkspace(this);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -428,13 +442,14 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) {
 | 
				
			||||||
				this->mWorkspaces.insertObject(workspace);
 | 
									this->mWorkspaces.insertObject(workspace);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			names.push_back(name);
 | 
								ids.push_back(id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (canCreate) {
 | 
				
			||||||
			auto removedWorkspaces = QVector<HyprlandWorkspace*>();
 | 
								auto removedWorkspaces = QVector<HyprlandWorkspace*>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (auto* workspace: mList) {
 | 
								for (auto* workspace: mList) {
 | 
				
			||||||
			if (!names.contains(workspace->name())) {
 | 
									if (!ids.contains(workspace->id())) {
 | 
				
			||||||
					removedWorkspaces.push_back(workspace);
 | 
										removedWorkspaces.push_back(workspace);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -443,6 +458,7 @@ void HyprlandIpc::refreshWorkspaces(bool canCreate) {
 | 
				
			||||||
				this->mWorkspaces.removeObject(workspace);
 | 
									this->mWorkspaces.removeObject(workspace);
 | 
				
			||||||
				delete workspace;
 | 
									delete workspace;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,6 +117,8 @@ void HyprlandMonitor::setActiveWorkspace(HyprlandWorkspace* workspace) {
 | 
				
			||||||
	this->mActiveWorkspace = workspace;
 | 
						this->mActiveWorkspace = workspace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (workspace != nullptr) {
 | 
						if (workspace != nullptr) {
 | 
				
			||||||
 | 
							workspace->setMonitor(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		QObject::connect(
 | 
							QObject::connect(
 | 
				
			||||||
		    workspace,
 | 
							    workspace,
 | 
				
			||||||
		    &QObject::destroyed,
 | 
							    &QObject::destroyed,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,18 +35,21 @@ void HyprlandWorkspace::updateInitial(qint32 id, QString name) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HyprlandWorkspace::updateFromObject(QVariantMap object) {
 | 
					void HyprlandWorkspace::updateFromObject(QVariantMap object) {
 | 
				
			||||||
	auto id = object.value("id").value<qint32>();
 | 
					 | 
				
			||||||
	auto name = object.value("name").value<QString>();
 | 
					 | 
				
			||||||
	auto monitorId = object.value("monitorID").value<qint32>();
 | 
						auto monitorId = object.value("monitorID").value<qint32>();
 | 
				
			||||||
	auto monitorName = object.value("monitor").value<QString>();
 | 
						auto monitorName = object.value("monitor").value<QString>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (id != this->mId) {
 | 
						auto initial = this->mId = -1;
 | 
				
			||||||
		this->mId = id;
 | 
					
 | 
				
			||||||
 | 
						// ID cannot be updated after creation
 | 
				
			||||||
 | 
						if (initial) {
 | 
				
			||||||
 | 
							this->mId = object.value("id").value<qint32>();
 | 
				
			||||||
		emit this->idChanged();
 | 
							emit this->idChanged();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (name != this->mName) {
 | 
						// No events we currently handle give a workspace id but not a name,
 | 
				
			||||||
		this->mName = std::move(name);
 | 
						// so we shouldn't set this if it isn't an initial query
 | 
				
			||||||
 | 
						if (initial) {
 | 
				
			||||||
 | 
							this->mName = object.value("name").value<QString>();
 | 
				
			||||||
		emit this->nameChanged();
 | 
							emit this->nameChanged();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue