Merge pull request #3740 from NoakPalander/feature/squash-list
Added a taskbar squash option
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ranges>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -69,6 +70,7 @@ class Task {
|
|||||||
Glib::RefPtr<Gio::DesktopAppInfo> app_info_;
|
Glib::RefPtr<Gio::DesktopAppInfo> app_info_;
|
||||||
bool button_visible_ = false;
|
bool button_visible_ = false;
|
||||||
bool ignored_ = false;
|
bool ignored_ = false;
|
||||||
|
bool squashed_ = false;
|
||||||
|
|
||||||
bool with_icon_ = false;
|
bool with_icon_ = false;
|
||||||
bool with_name_ = false;
|
bool with_name_ = false;
|
||||||
@@ -93,6 +95,7 @@ class Task {
|
|||||||
void set_minimize_hint();
|
void set_minimize_hint();
|
||||||
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();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Getter functions */
|
/* Getter functions */
|
||||||
@@ -164,6 +167,7 @@ class Taskbar : public waybar::AModule {
|
|||||||
|
|
||||||
IconLoader icon_loader_;
|
IconLoader icon_loader_;
|
||||||
std::unordered_set<std::string> ignore_list_;
|
std::unordered_set<std::string> ignore_list_;
|
||||||
|
std::unordered_set<std::string> squash_list_;
|
||||||
std::map<std::string, std::string> app_ids_replace_map_;
|
std::map<std::string, std::string> app_ids_replace_map_;
|
||||||
|
|
||||||
struct zwlr_foreign_toplevel_manager_v1* manager_;
|
struct zwlr_foreign_toplevel_manager_v1* manager_;
|
||||||
@@ -202,7 +206,14 @@ class Taskbar : public waybar::AModule {
|
|||||||
|
|
||||||
const IconLoader& icon_loader() const;
|
const IconLoader& icon_loader() const;
|
||||||
const std::unordered_set<std::string>& ignore_list() const;
|
const std::unordered_set<std::string>& ignore_list() const;
|
||||||
|
const std::unordered_set<std::string>& squash_list() const;
|
||||||
const std::map<std::string, std::string>& app_ids_replace_map() const;
|
const std::map<std::string, std::string>& app_ids_replace_map() const;
|
||||||
|
std::size_t task_id_count(std::string_view id) const;
|
||||||
|
std::size_t task_title_count(std::string_view title) const;
|
||||||
|
|
||||||
|
auto tasks() {
|
||||||
|
return tasks_ | std::views::transform([](auto& task) -> Task& { return *task; });
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_bar_css_class(const std::string&, bool);
|
void set_bar_css_class(const std::string&, bool);
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ void Task::handle_title(const char* title) {
|
|||||||
}
|
}
|
||||||
title_ = title;
|
title_ = title;
|
||||||
hide_if_ignored();
|
hide_if_ignored();
|
||||||
|
hide_if_duplicate();
|
||||||
|
|
||||||
if ((!with_icon_ && !with_name_) || app_info_) {
|
if ((!with_icon_ && !with_name_) || app_info_) {
|
||||||
return;
|
return;
|
||||||
@@ -258,6 +259,26 @@ void Task::set_minimize_hint() {
|
|||||||
minimize_hint.y, minimize_hint.w, minimize_hint.h);
|
minimize_hint.y, minimize_hint.w, minimize_hint.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Task::hide_if_duplicate() {
|
||||||
|
const auto& squash_list = tbar_->squash_list();
|
||||||
|
bool contains_app =
|
||||||
|
squash_list.contains("*") || squash_list.contains(title_) || squash_list.contains(app_id_);
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
squashed_ = true;
|
||||||
|
if (button_visible_) {
|
||||||
|
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
|
handle_output_leave(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!squashed_ && !ignored_) {
|
||||||
|
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
|
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;
|
||||||
@@ -265,7 +286,9 @@ void Task::hide_if_ignored() {
|
|||||||
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
auto output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
|
||||||
handle_output_leave(output);
|
handle_output_leave(output);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!ignored_ && !squashed_) {
|
||||||
bool is_was_ignored = ignored_;
|
bool is_was_ignored = ignored_;
|
||||||
ignored_ = false;
|
ignored_ = false;
|
||||||
if (is_was_ignored) {
|
if (is_was_ignored) {
|
||||||
@@ -283,6 +306,7 @@ void Task::handle_app_id(const char* app_id) {
|
|||||||
}
|
}
|
||||||
app_id_ = app_id;
|
app_id_ = app_id;
|
||||||
hide_if_ignored();
|
hide_if_ignored();
|
||||||
|
hide_if_duplicate();
|
||||||
|
|
||||||
auto ids_replace_map = tbar_->app_ids_replace_map();
|
auto ids_replace_map = tbar_->app_ids_replace_map();
|
||||||
if (ids_replace_map.count(app_id_)) {
|
if (ids_replace_map.count(app_id_)) {
|
||||||
@@ -322,6 +346,10 @@ void Task::handle_output_enter(struct wl_output* output) {
|
|||||||
spdlog::debug("{} is ignored", repr());
|
spdlog::debug("{} is ignored", repr());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (squashed_) {
|
||||||
|
spdlog::debug("{} was squashed", repr());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
spdlog::debug("{} entered output {}", repr(), (void*)output);
|
spdlog::debug("{} entered output {}", repr(), (void*)output);
|
||||||
|
|
||||||
@@ -419,6 +447,28 @@ void Task::handle_closed() {
|
|||||||
tbar_->remove_button(button);
|
tbar_->remove_button(button);
|
||||||
button_visible_ = false;
|
button_visible_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& squash_list = tbar_->squash_list();
|
||||||
|
const bool in_squash_list =
|
||||||
|
squash_list.contains("*") || squash_list.contains(title_) || squash_list.contains(app_id_);
|
||||||
|
if (in_squash_list && !squashed_ &&
|
||||||
|
(tbar_->task_id_count(app_id_) > 1 || tbar_->task_title_count(title_) > 1)) {
|
||||||
|
// Find next squashed task with same title or id (excluding ourselves)
|
||||||
|
auto tasks = tbar_->tasks();
|
||||||
|
const auto it = std::ranges::find_if(tasks, [this](auto&& task) {
|
||||||
|
return &task != this && task.squashed_ &&
|
||||||
|
(task.app_id() == app_id_ || task.title() == title_);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != tasks.end() && !(*it).ignored_) {
|
||||||
|
Task& task = *it;
|
||||||
|
task.squashed_ = false;
|
||||||
|
tbar_->add_button(task.button);
|
||||||
|
task.button.show();
|
||||||
|
task.button_visible_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tbar_->remove_task(id_);
|
tbar_->remove_task(id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,6 +722,13 @@ Taskbar::Taskbar(const std::string& id, const waybar::Bar& bar, const Json::Valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load squash-list
|
||||||
|
if (config_["squash-list"].isArray()) {
|
||||||
|
for (auto& app_name : config_["squash-list"]) {
|
||||||
|
squash_list_.emplace(app_name.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load app_id remappings
|
// Load app_id remappings
|
||||||
if (config_["app_ids-mapping"].isObject()) {
|
if (config_["app_ids-mapping"].isObject()) {
|
||||||
const Json::Value& mapping = config_["app_ids-mapping"];
|
const Json::Value& mapping = config_["app_ids-mapping"];
|
||||||
@@ -1056,8 +1113,18 @@ const IconLoader& Taskbar::icon_loader() const { return icon_loader_; }
|
|||||||
|
|
||||||
const std::unordered_set<std::string>& Taskbar::ignore_list() const { return ignore_list_; }
|
const std::unordered_set<std::string>& Taskbar::ignore_list() const { return ignore_list_; }
|
||||||
|
|
||||||
|
const std::unordered_set<std::string>& Taskbar::squash_list() const { return squash_list_; }
|
||||||
|
|
||||||
const std::map<std::string, std::string>& Taskbar::app_ids_replace_map() const {
|
const std::map<std::string, std::string>& Taskbar::app_ids_replace_map() const {
|
||||||
return app_ids_replace_map_;
|
return app_ids_replace_map_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t Taskbar::task_id_count(std::string_view id) const {
|
||||||
|
return std::ranges::count_if(tasks_, [=](auto&& task) { return id == task->app_id(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Taskbar::task_title_count(std::string_view title) const {
|
||||||
|
return std::ranges::count_if(tasks_, [=](auto&& task) { return title == task->title(); });
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace waybar::modules::wlr */
|
} /* namespace waybar::modules::wlr */
|
||||||
|
|||||||
Reference in New Issue
Block a user