diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 8083ae88..8849cc66 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -134,6 +134,14 @@ auto Workspaces::update() -> void { AModule::update(); } +bool isDoubleSpecial(std::string &workspace_name) { + // Hyprland's IPC sometimes reports the creation of workspaces strangely named + // `special:special:`. This function checks for that and is used + // to avoid creating (and then removing) such workspaces. + // See hyprwm/Hyprland#3424 for more info. + return workspace_name.find("special:special:") != std::string::npos; +} + void Workspaces::onEvent(const std::string &ev) { std::lock_guard lock(mutex_); std::string eventName(begin(ev), begin(ev) + ev.find_first_of('>')); @@ -143,15 +151,16 @@ void Workspaces::onEvent(const std::string &ev) { active_workspace_name_ = payload; } else if (eventName == "destroyworkspace") { - workspaces_to_remove_.push_back(payload); - + if (!isDoubleSpecial(payload)) { + workspaces_to_remove_.push_back(payload); + } } else if (eventName == "createworkspace") { const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); for (Json::Value workspace_json : workspaces_json) { std::string name = workspace_json["name"].asString(); if (name == payload && (all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) && - (show_special() || !name.starts_with("special"))) { + (show_special() || !name.starts_with("special")) && !isDoubleSpecial(payload)) { workspaces_to_create_.push_back(workspace_json); break; } @@ -238,8 +247,10 @@ void Workspaces::create_workspace(Json::Value &value) { } void Workspaces::remove_workspace(std::string name) { - auto workspace = std::find_if(workspaces_.begin(), workspaces_.end(), - [&](std::unique_ptr &x) { return x->name() == name; }); + auto workspace = + std::find_if(workspaces_.begin(), workspaces_.end(), [&](std::unique_ptr &x) { + return (name.starts_with("special:") && name.substr(8) == x->name()) || name == x->name(); + }); if (workspace == workspaces_.end()) { // happens when a workspace on another monitor is destroyed