workspace taskbars: Display windows in a consistent order

Use a vector instead of a map for for storing the workspace windows.
This orders the windows by the time they were added to the workspace, instead of sorting by address (which is effectively a random order). The new ordering seems to match the wlr/taskbar module
This commit is contained in:
Pol Rivero
2025-01-02 07:41:24 +01:00
parent e1649b001f
commit 53ca5a4883
4 changed files with 26 additions and 15 deletions

View File

@ -27,6 +27,7 @@ namespace waybar::modules::hyprland {
class Workspaces; class Workspaces;
struct WindowRepr { struct WindowRepr {
std::string address;
std::string window_class; std::string window_class;
std::string window_title; std::string window_title;
std::string repr_rewrite; std::string repr_rewrite;

View File

@ -54,9 +54,11 @@ class Workspace {
void setWindows(uint value) { m_windows = value; }; void setWindows(uint value) { m_windows = value; };
void setName(std::string const& value) { m_name = value; }; void setName(std::string const& value) { m_name = value; };
void setOutput(std::string const& value) { m_output = value; }; void setOutput(std::string const& value) { m_output = value; };
bool containsWindow(WindowAddress const& addr) const { return m_windowMap.contains(addr); } bool containsWindow(WindowAddress const& addr) const {
return std::ranges::any_of(m_windowMap,
[&addr](const auto& window) { return window.address == addr; });
};
void insertWindow(WindowCreationPayload create_window_paylod); void insertWindow(WindowCreationPayload create_window_paylod);
WindowRepr removeWindow(WindowAddress const& addr);
void initializeWindowMap(const Json::Value& clients_data); void initializeWindowMap(const Json::Value& clients_data);
bool onWindowOpened(WindowCreationPayload const& create_window_paylod); bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
@ -78,7 +80,7 @@ class Workspace {
bool m_isUrgent = false; bool m_isUrgent = false;
bool m_isVisible = false; bool m_isVisible = false;
std::map<WindowAddress, WindowRepr, std::less<>> m_windowMap; std::vector<WindowRepr> m_windowMap;
Gtk::Button m_button; Gtk::Button m_button;
Gtk::Box m_content; Gtk::Box m_content;

View File

@ -98,7 +98,8 @@ WindowRepr WindowCreationPayload::repr(Workspaces &workspace_manager) {
} }
if (std::holds_alternative<ClassAndTitle>(m_window)) { if (std::holds_alternative<ClassAndTitle>(m_window)) {
auto [window_class, window_title] = std::get<ClassAndTitle>(m_window); auto [window_class, window_title] = std::get<ClassAndTitle>(m_window);
return {window_class, window_title, workspace_manager.getRewrite(window_class, window_title)}; return {m_windowAddress, window_class, window_title,
workspace_manager.getRewrite(window_class, window_title)};
} }
// Unreachable // Unreachable
spdlog::error("WorkspaceWindow::repr: Unreachable"); spdlog::error("WorkspaceWindow::repr: Unreachable");

View File

@ -53,8 +53,13 @@ void addOrRemoveClass(const Glib::RefPtr<Gtk::StyleContext> &context, bool condi
} }
std::optional<WindowRepr> Workspace::closeWindow(WindowAddress const &addr) { std::optional<WindowRepr> Workspace::closeWindow(WindowAddress const &addr) {
if (m_windowMap.contains(addr)) { auto it = std::ranges::find_if(m_windowMap,
return removeWindow(addr); [&addr](const auto &window) { return window.address == addr; });
// If the vector contains the address, remove it and return the window representation
if (it != m_windowMap.end()) {
WindowRepr windowRepr = *it;
m_windowMap.erase(it);
return windowRepr;
} }
return std::nullopt; return std::nullopt;
} }
@ -101,7 +106,15 @@ void Workspace::insertWindow(WindowCreationPayload create_window_paylod) {
auto repr = create_window_paylod.repr(m_workspaceManager); auto repr = create_window_paylod.repr(m_workspaceManager);
if (!repr.empty()) { if (!repr.empty()) {
m_windowMap[create_window_paylod.getAddress()] = repr; auto addr = create_window_paylod.getAddress();
auto it = std::ranges::find_if(
m_windowMap, [&addr](const auto &window) { return window.address == addr; });
// If the vector contains the address, update the window representation, otherwise insert it
if (it != m_windowMap.end()) {
*it = repr;
} else {
m_windowMap.emplace_back(repr);
}
} }
} }
}; };
@ -114,12 +127,6 @@ bool Workspace::onWindowOpened(WindowCreationPayload const &create_window_paylod
return false; return false;
} }
WindowRepr Workspace::removeWindow(WindowAddress const &addr) {
WindowRepr windowRepr = m_windowMap[addr];
m_windowMap.erase(addr);
return windowRepr;
}
std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map) { std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map) {
spdlog::trace("Selecting icon for workspace {}", name()); spdlog::trace("Selecting icon for workspace {}", name());
if (isUrgent()) { if (isUrgent()) {
@ -212,7 +219,7 @@ void Workspace::update(const std::string &workspace_icon) {
bool isNotFirst = false; bool isNotFirst = false;
for (const auto &[_pid, window_repr] : m_windowMap) { for (const auto &window_repr : m_windowMap) {
if (isNotFirst) { if (isNotFirst) {
windows.append(windowSeparator); windows.append(windowSeparator);
} }
@ -238,7 +245,7 @@ void Workspace::updateTaskbar(const std::string &workspace_icon) {
} }
} }
for (const auto &[_addr, window_repr] : m_windowMap) { for (const auto &window_repr : m_windowMap) {
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_text(window_repr.window_title); window_box->set_tooltip_text(window_repr.window_title);