Merge pull request #4694 from whymusticode/max-icons
feat(hyprland/workspaces): add deduplication and max-icons option to workspace-taskbar
This commit is contained in:
@@ -53,6 +53,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
|
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
|
||||||
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
|
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
|
||||||
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
|
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
|
||||||
|
auto taskbarMaxIcons() const -> int { return m_taskbarMaxIcons; }
|
||||||
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
|
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
|
||||||
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
|
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
|
||||||
auto onClickWindow() const -> std::string { return m_onClickWindow; }
|
auto onClickWindow() const -> std::string { return m_onClickWindow; }
|
||||||
@@ -199,6 +200,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
std::string m_taskbarFormatBefore;
|
std::string m_taskbarFormatBefore;
|
||||||
std::string m_taskbarFormatAfter;
|
std::string m_taskbarFormatAfter;
|
||||||
int m_taskbarIconSize = 16;
|
int m_taskbarIconSize = 16;
|
||||||
|
int m_taskbarMaxIcons = 0; // 0 means unlimited
|
||||||
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
|
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
|
||||||
bool m_taskbarReverseDirection = false;
|
bool m_taskbarReverseDirection = false;
|
||||||
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
|
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ This setting is ignored if *workspace-taskbar.enable* is set to true.
|
|||||||
default: 16 ++
|
default: 16 ++
|
||||||
Size of the icons in the workspace taskbar.
|
Size of the icons in the workspace taskbar.
|
||||||
|
|
||||||
|
*max-icons*: ++
|
||||||
|
typeof: int ++
|
||||||
|
default: 0 (unlimited) ++
|
||||||
|
Maximum number of icons to show per workspace. When set, duplicate icons (windows with the same class) are removed first, then the list is trimmed to this limit. Set to 0 for unlimited icons.
|
||||||
|
|
||||||
*icon-theme*: ++
|
*icon-theme*: ++
|
||||||
typeof: string | array ++
|
typeof: string | array ++
|
||||||
default: [] ++
|
default: [] ++
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -516,11 +517,47 @@ void Workspace::updateTaskbar(const std::string& workspace_icon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFirst = true;
|
// Build a list of windows to display, removing duplicates by window_class
|
||||||
auto processWindow = [&](const WindowRepr& window_repr) {
|
// and respecting max-icons limit
|
||||||
|
std::vector<const WindowRepr*> windowsToShow;
|
||||||
|
std::set<std::string> seenClasses;
|
||||||
|
|
||||||
|
auto addWindowIfUnique = [&](const WindowRepr& window_repr) {
|
||||||
if (shouldSkipWindow(window_repr)) {
|
if (shouldSkipWindow(window_repr)) {
|
||||||
return; // skip
|
return;
|
||||||
}
|
}
|
||||||
|
// Deduplicate by window_class
|
||||||
|
if (seenClasses.find(window_repr.window_class) != seenClasses.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seenClasses.insert(window_repr.window_class);
|
||||||
|
windowsToShow.push_back(&window_repr);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_workspaceManager.taskbarReverseDirection()) {
|
||||||
|
for (auto it = m_windowMap.rbegin(); it != m_windowMap.rend(); ++it) {
|
||||||
|
addWindowIfUnique(*it);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const auto& window_repr : m_windowMap) {
|
||||||
|
addWindowIfUnique(window_repr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply max-icons limit if configured
|
||||||
|
int maxIcons = m_workspaceManager.taskbarMaxIcons();
|
||||||
|
if (maxIcons > 0 && static_cast<int>(windowsToShow.size()) > maxIcons) {
|
||||||
|
windowsToShow.resize(maxIcons);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply max-windows limit if configured
|
||||||
|
int maxWindows = m_workspaceManager.maxWindows();
|
||||||
|
if (maxWindows > 0 && static_cast<int>(windowsToShow.size()) > maxWindows) {
|
||||||
|
windowsToShow.resize(maxWindows);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFirst = true;
|
||||||
|
for (const auto* window_repr : windowsToShow) {
|
||||||
if (isFirst) {
|
if (isFirst) {
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
} else if (m_workspaceManager.getWindowSeparator() != "") {
|
} else if (m_workspaceManager.getWindowSeparator() != "") {
|
||||||
@@ -530,29 +567,29 @@ void Workspace::updateTaskbar(const std::string& workspace_icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
|
auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
window_box->set_tooltip_markup(window_repr.window_title);
|
window_box->set_tooltip_markup(window_repr->window_title);
|
||||||
|
|
||||||
auto button = Gtk::manage(new Gtk::Button());
|
auto button = Gtk::manage(new Gtk::Button());
|
||||||
button->set_relief(Gtk::RELIEF_NONE);
|
button->set_relief(Gtk::RELIEF_NONE);
|
||||||
button->add(*window_box);
|
button->add(*window_box);
|
||||||
button->get_style_context()->add_class("taskbar-window");
|
button->get_style_context()->add_class("taskbar-window");
|
||||||
if (window_repr.isActive) {
|
if (window_repr->isActive) {
|
||||||
button->get_style_context()->add_class("active");
|
button->get_style_context()->add_class("active");
|
||||||
}
|
}
|
||||||
if (m_workspaceManager.onClickWindow() != "") {
|
if (m_workspaceManager.onClickWindow() != "") {
|
||||||
button->signal_button_press_event().connect(
|
button->signal_button_press_event().connect(
|
||||||
sigc::bind(sigc::mem_fun(*this, &Workspace::handleClick), window_repr.address), false);
|
sigc::bind(sigc::mem_fun(*this, &Workspace::handleClick), window_repr->address), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto text_before = fmt::format(fmt::runtime(m_workspaceManager.taskbarFormatBefore()),
|
auto text_before = fmt::format(fmt::runtime(m_workspaceManager.taskbarFormatBefore()),
|
||||||
fmt::arg("title", window_repr.window_title));
|
fmt::arg("title", window_repr->window_title));
|
||||||
if (!text_before.empty()) {
|
if (!text_before.empty()) {
|
||||||
auto window_label_before = Gtk::make_managed<Gtk::Label>(text_before);
|
auto window_label_before = Gtk::make_managed<Gtk::Label>(text_before);
|
||||||
window_box->pack_start(*window_label_before, true, true);
|
window_box->pack_start(*window_label_before, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_workspaceManager.taskbarWithIcon()) {
|
if (m_workspaceManager.taskbarWithIcon()) {
|
||||||
auto app_info_ = IconLoader::get_app_info_from_app_id_list(window_repr.window_class);
|
auto app_info_ = IconLoader::get_app_info_from_app_id_list(window_repr->window_class);
|
||||||
int icon_size = m_workspaceManager.taskbarIconSize();
|
int icon_size = m_workspaceManager.taskbarIconSize();
|
||||||
auto window_icon = Gtk::make_managed<Gtk::Image>();
|
auto window_icon = Gtk::make_managed<Gtk::Image>();
|
||||||
m_workspaceManager.iconLoader().image_load_icon(*window_icon, app_info_, icon_size);
|
m_workspaceManager.iconLoader().image_load_icon(*window_icon, app_info_, icon_size);
|
||||||
@@ -560,7 +597,7 @@ void Workspace::updateTaskbar(const std::string& workspace_icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto text_after = fmt::format(fmt::runtime(m_workspaceManager.taskbarFormatAfter()),
|
auto text_after = fmt::format(fmt::runtime(m_workspaceManager.taskbarFormatAfter()),
|
||||||
fmt::arg("title", window_repr.window_title));
|
fmt::arg("title", window_repr->window_title));
|
||||||
if (!text_after.empty()) {
|
if (!text_after.empty()) {
|
||||||
auto window_label_after = Gtk::make_managed<Gtk::Label>(text_after);
|
auto window_label_after = Gtk::make_managed<Gtk::Label>(text_after);
|
||||||
window_box->pack_start(*window_label_after, true, true);
|
window_box->pack_start(*window_label_after, true, true);
|
||||||
@@ -568,24 +605,6 @@ void Workspace::updateTaskbar(const std::string& workspace_icon) {
|
|||||||
|
|
||||||
m_content.pack_start(*button, true, false);
|
m_content.pack_start(*button, true, false);
|
||||||
button->show_all();
|
button->show_all();
|
||||||
};
|
|
||||||
|
|
||||||
if (m_workspaceManager.taskbarReverseDirection()) {
|
|
||||||
auto rend_it = m_workspaceManager.maxWindows() == 0
|
|
||||||
? m_windowMap.rend()
|
|
||||||
: m_windowMap.rbegin() + m_workspaceManager.maxWindows();
|
|
||||||
|
|
||||||
for (auto it = m_windowMap.rbegin(); it != rend_it; ++it) {
|
|
||||||
processWindow(*it);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto end_it = m_workspaceManager.maxWindows() == 0
|
|
||||||
? m_windowMap.end()
|
|
||||||
: m_windowMap.begin() + m_workspaceManager.maxWindows();
|
|
||||||
|
|
||||||
for (auto it = m_windowMap.begin(); it != end_it; ++it) {
|
|
||||||
processWindow(*it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto formatAfter = m_workspaceManager.formatAfter();
|
auto formatAfter = m_workspaceManager.formatAfter();
|
||||||
|
|||||||
@@ -826,6 +826,9 @@ auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value& config) -> vo
|
|||||||
if (workspaceTaskbar["icon-size"].isInt()) {
|
if (workspaceTaskbar["icon-size"].isInt()) {
|
||||||
m_taskbarIconSize = workspaceTaskbar["icon-size"].asInt();
|
m_taskbarIconSize = workspaceTaskbar["icon-size"].asInt();
|
||||||
}
|
}
|
||||||
|
if (workspaceTaskbar["max-icons"].isInt()) {
|
||||||
|
m_taskbarMaxIcons = workspaceTaskbar["max-icons"].asInt();
|
||||||
|
}
|
||||||
if (workspaceTaskbar["orientation"].isString() &&
|
if (workspaceTaskbar["orientation"].isString() &&
|
||||||
toLower(workspaceTaskbar["orientation"].asString()) == "vertical") {
|
toLower(workspaceTaskbar["orientation"].asString()) == "vertical") {
|
||||||
m_taskbarOrientation = Gtk::ORIENTATION_VERTICAL;
|
m_taskbarOrientation = Gtk::ORIENTATION_VERTICAL;
|
||||||
|
|||||||
Reference in New Issue
Block a user