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

View File

@ -52,6 +52,11 @@ Addressed by *wlr/taskbar*
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.
*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*: ++
typeof: string ++
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} {
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(icon_);
content_.add(text_after_);
content_.show();
button_.add(content_);
button.add(content_);
format_before_.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()) {
}
button_.add_events(Gdk::BUTTON_PRESS_MASK);
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),
false);
button_.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify),
button.add_events(Gdk::BUTTON_PRESS_MASK);
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),
false);
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.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify),
false);
button_.signal_drag_data_get().connect(sigc::mem_fun(*this, &Task::handle_drag_data_get), false);
button_.signal_drag_data_received().connect(
sigc::mem_fun(*this, &Task::handle_drag_data_received), false);
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.signal_drag_data_get().connect(sigc::mem_fun(*this, &Task::handle_drag_data_get), false);
button.signal_drag_data_received().connect(sigc::mem_fun(*this, &Task::handle_drag_data_received),
false);
}
Task::~Task() {
@ -339,7 +339,7 @@ Task::~Task() {
handle_ = nullptr;
}
if (button_visible_) {
tbar_->remove_button(button_);
tbar_->remove_button(button);
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))) {
/* The task entered the output of the current bar make the button visible */
tbar_->add_button(button_);
button_.show();
tbar_->add_button(button);
button.show();
button_visible_ = true;
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)) {
/* The task left the output of the current bar, make the button invisible */
tbar_->remove_button(button_);
button_.hide();
tbar_->remove_button(button);
button.hide();
button_visible_ = false;
spdlog::debug("{} now invisible on {}", repr(), bar_.output->name);
}
@ -473,31 +473,31 @@ void Task::handle_done() {
spdlog::debug("{} changed", repr());
if (state_ & MAXIMIZED) {
button_.get_style_context()->add_class("maximized");
button.get_style_context()->add_class("maximized");
} else if (!(state_ & MAXIMIZED)) {
button_.get_style_context()->remove_class("maximized");
button.get_style_context()->remove_class("maximized");
}
if (state_ & MINIMIZED) {
button_.get_style_context()->add_class("minimized");
button.get_style_context()->add_class("minimized");
} else if (!(state_ & MINIMIZED)) {
button_.get_style_context()->remove_class("minimized");
button.get_style_context()->remove_class("minimized");
}
if (state_ & ACTIVE) {
button_.get_style_context()->add_class("active");
button.get_style_context()->add_class("active");
} else if (!(state_ & ACTIVE)) {
button_.get_style_context()->remove_class("active");
button.get_style_context()->remove_class("active");
}
if (state_ & FULLSCREEN) {
button_.get_style_context()->add_class("fullscreen");
button.get_style_context()->add_class("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())
tbar_->move_button(button_, 0);
tbar_->move_button(button, 0);
tbar_->dp.emit();
}
@ -507,7 +507,7 @@ void Task::handle_closed() {
zwlr_foreign_toplevel_handle_v1_destroy(handle_);
handle_ = nullptr;
if (button_visible_) {
tbar_->remove_button(button_);
tbar_->remove_button(button);
button_visible_ = false;
}
tbar_->remove_task(id_);
@ -563,12 +563,12 @@ bool Task::handle_button_release(GdkEventButton *bt) {
bool Task::handle_motion_notify(GdkEventMotion *mn) {
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 */
auto target_list = Gtk::TargetList::create(target_entries);
auto refptr = Glib::RefPtr<Gtk::TargetList>(target_list);
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;
@ -577,7 +577,7 @@ bool Task::handle_motion_notify(GdkEventMotion *mn) {
void Task::handle_drag_data_get(const Glib::RefPtr<Gdk::DragContext> &context,
Gtk::SelectionData &selection_data, guint info, guint time) {
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));
}
@ -588,16 +588,16 @@ void Task::handle_drag_data_received(const Glib::RefPtr<Gdk::DragContext> &conte
gpointer handle = *(gpointer *)selection_data.get_data();
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_dest = this->button_.get_parent();
auto parent_of_dest = this->button.get_parent();
if (parent_of_dragged != parent_of_dest) return;
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();
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("short_state", state_string(true)));
if (markup)
button_.set_tooltip_markup(txt);
button.set_tooltip_markup(txt);
else
button_.set_tooltip_text(txt);
button.set_tooltip_text(txt);
}
}
@ -791,6 +791,17 @@ void Taskbar::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();
}