diff --git a/README.md b/README.md index 37c0cfc7..98b99a2d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Waybar [![Travis](https://travis-ci.org/Alexays/Waybar.svg?branch=master)](https://travis-ci.org/Alexays/Waybar) [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Paypal Donate](https://img.shields.io/badge/Donate-Paypal-2244dd.svg)](https://paypal.me/ARouillard)
![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png) +# Waybar [![Licence](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Paypal Donate](https://img.shields.io/badge/Donate-Paypal-2244dd.svg)](https://paypal.me/ARouillard)
![Waybar](https://raw.githubusercontent.com/alexays/waybar/master/preview-2.png) > Highly customizable Wayland bar for Sway and Wlroots based compositors.
> Available in Arch [community](https://www.archlinux.org/packages/community/x86_64/waybar/) or diff --git a/include/modules/river/tags.hpp b/include/modules/river/tags.hpp index f80b3c59..9b75fbd3 100644 --- a/include/modules/river/tags.hpp +++ b/include/modules/river/tags.hpp @@ -18,6 +18,7 @@ class Tags : public waybar::AModule { // Handlers for wayland events void handle_focused_tags(uint32_t tags); void handle_view_tags(struct wl_array *tags); + void handle_urgent_tags(uint32_t tags); struct zriver_status_manager_v1 *status_manager_; diff --git a/include/modules/sni/host.hpp b/include/modules/sni/host.hpp index f97900fd..8d321036 100644 --- a/include/modules/sni/host.hpp +++ b/include/modules/sni/host.hpp @@ -5,13 +5,15 @@ #include #include #include +#include "bar.hpp" #include "modules/sni/item.hpp" namespace waybar::modules::SNI { class Host { public: - Host(const std::size_t id, const Json::Value&, const std::function&)>&, + Host(const std::size_t id, const Json::Value&, const Bar&, + const std::function&)>&, const std::function&)>&); ~Host(); @@ -36,6 +38,7 @@ class Host { GCancellable* cancellable_ = nullptr; SnWatcher* watcher_ = nullptr; const Json::Value& config_; + const Bar& bar_; const std::function&)> on_add_; const std::function&)> on_remove_; }; diff --git a/include/modules/sni/item.hpp b/include/modules/sni/item.hpp index 1115145d..430c351c 100644 --- a/include/modules/sni/item.hpp +++ b/include/modules/sni/item.hpp @@ -14,6 +14,8 @@ #include #include +#include "bar.hpp" + namespace waybar::modules::SNI { struct ToolTip { @@ -23,7 +25,7 @@ struct ToolTip { class Item : public sigc::trackable { public: - Item(const std::string&, const std::string&, const Json::Value&); + Item(const std::string&, const std::string&, const Json::Value&, const Bar&); ~Item() = default; std::string bus_name; @@ -56,6 +58,7 @@ class Item : public sigc::trackable { bool item_is_menu = true; private: + void onConfigure(GdkEventConfigure* ev); void proxyReady(Glib::RefPtr& result); void setProperty(const Glib::ustring& name, Glib::VariantBase& value); void setStatus(const Glib::ustring& value); diff --git a/include/modules/sway/language.hpp b/include/modules/sway/language.hpp index b310b7f3..1faf52b3 100644 --- a/include/modules/sway/language.hpp +++ b/include/modules/sway/language.hpp @@ -21,10 +21,17 @@ class Language : public ALabel, public sigc::trackable { auto update() -> void; private: + enum class DispayedShortFlag { + None = 0, + ShortName = 1, + ShortDescription = 1 << 1 + }; + struct Layout { std::string full_name; std::string short_name; std::string variant; + std::string short_description; }; class XKBContext { @@ -36,6 +43,7 @@ class Language : public ALabel, public sigc::trackable { rxkb_context* context_ = nullptr; rxkb_layout* xkb_layout_ = nullptr; Layout* layout_ = nullptr; + std::map base_layouts_by_name_; }; void onEvent(const struct Ipc::ipc_response&); @@ -50,8 +58,8 @@ class Language : public ALabel, public sigc::trackable { Layout layout_; std::string tooltip_format_ = ""; std::map layouts_map_; - XKBContext xkb_context_; bool is_variant_displayed; + std::byte displayed_short_flag = static_cast(DispayedShortFlag::None); util::JsonParser parser_; std::mutex mutex_; diff --git a/man/waybar-cpu.5.scd b/man/waybar-cpu.5.scd index fbf6206f..679ca2ce 100644 --- a/man/waybar-cpu.5.scd +++ b/man/waybar-cpu.5.scd @@ -20,6 +20,11 @@ The *cpu* module displays the current cpu utilization. default: {usage}% ++ The format, how information should be displayed. On {} data gets inserted. +*format-icons*: ++ + typeof: array/object ++ + Based on the current usage, the corresponding icon gets selected. ++ + The order is *low* to *high*. Or by the state if it is an object. + *max-length*: ++ typeof: integer ++ The maximum length in character the module should display. diff --git a/man/waybar-memory.5.scd b/man/waybar-memory.5.scd index 3ff4c35b..0639c07c 100644 --- a/man/waybar-memory.5.scd +++ b/man/waybar-memory.5.scd @@ -22,6 +22,11 @@ Addressed by *memory* default: {percentage}% ++ The format, how information should be displayed. +*format-icons*: ++ + typeof: array/object ++ + Based on the current percentage, the corresponding icon gets selected. ++ + The order is *low* to *high*. Or by the state if it is an object. + *rotate*: ++ typeof: integer ++ Positive value to rotate the text label. diff --git a/man/waybar-river-tags.5.scd b/man/waybar-river-tags.5.scd index 0f027249..65b90332 100644 --- a/man/waybar-river-tags.5.scd +++ b/man/waybar-river-tags.5.scd @@ -15,7 +15,7 @@ Addressed by *river/tags* *num-tags*: ++ typeof: uint ++ default: 9 ++ - The number of tags that should be displayed. + The number of tags that should be displayed. Max 32. *tag-labels*: ++ typeof: array ++ @@ -34,8 +34,10 @@ Addressed by *river/tags* - *#tags button* - *#tags button.occupied* - *#tags button.focused* +- *#tags button.urgent* -Note that a tag can be both occupied and focused at the same time. +Note that occupied/focused/urgent status may overlap. That is, a tag may be +both occupied and focused at the same time. # SEE ALSO diff --git a/man/waybar-sway-language.5.scd b/man/waybar-sway-language.5.scd index 76bc7208..92a647e6 100644 --- a/man/waybar-sway-language.5.scd +++ b/man/waybar-sway-language.5.scd @@ -29,11 +29,13 @@ Addressed by *sway/language* # FORMAT REPLACEMENTS -*{short}*: Short name of layout (e.g. "en"). Equals to {}. +*{short}*: Short name of layout (e.g. "us"). Equals to {}. + +*{shortDescription}*: Short description of layout (e.g. "en"). *{long}*: Long name of layout (e.g. "English (Dvorak)"). -*{variant}*: Variant of layout (e.g. "Dvorak"). +*{variant}*: Variant of layout (e.g. "dvorak"). # EXAMPLES diff --git a/meson.build b/meson.build index 1c065f7f..835b70e3 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'waybar', 'cpp', 'c', - version: '0.9.7', + version: '0.9.8', license: 'MIT', meson_version: '>= 0.49.0', default_options : [ diff --git a/protocol/river-status-unstable-v1.xml b/protocol/river-status-unstable-v1.xml index a4d6f4e5..13affaa7 100644 --- a/protocol/river-status-unstable-v1.xml +++ b/protocol/river-status-unstable-v1.xml @@ -1,7 +1,7 @@ - Copyright 2020 Isaac Freund + Copyright 2020 The River Developers Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - + A global factory for objects that receive status information specific to river. It could be used to implement, for example, a status bar. @@ -47,7 +47,7 @@ - + This interface allows clients to receive information about the current windowing state of an output. @@ -75,12 +75,21 @@ + + + + Sent once on binding the interface and again whenever the set of + tags with at least one urgent view changes. + + + This interface allows clients to receive information about the current - focus of a seat. + focus of a seat. Note that (un)focused_output events will only be sent + if the client has bound the relevant wl_output globals. diff --git a/src/modules/cpu/common.cpp b/src/modules/cpu/common.cpp index 2ca74212..767cde92 100644 --- a/src/modules/cpu/common.cpp +++ b/src/modules/cpu/common.cpp @@ -26,9 +26,11 @@ auto waybar::modules::Cpu::update() -> void { event_box_.hide(); } else { event_box_.show(); + auto icons = std::vector{state}; label_.set_markup(fmt::format(format, fmt::arg("load", cpu_load), fmt::arg("usage", cpu_usage), + fmt::arg("icon", getIcon(cpu_usage, icons)), fmt::arg("max_frequency", max_frequency), fmt::arg("min_frequency", min_frequency), fmt::arg("avg_frequency", avg_frequency))); diff --git a/src/modules/memory/common.cpp b/src/modules/memory/common.cpp index 09ce8e83..31219ed6 100644 --- a/src/modules/memory/common.cpp +++ b/src/modules/memory/common.cpp @@ -38,8 +38,10 @@ auto waybar::modules::Memory::update() -> void { event_box_.hide(); } else { event_box_.show(); + auto icons = std::vector{state}; label_.set_markup(fmt::format(format, used_ram_percentage, + fmt::arg("icon", getIcon(used_ram_percentage, icons)), fmt::arg("total", total_ram_gigabytes), fmt::arg("percentage", used_ram_percentage), fmt::arg("used", used_ram_gigabytes), diff --git a/src/modules/river/tags.cpp b/src/modules/river/tags.cpp index e96b2016..2628af2d 100644 --- a/src/modules/river/tags.cpp +++ b/src/modules/river/tags.cpp @@ -22,14 +22,24 @@ static void listen_view_tags(void *data, struct zriver_output_status_v1 *zriver_ static_cast(data)->handle_view_tags(tags); } +static void listen_urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, + uint32_t tags) { + static_cast(data)->handle_urgent_tags(tags); +} + static const zriver_output_status_v1_listener output_status_listener_impl{ .focused_tags = listen_focused_tags, .view_tags = listen_view_tags, + .urgent_tags = listen_urgent_tags, }; static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { if (std::strcmp(interface, zriver_status_manager_v1_interface.name) == 0) { + version = std::min(version, 2); + if (version < ZRIVER_OUTPUT_STATUS_V1_URGENT_TAGS_SINCE_VERSION) { + spdlog::warn("river server does not support urgent tags"); + } static_cast(data)->status_manager_ = static_cast( wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, version)); } @@ -64,8 +74,9 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con } event_box_.add(box_); - // Default to 9 tags - const uint32_t num_tags = config["num-tags"].isUInt() ? config_["num-tags"].asUInt() : 9; + // Default to 9 tags, cap at 32 + const uint32_t num_tags = + config["num-tags"].isUInt() ? std::min(32, config_["num-tags"].asUInt()) : 9; std::vector tag_labels(num_tags); for (uint32_t tag = 0; tag < num_tags; ++tag) { @@ -129,4 +140,16 @@ void Tags::handle_view_tags(struct wl_array *view_tags) { } } +void Tags::handle_urgent_tags(uint32_t tags) { + uint32_t i = 0; + for (auto &button : buttons_) { + if ((1 << i) & tags) { + button.get_style_context()->add_class("urgent"); + } else { + button.get_style_context()->remove_class("urgent"); + } + ++i; + } +} + } /* namespace waybar::modules::river */ diff --git a/src/modules/sni/host.cpp b/src/modules/sni/host.cpp index 868fcd6e..414f1515 100644 --- a/src/modules/sni/host.cpp +++ b/src/modules/sni/host.cpp @@ -4,7 +4,7 @@ namespace waybar::modules::SNI { -Host::Host(const std::size_t id, const Json::Value& config, +Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar, const std::function&)>& on_add, const std::function&)>& on_remove) : bus_name_("org.kde.StatusNotifierHost-" + std::to_string(getpid()) + "-" + @@ -13,6 +13,7 @@ Host::Host(const std::size_t id, const Json::Value& config, bus_name_id_(Gio::DBus::own_name(Gio::DBus::BusType::BUS_TYPE_SESSION, bus_name_, sigc::mem_fun(*this, &Host::busAcquired))), config_(config), + bar_(bar), on_add_(on_add), on_remove_(on_remove) {} @@ -136,7 +137,7 @@ void Host::addRegisteredItem(std::string service) { return bus_name == item->bus_name && object_path == item->object_path; }); if (it == items_.end()) { - items_.emplace_back(new Item(bus_name, object_path, config_)); + items_.emplace_back(new Item(bus_name, object_path, config_, bar_)); on_add_(items_.back()); } } diff --git a/src/modules/sni/item.cpp b/src/modules/sni/item.cpp index d40f0ddf..991ccc4d 100644 --- a/src/modules/sni/item.cpp +++ b/src/modules/sni/item.cpp @@ -39,7 +39,7 @@ namespace waybar::modules::SNI { static const Glib::ustring SNI_INTERFACE_NAME = sn_item_interface_info()->name; static const unsigned UPDATE_DEBOUNCE_TIME = 10; -Item::Item(const std::string& bn, const std::string& op, const Json::Value& config) +Item::Item(const std::string& bn, const std::string& op, const Json::Value& config, const Bar& bar) : bus_name(bn), object_path(op), icon_size(16), @@ -54,6 +54,9 @@ Item::Item(const std::string& bn, const std::string& op, const Json::Value& conf if (config["show-passive-items"].isBool()) { show_passive_ = config["show-passive-items"].asBool(); } + + auto &window = const_cast(bar).window; + window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Item::onConfigure)); event_box.add(image); event_box.add_events(Gdk::BUTTON_PRESS_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); event_box.signal_button_press_event().connect(sigc::mem_fun(*this, &Item::handleClick)); @@ -73,6 +76,10 @@ Item::Item(const std::string& bn, const std::string& op, const Json::Value& conf interface); } +void Item::onConfigure(GdkEventConfigure* ev) { + this->updateImage(); +} + void Item::proxyReady(Glib::RefPtr& result) { try { this->proxy_ = Gio::DBus::Proxy::create_for_bus_finish(result); diff --git a/src/modules/sni/tray.cpp b/src/modules/sni/tray.cpp index ae3702c2..e73c9eb4 100644 --- a/src/modules/sni/tray.cpp +++ b/src/modules/sni/tray.cpp @@ -7,7 +7,7 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config) : AModule(config, "tray", id), box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), watcher_(SNI::Watcher::getInstance()), - host_(nb_hosts_, config, std::bind(&Tray::onAdd, this, std::placeholders::_1), + host_(nb_hosts_, config, bar, std::bind(&Tray::onAdd, this, std::placeholders::_1), std::bind(&Tray::onRemove, this, std::placeholders::_1)) { spdlog::warn( "For a functional tray you must have libappindicator-* installed and export " diff --git a/src/modules/sway/language.cpp b/src/modules/sway/language.cpp index 5f3ce065..85dc769e 100644 --- a/src/modules/sway/language.cpp +++ b/src/modules/sway/language.cpp @@ -20,6 +20,12 @@ const std::string Language::XKB_ACTIVE_LAYOUT_NAME_KEY = "xkb_active_layout_name Language::Language(const std::string& id, const Json::Value& config) : ALabel(config, "language", id, "{}", 0, true) { is_variant_displayed = format_.find("{variant}") != std::string::npos; + if (format_.find("{}") != std::string::npos || format_.find("{short}") != std::string::npos) { + displayed_short_flag |= static_cast(DispayedShortFlag::ShortName); + } + if (format_.find("{shortDescription}") != std::string::npos) { + displayed_short_flag |= static_cast(DispayedShortFlag::ShortDescription); + } if (config.isMember("tooltip-format")) { tooltip_format_ = config["tooltip-format"].asString(); } @@ -88,8 +94,10 @@ void Language::onEvent(const struct Ipc::ipc_response& res) { } auto Language::update() -> void { + std::lock_guard lock(mutex_); auto display_layout = trim(fmt::format(format_, fmt::arg("short", layout_.short_name), + fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant))); label_.set_markup(display_layout); @@ -97,10 +105,10 @@ auto Language::update() -> void { if (tooltip_format_ != "") { auto tooltip_display_layout = trim(fmt::format(tooltip_format_, fmt::arg("short", layout_.short_name), + fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant))); label_.set_tooltip_markup(tooltip_display_layout); - } else { label_.set_tooltip_markup(display_layout); } @@ -118,8 +126,9 @@ auto Language::set_current_layout(std::string current_layout) -> void { auto Language::init_layouts_map(const std::vector& used_layouts) -> void { std::map> found_by_short_names; - auto layout = xkb_context_.next_layout(); - for (; layout != nullptr; layout = xkb_context_.next_layout()) { + XKBContext xkb_context; + auto layout = xkb_context.next_layout(); + for (; layout != nullptr; layout = xkb_context.next_layout()) { if (std::find(used_layouts.begin(), used_layouts.end(), layout->full_name) == used_layouts.end()) { continue; @@ -145,7 +154,6 @@ auto Language::init_layouts_map(const std::vector& used_layouts) -> for (const auto& used_layout_name : used_layouts) { auto used_layout = &layouts_map_.find(used_layout_name)->second; auto layouts_with_same_name_list = found_by_short_names[used_layout->short_name]; - spdlog::info("SIZE: " + std::to_string(layouts_with_same_name_list.size())); if (layouts_with_same_name_list.size() < 2) { continue; } @@ -153,9 +161,15 @@ auto Language::init_layouts_map(const std::vector& used_layouts) -> if (short_name_to_number_map.count(used_layout->short_name) == 0) { short_name_to_number_map[used_layout->short_name] = 1; } - - used_layout->short_name = - used_layout->short_name + std::to_string(short_name_to_number_map[used_layout->short_name]++); + + if (displayed_short_flag != static_cast(0)) { + int& number = short_name_to_number_map[used_layout->short_name]; + used_layout->short_name = + used_layout->short_name + std::to_string(number); + used_layout->short_description = + used_layout->short_description + std::to_string(number); + ++number; + } } } @@ -180,10 +194,22 @@ auto Language::XKBContext::next_layout() -> Layout* { auto name = std::string(rxkb_layout_get_name(xkb_layout_)); auto variant_ = rxkb_layout_get_variant(xkb_layout_); std::string variant = variant_ == nullptr ? "" : std::string(variant_); - - layout_ = new Layout{description, name, variant}; + auto short_description_ = rxkb_layout_get_brief(xkb_layout_); + std::string short_description; + if (short_description_ != nullptr) { + short_description = std::string(short_description_); + base_layouts_by_name_.emplace(name, xkb_layout_); + } else { + auto base_layout = base_layouts_by_name_[name]; + short_description = base_layout == nullptr ? "" : std::string(rxkb_layout_get_brief(base_layout)); + } + delete layout_; + layout_ = new Layout{description, name, variant, short_description}; return layout_; } -Language::XKBContext::~XKBContext() { rxkb_context_unref(context_); } +Language::XKBContext::~XKBContext() { + rxkb_context_unref(context_); + delete layout_; +} } // namespace waybar::modules::sway