fix(wlr/taskbar): stop forcing tasks onto every output's bar

hide_if_duplicate() unconditionally re-ran handle_output_enter() with
the bar's own wl_output for every non-squashed task, so any app_id or
title event made the task visible on all bars and "all-outputs": false
was effectively ignored. The un-squash path in handle_closed() showed
the replacement task unconditionally, with the same effect.

Track whether the toplevel is actually on the bar's output from the
protocol's output_enter/output_leave events, split the button
show/hide logic out of the protocol handlers, and gate every synthetic
re-show on all-outputs or the tracked output membership.

Fixes #5178
This commit is contained in:
Austin Horstman
2026-07-05 10:23:06 -05:00
parent bf59a21815
commit cbad42bc9b
2 changed files with 58 additions and 34 deletions
+6
View File
@@ -71,6 +71,10 @@ class Task {
bool button_visible_ = false; bool button_visible_ = false;
bool ignored_ = false; bool ignored_ = false;
bool squashed_ = false; bool squashed_ = false;
/* Whether the toplevel is on this bar's output, per the protocol's
* output_enter/output_leave events */
bool on_bar_output_ = false;
bool size_allocate_connected_ = false;
bool with_icon_ = false; bool with_icon_ = false;
bool with_name_ = false; bool with_name_ = false;
@@ -96,6 +100,8 @@ class Task {
void on_button_size_allocated(Gtk::Allocation& alloc); void on_button_size_allocated(Gtk::Allocation& alloc);
void hide_if_ignored(); void hide_if_ignored();
void hide_if_duplicate(); void hide_if_duplicate();
void show_button();
void hide_button();
public: public:
/* Getter functions */ /* Getter functions */
+52 -34
View File
@@ -278,25 +278,18 @@ void Task::hide_if_duplicate() {
// Squashes if the app is in the squash list and more than 1 instance is open // Squashes if the app is in the squash list and more than 1 instance is open
if (contains_app && (tbar_->task_id_count(app_id_) > 1 || tbar_->task_title_count(title_) > 1)) { if (contains_app && (tbar_->task_id_count(app_id_) > 1 || tbar_->task_title_count(title_) > 1)) {
squashed_ = true; squashed_ = true;
if (button_visible_) { hide_button();
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
handle_output_leave(output);
}
} }
if (!squashed_ && !ignored_) { if (!squashed_ && !ignored_ && (tbar_->all_outputs() || on_bar_output_)) {
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj()); show_button();
handle_output_enter(output);
} }
} }
void Task::hide_if_ignored() { void Task::hide_if_ignored() {
if (tbar_->ignore_list().count(app_id_) || tbar_->ignore_list().count(title_)) { if (tbar_->ignore_list().count(app_id_) || tbar_->ignore_list().count(title_)) {
ignored_ = true; ignored_ = true;
if (button_visible_) { hide_button();
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
handle_output_leave(output);
}
} }
if (!ignored_ && !squashed_) { if (!ignored_ && !squashed_) {
@@ -353,6 +346,12 @@ void Task::on_button_size_allocated(Gtk::Allocation& alloc) {
} }
void Task::handle_output_enter(struct wl_output* output) { void Task::handle_output_enter(struct wl_output* output) {
spdlog::debug("{} entered output {}", repr(), (void*)output);
if (tbar_->show_output(output)) {
on_bar_output_ = true;
}
if (ignored_) { if (ignored_) {
spdlog::debug("{} is ignored", repr()); spdlog::debug("{} is ignored", repr());
return; return;
@@ -362,33 +361,52 @@ void Task::handle_output_enter(struct wl_output* output) {
return; return;
} }
spdlog::debug("{} entered output {}", repr(), (void*)output); if (tbar_->all_outputs() || on_bar_output_) {
/* The task entered the output of the current bar, make the button visible */
if (!button_visible_ && (tbar_->all_outputs() || tbar_->show_output(output))) { show_button();
/* The task entered the output of the current bar make the button visible */
button.signal_size_allocate().connect_notify(
sigc::mem_fun(this, &Task::on_button_size_allocated));
tbar_->add_button(button);
if (!config_["active-only"].asBool() || active()) {
button.show();
}
button_visible_ = true;
spdlog::debug("{} now visible on {}", repr(), bar_.output->name);
tbar_->update_bar_css_classes();
} }
} }
void Task::handle_output_leave(struct wl_output* output) { void Task::handle_output_leave(struct wl_output* output) {
spdlog::debug("{} left output {}", repr(), (void*)output); spdlog::debug("{} left output {}", repr(), (void*)output);
if (button_visible_ && !tbar_->all_outputs() && tbar_->show_output(output)) { if (tbar_->show_output(output)) {
/* The task left the output of the current bar, make the button invisible */ on_bar_output_ = false;
tbar_->remove_button(button);
button.hide();
button_visible_ = false;
spdlog::debug("{} now invisible on {}", repr(), bar_.output->name);
tbar_->update_bar_css_classes();
} }
if (!tbar_->all_outputs() && !on_bar_output_) {
/* The task left the output of the current bar, make the button invisible */
hide_button();
}
}
void Task::show_button() {
if (button_visible_) {
return;
}
if (!size_allocate_connected_) {
button.signal_size_allocate().connect_notify(
sigc::mem_fun(this, &Task::on_button_size_allocated));
size_allocate_connected_ = true;
}
tbar_->add_button(button);
if (!config_["active-only"].asBool() || active()) {
button.show();
}
button_visible_ = true;
spdlog::debug("{} now visible on {}", repr(), bar_.output->name);
tbar_->update_bar_css_classes();
}
void Task::hide_button() {
if (!button_visible_) {
return;
}
tbar_->remove_button(button);
button.hide();
button_visible_ = false;
spdlog::debug("{} now invisible on {}", repr(), bar_.output->name);
tbar_->update_bar_css_classes();
} }
void Task::handle_state(struct wl_array* state) { void Task::handle_state(struct wl_array* state) {
@@ -474,9 +492,9 @@ void Task::handle_closed() {
if (it != tasks.end() && !(*it).ignored_) { if (it != tasks.end() && !(*it).ignored_) {
Task& task = *it; Task& task = *it;
task.squashed_ = false; task.squashed_ = false;
tbar_->add_button(task.button); if (tbar_->all_outputs() || task.on_bar_output_) {
task.button.show(); task.show_button();
task.button_visible_ = true; }
} }
} }