wlr-taskbar: allow sorting by app_id

some users (maybe only myself) may want to sort the task bar by app_id
which then places occurrences of the same task next to each other.

Signed-off-by: Louis DeLosSantos <louis.delos@gmail.com>
This commit is contained in:
Louis DeLosSantos 2023-01-10 17:32:10 +00:00 committed by ldelossa
parent b7e6a2dc25
commit 79eb2f5bc1
3 changed files with 54 additions and 37 deletions

View File

@ -40,6 +40,8 @@ class Task {
FULLSCREEN = (1 << 3), FULLSCREEN = (1 << 3),
INVALID = (1 << 4) INVALID = (1 << 4)
}; };
// made public so TaskBar can reorder based on configuration.
Gtk::Button button;
private: private:
static uint32_t global_id; static uint32_t global_id;
@ -53,7 +55,6 @@ class Task {
uint32_t id_; uint32_t id_;
Gtk::Button button_;
Gtk::Box content_; Gtk::Box content_;
Gtk::Image icon_; Gtk::Image icon_;
Gtk::Label text_before_; Gtk::Label text_before_;

View File

@ -52,6 +52,11 @@ Addressed by *wlr/taskbar*
default: false ++ default: false ++
If set to true, always reorder the tasks in the taskbar so that the currently active one is first. Otherwise don't reorder. If set to true, always reorder the tasks in the taskbar so that the currently active one is first. Otherwise don't reorder.
*sort-by-app-id*: ++
typeof: bool ++
default: false ++
If set to true, group tasks by their app_id. Cannot be used with 'active-first'.
*on-click*: ++ *on-click*: ++
typeof: string ++ typeof: string ++
The action which should be triggered when clicking on the application button with the left mouse button. The action which should be triggered when clicking on the application button with the left mouse button.

View File

@ -268,14 +268,14 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
content_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} { content_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
zwlr_foreign_toplevel_handle_v1_add_listener(handle_, &toplevel_handle_impl, this); zwlr_foreign_toplevel_handle_v1_add_listener(handle_, &toplevel_handle_impl, this);
button_.set_relief(Gtk::RELIEF_NONE); button.set_relief(Gtk::RELIEF_NONE);
content_.add(text_before_); content_.add(text_before_);
content_.add(icon_); content_.add(icon_);
content_.add(text_after_); content_.add(text_after_);
content_.show(); content_.show();
button_.add(content_); button.add(content_);
format_before_.clear(); format_before_.clear();
format_after_.clear(); format_after_.clear();
@ -317,20 +317,20 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
config_["on-click-right"].isString()) { config_["on-click-right"].isString()) {
} }
button_.add_events(Gdk::BUTTON_PRESS_MASK); button.add_events(Gdk::BUTTON_PRESS_MASK);
button_.signal_button_press_event().connect(sigc::mem_fun(*this, &Task::handle_clicked), false); button.signal_button_press_event().connect(sigc::mem_fun(*this, &Task::handle_clicked), false);
button_.signal_button_release_event().connect(sigc::mem_fun(*this, &Task::handle_button_release), button.signal_button_release_event().connect(sigc::mem_fun(*this, &Task::handle_button_release),
false); false);
button_.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify), button.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify),
false); false);
button_.drag_source_set(target_entries, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE); button.drag_source_set(target_entries, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE);
button_.drag_dest_set(target_entries, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE); button.drag_dest_set(target_entries, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE);
button_.signal_drag_data_get().connect(sigc::mem_fun(*this, &Task::handle_drag_data_get), false); button.signal_drag_data_get().connect(sigc::mem_fun(*this, &Task::handle_drag_data_get), false);
button_.signal_drag_data_received().connect( button.signal_drag_data_received().connect(sigc::mem_fun(*this, &Task::handle_drag_data_received),
sigc::mem_fun(*this, &Task::handle_drag_data_received), false); false);
} }
Task::~Task() { Task::~Task() {
@ -339,7 +339,7 @@ Task::~Task() {
handle_ = nullptr; handle_ = nullptr;
} }
if (button_visible_) { if (button_visible_) {
tbar_->remove_button(button_); tbar_->remove_button(button);
button_visible_ = false; button_visible_ = false;
} }
} }
@ -438,8 +438,8 @@ void Task::handle_output_enter(struct wl_output *output) {
if (!button_visible_ && (tbar_->all_outputs() || tbar_->show_output(output))) { if (!button_visible_ && (tbar_->all_outputs() || tbar_->show_output(output))) {
/* The task entered the output of the current bar make the button visible */ /* The task entered the output of the current bar make the button visible */
tbar_->add_button(button_); tbar_->add_button(button);
button_.show(); button.show();
button_visible_ = true; button_visible_ = true;
spdlog::debug("{} now visible on {}", repr(), bar_.output->name); spdlog::debug("{} now visible on {}", repr(), bar_.output->name);
} }
@ -450,8 +450,8 @@ void Task::handle_output_leave(struct wl_output *output) {
if (button_visible_ && !tbar_->all_outputs() && tbar_->show_output(output)) { if (button_visible_ && !tbar_->all_outputs() && tbar_->show_output(output)) {
/* The task left the output of the current bar, make the button invisible */ /* The task left the output of the current bar, make the button invisible */
tbar_->remove_button(button_); tbar_->remove_button(button);
button_.hide(); button.hide();
button_visible_ = false; button_visible_ = false;
spdlog::debug("{} now invisible on {}", repr(), bar_.output->name); spdlog::debug("{} now invisible on {}", repr(), bar_.output->name);
} }
@ -473,31 +473,31 @@ void Task::handle_done() {
spdlog::debug("{} changed", repr()); spdlog::debug("{} changed", repr());
if (state_ & MAXIMIZED) { if (state_ & MAXIMIZED) {
button_.get_style_context()->add_class("maximized"); button.get_style_context()->add_class("maximized");
} else if (!(state_ & MAXIMIZED)) { } else if (!(state_ & MAXIMIZED)) {
button_.get_style_context()->remove_class("maximized"); button.get_style_context()->remove_class("maximized");
} }
if (state_ & MINIMIZED) { if (state_ & MINIMIZED) {
button_.get_style_context()->add_class("minimized"); button.get_style_context()->add_class("minimized");
} else if (!(state_ & MINIMIZED)) { } else if (!(state_ & MINIMIZED)) {
button_.get_style_context()->remove_class("minimized"); button.get_style_context()->remove_class("minimized");
} }
if (state_ & ACTIVE) { if (state_ & ACTIVE) {
button_.get_style_context()->add_class("active"); button.get_style_context()->add_class("active");
} else if (!(state_ & ACTIVE)) { } else if (!(state_ & ACTIVE)) {
button_.get_style_context()->remove_class("active"); button.get_style_context()->remove_class("active");
} }
if (state_ & FULLSCREEN) { if (state_ & FULLSCREEN) {
button_.get_style_context()->add_class("fullscreen"); button.get_style_context()->add_class("fullscreen");
} else if (!(state_ & FULLSCREEN)) { } else if (!(state_ & FULLSCREEN)) {
button_.get_style_context()->remove_class("fullscreen"); button.get_style_context()->remove_class("fullscreen");
} }
if (config_["active-first"].isBool() && config_["active-first"].asBool() && active()) if (config_["active-first"].isBool() && config_["active-first"].asBool() && active())
tbar_->move_button(button_, 0); tbar_->move_button(button, 0);
tbar_->dp.emit(); tbar_->dp.emit();
} }
@ -507,7 +507,7 @@ void Task::handle_closed() {
zwlr_foreign_toplevel_handle_v1_destroy(handle_); zwlr_foreign_toplevel_handle_v1_destroy(handle_);
handle_ = nullptr; handle_ = nullptr;
if (button_visible_) { if (button_visible_) {
tbar_->remove_button(button_); tbar_->remove_button(button);
button_visible_ = false; button_visible_ = false;
} }
tbar_->remove_task(id_); tbar_->remove_task(id_);
@ -563,12 +563,12 @@ bool Task::handle_button_release(GdkEventButton *bt) {
bool Task::handle_motion_notify(GdkEventMotion *mn) { bool Task::handle_motion_notify(GdkEventMotion *mn) {
if (drag_start_button == -1) return false; if (drag_start_button == -1) return false;
if (button_.drag_check_threshold(drag_start_x, drag_start_y, mn->x, mn->y)) { if (button.drag_check_threshold(drag_start_x, drag_start_y, mn->x, mn->y)) {
/* start drag in addition to other assigned action */ /* start drag in addition to other assigned action */
auto target_list = Gtk::TargetList::create(target_entries); auto target_list = Gtk::TargetList::create(target_entries);
auto refptr = Glib::RefPtr<Gtk::TargetList>(target_list); auto refptr = Glib::RefPtr<Gtk::TargetList>(target_list);
auto drag_context = auto drag_context =
button_.drag_begin(refptr, Gdk::DragAction::ACTION_MOVE, drag_start_button, (GdkEvent *)mn); button.drag_begin(refptr, Gdk::DragAction::ACTION_MOVE, drag_start_button, (GdkEvent *)mn);
} }
return false; return false;
@ -577,7 +577,7 @@ bool Task::handle_motion_notify(GdkEventMotion *mn) {
void Task::handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context, void Task::handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context,
Gtk::SelectionData &selection_data, guint info, guint time) { Gtk::SelectionData &selection_data, guint info, guint time) {
spdlog::debug("drag_data_get"); spdlog::debug("drag_data_get");
void *button_addr = (void *)&this->button_; void *button_addr = (void *)&this->button;
selection_data.set("WAYBAR_TOPLEVEL", 32, (const guchar *)&button_addr, sizeof(gpointer)); selection_data.set("WAYBAR_TOPLEVEL", 32, (const guchar *)&button_addr, sizeof(gpointer));
} }
@ -588,16 +588,16 @@ void Task::handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &conte
gpointer handle = *(gpointer *)selection_data.get_data(); gpointer handle = *(gpointer *)selection_data.get_data();
auto dragged_button = (Gtk::Button *)handle; auto dragged_button = (Gtk::Button *)handle;
if (dragged_button == &this->button_) return; if (dragged_button == &this->button) return;
auto parent_of_dragged = dragged_button->get_parent(); auto parent_of_dragged = dragged_button->get_parent();
auto parent_of_dest = this->button_.get_parent(); auto parent_of_dest = this->button.get_parent();
if (parent_of_dragged != parent_of_dest) return; if (parent_of_dragged != parent_of_dest) return;
auto box = (Gtk::Box *)parent_of_dragged; auto box = (Gtk::Box *)parent_of_dragged;
auto position_prop = box->child_property_position(this->button_); auto position_prop = box->child_property_position(this->button);
auto position = position_prop.get_value(); auto position = position_prop.get_value();
box->reorder_child(*dragged_button, position); box->reorder_child(*dragged_button, position);
@ -646,9 +646,9 @@ void Task::update() {
fmt::arg("app_id", app_id), fmt::arg("state", state_string()), fmt::arg("app_id", app_id), fmt::arg("state", state_string()),
fmt::arg("short_state", state_string(true))); fmt::arg("short_state", state_string(true)));
if (markup) if (markup)
button_.set_tooltip_markup(txt); button.set_tooltip_markup(txt);
else else
button_.set_tooltip_text(txt); button.set_tooltip_text(txt);
} }
} }
@ -791,6 +791,17 @@ void Taskbar::update() {
t->update(); t->update();
} }
if (config_["sort-by-app-id"].asBool()) {
std::stable_sort(tasks_.begin(), tasks_.end(),
[](const std::unique_ptr<Task> &a, const std::unique_ptr<Task> &b) {
return a->app_id() < b->app_id();
});
for (unsigned long i = 0; i < tasks_.size(); i++) {
move_button(tasks_[i]->button, i);
}
}
AModule::update(); AModule::update();
} }