diff --git a/include/AModule.hpp b/include/AModule.hpp index 0a1216d5..659aa68e 100644 --- a/include/AModule.hpp +++ b/include/AModule.hpp @@ -20,6 +20,7 @@ class AModule : public IModule { static constexpr const char* MODULE_CLASS = "module"; ~AModule() override; + sigc::signal signal_updated; auto update() -> void override; virtual auto refresh(int shouldRefresh) -> void {}; operator Gtk::Widget&() override; diff --git a/include/group.hpp b/include/group.hpp index afd705b0..0e981d0d 100644 --- a/include/group.hpp +++ b/include/group.hpp @@ -19,7 +19,7 @@ class Group : public AModule { operator Gtk::Widget&() override; virtual Gtk::Box& getBox(); - void addWidget(Gtk::Widget& widget); + void addWidget(AModule* module); protected: Gtk::Box box; @@ -28,6 +28,7 @@ class Group : public AModule { bool is_first_widget = true; bool is_drawer = false; bool click_to_reveal = false; + std::string always_visible_class; bool empty_if_drawer_empty = false; int reveal_delay = 0; std::string add_class_to_drawer_children; @@ -37,6 +38,10 @@ class Group : public AModule { bool handleScroll(GdkEventScroll* e) override; void show_group(); void hide_group(); + void manage_visibility(AModule* module); + void show_widget(Gtk::Widget& widget); + void hide_widget(Gtk::Widget& widget); + void hide_current_widget_if_inactive(); }; } // namespace waybar diff --git a/src/AModule.cpp b/src/AModule.cpp index ec29576f..227c9c3c 100644 --- a/src/AModule.cpp +++ b/src/AModule.cpp @@ -110,6 +110,7 @@ auto AModule::update() -> void { if (config_["on-update"].isString()) { pid_children_.push_back(util::command::forkExec(config_["on-update"].asString())); } + signal_updated.emit(this); } // Get mapping between event name and module action name // Then call overridden doAction in order to call appropriate module action diff --git a/src/bar.cpp b/src/bar.cpp index bea77db7..cf284e0d 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -598,7 +598,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos, std::shared_ptr module_sp(module); modules_all_.emplace_back(module_sp); if (group != nullptr) { - group->addWidget(*module); + group->addWidget(module); } else { if (pos == "modules-left") { modules_left_.emplace_back(module_sp); diff --git a/src/group.cpp b/src/group.cpp index 729a3080..9f11661f 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -68,6 +68,9 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value& : false); click_to_reveal = drawer_config["click-to-reveal"].asBool(); + always_visible_class = (drawer_config["always-visible-class"].isString() + ? drawer_config["always-visible-class"].asString() + : ""); reveal_delay = drawer_config["reveal-delay"].asInt(); const bool start_expanded = @@ -108,6 +111,54 @@ void Group::show_group() { box.get_style_context()->add_class("expanded"); } +void Group::hide_widget(Gtk::Widget& widget) { + widget.get_style_context()->add_class(add_class_to_drawer_children); + box.remove(widget); + revealer_box.pack_start(widget, false, false); +} + +void Group::show_widget(Gtk::Widget& widget) { + widget.get_style_context()->remove_class(add_class_to_drawer_children); + revealer_box.remove(widget); + box.pack_end(widget, false, false); +} + +void Group::hide_current_widget_if_inactive() { + for (auto* event_box : box.get_children()) { + if (event_box == &revealer) { + continue; + } + if (auto event_box_container = dynamic_cast(event_box)) { + for (auto* the_only_visible : event_box_container->get_children()) { + if (!the_only_visible->get_style_context()->has_class(always_visible_class)) { + hide_widget(*event_box); + } + } + } + } +} + +void Group::manage_visibility(AModule* module) { + Gtk::Widget& widget = *module; + + if (auto container = dynamic_cast(&widget)) { + for (auto* base_element : container->get_children()) { + if (base_element->get_style_context()->has_class(always_visible_class)) { + if (box.get_children().size() == 2) { + Group::hide_current_widget_if_inactive(); + } + show_widget(widget); + } else { + // Do not hide if it's the only widget + revealer + if (box.get_children().size() <= 2) { + return; + } + hide_widget(widget); + } + } + } +} + void Group::hide_group() { box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT); revealer.set_reveal_child(false); @@ -205,7 +256,9 @@ bool Group::handleScroll(GdkEventScroll* e) { Gtk::Box& Group::getBox() { return is_drawer ? (is_first_widget ? box : revealer_box) : box; } -void Group::addWidget(Gtk::Widget& widget) { +void Group::addWidget(AModule* module) { + Gtk::Widget& widget = *module; + getBox().pack_start(widget, false, false); if (is_drawer && !is_first_widget) { @@ -213,8 +266,13 @@ void Group::addWidget(Gtk::Widget& widget) { } is_first_widget = false; + widget.property_visible().signal_changed().connect(sigc::mem_fun(*this, &Group::update)); update(); + + if (!always_visible_class.empty()) { + module->signal_updated.connect(sigc::mem_fun(*this, &Group::manage_visibility)); + } } Group::operator Gtk::Widget&() { return event_box_; }