From ed65d9cdbdfb8842c1ec1c7bb74f660945f3674b Mon Sep 17 00:00:00 2001 From: zjeffer <4633209+zjeffer@users.noreply.github.com> Date: Sat, 21 Oct 2023 16:52:23 +0200 Subject: [PATCH 1/5] General cleanup in hyprland/workspaces --- include/modules/hyprland/window.hpp | 2 +- include/modules/hyprland/workspaces.hpp | 50 +++++----- src/modules/hyprland/workspaces.cpp | 127 ++++++++++++------------ 3 files changed, 92 insertions(+), 87 deletions(-) diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index c9f0be03..ea4d83b2 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -14,7 +14,7 @@ namespace waybar::modules::hyprland { class Window : public waybar::AAppIconLabel, public EventHandler { public: Window(const std::string&, const waybar::Bar&, const Json::Value&); - virtual ~Window(); + ~Window() override; auto update() -> void override; diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index dde564df..6ca2877b 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -26,12 +26,13 @@ namespace waybar::modules::hyprland { class Workspaces; -class CreateWindow { +class WorkspaceWindow { 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); + WorkspaceWindow(std::string workspace_name, WindowAddress window_address, + std::string window_repr); + WorkspaceWindow(std::string workspace_name, WindowAddress window_address, + std::string window_class, std::string window_title); + WorkspaceWindow(Json::Value const& client_data); int increment_time_spent_uncreated(); bool is_empty(Workspaces& workspace_manager); @@ -49,18 +50,18 @@ class CreateWindow { 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, - const Json::Value& clients_json = Json::Value::nullRef); + const Json::Value& clients_data = Json::Value::nullRef); std::string& select_icon(std::map& icons_map); Gtk::Button& button() { return button_; }; @@ -74,21 +75,20 @@ class Workspace { bool is_empty() const { return windows_ == 0; }; bool is_urgent() const { return is_urgent_; }; - auto handle_clicked(GdkEventButton* bt) -> bool; + bool handle_clicked(GdkEventButton* bt) const; void set_active(bool value = true) { active_ = value; }; void set_persistent(bool value = true) { is_persistent_ = value; }; void set_urgent(bool value = true) { is_urgent_ = value; }; void set_visible(bool value = true) { is_visible_ = value; }; 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(CreateWindow create_window_paylod); - std::string remove_window(WindowAddress addr); + void set_name(std::string const& value) { name_ = value; }; + bool contains_window(WindowAddress const& addr) const { return window_map_.contains(addr); } + void insert_window(WorkspaceWindow create_window_paylod); + std::string remove_window(WindowAddress const& addr); void initialize_window_map(const Json::Value& clients_data); - bool on_window_opened(CreateWindow create_window_paylod); - - std::optional on_window_closed(WindowAddress& addr); + bool on_window_opened(WorkspaceWindow const& create_window_paylod); + std::optional on_window_closed(WindowAddress const& addr); void update(const std::string& format, const std::string& icon); @@ -132,21 +132,21 @@ class Workspaces : public AModule, public EventHandler { bool window_rewrite_config_uses_title() const { return any_window_rewrite_rule_uses_title_; } private: - void onEvent(const std::string&) override; + void onEvent(const std::string& e) override; void update_window_count(); void sort_workspaces(); - void create_workspace(Json::Value& workspace_data, - const Json::Value& clients_data = Json::Value::nullRef); - void remove_workspace(std::string name); - void set_urgent_workspace(std::string windowaddress); + void create_workspace(Json::Value const& workspace_data, + Json::Value const& clients_data = Json::Value::nullRef); + void remove_workspace(std::string const& name); + void set_urgent_workspace(std::string const& windowaddress); void parse_config(const Json::Value& config); void register_ipc(); - void on_window_opened(std::string payload); - void on_window_closed(std::string payload); - void on_window_moved(std::string payload); + void on_window_opened(std::string const& payload); + void on_window_closed(std::string const& payload); + void on_window_moved(std::string const& payload); - int window_rewrite_priority_function(std::string& window_rule); + int window_rewrite_priority_function(std::string const& window_rule); bool all_outputs_ = false; bool show_special_ = false; @@ -178,7 +178,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 windows_to_create_; std::vector ignore_workspaces_; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 4facacfb..d9760e3e 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -14,23 +14,28 @@ namespace waybar::modules::hyprland { -int Workspaces::window_rewrite_priority_function(std::string &window_rule) { +namespace { +auto constexpr WINDOW_CREATION_TIMEOUT = 2; +} + +int Workspaces::window_rewrite_priority_function(std::string const &window_rule) { // Rules that match against title are prioritized // Rules that don't specify if they're matching against either title or class are deprioritized - bool has_title = window_rule.find("title") != std::string::npos; - bool has_class = window_rule.find("class") != std::string::npos; + bool const has_title = window_rule.find("title") != std::string::npos; + bool const has_class = window_rule.find("class") != std::string::npos; if (has_title && has_class) { any_window_rewrite_rule_uses_title_ = true; return 3; - } else if (has_title) { + } + if (has_title) { any_window_rewrite_rule_uses_title_ = true; return 2; - } else if (has_class) { - return 1; - } else { - return 0; } + if (has_class) { + return 1; + } + return 0; } Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config) @@ -51,7 +56,7 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value } auto Workspaces::parse_config(const Json::Value &config) -> void { - Json::Value config_format = config["format"]; + const Json::Value &config_format = config["format"]; format_ = config_format.isString() ? config_format.asString() : "{name}"; with_icon_ = format_.find("{icon}") != std::string::npos; @@ -109,13 +114,13 @@ auto Workspaces::parse_config(const Json::Value &config) -> void { } } - Json::Value format_window_separator = config["format-window-separator"]; + const Json::Value &format_window_separator = config["format-window-separator"]; format_window_separator_ = format_window_separator.isString() ? format_window_separator.asString() : " "; - Json::Value window_rewrite = config["window-rewrite"]; + const Json::Value &window_rewrite = config["window-rewrite"]; - Json::Value window_rewrite_default_config = config["window-rewrite-default"]; + const Json::Value &window_rewrite_default_config = config["window-rewrite-default"]; std::string window_rewrite_default = window_rewrite_default_config.isString() ? window_rewrite_default_config.asString() : "?"; @@ -152,13 +157,13 @@ auto Workspaces::register_ipc() -> void { } auto Workspaces::update() -> void { - for (std::string workspace_to_remove : workspaces_to_remove_) { + for (const std::string &workspace_to_remove : workspaces_to_remove_) { remove_workspace(workspace_to_remove); } workspaces_to_remove_.clear(); - for (Json::Value &workspace_to_create : workspaces_to_create_) { + for (Json::Value const &workspace_to_create : workspaces_to_create_) { create_workspace(workspace_to_create); } @@ -195,7 +200,7 @@ auto Workspaces::update() -> void { } bool any_window_created = false; - std::vector not_created; + std::vector not_created; for (auto &window_payload : windows_to_create_) { bool created = false; @@ -207,7 +212,6 @@ auto Workspaces::update() -> void { } } 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); } @@ -334,7 +338,7 @@ void Workspaces::onEvent(const std::string &ev) { dp.emit(); } -void Workspaces::on_window_opened(std::string payload) { +void Workspaces::on_window_opened(std::string const &payload) { size_t last_comma_idx = 0; size_t next_comma_idx = payload.find(','); std::string window_address = payload.substr(last_comma_idx, next_comma_idx - last_comma_idx); @@ -351,11 +355,10 @@ 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_.emplace_back( - CreateWindow(workspace_name, window_address, window_class, window_title)); + windows_to_create_.emplace_back(workspace_name, window_address, window_class, window_title); } -void Workspaces::on_window_closed(std::string addr) { +void Workspaces::on_window_closed(std::string const &addr) { for (auto &workspace : workspaces_) { if (workspace->on_window_closed(addr)) { break; @@ -363,7 +366,7 @@ void Workspaces::on_window_closed(std::string addr) { } } -void Workspaces::on_window_moved(std::string payload) { +void Workspaces::on_window_moved(std::string const &payload) { size_t last_comma_idx = 0; size_t next_comma_idx = payload.find(','); std::string window_address = payload.substr(last_comma_idx, next_comma_idx - last_comma_idx); @@ -395,7 +398,7 @@ void Workspaces::on_window_moved(std::string payload) { // ...and add it to the new workspace if (!window_repr.empty()) { - windows_to_create_.emplace_back(CreateWindow(workspace_name, window_address, window_repr)); + windows_to_create_.emplace_back(workspace_name, window_address, window_repr); } } @@ -426,37 +429,35 @@ void Workspace::initialize_window_map(const Json::Value &clients_data) { } } -void Workspace::insert_window(CreateWindow create_window_paylod) { +void Workspace::insert_window(WorkspaceWindow create_window_paylod) { if (!create_window_paylod.is_empty(workspace_manager_)) { window_map_[create_window_paylod.addr()] = create_window_paylod.repr(workspace_manager_); } }; -std::string Workspace::remove_window(WindowAddress addr) { +std::string Workspace::remove_window(WindowAddress const &addr) { std::string window_repr = window_map_[addr]; window_map_.erase(addr); - return window_repr; } -bool Workspace::on_window_opened(CreateWindow create_window_paylod) { +bool Workspace::on_window_opened(WorkspaceWindow const &create_window_paylod) { if (create_window_paylod.workspace_name() == name()) { insert_window(create_window_paylod); return true; - } else { - return false; } + return false; } -std::optional Workspace::on_window_closed(WindowAddress &addr) { +std::optional Workspace::on_window_closed(WindowAddress const &addr) { if (window_map_.contains(addr)) { return remove_window(addr); - } else { - return {}; } + return {}; } -void Workspaces::create_workspace(Json::Value &workspace_data, const Json::Value &clients_data) { +void Workspaces::create_workspace(Json::Value const &workspace_data, + Json::Value const &clients_data) { // avoid recreating existing workspaces auto workspace_name = workspace_data["name"].asString(); auto workspace = std::find_if( @@ -477,7 +478,7 @@ void Workspaces::create_workspace(Json::Value &workspace_data, const Json::Value new_workspace_button.show_all(); } -void Workspaces::remove_workspace(std::string name) { +void Workspaces::remove_workspace(std::string const &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(); @@ -816,7 +817,7 @@ std::string &Workspace::select_icon(std::map &icons_ma return name_; } -auto Workspace::handle_clicked(GdkEventButton *bt) -> bool { +bool Workspace::handle_clicked(GdkEventButton *bt) const { try { if (id() > 0) { // normal or numbered persistent gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id())); @@ -834,7 +835,7 @@ auto Workspace::handle_clicked(GdkEventButton *bt) -> bool { return false; } -void Workspaces::set_urgent_workspace(std::string windowaddress) { +void Workspaces::set_urgent_workspace(std::string const &windowaddress) { const Json::Value clients_json = gIPC->getSocket1JsonReply("clients"); int workspace_id = -1; @@ -863,58 +864,62 @@ 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) { +WorkspaceWindow::WorkspaceWindow(std::string workspace_name, WindowAddress window_address, + std::string window_repr) + : window_(std::move(window_repr)), + window_address_(std::move(window_address)), + workspace_name_(std::move(workspace_name)) { clear_addr(); clear_workspace_name(); } -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) { +WorkspaceWindow::WorkspaceWindow(std::string workspace_name, WindowAddress window_address, + std::string window_class, std::string window_title) + : window_(std::make_pair(std::move(window_class), std::move(window_title))), + window_address_(std::move(window_address)), + workspace_name_(std::move(workspace_name)) { clear_addr(); clear_workspace_name(); } -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()); +WorkspaceWindow::WorkspaceWindow(Json::Value const &client_data) + : window_(std::make_pair(client_data["class"].asString(), client_data["title"].asString())), + window_address_(client_data["address"].asString()), + workspace_name_(client_data["workspace"]["name"].asString()) { clear_addr(); clear_workspace_name(); } -std::string CreateWindow::repr(Workspaces &workspace_manager) { +std::string WorkspaceWindow::repr(Workspaces &workspace_manager) { if (std::holds_alternative(window_)) { return std::get(window_); - } else if (std::holds_alternative(window_)) { + } + 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 ""; } + // Unreachable + spdlog::error("WorkspaceWindow::repr: Unreachable"); + throw std::runtime_error("WorkspaceWindow::repr: Unreachable"); } -bool CreateWindow::is_empty(Workspaces &workspace_manager) { +bool WorkspaceWindow::is_empty(Workspaces &workspace_manager) { if (std::holds_alternative(window_)) { return std::get(window_).empty(); - } else if (std::holds_alternative(window_)) { + } + 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; } + // Unreachable + spdlog::error("WorkspaceWindow::is_empty: Unreachable"); + throw std::runtime_error("WorkspaceWindow::is_empty: Unreachable"); } -int CreateWindow::increment_time_spent_uncreated() { return time_spent_uncreated_++; } +int WorkspaceWindow::increment_time_spent_uncreated() { return time_spent_uncreated_++; } -void CreateWindow::clear_addr() { +void WorkspaceWindow::clear_addr() { // substr(2, ...) is necessary because Hyprland's JSON follows this format: // 0x{ADDR} // While Hyprland's IPC follows this format: @@ -928,7 +933,7 @@ void CreateWindow::clear_addr() { } } -void CreateWindow::clear_workspace_name() { +void WorkspaceWindow::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 @@ -943,7 +948,7 @@ void CreateWindow::clear_workspace_name() { } } -void CreateWindow::move_to_worksace(std::string &new_workspace_name) { +void WorkspaceWindow::move_to_worksace(std::string &new_workspace_name) { workspace_name_ = new_workspace_name; } From 7576611782f70f3fffc7ce78692332b7a5675ec0 Mon Sep 17 00:00:00 2001 From: zjeffer <4633209+zjeffer@users.noreply.github.com> Date: Sat, 21 Oct 2023 17:06:02 +0200 Subject: [PATCH 2/5] formatting --- src/modules/network.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/network.cpp b/src/modules/network.cpp index d203ec7b..654afbe8 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -655,8 +655,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { higher priority. Disable router -> RTA_GATEWAY -> up new router -> set higher priority added checking route id **/ - if (!is_del_event && - ((net->ifid_ == -1) || (priority < net->route_priority))) { + if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority))) { // Clear if's state for the case were there is a higher priority // route on a different interface. net->clearIface(); From 2d614c68f585bd7c0c5df37d1f5017b57e33365b Mon Sep 17 00:00:00 2001 From: zjeffer <4633209+zjeffer@users.noreply.github.com> Date: Sat, 21 Oct 2023 18:15:22 +0200 Subject: [PATCH 3/5] code review --- include/modules/hyprland/workspaces.hpp | 18 ++++++------- src/modules/hyprland/workspaces.cpp | 34 ++++++++++++------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 6ca2877b..f2ca74ed 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -26,13 +26,13 @@ namespace waybar::modules::hyprland { class Workspaces; -class WorkspaceWindow { +class WindowCreationPayload { public: - WorkspaceWindow(std::string workspace_name, WindowAddress window_address, - std::string window_repr); - WorkspaceWindow(std::string workspace_name, WindowAddress window_address, - std::string window_class, std::string window_title); - WorkspaceWindow(Json::Value const& client_data); + WindowCreationPayload(std::string workspace_name, WindowAddress window_address, + std::string window_repr); + WindowCreationPayload(std::string workspace_name, WindowAddress window_address, + std::string window_class, std::string window_title); + WindowCreationPayload(Json::Value const& client_data); int increment_time_spent_uncreated(); bool is_empty(Workspaces& workspace_manager); @@ -83,11 +83,11 @@ class Workspace { void set_windows(uint value) { windows_ = value; }; void set_name(std::string const& value) { name_ = value; }; bool contains_window(WindowAddress const& addr) const { return window_map_.contains(addr); } - void insert_window(WorkspaceWindow create_window_paylod); + void insert_window(WindowCreationPayload create_window_paylod); std::string remove_window(WindowAddress const& addr); void initialize_window_map(const Json::Value& clients_data); - bool on_window_opened(WorkspaceWindow const& create_window_paylod); + bool on_window_opened(WindowCreationPayload const& create_window_paylod); std::optional on_window_closed(WindowAddress const& addr); void update(const std::string& format, const std::string& icon); @@ -178,7 +178,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 windows_to_create_; std::vector ignore_workspaces_; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index d9760e3e..e70ad46e 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -14,10 +14,6 @@ namespace waybar::modules::hyprland { -namespace { -auto constexpr WINDOW_CREATION_TIMEOUT = 2; -} - int Workspaces::window_rewrite_priority_function(std::string const &window_rule) { // Rules that match against title are prioritized // Rules that don't specify if they're matching against either title or class are deprioritized @@ -200,7 +196,7 @@ auto Workspaces::update() -> void { } bool any_window_created = false; - std::vector not_created; + std::vector not_created; for (auto &window_payload : windows_to_create_) { bool created = false; @@ -212,6 +208,7 @@ auto Workspaces::update() -> void { } } if (!created) { + static auto const WINDOW_CREATION_TIMEOUT = 2; if (window_payload.increment_time_spent_uncreated() < WINDOW_CREATION_TIMEOUT) { not_created.push_back(window_payload); } @@ -429,7 +426,7 @@ void Workspace::initialize_window_map(const Json::Value &clients_data) { } } -void Workspace::insert_window(WorkspaceWindow create_window_paylod) { +void Workspace::insert_window(WindowCreationPayload create_window_paylod) { if (!create_window_paylod.is_empty(workspace_manager_)) { window_map_[create_window_paylod.addr()] = create_window_paylod.repr(workspace_manager_); } @@ -441,7 +438,7 @@ std::string Workspace::remove_window(WindowAddress const &addr) { return window_repr; } -bool Workspace::on_window_opened(WorkspaceWindow const &create_window_paylod) { +bool Workspace::on_window_opened(WindowCreationPayload const &create_window_paylod) { if (create_window_paylod.workspace_name() == name()) { insert_window(create_window_paylod); return true; @@ -864,8 +861,8 @@ std::string Workspaces::get_rewrite(std::string window_class, std::string window return window_rewrite_rules_.get(window_repr_key); } -WorkspaceWindow::WorkspaceWindow(std::string workspace_name, WindowAddress window_address, - std::string window_repr) +WindowCreationPayload::WindowCreationPayload(std::string workspace_name, + WindowAddress window_address, std::string window_repr) : window_(std::move(window_repr)), window_address_(std::move(window_address)), workspace_name_(std::move(workspace_name)) { @@ -873,8 +870,9 @@ WorkspaceWindow::WorkspaceWindow(std::string workspace_name, WindowAddress windo clear_workspace_name(); } -WorkspaceWindow::WorkspaceWindow(std::string workspace_name, WindowAddress window_address, - std::string window_class, std::string window_title) +WindowCreationPayload::WindowCreationPayload(std::string workspace_name, + WindowAddress window_address, std::string window_class, + std::string window_title) : window_(std::make_pair(std::move(window_class), std::move(window_title))), window_address_(std::move(window_address)), workspace_name_(std::move(workspace_name)) { @@ -882,7 +880,7 @@ WorkspaceWindow::WorkspaceWindow(std::string workspace_name, WindowAddress windo clear_workspace_name(); } -WorkspaceWindow::WorkspaceWindow(Json::Value const &client_data) +WindowCreationPayload::WindowCreationPayload(Json::Value const &client_data) : window_(std::make_pair(client_data["class"].asString(), client_data["title"].asString())), window_address_(client_data["address"].asString()), workspace_name_(client_data["workspace"]["name"].asString()) { @@ -890,7 +888,7 @@ WorkspaceWindow::WorkspaceWindow(Json::Value const &client_data) clear_workspace_name(); } -std::string WorkspaceWindow::repr(Workspaces &workspace_manager) { +std::string WindowCreationPayload::repr(Workspaces &workspace_manager) { if (std::holds_alternative(window_)) { return std::get(window_); } @@ -903,7 +901,7 @@ std::string WorkspaceWindow::repr(Workspaces &workspace_manager) { throw std::runtime_error("WorkspaceWindow::repr: Unreachable"); } -bool WorkspaceWindow::is_empty(Workspaces &workspace_manager) { +bool WindowCreationPayload::is_empty(Workspaces &workspace_manager) { if (std::holds_alternative(window_)) { return std::get(window_).empty(); } @@ -917,9 +915,9 @@ bool WorkspaceWindow::is_empty(Workspaces &workspace_manager) { throw std::runtime_error("WorkspaceWindow::is_empty: Unreachable"); } -int WorkspaceWindow::increment_time_spent_uncreated() { return time_spent_uncreated_++; } +int WindowCreationPayload::increment_time_spent_uncreated() { return time_spent_uncreated_++; } -void WorkspaceWindow::clear_addr() { +void WindowCreationPayload::clear_addr() { // substr(2, ...) is necessary because Hyprland's JSON follows this format: // 0x{ADDR} // While Hyprland's IPC follows this format: @@ -933,7 +931,7 @@ void WorkspaceWindow::clear_addr() { } } -void WorkspaceWindow::clear_workspace_name() { +void WindowCreationPayload::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 @@ -948,7 +946,7 @@ void WorkspaceWindow::clear_workspace_name() { } } -void WorkspaceWindow::move_to_worksace(std::string &new_workspace_name) { +void WindowCreationPayload::move_to_worksace(std::string &new_workspace_name) { workspace_name_ = new_workspace_name; } From acc911737d9ea3a9a7b7f763a01c2873046c9f49 Mon Sep 17 00:00:00 2001 From: zjeffer <4633209+zjeffer@users.noreply.github.com> Date: Sat, 21 Oct 2023 18:53:53 +0200 Subject: [PATCH 4/5] update window count inside the on_window_* functions --- src/modules/hyprland/workspaces.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index e70ad46e..29a8868e 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -289,13 +289,10 @@ void Workspaces::onEvent(const std::string &ev) { workspaces_to_remove_.push_back(workspace); } } else if (eventName == "openwindow") { - update_window_count(); on_window_opened(payload); } else if (eventName == "closewindow") { - update_window_count(); on_window_closed(payload); } else if (eventName == "movewindow") { - update_window_count(); on_window_moved(payload); } else if (eventName == "urgent") { set_urgent_workspace(payload); @@ -336,6 +333,7 @@ void Workspaces::onEvent(const std::string &ev) { } void Workspaces::on_window_opened(std::string const &payload) { + update_window_count(); size_t last_comma_idx = 0; size_t next_comma_idx = payload.find(','); std::string window_address = payload.substr(last_comma_idx, next_comma_idx - last_comma_idx); @@ -356,6 +354,7 @@ void Workspaces::on_window_opened(std::string const &payload) { } void Workspaces::on_window_closed(std::string const &addr) { + update_window_count(); for (auto &workspace : workspaces_) { if (workspace->on_window_closed(addr)) { break; @@ -364,6 +363,7 @@ void Workspaces::on_window_closed(std::string const &addr) { } void Workspaces::on_window_moved(std::string const &payload) { + update_window_count(); size_t last_comma_idx = 0; size_t next_comma_idx = payload.find(','); std::string window_address = payload.substr(last_comma_idx, next_comma_idx - last_comma_idx); From dab1493644582fb36ecdcb233fc7bfad6ec9fb40 Mon Sep 17 00:00:00 2001 From: zjeffer <4633209+zjeffer@users.noreply.github.com> Date: Sat, 21 Oct 2023 19:33:55 +0200 Subject: [PATCH 5/5] cleanup onEvent, dont use try/catch for flow control --- include/modules/hyprland/workspaces.hpp | 17 ++- src/modules/hyprland/workspaces.cpp | 169 ++++++++++++++---------- 2 files changed, 111 insertions(+), 75 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index f2ca74ed..53bc55fc 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -88,7 +88,7 @@ class Workspace { void initialize_window_map(const Json::Value& clients_data); bool on_window_opened(WindowCreationPayload const& create_window_paylod); - std::optional on_window_closed(WindowAddress const& addr); + std::optional close_window(WindowAddress const& addr); void update(const std::string& format, const std::string& icon); @@ -127,7 +127,7 @@ class Workspaces : public AModule, public EventHandler { std::string get_rewrite(std::string window_class, std::string window_title); std::string& get_window_separator() { return format_window_separator_; } - bool is_workspace_ignored(std::string& workspace_name); + bool is_workspace_ignored(std::string const& workspace_name); bool window_rewrite_config_uses_title() const { return any_window_rewrite_rule_uses_title_; } @@ -142,10 +142,23 @@ class Workspaces : public AModule, public EventHandler { void parse_config(const Json::Value& config); void register_ipc(); + // workspace events + void on_workspace_activated(std::string const& payload); + void on_workspace_destroyed(std::string const& payload); + void on_workspace_created(std::string const& payload); + void on_workspace_moved(std::string const& payload); + void on_workspace_renamed(std::string const& payload); + + // monitor events + void on_monitor_focused(std::string const& payload); + + // window events void on_window_opened(std::string const& payload); void on_window_closed(std::string const& payload); void on_window_moved(std::string const& payload); + void on_window_title_event(std::string const& payload); + int window_rewrite_priority_function(std::string const& window_rule); bool all_outputs_ = false; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 29a8868e..aa84b454 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -225,7 +225,7 @@ auto Workspaces::update() -> void { AModule::update(); } -bool isDoubleSpecial(std::string &workspace_name) { +bool isDoubleSpecial(std::string const &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. @@ -233,7 +233,7 @@ bool isDoubleSpecial(std::string &workspace_name) { return workspace_name.find("special:special:") != std::string::npos; } -bool Workspaces::is_workspace_ignored(std::string &name) { +bool Workspaces::is_workspace_ignored(std::string const &name) { for (auto &rule : ignore_workspaces_) { if (std::regex_match(name, rule)) { return true; @@ -250,44 +250,15 @@ void Workspaces::onEvent(const std::string &ev) { std::string payload = ev.substr(eventName.size() + 2); if (eventName == "workspace") { - active_workspace_name_ = payload; - + on_workspace_activated(payload); } else if (eventName == "destroyworkspace") { - if (!isDoubleSpecial(payload)) { - workspaces_to_remove_.push_back(payload); - } + on_workspace_destroyed(payload); } else if (eventName == "createworkspace") { - const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); - - if (!is_workspace_ignored(payload)) { - 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")) && !isDoubleSpecial(payload)) { - workspaces_to_create_.push_back(workspace_json); - break; - } - } - } + on_workspace_created(payload); } else if (eventName == "focusedmon") { - active_workspace_name_ = payload.substr(payload.find(',') + 1); - + on_monitor_focused(payload); } else if (eventName == "moveworkspace" && !all_outputs()) { - std::string workspace = payload.substr(0, payload.find(',')); - std::string new_output = payload.substr(payload.find(',') + 1); - if (bar_.output->name == new_output) { // TODO: implement this better - const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); - for (Json::Value workspace_json : workspaces_json) { - std::string name = workspace_json["name"].asString(); - if (name == workspace && bar_.output->name == workspace_json["monitor"].asString()) { - workspaces_to_create_.push_back(workspace_json); - break; - } - } - } else { - workspaces_to_remove_.push_back(workspace); - } + on_workspace_moved(payload); } else if (eventName == "openwindow") { on_window_opened(payload); } else if (eventName == "closewindow") { @@ -297,41 +268,76 @@ void Workspaces::onEvent(const std::string &ev) { } else if (eventName == "urgent") { set_urgent_workspace(payload); } else if (eventName == "renameworkspace") { - std::string workspace_id_str = payload.substr(0, payload.find(',')); - int workspace_id = workspace_id_str == "special" ? -99 : std::stoi(workspace_id_str); - std::string new_name = payload.substr(payload.find(',') + 1); - for (auto &workspace : workspaces_) { - if (workspace->id() == workspace_id) { - if (workspace->name() == active_workspace_name_) { - active_workspace_name_ = new_name; - } - workspace->set_name(new_name); - break; - } - } + on_workspace_renamed(payload); } else if (eventName == "windowtitle") { - auto window_workspace = - std::find_if(workspaces_.begin(), workspaces_.end(), - [payload](auto &workspace) { return workspace->contains_window(payload); }); - - if (window_workspace != workspaces_.end()) { - Json::Value clients_data = gIPC->getSocket1JsonReply("clients"); - std::string json_window_address = fmt::format("0x{}", payload); - - auto client = std::find_if(clients_data.begin(), clients_data.end(), - [json_window_address](auto &client) { - return client["address"].asString() == json_window_address; - }); - - if (!client->empty()) { - (*window_workspace)->insert_window({*client}); - } - } + on_window_title_event(payload); } dp.emit(); } +void Workspaces::on_workspace_activated(std::string const &payload) { + active_workspace_name_ = payload; +} + +void Workspaces::on_workspace_destroyed(std::string const &payload) { + if (!isDoubleSpecial(payload)) { + workspaces_to_remove_.push_back(payload); + } +} + +void Workspaces::on_workspace_created(std::string const &payload) { + const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); + + if (!is_workspace_ignored(payload)) { + 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")) && !isDoubleSpecial(payload)) { + workspaces_to_create_.push_back(workspace_json); + break; + } + } + } +} + +void Workspaces::on_workspace_moved(std::string const &payload) { + std::string workspace = payload.substr(0, payload.find(',')); + std::string new_output = payload.substr(payload.find(',') + 1); + if (bar_.output->name == new_output) { // TODO: implement this better + const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); + for (Json::Value workspace_json : workspaces_json) { + std::string name = workspace_json["name"].asString(); + if (name == workspace && bar_.output->name == workspace_json["monitor"].asString()) { + workspaces_to_create_.push_back(workspace_json); + break; + } + } + } else { + workspaces_to_remove_.push_back(workspace); + } +} + +void Workspaces::on_workspace_renamed(std::string const &payload) { + std::string workspace_id_str = payload.substr(0, payload.find(',')); + int workspace_id = workspace_id_str == "special" ? -99 : std::stoi(workspace_id_str); + std::string new_name = payload.substr(payload.find(',') + 1); + for (auto &workspace : workspaces_) { + if (workspace->id() == workspace_id) { + if (workspace->name() == active_workspace_name_) { + active_workspace_name_ = new_name; + } + workspace->set_name(new_name); + break; + } + } +} + +void Workspaces::on_monitor_focused(std::string const &payload) { + active_workspace_name_ = payload.substr(payload.find(',') + 1); +} + void Workspaces::on_window_opened(std::string const &payload) { update_window_count(); size_t last_comma_idx = 0; @@ -356,7 +362,7 @@ void Workspaces::on_window_opened(std::string const &payload) { void Workspaces::on_window_closed(std::string const &addr) { update_window_count(); for (auto &workspace : workspaces_) { - if (workspace->on_window_closed(addr)) { + if (workspace->close_window(addr)) { break; } } @@ -384,12 +390,9 @@ void Workspaces::on_window_moved(std::string const &payload) { // Take the window's representation from the old workspace... for (auto &workspace : workspaces_) { - try { - window_repr = workspace->on_window_closed(window_address).value(); + if (auto window_addr = workspace->close_window(window_address); window_addr != std::nullopt) { + window_repr = window_addr.value(); break; - } catch (const std::bad_optional_access &e) { - // window was not found in this workspace - continue; } } @@ -399,6 +402,26 @@ void Workspaces::on_window_moved(std::string const &payload) { } } +void Workspaces::on_window_title_event(std::string const &payload) { + auto window_workspace = + std::find_if(workspaces_.begin(), workspaces_.end(), + [payload](auto &workspace) { return workspace->contains_window(payload); }); + + if (window_workspace != workspaces_.end()) { + Json::Value clients_data = gIPC->getSocket1JsonReply("clients"); + std::string json_window_address = fmt::format("0x{}", payload); + + auto client = + std::find_if(clients_data.begin(), clients_data.end(), [json_window_address](auto &client) { + return client["address"].asString() == json_window_address; + }); + + if (!client->empty()) { + (*window_workspace)->insert_window({*client}); + } + } +} + void Workspaces::update_window_count() { const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); for (auto &workspace : workspaces_) { @@ -446,11 +469,11 @@ bool Workspace::on_window_opened(WindowCreationPayload const &create_window_payl return false; } -std::optional Workspace::on_window_closed(WindowAddress const &addr) { +std::optional Workspace::close_window(WindowAddress const &addr) { if (window_map_.contains(addr)) { return remove_window(addr); } - return {}; + return std::nullopt; } void Workspaces::create_workspace(Json::Value const &workspace_data,