feat: sway/window: provide {marks} format replacement

This commit is contained in:
Rene D. Obermueller
2025-05-04 07:26:55 +02:00
parent 0332d2ebf8
commit f4b68f41e6
3 changed files with 50 additions and 20 deletions

View File

@ -19,10 +19,11 @@ class Window : public AAppIconLabel, public sigc::trackable {
auto update() -> void override; auto update() -> void override;
private: private:
void setClass(std::string classname, bool enable); void setClass(const std::string& classname, bool enable);
void onEvent(const struct Ipc::ipc_response&); void onEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&); void onCmd(const struct Ipc::ipc_response&);
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string> std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string,
std::string>
getFocusedNode(const Json::Value& nodes, std::string& output); getFocusedNode(const Json::Value& nodes, std::string& output);
void getTree(); void getTree();
@ -35,6 +36,7 @@ class Window : public AAppIconLabel, public sigc::trackable {
std::string old_app_id_; std::string old_app_id_;
std::size_t app_nb_; std::size_t app_nb_;
std::string shell_; std::string shell_;
std::string marks_;
int floating_count_; int floating_count_;
util::JsonParser parser_; util::JsonParser parser_;
std::mutex mutex_; std::mutex mutex_;

View File

@ -89,6 +89,11 @@ Addressed by *sway/window*
default: false ++ 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. 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*: ++ *rewrite*: ++
typeof: object ++ typeof: object ++
Rules to rewrite the module format output. See *rewrite rules*. 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 *{shell}*: The shell of the focused window. It's 'xwayland' when the window is
running through xwayland, otherwise, it's 'xdg-shell'. running through xwayland, otherwise, it's 'xdg-shell'.
*{marks}*: Marks of the window.
# REWRITE RULES # REWRITE RULES
*rewrite* is an object where keys are regular expressions and values are *rewrite* is an object where keys are regular expressions and values are

View File

@ -41,8 +41,8 @@ void Window::onCmd(const struct Ipc::ipc_response& res) {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
auto payload = parser_.parse(res.payload); auto payload = parser_.parse(res.payload);
auto output = payload["output"].isString() ? payload["output"].asString() : ""; auto output = payload["output"].isString() ? payload["output"].asString() : "";
std::tie(app_nb_, floating_count_, windowId_, window_, app_id_, app_class_, shell_, layout_) = std::tie(app_nb_, floating_count_, windowId_, window_, app_id_, app_class_, shell_, layout_,
getFocusedNode(payload["nodes"], output); marks_) = getFocusedNode(payload["nodes"], output);
updateAppIconName(app_id_, app_class_); updateAppIconName(app_id_, app_class_);
dp.emit(); dp.emit();
} catch (const std::exception& e) { } catch (const std::exception& e) {
@ -96,7 +96,7 @@ auto Window::update() -> void {
label_.set_markup(waybar::util::rewriteString( label_.set_markup(waybar::util::rewriteString(
fmt::format(fmt::runtime(format_), fmt::arg("title", window_), fmt::arg("app_id", app_id_), 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"])); config_["rewrite"]));
if (tooltipEnabled()) { if (tooltipEnabled()) {
label_.set_tooltip_text(window_); label_.set_tooltip_text(window_);
@ -108,7 +108,7 @@ auto Window::update() -> void {
AAppIconLabel::update(); AAppIconLabel::update();
} }
void Window::setClass(std::string classname, bool enable) { void Window::setClass(const std::string& classname, bool enable) {
if (enable) { if (enable) {
if (!bar_.window.get_style_context()->has_class(classname)) { if (!bar_.window.get_style_context()->has_class(classname)) {
bar_.window.get_style_context()->add_class(classname); bar_.window.get_style_context()->add_class(classname);
@ -169,17 +169,31 @@ std::optional<std::reference_wrapper<const Json::Value>> getSingleChildNode(
return {getSingleChildNode(child)}; return {getSingleChildNode(child)};
} }
std::tuple<std::string, std::string, std::string> getWindowInfo(const Json::Value& node) { std::tuple<std::string, std::string, std::string, std::string> getWindowInfo(
const Json::Value& node, bool showHidden) {
const auto app_id = node["app_id"].isString() ? node["app_id"].asString() const auto app_id = node["app_id"].isString() ? node["app_id"].asString()
: node["window_properties"]["instance"].asString(); : node["window_properties"]["instance"].asString();
const auto app_class = node["window_properties"]["class"].isString() const auto app_class = node["window_properties"]["class"].isString()
? node["window_properties"]["class"].asString() ? node["window_properties"]["class"].asString()
: ""; : "";
const auto shell = node["shell"].isString() ? node["shell"].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::size_t, int, int, std::string, std::string, std::string, std::string, std::string> std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string,
std::string>
gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Value& config_, gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Value& config_,
const Bar& bar_, Json::Value& parentWorkspace, const Bar& bar_, Json::Value& parentWorkspace,
const Json::Value& immediateParent) { 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; parentWorkspace = node;
} else if ((node["type"].asString() == "con" || node["type"].asString() == "floating_con") && } 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 // found node
spdlog::trace("actual output {}, output found {}, node (focused) found {}", bar_.output->name, spdlog::trace("actual output {}, output found {}, node (focused) found {}", bar_.output->name,
output, node["name"].asString()); 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 nb = node.size();
int floating_count = 0; int floating_count = 0;
std::string workspace_layout = ""; std::string workspace_layout = "";
@ -232,20 +248,21 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu
app_id, app_id,
app_class, app_class,
shell, shell,
workspace_layout}; workspace_layout,
marks};
} }
// iterate // 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); 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); 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 || name2.empty()) && id > -1)) && !name.empty()) {
if ((id > 0) || (id2 < 0 && id > -1)) { 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()) { } 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_id = "";
std::string app_class = ""; std::string app_class = "";
std::string workspace_layout = ""; std::string workspace_layout = "";
std::string marks = "";
if (all_leaf_nodes.first == 1) { if (all_leaf_nodes.first == 1) {
const auto single_child = getSingleChildNode(immediateParent); const auto single_child = getSingleChildNode(immediateParent);
if (single_child.has_value()) { 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, return {all_leaf_nodes.first,
@ -273,13 +292,15 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu
app_id, app_id,
app_class, app_class,
workspace_layout, workspace_layout,
immediateParent["layout"].asString()}; immediateParent["layout"].asString(),
marks};
} }
return {0, 0, -1, "", "", "", "", ""}; return {0, 0, -1, "", "", "", "", "", ""};
} }
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string> std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string,
std::string>
Window::getFocusedNode(const Json::Value& nodes, std::string& output) { Window::getFocusedNode(const Json::Value& nodes, std::string& output) {
Json::Value placeholder = Json::Value::null; Json::Value placeholder = Json::Value::null;
return gfnWithWorkspace(nodes, output, config_, bar_, placeholder, placeholder); return gfnWithWorkspace(nodes, output, config_, bar_, placeholder, placeholder);