Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/modules/hyprland/workspaces.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class Workspaces : public AModule, public EventHandler {
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
auto taskbarIconSize() const -> int { return m_taskbarIconSize; }
auto taskbarMaxIcons() const -> int { return m_taskbarMaxIcons; }
auto taskbarOrientation() const -> Gtk::Orientation { return m_taskbarOrientation; }
auto taskbarReverseDirection() const -> bool { return m_taskbarReverseDirection; }
auto onClickWindow() const -> std::string { return m_onClickWindow; }
Expand Down Expand Up @@ -186,6 +187,7 @@ class Workspaces : public AModule, public EventHandler {
std::string m_taskbarFormatBefore;
std::string m_taskbarFormatAfter;
int m_taskbarIconSize = 16;
int m_taskbarMaxIcons = 0; // 0 means unlimited
Gtk::Orientation m_taskbarOrientation = Gtk::ORIENTATION_HORIZONTAL;
bool m_taskbarReverseDirection = false;
util::EnumParser<ActiveWindowPosition> m_activeWindowEnumParser;
Expand Down
5 changes: 5 additions & 0 deletions man/waybar-hyprland-workspaces.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ This setting is ignored if *workspace-taskbar.enable* is set to true.
default: 16 ++
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*: ++
typeof: string | array ++
default: [] ++
Expand Down
59 changes: 40 additions & 19 deletions src/modules/hyprland/workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <spdlog/spdlog.h>

#include <memory>
#include <set>
#include <string>
#include <utility>

Expand Down Expand Up @@ -286,11 +287,41 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
}
}

bool isFirst = true;
auto processWindow = [&](const WindowRepr &window_repr) {
// Build a list of windows to display, removing duplicates by window_class
// 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)) {
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);
}

bool isFirst = true;
for (const auto *window_repr : windowsToShow) {
if (isFirst) {
isFirst = false;
} else if (m_workspaceManager.getWindowSeparator() != "") {
Expand All @@ -300,52 +331,42 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
}

auto window_box = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL);
window_box->set_tooltip_text(window_repr.window_title);
window_box->set_tooltip_text(window_repr->window_title);
window_box->get_style_context()->add_class("taskbar-window");
if (window_repr.isActive) {
if (window_repr->isActive) {
window_box->get_style_context()->add_class("active");
}
auto event_box = Gtk::manage(new Gtk::EventBox());
event_box->add(*window_box);
if (m_workspaceManager.onClickWindow() != "") {
event_box->signal_button_press_event().connect(
sigc::bind(sigc::mem_fun(*this, &Workspace::handleClick), window_repr.address));
sigc::bind(sigc::mem_fun(*this, &Workspace::handleClick), window_repr->address));
}

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()) {
auto window_label_before = Gtk::make_managed<Gtk::Label>(text_before);
window_box->pack_start(*window_label_before, true, true);
}

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();
auto window_icon = Gtk::make_managed<Gtk::Image>();
m_workspaceManager.iconLoader().image_load_icon(*window_icon, app_info_, icon_size);
window_box->pack_start(*window_icon, false, false);
}

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()) {
auto window_label_after = Gtk::make_managed<Gtk::Label>(text_after);
window_box->pack_start(*window_label_after, true, true);
}

m_content.pack_start(*event_box, true, false);
event_box->show_all();
};

if (m_workspaceManager.taskbarReverseDirection()) {
for (auto it = m_windowMap.rbegin(); it != m_windowMap.rend(); ++it) {
processWindow(*it);
}
} else {
for (const auto &window_repr : m_windowMap) {
processWindow(window_repr);
}
}

auto formatAfter = m_workspaceManager.formatAfter();
Expand Down
3 changes: 3 additions & 0 deletions src/modules/hyprland/workspaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,9 @@ auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> vo
if (workspaceTaskbar["icon-size"].isInt()) {
m_taskbarIconSize = workspaceTaskbar["icon-size"].asInt();
}
if (workspaceTaskbar["max-icons"].isInt()) {
m_taskbarMaxIcons = workspaceTaskbar["max-icons"].asInt();
}
if (workspaceTaskbar["orientation"].isString() &&
toLower(workspaceTaskbar["orientation"].asString()) == "vertical") {
m_taskbarOrientation = Gtk::ORIENTATION_VERTICAL;
Expand Down
Empty file added subprojects/.wraplock
Empty file.