From f4b68f41e6d58e9659705d58d1fef7bd154ada38 Mon Sep 17 00:00:00 2001 From: "Rene D. Obermueller" Date: Sun, 4 May 2025 07:26:55 +0200 Subject: [PATCH] feat: sway/window: provide {marks} format replacement --- include/modules/sway/window.hpp | 6 ++-- man/waybar-sway-window.5.scd | 7 ++++ src/modules/sway/window.cpp | 57 ++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index 427c2e81..60cd2679 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -19,10 +19,11 @@ class Window : public AAppIconLabel, public sigc::trackable { auto update() -> void override; private: - void setClass(std::string classname, bool enable); + void setClass(const std::string& classname, bool enable); void onEvent(const struct Ipc::ipc_response&); void onCmd(const struct Ipc::ipc_response&); - std::tuple + std::tuple getFocusedNode(const Json::Value& nodes, std::string& output); void getTree(); @@ -35,6 +36,7 @@ class Window : public AAppIconLabel, public sigc::trackable { std::string old_app_id_; std::size_t app_nb_; std::string shell_; + std::string marks_; int floating_count_; util::JsonParser parser_; std::mutex mutex_; diff --git a/man/waybar-sway-window.5.scd b/man/waybar-sway-window.5.scd index a7eb4f05..6fa9170b 100644 --- a/man/waybar-sway-window.5.scd +++ b/man/waybar-sway-window.5.scd @@ -89,6 +89,11 @@ Addressed by *sway/window* default: false ++ If the workspace itself is focused and the workspace contains nodes or floating_nodes, show the workspace name. If not set, text remains empty but styles according to nodes in the workspace are still applied. +*show-hidden-marks*: ++ + typeof: bool ++ + default: false ++ + For the *{marks}* format replacement, include hidden marks that start with an underscore. + *rewrite*: ++ typeof: object ++ Rules to rewrite the module format output. See *rewrite rules*. @@ -117,6 +122,8 @@ Addressed by *sway/window* *{shell}*: The shell of the focused window. It's 'xwayland' when the window is running through xwayland, otherwise, it's 'xdg-shell'. +*{marks}*: Marks of the window. + # REWRITE RULES *rewrite* is an object where keys are regular expressions and values are diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index 25e430a7..68655a76 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -41,8 +41,8 @@ void Window::onCmd(const struct Ipc::ipc_response& res) { std::lock_guard lock(mutex_); auto payload = parser_.parse(res.payload); auto output = payload["output"].isString() ? payload["output"].asString() : ""; - std::tie(app_nb_, floating_count_, windowId_, window_, app_id_, app_class_, shell_, layout_) = - getFocusedNode(payload["nodes"], output); + std::tie(app_nb_, floating_count_, windowId_, window_, app_id_, app_class_, shell_, layout_, + marks_) = getFocusedNode(payload["nodes"], output); updateAppIconName(app_id_, app_class_); dp.emit(); } catch (const std::exception& e) { @@ -96,7 +96,7 @@ auto Window::update() -> void { label_.set_markup(waybar::util::rewriteString( fmt::format(fmt::runtime(format_), fmt::arg("title", window_), fmt::arg("app_id", app_id_), - fmt::arg("shell", shell_)), + fmt::arg("shell", shell_), fmt::arg("marks", marks_)), config_["rewrite"])); if (tooltipEnabled()) { label_.set_tooltip_text(window_); @@ -108,7 +108,7 @@ auto Window::update() -> void { AAppIconLabel::update(); } -void Window::setClass(std::string classname, bool enable) { +void Window::setClass(const std::string& classname, bool enable) { if (enable) { if (!bar_.window.get_style_context()->has_class(classname)) { bar_.window.get_style_context()->add_class(classname); @@ -169,17 +169,31 @@ std::optional> getSingleChildNode( return {getSingleChildNode(child)}; } -std::tuple getWindowInfo(const Json::Value& node) { +std::tuple getWindowInfo( + const Json::Value& node, bool showHidden) { const auto app_id = node["app_id"].isString() ? node["app_id"].asString() : node["window_properties"]["instance"].asString(); const auto app_class = node["window_properties"]["class"].isString() ? node["window_properties"]["class"].asString() : ""; const auto shell = node["shell"].isString() ? node["shell"].asString() : ""; - return {app_id, app_class, shell}; + std::string marks = ""; + if (node["marks"].isArray()) { + for (const auto& m : node["marks"]) { + if (!m.isString() || (!showHidden && m.asString().at(0) == '_')) { + continue; + } + if (!marks.empty()) { + marks += ','; + } + marks += m.asString(); + } + } + return {app_id, app_class, shell, marks}; } -std::tuple +std::tuple gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Value& config_, const Bar& bar_, Json::Value& parentWorkspace, const Json::Value& immediateParent) { @@ -207,7 +221,8 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu "", "", "", - node["layout"].asString()}; + node["layout"].asString(), + ""}; } parentWorkspace = node; } else if ((node["type"].asString() == "con" || node["type"].asString() == "floating_con") && @@ -215,7 +230,8 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu // found node spdlog::trace("actual output {}, output found {}, node (focused) found {}", bar_.output->name, output, node["name"].asString()); - const auto [app_id, app_class, shell] = getWindowInfo(node); + const auto [app_id, app_class, shell, marks] = + getWindowInfo(node, config_["show-hidden-marks"].asBool()); int nb = node.size(); int floating_count = 0; std::string workspace_layout = ""; @@ -232,20 +248,21 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu app_id, app_class, shell, - workspace_layout}; + workspace_layout, + marks}; } // iterate - auto [nb, f, id, name, app_id, app_class, shell, workspace_layout] = + auto [nb, f, id, name, app_id, app_class, shell, workspace_layout, marks] = gfnWithWorkspace(node["nodes"], output, config_, bar_, parentWorkspace, node); - auto [nb2, f2, id2, name2, app_id2, app_class2, shell2, workspace_layout2] = + auto [nb2, f2, id2, name2, app_id2, app_class2, shell2, workspace_layout2, marks2] = gfnWithWorkspace(node["floating_nodes"], output, config_, bar_, parentWorkspace, node); // if ((id > 0 || ((id2 < 0 || name2.empty()) && id > -1)) && !name.empty()) { if ((id > 0) || (id2 < 0 && id > -1)) { - return {nb, f, id, name, app_id, app_class, shell, workspace_layout}; + return {nb, f, id, name, app_id, app_class, shell, workspace_layout, marks}; } else if (id2 > 0 && !name2.empty()) { - return {nb2, f2, id2, name2, app_id2, app_class, shell2, workspace_layout2}; + return {nb2, f2, id2, name2, app_id2, app_class, shell2, workspace_layout2, marks2}; } } @@ -258,10 +275,12 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu std::string app_id = ""; std::string app_class = ""; std::string workspace_layout = ""; + std::string marks = ""; if (all_leaf_nodes.first == 1) { const auto single_child = getSingleChildNode(immediateParent); if (single_child.has_value()) { - std::tie(app_id, app_class, workspace_layout) = getWindowInfo(single_child.value()); + std::tie(app_id, app_class, workspace_layout, marks) = + getWindowInfo(single_child.value(), config_["show-hidden-marks"].asBool()); } } return {all_leaf_nodes.first, @@ -273,13 +292,15 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu app_id, app_class, workspace_layout, - immediateParent["layout"].asString()}; + immediateParent["layout"].asString(), + marks}; } - return {0, 0, -1, "", "", "", "", ""}; + return {0, 0, -1, "", "", "", "", "", ""}; } -std::tuple +std::tuple Window::getFocusedNode(const Json::Value& nodes, std::string& output) { Json::Value placeholder = Json::Value::null; return gfnWithWorkspace(nodes, output, config_, bar_, placeholder, placeholder);