From 79eb2f5bc102b421c3b8e8dcfcf56b0a630daa27 Mon Sep 17 00:00:00 2001 From: Louis DeLosSantos Date: Tue, 10 Jan 2023 17:32:10 +0000 Subject: [PATCH] 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 --- include/modules/wlr/taskbar.hpp | 3 +- man/waybar-wlr-taskbar.5.scd | 5 ++ src/modules/wlr/taskbar.cpp | 83 +++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/include/modules/wlr/taskbar.hpp b/include/modules/wlr/taskbar.hpp index 7a1f17a6..4465dd06 100644 --- a/include/modules/wlr/taskbar.hpp +++ b/include/modules/wlr/taskbar.hpp @@ -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_; diff --git a/man/waybar-wlr-taskbar.5.scd b/man/waybar-wlr-taskbar.5.scd index b2946ac5..8737196d 100644 --- a/man/waybar-wlr-taskbar.5.scd +++ b/man/waybar-wlr-taskbar.5.scd @@ -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. diff --git a/src/modules/wlr/taskbar.cpp b/src/modules/wlr/taskbar.cpp index 427083ba..74b8be5d 100644 --- a/src/modules/wlr/taskbar.cpp +++ b/src/modules/wlr/taskbar.cpp @@ -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(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 &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 &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 &a, const std::unique_ptr &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(); }