From b6d0a4b63fb298fe4df24a7679b683b65d64b727 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Sun, 28 Nov 2021 12:19:45 -0800 Subject: [PATCH] feat(bar): allow customization of bar modes Allow changing existing modes and adding new ones via `modes` configuration key. `modes` accepts a JSON object roughly described by the following type ```typescript type BarMode = { layer: 'bottom' | 'top' | 'overlay'; exclusive: bool; passthrough: bool; visible: bool; }; type BarModeList = { [name: string]: BarMode; }; ``` and will be merged with the default modes defined in `bar.cpp`. Note that with absence of other ways to set mode, only those defined in the `sway-bar(5)`[1] documentation could be used right now. [1]: https://github.com/swaywm/sway/blob/master/sway/sway-bar.5.scd --- src/bar.cpp | 62 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/src/bar.cpp b/src/bar.cpp index 26d64ec6..789bea95 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -63,6 +63,48 @@ const std::string_view Bar::MODE_DEFAULT = "default"; const std::string_view Bar::MODE_INVISIBLE = "invisible"; const std::string_view DEFAULT_BAR_ID = "bar-0"; +/* Deserializer for enum bar_layer */ +void from_json(const Json::Value& j, bar_layer& l) { + if (j == "bottom") { + l = bar_layer::BOTTOM; + } else if (j == "top") { + l = bar_layer::TOP; + } else if (j == "overlay") { + l = bar_layer::OVERLAY; + } +} + +/* Deserializer for struct bar_mode */ +void from_json(const Json::Value& j, bar_mode& m) { + if (j.isObject()) { + if (auto v = j["layer"]; v.isString()) { + from_json(v, m.layer); + } + if (auto v = j["exclusive"]; v.isBool()) { + m.exclusive = v.asBool(); + } + if (auto v = j["passthrough"]; v.isBool()) { + m.passthrough = v.asBool(); + } + if (auto v = j["visible"]; v.isBool()) { + m.visible = v.asBool(); + } + } +} + +/* Deserializer for JSON Object -> map + * Assumes that all the values in the object are deserializable to the same type. + */ +template ::value>> +void from_json(const Json::Value& j, std::map& m) { + if (j.isObject()) { + for (auto it = j.begin(); it != j.end(); ++it) { + from_json(*it, m[it.key().asString()]); + } + } +} + #ifdef HAVE_GTK_LAYER_SHELL struct GLSSurfaceImpl : public BarSurface, public sigc::trackable { GLSSurfaceImpl(Gtk::Window& window, struct waybar_output& output) : window_{window} { @@ -527,23 +569,15 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) surface_impl_->setPosition(position); surface_impl_->setSize(width, height); - /* Init "default" mode from globals */ - auto& default_mode = configured_modes[MODE_DEFAULT]; - if (config["layer"] == "top") { - default_mode.layer = bar_layer::TOP; - } else if (config["layer"] == "overlay") { - default_mode.layer = bar_layer::OVERLAY; + /* Read custom modes if available */ + if (auto modes = config.get("modes", {}); modes.isObject()) { + from_json(modes, configured_modes); } - if (config["exclusive"].isBool()) { - default_mode.exclusive = config["exclusive"].asBool(); - } + /* Update "default" mode with the global bar options */ + from_json(config, configured_modes[MODE_DEFAULT]); - if (config["passthrough"].isBool()) { - default_mode.passthrough = config["passthrough"].asBool(); - } - - if (auto mode = config["mode"]; mode.isString()) { + if (auto mode = config.get("mode", {}); mode.isString()) { setMode(config["mode"].asString()); } else { setMode(MODE_DEFAULT);