feat(Group): enhance widget visibility management - set visibility instantly on module update using dynamic signal handling.

Improve performance - manage the visibility of updated module only instead of iterating over all modules on `hide_group`.
This commit is contained in:
Piotr Piwoński
2025-03-30 14:49:07 +00:00
parent 653732dfc6
commit 67df5f5838
5 changed files with 51 additions and 35 deletions
+1
View File
@@ -15,6 +15,7 @@ class AModule : public IModule {
static constexpr const char *MODULE_CLASS = "module"; static constexpr const char *MODULE_CLASS = "module";
~AModule() override; ~AModule() override;
sigc::signal<void, AModule*> signal_updated;
auto update() -> void override; auto update() -> void override;
virtual auto refresh(int shouldRefresh) -> void {}; virtual auto refresh(int shouldRefresh) -> void {};
operator Gtk::Widget &() override; operator Gtk::Widget &() override;
+5 -2
View File
@@ -17,7 +17,7 @@ class Group : public AModule {
operator Gtk::Widget &() override; operator Gtk::Widget &() override;
virtual Gtk::Box &getBox(); virtual Gtk::Box &getBox();
void addWidget(Gtk::Widget &widget); void addWidget(AModule* module);
protected: protected:
Gtk::Box box; Gtk::Box box;
@@ -33,7 +33,10 @@ class Group : public AModule {
bool handleToggle(GdkEventButton *const &ev) override; bool handleToggle(GdkEventButton *const &ev) override;
void show_group(); void show_group();
void hide_group(); void hide_group();
void update_always_visible_modules(); 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 } // namespace waybar
+1
View File
@@ -95,6 +95,7 @@ auto AModule::update() -> void {
if (config_["on-update"].isString()) { if (config_["on-update"].isString()) {
pid_.push_back(util::command::forkExec(config_["on-update"].asString())); pid_.push_back(util::command::forkExec(config_["on-update"].asString()));
} }
signal_updated.emit(this);
} }
// Get mapping between event name and module action name // Get mapping between event name and module action name
// Then call overrided doAction in order to call appropriate module action // Then call overrided doAction in order to call appropriate module action
+1 -1
View File
@@ -506,7 +506,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
std::shared_ptr<AModule> module_sp(module); std::shared_ptr<AModule> module_sp(module);
modules_all_.emplace_back(module_sp); modules_all_.emplace_back(module_sp);
if (group != nullptr) { if (group != nullptr) {
group->addWidget(*module); group->addWidget(module);
} else { } else {
if (pos == "modules-left") { if (pos == "modules-left") {
modules_left_.emplace_back(module_sp); modules_left_.emplace_back(module_sp);
+41 -30
View File
@@ -92,52 +92,57 @@ void Group::show_group() {
revealer.set_reveal_child(true); revealer.set_reveal_child(true);
} }
void Group::update_always_visible_modules() { void Group::hide_widget(Gtk::Widget& widget) {
if (always_visible_class.empty()) { widget.get_style_context()->add_class(add_class_to_drawer_children);
return; box.remove(widget);
revealer_box.pack_start(widget, false, false);
} }
for (auto* event_box : revealer_box.get_children()) { void Group::show_widget(Gtk::Widget& widget) {
if (auto container = dynamic_cast<Gtk::Container*>(event_box)) { widget.get_style_context()->remove_class(add_class_to_drawer_children);
for (auto* base_element : container->get_children()) { revealer_box.remove(widget);
if (base_element->get_style_context()->has_class(always_visible_class)) { box.pack_end(widget, false, false);
event_box->get_style_context()->remove_class(add_class_to_drawer_children);
revealer_box.remove(*event_box);
box.pack_end(*event_box, false, false);
event_box->show();
}
}
}
} }
void Group::hide_current_widget_if_inactive() {
for (auto* event_box : box.get_children()) { for (auto* event_box : box.get_children()) {
if (event_box == &revealer) { if (event_box == &revealer) {
continue; continue;
} }
if (box.get_children().size() <= 2) { if (auto event_box_container = dynamic_cast<Gtk::Container*>(event_box)) {
break; 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);
} }
if (auto container = dynamic_cast<Gtk::Container*>(event_box)) { }
}
}
}
void Group::manage_visibility(AModule* module) {
Gtk::Widget& widget = *module;
if (auto container = dynamic_cast<Gtk::Container*>(&widget)) {
for (auto* base_element : container->get_children()) { for (auto* base_element : container->get_children()) {
if (!base_element->get_style_context()->has_class(always_visible_class)) { if (base_element->get_style_context()->has_class(always_visible_class)) {
event_box->get_style_context()->add_class(add_class_to_drawer_children); if (box.get_children().size() == 2) {
Group::hide_current_widget_if_inactive();
box.remove(*event_box); }
revealer_box.pack_start(*event_box, false, false); show_widget(widget);
event_box->show(); } 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() { void Group::hide_group() {
box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT); box.unset_state_flags(Gtk::StateFlags::STATE_FLAG_PRELIGHT);
revealer.set_reveal_child(false); revealer.set_reveal_child(false);
Group::update_always_visible_modules();
} }
bool Group::handleMouseEnter(GdkEventCrossing* const& e) { bool Group::handleMouseEnter(GdkEventCrossing* const& e) {
@@ -167,12 +172,14 @@ bool Group::handleToggle(GdkEventButton* const& e) {
} }
auto Group::update() -> void { auto Group::update() -> void {
Group::update_always_visible_modules(); // noop
} }
Gtk::Box& Group::getBox() { return is_drawer ? (is_first_widget ? box : revealer_box) : box; } 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); getBox().pack_start(widget, false, false);
if (is_drawer && !is_first_widget) { if (is_drawer && !is_first_widget) {
@@ -180,6 +187,10 @@ void Group::addWidget(Gtk::Widget& widget) {
} }
is_first_widget = false; is_first_widget = false;
if (!always_visible_class.empty()) {
module->signal_updated.connect(sigc::mem_fun(*this, &Group::manage_visibility));
}
} }
Group::operator Gtk::Widget&() { return event_box_; } Group::operator Gtk::Widget&() { return event_box_; }