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] 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,