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
This commit is contained in:
Aleksei Bavshin 2021-11-28 12:19:45 -08:00
parent cf5ddb2a5e
commit b6d0a4b63f
No known key found for this signature in database
GPG Key ID: 4F071603387A382A

View File

@ -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<string compatible type, Value>
* Assumes that all the values in the object are deserializable to the same type.
*/
template <typename Key, typename Value,
typename = std::enable_if_t<std::is_convertible<std::string_view, Key>::value>>
void from_json(const Json::Value& j, std::map<Key, Value>& 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);