From 67c0c9a66c04afe0407ea84725fca69d473d8828 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 16 Oct 2023 19:07:00 -0300 Subject: [PATCH 01/10] fix: delay window creation to await for hyprland to create a workspace --- include/modules/hyprland/workspaces.hpp | 37 ++++++- src/modules/hyprland/workspaces.cpp | 139 ++++++++++++++++-------- 2 files changed, 129 insertions(+), 47 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index c5851cad..263a56ce 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "AModule.hpp" @@ -25,6 +26,35 @@ namespace waybar::modules::hyprland { class Workspaces; +class CreateWindow { + public: + CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_repr); + CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_class, std::string window_title); + CreateWindow(Json::Value& client_data); + + int increment_time_spent_uncreated(); + bool is_empty(Workspaces& workspace_manager); + bool repr_is_ready() const { return std::holds_alternative(window_); } + std::string repr(Workspaces& workspace_manager); + + std::string workspace_name() const { return workspace_name_; } + WindowAddress addr() const { return window_address_; } + + private: + + void clear_addr(); + + using Repr = std::string; + using ClassAndTitle = std::pair; + + std::variant window_; + + WindowAddress window_address_; + std::string workspace_name_; + int time_spent_uncreated_ = 0; + +}; + class Workspace { public: explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager, @@ -50,13 +80,11 @@ class Workspace { void set_windows(uint value) { windows_ = value; }; void set_name(std::string value) { name_ = value; }; bool contains_window(WindowAddress addr) const { return window_map_.contains(addr); } - void insert_window(WindowAddress addr, std::string window_class, std::string window_title); + void insert_window(CreateWindow create_window_paylod); std::string remove_window(WindowAddress addr); void initialize_window_map(const Json::Value& clients_data); - bool on_window_opened(WindowAddress& addr, std::string& workspace_name, std::string window_repr); - bool on_window_opened(WindowAddress& addr, std::string& workspace_name, std::string& window_class, - std::string& window_title); + bool on_window_opened(CreateWindow create_window_paylod); std::optional on_window_closed(WindowAddress& addr); @@ -149,6 +177,7 @@ class Workspaces : public AModule, public EventHandler { std::vector> workspaces_; std::vector workspaces_to_create_; std::vector workspaces_to_remove_; + std::vector windows_to_create_; std::vector ignore_workspaces_; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index b3faeac1..b6c37a7a 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "util/regex_collection.hpp" @@ -191,6 +193,28 @@ auto Workspaces::update() -> void { } workspace->update(format_, workspace_icon); } + + std::vector not_created; + + for (auto &window_payload : windows_to_create_) { + bool created = false; + for (auto &workspace : workspaces_) { + if (workspace->on_window_opened(window_payload)) { + created = true; + break; + } + } + if (!created) { + static const int WINDOW_CREATION_TIMEOUT = 2; + if (window_payload.increment_time_spent_uncreated() < WINDOW_CREATION_TIMEOUT) { + not_created.push_back(window_payload); + } + } + } + + windows_to_create_.clear(); + windows_to_create_ = not_created; + AModule::update(); } @@ -297,7 +321,7 @@ void Workspaces::onEvent(const std::string &ev) { if (!client->empty()) { (*window_workspace) - ->insert_window(payload, (*client)["class"].asString(), (*client)["title"].asString()); + ->insert_window({*client}); } } } @@ -322,11 +346,7 @@ void Workspaces::on_window_opened(std::string payload) { std::string window_title = payload.substr(next_comma_idx + 1, payload.length() - next_comma_idx); - for (auto &workspace : workspaces_) { - if (workspace->on_window_opened(window_address, workspace_name, window_class, window_title)) { - break; - } - } + windows_to_create_.push_back({workspace_name, window_address, window_class, window_title}); } void Workspaces::on_window_closed(std::string addr) { @@ -359,11 +379,7 @@ void Workspaces::on_window_moved(std::string payload) { } // ...and add it to the new workspace - for (auto &workspace : workspaces_) { - if (workspace->on_window_opened(window_address, workspace_name, window_repr)) { - break; - } - } + windows_to_create_.push_back({workspace_name, window_address, window_repr}); } void Workspaces::update_window_count() { @@ -395,28 +411,14 @@ void Workspace::initialize_window_map(const Json::Value &clients_data) { window_map_.clear(); for (auto client : clients_data) { if (client["workspace"]["id"].asInt() == id()) { - // substr(2, ...) is necessary because Hyprland's JSON follows this format: - // 0x{ADDR} - // While Hyprland's IPC follows this format: - // {ADDR} - WindowAddress client_address = client["address"].asString(); - client_address = client_address.substr(2, client_address.length() - 2); - insert_window(client_address, client["class"].asString(), client["title"].asString()); + insert_window({client}); } } } -void Workspace::insert_window(WindowAddress addr, std::string window_class, - std::string window_title) { - if (window_class.empty() && - (!workspace_manager_.window_rewrite_config_uses_title() || window_title.empty())) { - return; - } - - auto window_repr = workspace_manager_.get_rewrite(window_class, window_title); - - if (!window_repr.empty()) { - window_map_[addr] = window_repr; +void Workspace::insert_window(CreateWindow create_window_paylod) { + if (!create_window_paylod.is_empty(workspace_manager_)) { + window_map_[create_window_paylod.addr()] = create_window_paylod.repr(workspace_manager_); } }; @@ -427,20 +429,9 @@ std::string Workspace::remove_window(WindowAddress addr) { return window_repr; } -bool Workspace::on_window_opened(WindowAddress &addr, std::string &workspace_name, - std::string window_repr) { - if (workspace_name == name()) { - window_map_[addr] = window_repr; - return true; - } else { - return false; - } -} - -bool Workspace::on_window_opened(WindowAddress &addr, std::string &workspace_name, - std::string &window_class, std::string &window_title) { - if (workspace_name == name()) { - insert_window(addr, window_class, window_title); +bool Workspace::on_window_opened(CreateWindow create_window_paylod) { + if (create_window_paylod.workspace_name() == name()) { + insert_window(create_window_paylod); return true; } else { return false; @@ -863,4 +854,66 @@ std::string Workspaces::get_rewrite(std::string window_class, std::string window return window_rewrite_rules_.get(window_repr_key); } +CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_repr) + : window_(window_repr), + window_address_(window_address), + workspace_name_(workspace_name) { + clear_addr(); +} + +CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_class, std::string window_title) + : window_(std::make_pair(window_class, window_title)), + window_address_(window_address), + workspace_name_(workspace_name) { + clear_addr(); +} + +CreateWindow::CreateWindow(Json::Value& client_data) { + window_address_ = client_data["address"].asString(); + workspace_name_ = client_data["workspace"]["name"].asString(); + window_ = std::make_pair(client_data["class"].asString(), client_data["title"].asString()); + clear_addr(); +} + +std::string CreateWindow::repr(Workspaces& workspace_manager) { + if (std::holds_alternative(window_)) { + return std::get(window_); + } else if (std::holds_alternative(window_)) { + auto [window_class, window_title] = std::get(window_); + return workspace_manager.get_rewrite(window_class, window_title); + } else { + // Unreachable + return ""; + } +} + +bool CreateWindow::is_empty(Workspaces& workspace_manager) { + if (std::holds_alternative(window_)) { + return std::get(window_).empty(); + } else if (std::holds_alternative(window_)) { + auto [window_class, window_title] = std::get(window_); + return ( + window_class.empty() && + (!workspace_manager.window_rewrite_config_uses_title() || window_title.empty()) + ); + } else { + // Unreachable + return true; + } +} + +int CreateWindow::increment_time_spent_uncreated() { + return time_spent_uncreated_++; +} + +void CreateWindow::clear_addr() { + // substr(2, ...) is necessary because Hyprland's JSON follows this format: + // 0x{ADDR} + // While Hyprland's IPC follows this format: + // {ADDR} + if (window_address_.starts_with("0x")) { + window_address_ = window_address_.substr(2, window_address_.length() - 2); + } +} + } // namespace waybar::modules::hyprland From e70a67d9583ab9cce2a1186c29ce44e4369e9e6f Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 16 Oct 2023 19:14:50 -0300 Subject: [PATCH 02/10] chore: lint chore: swap push_back to emplace_back --- include/modules/hyprland/workspaces.hpp | 5 ++- src/modules/hyprland/workspaces.cpp | 44 +++++++++++-------------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 263a56ce..37fb7d09 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -29,7 +29,8 @@ class Workspaces; class CreateWindow { public: CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_repr); - CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_class, std::string window_title); + CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_class, + std::string window_title); CreateWindow(Json::Value& client_data); int increment_time_spent_uncreated(); @@ -41,7 +42,6 @@ class CreateWindow { WindowAddress addr() const { return window_address_; } private: - void clear_addr(); using Repr = std::string; @@ -52,7 +52,6 @@ class CreateWindow { WindowAddress window_address_; std::string workspace_name_; int time_spent_uncreated_ = 0; - }; class Workspace { diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index b6c37a7a..5ccbd52e 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -320,8 +320,7 @@ void Workspaces::onEvent(const std::string &ev) { }); if (!client->empty()) { - (*window_workspace) - ->insert_window({*client}); + (*window_workspace)->insert_window({*client}); } } } @@ -346,7 +345,8 @@ void Workspaces::on_window_opened(std::string payload) { std::string window_title = payload.substr(next_comma_idx + 1, payload.length() - next_comma_idx); - windows_to_create_.push_back({workspace_name, window_address, window_class, window_title}); + windows_to_create_.emplace_back( + CreateWindow(workspace_name, window_address, window_class, window_title)); } void Workspaces::on_window_closed(std::string addr) { @@ -379,7 +379,7 @@ void Workspaces::on_window_moved(std::string payload) { } // ...and add it to the new workspace - windows_to_create_.push_back({workspace_name, window_address, window_repr}); + windows_to_create_.emplace_back(CreateWindow(workspace_name, window_address, window_repr)); } void Workspaces::update_window_count() { @@ -854,28 +854,28 @@ std::string Workspaces::get_rewrite(std::string window_class, std::string window return window_rewrite_rules_.get(window_repr_key); } -CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_repr) - : window_(window_repr), - window_address_(window_address), - workspace_name_(workspace_name) { - clear_addr(); +CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, + std::string window_repr) + : window_(window_repr), window_address_(window_address), workspace_name_(workspace_name) { + clear_addr(); } -CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, std::string window_class, std::string window_title) - : window_(std::make_pair(window_class, window_title)), - window_address_(window_address), - workspace_name_(workspace_name) { - clear_addr(); +CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, + std::string window_class, std::string window_title) + : window_(std::make_pair(window_class, window_title)), + window_address_(window_address), + workspace_name_(workspace_name) { + clear_addr(); } -CreateWindow::CreateWindow(Json::Value& client_data) { +CreateWindow::CreateWindow(Json::Value &client_data) { window_address_ = client_data["address"].asString(); workspace_name_ = client_data["workspace"]["name"].asString(); window_ = std::make_pair(client_data["class"].asString(), client_data["title"].asString()); clear_addr(); } -std::string CreateWindow::repr(Workspaces& workspace_manager) { +std::string CreateWindow::repr(Workspaces &workspace_manager) { if (std::holds_alternative(window_)) { return std::get(window_); } else if (std::holds_alternative(window_)) { @@ -887,24 +887,20 @@ std::string CreateWindow::repr(Workspaces& workspace_manager) { } } -bool CreateWindow::is_empty(Workspaces& workspace_manager) { +bool CreateWindow::is_empty(Workspaces &workspace_manager) { if (std::holds_alternative(window_)) { return std::get(window_).empty(); } else if (std::holds_alternative(window_)) { auto [window_class, window_title] = std::get(window_); - return ( - window_class.empty() && - (!workspace_manager.window_rewrite_config_uses_title() || window_title.empty()) - ); + return (window_class.empty() && + (!workspace_manager.window_rewrite_config_uses_title() || window_title.empty())); } else { // Unreachable return true; } } -int CreateWindow::increment_time_spent_uncreated() { - return time_spent_uncreated_++; -} +int CreateWindow::increment_time_spent_uncreated() { return time_spent_uncreated_++; } void CreateWindow::clear_addr() { // substr(2, ...) is necessary because Hyprland's JSON follows this format: From 6ddd283d0f16ec65c04ee4955270220fb0aef2c7 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 16 Oct 2023 20:48:52 -0300 Subject: [PATCH 03/10] fix: special workspaces weren't registering windows because of the special qualifier prefix --- include/modules/hyprland/workspaces.hpp | 1 + src/modules/hyprland/workspaces.cpp | 26 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 37fb7d09..c76ac267 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -43,6 +43,7 @@ class CreateWindow { private: void clear_addr(); + void clear_workspace_name(); using Repr = std::string; using ClassAndTitle = std::pair; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 5ccbd52e..e26fe757 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -858,6 +858,7 @@ CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_addr std::string window_repr) : window_(window_repr), window_address_(window_address), workspace_name_(workspace_name) { clear_addr(); + clear_workspace_name(); } CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_address, @@ -866,6 +867,7 @@ CreateWindow::CreateWindow(std::string workspace_name, WindowAddress window_addr window_address_(window_address), workspace_name_(workspace_name) { clear_addr(); + clear_workspace_name(); } CreateWindow::CreateWindow(Json::Value &client_data) { @@ -873,6 +875,7 @@ CreateWindow::CreateWindow(Json::Value &client_data) { workspace_name_ = client_data["workspace"]["name"].asString(); window_ = std::make_pair(client_data["class"].asString(), client_data["title"].asString()); clear_addr(); + clear_workspace_name(); } std::string CreateWindow::repr(Workspaces &workspace_manager) { @@ -907,8 +910,27 @@ void CreateWindow::clear_addr() { // 0x{ADDR} // While Hyprland's IPC follows this format: // {ADDR} - if (window_address_.starts_with("0x")) { - window_address_ = window_address_.substr(2, window_address_.length() - 2); + static const std::string ADDR_PREFIX = "0x"; + static const int ADDR_PREFIX_LEN = ADDR_PREFIX.length(); + + if (window_address_.starts_with(ADDR_PREFIX)) { + window_address_ = + window_address_.substr(ADDR_PREFIX_LEN, window_address_.length() - ADDR_PREFIX_LEN); + } +} + +void CreateWindow::clear_workspace_name() { + // The workspace name may optionally feature "special:" at the beginning. + // If so, we need to remove it because the workspace is saved WITHOUT the + // special qualifier. The reasoning is that not all of Hyprland's IPC events + // use this qualifier, so it's better to be consistent about our uses. + + static const std::string SPECIAL_QUALIFIER_PREFIX = "special:"; + static const int SPECIAL_QUALIFIER_PREFIX_LEN = SPECIAL_QUALIFIER_PREFIX.length(); + + if (workspace_name_.starts_with(SPECIAL_QUALIFIER_PREFIX)) { + workspace_name_ = workspace_name_.substr( + SPECIAL_QUALIFIER_PREFIX_LEN, workspace_name_.length() - SPECIAL_QUALIFIER_PREFIX_LEN); } } From 193040c41ee996ff3dd1b8d8c5574620d479da64 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Wed, 18 Oct 2023 19:04:09 -0300 Subject: [PATCH 04/10] feat: attempt to move windows out of the create window payload before taking them from workspaces --- include/modules/hyprland/workspaces.hpp | 2 ++ src/modules/hyprland/workspaces.cpp | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index c76ac267..0a834f11 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -41,6 +41,8 @@ class CreateWindow { std::string workspace_name() const { return workspace_name_; } WindowAddress addr() const { return window_address_; } + void move_to_worksace(std::string& new_workspace_name); + private: void clear_addr(); void clear_workspace_name(); diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index e26fe757..416e06f3 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -367,6 +367,15 @@ void Workspaces::on_window_moved(std::string payload) { std::string window_repr; + // If the window was still queued to be created, just change its destination + // and exit + for (auto &window : windows_to_create_) { + if (window.addr() == window_address) { + window.move_to_worksace(workspace_name); + return; + } + } + // Take the window's representation from the old workspace... for (auto &workspace : workspaces_) { try { @@ -379,7 +388,9 @@ void Workspaces::on_window_moved(std::string payload) { } // ...and add it to the new workspace - windows_to_create_.emplace_back(CreateWindow(workspace_name, window_address, window_repr)); + if (!window_repr.empty()) { + windows_to_create_.emplace_back(CreateWindow(workspace_name, window_address, window_repr)); + } } void Workspaces::update_window_count() { @@ -934,4 +945,8 @@ void CreateWindow::clear_workspace_name() { } } +void CreateWindow::move_to_worksace(std::string &new_workspace_name) { + workspace_name_ = new_workspace_name; +} + } // namespace waybar::modules::hyprland From e845db84adf37d2b37a657c7ec38c3e304791ab8 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Wed, 18 Oct 2023 19:06:36 -0300 Subject: [PATCH 05/10] feat: avoid recreating workspaces --- src/modules/hyprland/workspaces.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 416e06f3..5c009202 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -458,17 +458,16 @@ std::optional Workspace::on_window_closed(WindowAddress &addr) { } void Workspaces::create_workspace(Json::Value &workspace_data, const Json::Value &clients_data) { - // replace the existing persistent workspace if it exists + // avoid recreating existing workspaces auto workspace = std::find_if( workspaces_.begin(), workspaces_.end(), [&](std::unique_ptr const &x) { auto name = workspace_data["name"].asString(); return x->is_persistent() && ((name.starts_with("special:") && name.substr(8) == x->name()) || name == x->name()); }); + if (workspace != workspaces_.end()) { - // replace workspace, but keep persistent flag - workspaces_.erase(workspace); - workspace_data["persistent"] = true; + return; } // create new workspace From 846842be8089da4ea7a936d39148f723a41b0faa Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Thu, 19 Oct 2023 10:45:00 -0300 Subject: [PATCH 06/10] feat: emit dispatcher when any window is created during update --- src/modules/hyprland/workspaces.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 5c009202..a01dd2f0 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -194,6 +194,7 @@ auto Workspaces::update() -> void { workspace->update(format_, workspace_icon); } + bool any_window_created = false; std::vector not_created; for (auto &window_payload : windows_to_create_) { @@ -201,6 +202,7 @@ auto Workspaces::update() -> void { for (auto &workspace : workspaces_) { if (workspace->on_window_opened(window_payload)) { created = true; + any_window_created = true; break; } } @@ -212,6 +214,10 @@ auto Workspaces::update() -> void { } } + if (any_window_created) { + dp.emit(); + } + windows_to_create_.clear(); windows_to_create_ = not_created; From e14a3b86874bf3ca121645fc61743ed74742f3c8 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Thu, 19 Oct 2023 21:19:08 -0300 Subject: [PATCH 07/10] fix: fill persistent workspaces' windows at init --- include/modules/hyprland/workspaces.hpp | 2 +- src/modules/hyprland/workspaces.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 0a834f11..556a5c24 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -162,7 +162,7 @@ class Workspaces : public AModule, public EventHandler { {"DEFAULT", SORT_METHOD::DEFAULT}}; void fill_persistent_workspaces(); - void create_persistent_workspaces(); + void create_persistent_workspaces(const Json::Value& clients_data); std::vector persistent_workspaces_to_create_; bool persistent_created_ = false; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index a01dd2f0..7685de8a 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -562,7 +562,7 @@ void Workspaces::fill_persistent_workspaces() { } } -void Workspaces::create_persistent_workspaces() { +void Workspaces::create_persistent_workspaces(const Json::Value &clients_data) { for (const std::string &workspace_name : persistent_workspaces_to_create_) { Json::Value new_workspace; try { @@ -577,7 +577,7 @@ void Workspaces::create_persistent_workspaces() { new_workspace["windows"] = 0; new_workspace["persistent"] = true; - create_workspace(new_workspace); + create_workspace(new_workspace, clients_data); } } @@ -596,12 +596,12 @@ void Workspaces::init() { monitor_id_ = (*current_monitor)["id"].asInt(); } - fill_persistent_workspaces(); - create_persistent_workspaces(); - const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); const Json::Value clients_json = gIPC->getSocket1JsonReply("clients"); + fill_persistent_workspaces(); + create_persistent_workspaces(clients_json); + for (Json::Value workspace_json : workspaces_json) { std::string workspace_name = workspace_json["name"].asString(); if ((all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) && From a0d2d95b41a00e8e1fad57f3367ca81b3eea73b9 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Thu, 19 Oct 2023 21:21:55 -0300 Subject: [PATCH 08/10] chore: remove unused function --- include/modules/hyprland/workspaces.hpp | 1 - src/modules/hyprland/workspaces.cpp | 7 ------- 2 files changed, 8 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 556a5c24..6a0c2634 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -134,7 +134,6 @@ class Workspaces : public AModule, public EventHandler { private: void onEvent(const std::string&) override; void update_window_count(); - void initialize_window_maps(); void sort_workspaces(); void create_workspace(Json::Value& workspace_data, const Json::Value& clients_data = Json::Value::nullRef); diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 7685de8a..6ffdf237 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -417,13 +417,6 @@ void Workspaces::update_window_count() { } } -void Workspaces::initialize_window_maps() { - Json::Value clients_data = gIPC->getSocket1JsonReply("clients"); - for (auto &workspace : workspaces_) { - workspace->initialize_window_map(clients_data); - } -} - void Workspace::initialize_window_map(const Json::Value &clients_data) { window_map_.clear(); for (auto client : clients_data) { From a41225c4e083bacf4d69c7018ed02792576eedc3 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Thu, 19 Oct 2023 21:23:00 -0300 Subject: [PATCH 09/10] Revert "fix: fill persistent workspaces' windows at init" This reverts commit e14a3b86874bf3ca121645fc61743ed74742f3c8. --- include/modules/hyprland/workspaces.hpp | 2 +- src/modules/hyprland/workspaces.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 6a0c2634..dde564df 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -161,7 +161,7 @@ class Workspaces : public AModule, public EventHandler { {"DEFAULT", SORT_METHOD::DEFAULT}}; void fill_persistent_workspaces(); - void create_persistent_workspaces(const Json::Value& clients_data); + void create_persistent_workspaces(); std::vector persistent_workspaces_to_create_; bool persistent_created_ = false; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 6ffdf237..42e112d2 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -555,7 +555,7 @@ void Workspaces::fill_persistent_workspaces() { } } -void Workspaces::create_persistent_workspaces(const Json::Value &clients_data) { +void Workspaces::create_persistent_workspaces() { for (const std::string &workspace_name : persistent_workspaces_to_create_) { Json::Value new_workspace; try { @@ -570,7 +570,7 @@ void Workspaces::create_persistent_workspaces(const Json::Value &clients_data) { new_workspace["windows"] = 0; new_workspace["persistent"] = true; - create_workspace(new_workspace, clients_data); + create_workspace(new_workspace); } } @@ -589,12 +589,12 @@ void Workspaces::init() { monitor_id_ = (*current_monitor)["id"].asInt(); } + fill_persistent_workspaces(); + create_persistent_workspaces(); + const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); const Json::Value clients_json = gIPC->getSocket1JsonReply("clients"); - fill_persistent_workspaces(); - create_persistent_workspaces(clients_json); - for (Json::Value workspace_json : workspaces_json) { std::string workspace_name = workspace_json["name"].asString(); if ((all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) && From 7d5577a2ed89cc98cf2b1e6f81d53b24f737e74e Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Thu, 19 Oct 2023 21:28:28 -0300 Subject: [PATCH 10/10] feat: create persistent workspaces after regular ones at init feat: avoid recreating duplicate workspaces --- src/modules/hyprland/workspaces.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 42e112d2..4facacfb 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -458,11 +458,11 @@ std::optional Workspace::on_window_closed(WindowAddress &addr) { void Workspaces::create_workspace(Json::Value &workspace_data, const Json::Value &clients_data) { // avoid recreating existing workspaces + auto workspace_name = workspace_data["name"].asString(); auto workspace = std::find_if( - workspaces_.begin(), workspaces_.end(), [&](std::unique_ptr const &x) { - auto name = workspace_data["name"].asString(); - return x->is_persistent() && - ((name.starts_with("special:") && name.substr(8) == x->name()) || name == x->name()); + workspaces_.begin(), workspaces_.end(), [&](std::unique_ptr const &w) { + return (workspace_name.starts_with("special:") && workspace_name.substr(8) == w->name()) || + workspace_name == w->name(); }); if (workspace != workspaces_.end()) { @@ -589,9 +589,6 @@ void Workspaces::init() { monitor_id_ = (*current_monitor)["id"].asInt(); } - fill_persistent_workspaces(); - create_persistent_workspaces(); - const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); const Json::Value clients_json = gIPC->getSocket1JsonReply("clients"); @@ -604,6 +601,9 @@ void Workspaces::init() { } } + fill_persistent_workspaces(); + create_persistent_workspaces(); + update_window_count(); sort_workspaces();