workspace taskbars: Add config parsing
Use format from config instead of hardcoding
This commit is contained in:
@ -62,7 +62,8 @@ class Workspace {
|
|||||||
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
bool onWindowOpened(WindowCreationPayload const& create_window_paylod);
|
||||||
std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
|
std::optional<WindowRepr> closeWindow(WindowAddress const& addr);
|
||||||
|
|
||||||
void update(const std::string& format, const std::string& icon);
|
void update(const std::string& workspace_icon);
|
||||||
|
void updateTaskbar(const std::string& workspace_icon);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Workspaces& m_workspaceManager;
|
Workspaces& m_workspaceManager;
|
||||||
@ -82,7 +83,8 @@ class Workspace {
|
|||||||
|
|
||||||
Gtk::Button m_button;
|
Gtk::Button m_button;
|
||||||
Gtk::Box m_content;
|
Gtk::Box m_content;
|
||||||
Gtk::Label m_label;
|
Gtk::Label m_labelBefore;
|
||||||
|
Gtk::Label m_labelAfter;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::hyprland
|
} // namespace waybar::modules::hyprland
|
||||||
|
@ -38,8 +38,14 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto activeOnly() const -> bool { return m_activeOnly; }
|
auto activeOnly() const -> bool { return m_activeOnly; }
|
||||||
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
|
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
|
||||||
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
auto moveToMonitor() const -> bool { return m_moveToMonitor; }
|
||||||
|
auto enableWorkspaceTaskbar() const -> bool { return m_enableWorkspaceTaskbar; }
|
||||||
|
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
|
||||||
|
|
||||||
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
auto getBarOutput() const -> std::string { return m_bar.output->name; }
|
||||||
|
auto formatBefore() const -> std::string { return m_formatBefore; }
|
||||||
|
auto formatAfter() const -> std::string { return m_formatAfter; }
|
||||||
|
auto taskbarFormatBefore() const -> std::string { return m_taskbarFormatBefore; }
|
||||||
|
auto taskbarFormatAfter() const -> std::string { return m_taskbarFormatAfter; }
|
||||||
|
|
||||||
std::string getRewrite(std::string window_class, std::string window_title);
|
std::string getRewrite(std::string window_class, std::string window_title);
|
||||||
std::string& getWindowSeparator() { return m_formatWindowSeparator; }
|
std::string& getWindowSeparator() { return m_formatWindowSeparator; }
|
||||||
@ -69,6 +75,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
|
auto populateIgnoreWorkspacesConfig(const Json::Value& config) -> void;
|
||||||
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
|
auto populateFormatWindowSeparatorConfig(const Json::Value& config) -> void;
|
||||||
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
|
auto populateWindowRewriteConfig(const Json::Value& config) -> void;
|
||||||
|
auto populateWorkspaceTaskbarConfig(const Json::Value& config) -> void;
|
||||||
|
|
||||||
void registerIpc();
|
void registerIpc();
|
||||||
|
|
||||||
@ -121,7 +128,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
// Map for windows stored in workspaces not present in the current bar.
|
// Map for windows stored in workspaces not present in the current bar.
|
||||||
// This happens when the user has multiple monitors (hence, multiple bars)
|
// This happens when the user has multiple monitors (hence, multiple bars)
|
||||||
// and doesn't share windows accross bars (a.k.a `all-outputs` = false)
|
// and doesn't share windows accross bars (a.k.a `all-outputs` = false)
|
||||||
std::map<WindowAddress, WindowRepr> m_orphanWindowMap;
|
std::map<WindowAddress, WindowRepr, std::less<>> m_orphanWindowMap;
|
||||||
|
|
||||||
enum class SortMethod { ID, NAME, NUMBER, DEFAULT };
|
enum class SortMethod { ID, NAME, NUMBER, DEFAULT };
|
||||||
util::EnumParser<SortMethod> m_enumParser;
|
util::EnumParser<SortMethod> m_enumParser;
|
||||||
@ -131,14 +138,14 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
{"NUMBER", SortMethod::NUMBER},
|
{"NUMBER", SortMethod::NUMBER},
|
||||||
{"DEFAULT", SortMethod::DEFAULT}};
|
{"DEFAULT", SortMethod::DEFAULT}};
|
||||||
|
|
||||||
std::string m_format;
|
std::string m_formatBefore;
|
||||||
|
std::string m_formatAfter;
|
||||||
|
|
||||||
std::map<std::string, std::string> m_iconsMap;
|
std::map<std::string, std::string> m_iconsMap;
|
||||||
util::RegexCollection m_windowRewriteRules;
|
util::RegexCollection m_windowRewriteRules;
|
||||||
bool m_anyWindowRewriteRuleUsesTitle = false;
|
bool m_anyWindowRewriteRuleUsesTitle = false;
|
||||||
std::string m_formatWindowSeparator;
|
std::string m_formatWindowSeparator;
|
||||||
|
|
||||||
IconLoader m_iconLoader;
|
|
||||||
bool m_withIcon;
|
bool m_withIcon;
|
||||||
uint64_t m_monitorId;
|
uint64_t m_monitorId;
|
||||||
std::string m_activeWorkspaceName;
|
std::string m_activeWorkspaceName;
|
||||||
@ -148,6 +155,12 @@ class Workspaces : public AModule, public EventHandler {
|
|||||||
std::vector<std::string> m_workspacesToRemove;
|
std::vector<std::string> m_workspacesToRemove;
|
||||||
std::vector<WindowCreationPayload> m_windowsToCreate;
|
std::vector<WindowCreationPayload> m_windowsToCreate;
|
||||||
|
|
||||||
|
IconLoader m_iconLoader;
|
||||||
|
bool m_enableWorkspaceTaskbar = false;
|
||||||
|
bool m_taskbarWithIcon = false;
|
||||||
|
std::string m_taskbarFormatBefore;
|
||||||
|
std::string m_taskbarFormatAfter;
|
||||||
|
|
||||||
std::vector<std::regex> m_ignoreWorkspaces;
|
std::vector<std::regex> m_ignoreWorkspaces;
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
|
@ -35,9 +35,9 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma
|
|||||||
if (true) {
|
if (true) {
|
||||||
// TODO-WorkspaceTaskbar: Allow vertical?
|
// TODO-WorkspaceTaskbar: Allow vertical?
|
||||||
m_content.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
|
m_content.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
|
||||||
m_content.pack_start(m_label, false, false);
|
m_content.pack_start(m_labelBefore, false, false);
|
||||||
} else {
|
} else {
|
||||||
m_content.set_center_widget(m_label);
|
m_content.set_center_widget(m_labelBefore);
|
||||||
}
|
}
|
||||||
m_button.add(m_content);
|
m_button.add(m_content);
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::update(const std::string &format, const std::string &icon) {
|
void Workspace::update(const std::string &workspace_icon) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
if (this->m_workspaceManager.activeOnly() && \
|
if (this->m_workspaceManager.activeOnly() && \
|
||||||
!this->isActive() && \
|
!this->isActive() && \
|
||||||
@ -206,13 +206,14 @@ void Workspace::update(const std::string &format, const std::string &icon) {
|
|||||||
addOrRemoveClass(styleContext, m_workspaceManager.getBarOutput() == output(), "hosting-monitor");
|
addOrRemoveClass(styleContext, m_workspaceManager.getBarOutput() == output(), "hosting-monitor");
|
||||||
|
|
||||||
std::string windows;
|
std::string windows;
|
||||||
// TODO-WorkspaceTaskbar
|
// Optimization: The {windows} substitution string is only possible if the taskbar is disabled, no
|
||||||
if (false) {
|
// need to compute this if enableWorkspaceTaskbar() is true
|
||||||
|
if (!m_workspaceManager.enableWorkspaceTaskbar()) {
|
||||||
auto windowSeparator = m_workspaceManager.getWindowSeparator();
|
auto windowSeparator = m_workspaceManager.getWindowSeparator();
|
||||||
|
|
||||||
bool isNotFirst = false;
|
bool isNotFirst = false;
|
||||||
|
|
||||||
for (auto &[_pid, window_repr] : m_windowMap) {
|
for (const auto &[_pid, window_repr] : m_windowMap) {
|
||||||
if (isNotFirst) {
|
if (isNotFirst) {
|
||||||
windows.append(windowSeparator);
|
windows.append(windowSeparator);
|
||||||
}
|
}
|
||||||
@ -221,38 +222,63 @@ void Workspace::update(const std::string &format, const std::string &icon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_label.set_markup(fmt::format(fmt::runtime(format), fmt::arg("id", id()),
|
auto formatBefore = m_workspaceManager.formatBefore();
|
||||||
fmt::arg("name", name()), fmt::arg("icon", icon),
|
m_labelBefore.set_markup(fmt::format(fmt::runtime(formatBefore), fmt::arg("id", id()),
|
||||||
fmt::arg("windows", windows)));
|
fmt::arg("name", name()), fmt::arg("icon", workspace_icon),
|
||||||
|
fmt::arg("windows", windows)));
|
||||||
|
|
||||||
auto children = m_content.get_children();
|
if (m_workspaceManager.enableWorkspaceTaskbar()) {
|
||||||
for (auto child : children) {
|
updateTaskbar(workspace_icon);
|
||||||
if (child != &m_label) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::updateTaskbar(const std::string &workspace_icon) {
|
||||||
|
for (auto child : m_content.get_children()) {
|
||||||
|
if (child != &m_labelBefore) {
|
||||||
m_content.remove(*child);
|
m_content.remove(*child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &[_addr, window_repr] : m_windowMap) {
|
for (const auto &[_addr, 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);
|
||||||
auto window_icon = Gtk::make_managed<Gtk::Image>();
|
|
||||||
auto window_label = Gtk::make_managed<Gtk::Label>(window_repr.window_title);
|
|
||||||
|
|
||||||
// TODO-WorkspaceTaskbar: customizable max width and ellipsize
|
|
||||||
window_label->set_max_width_chars(20);
|
|
||||||
window_label->set_ellipsize(Pango::ELLIPSIZE_END);
|
|
||||||
|
|
||||||
// TODO-WorkspaceTaskbar: support themes
|
|
||||||
auto app_info_ = IconLoader::get_app_info_from_app_id_list(window_repr.window_class);
|
|
||||||
// TODO-WorkspaceTaskbar: icon size
|
|
||||||
m_workspaceManager.iconLoader().image_load_icon(*window_icon, app_info_, 24);
|
|
||||||
|
|
||||||
window_box->pack_start(*window_icon, false, false);
|
|
||||||
window_box->pack_start(*window_label, true, true);
|
|
||||||
window_box->set_tooltip_text(window_repr.window_title);
|
window_box->set_tooltip_text(window_repr.window_title);
|
||||||
|
|
||||||
|
auto text_before = fmt::format(fmt::runtime(m_workspaceManager.taskbarFormatBefore()),
|
||||||
|
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()) {
|
||||||
|
// TODO-WorkspaceTaskbar: support themes
|
||||||
|
auto app_info_ = IconLoader::get_app_info_from_app_id_list(window_repr.window_class);
|
||||||
|
|
||||||
|
// TODO-WorkspaceTaskbar: icon size
|
||||||
|
auto window_icon = Gtk::make_managed<Gtk::Image>();
|
||||||
|
m_workspaceManager.iconLoader().image_load_icon(*window_icon, app_info_, 24);
|
||||||
|
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));
|
||||||
|
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(*window_box, true, false);
|
m_content.pack_start(*window_box, true, false);
|
||||||
window_box->show_all();
|
window_box->show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto formatAfter = m_workspaceManager.formatAfter();
|
||||||
|
if (!formatAfter.empty()) {
|
||||||
|
m_labelAfter.set_markup(fmt::format(fmt::runtime(formatAfter), fmt::arg("id", id()),
|
||||||
|
fmt::arg("name", name()),
|
||||||
|
fmt::arg("icon", workspace_icon)));
|
||||||
|
m_content.pack_end(m_labelAfter, false, false);
|
||||||
|
m_labelAfter.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace waybar::modules::hyprland
|
} // namespace waybar::modules::hyprland
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "util/regex_collection.hpp"
|
#include "util/regex_collection.hpp"
|
||||||
|
#include "util/string.hpp"
|
||||||
|
|
||||||
namespace waybar::modules::hyprland {
|
namespace waybar::modules::hyprland {
|
||||||
|
|
||||||
@ -563,8 +564,9 @@ void Workspaces::onConfigReloaded() {
|
|||||||
|
|
||||||
auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
||||||
const auto &configFormat = config["format"];
|
const auto &configFormat = config["format"];
|
||||||
m_format = configFormat.isString() ? configFormat.asString() : "{name}";
|
m_formatBefore = configFormat.isString() ? configFormat.asString() : "{name}";
|
||||||
m_withIcon = m_format.find("{icon}") != std::string::npos;
|
m_withIcon = m_formatBefore.find("{icon}") != std::string::npos;
|
||||||
|
auto withWindows = m_formatBefore.find("{windows}") != std::string::npos;
|
||||||
|
|
||||||
if (m_withIcon && m_iconsMap.empty()) {
|
if (m_withIcon && m_iconsMap.empty()) {
|
||||||
populateIconsMap(config["format-icons"]);
|
populateIconsMap(config["format-icons"]);
|
||||||
@ -581,6 +583,15 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
|||||||
populateIgnoreWorkspacesConfig(config);
|
populateIgnoreWorkspacesConfig(config);
|
||||||
populateFormatWindowSeparatorConfig(config);
|
populateFormatWindowSeparatorConfig(config);
|
||||||
populateWindowRewriteConfig(config);
|
populateWindowRewriteConfig(config);
|
||||||
|
|
||||||
|
if (withWindows) {
|
||||||
|
populateWorkspaceTaskbarConfig(config);
|
||||||
|
}
|
||||||
|
if (m_enableWorkspaceTaskbar) {
|
||||||
|
auto parts = split(m_formatBefore, "{windows}", 1);
|
||||||
|
m_formatBefore = parts[0];
|
||||||
|
m_formatAfter = parts.size() > 1 ? parts[1] : "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::populateIconsMap(const Json::Value &formatIcons) -> void {
|
auto Workspaces::populateIconsMap(const Json::Value &formatIcons) -> void {
|
||||||
@ -653,6 +664,29 @@ auto Workspaces::populateWindowRewriteConfig(const Json::Value &config) -> void
|
|||||||
[this](std::string &window_rule) { return windowRewritePriorityFunction(window_rule); });
|
[this](std::string &window_rule) { return windowRewritePriorityFunction(window_rule); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Workspaces::populateWorkspaceTaskbarConfig(const Json::Value &config) -> void {
|
||||||
|
const auto &workspaceTaskbar = config["workspace-taskbar"];
|
||||||
|
if (!workspaceTaskbar.isObject()) {
|
||||||
|
spdlog::debug("workspace-taskbar is not defined or is not an object, using default rules.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
populateBoolConfig(workspaceTaskbar, "enable", m_enableWorkspaceTaskbar);
|
||||||
|
|
||||||
|
if (workspaceTaskbar["format"].isString()) {
|
||||||
|
/* The user defined a format string, use it */
|
||||||
|
auto parts = split(workspaceTaskbar["format"].asString(), "{icon}", 1);
|
||||||
|
m_taskbarFormatBefore = parts[0];
|
||||||
|
if (parts.size() > 1) {
|
||||||
|
m_taskbarWithIcon = true;
|
||||||
|
m_taskbarFormatAfter = parts[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* The default is to only show the icon */
|
||||||
|
m_taskbarWithIcon = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_payload) {
|
void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_payload) {
|
||||||
if (!create_window_payload.isEmpty(*this)) {
|
if (!create_window_payload.isEmpty(*this)) {
|
||||||
m_orphanWindowMap[create_window_payload.getAddress()] = create_window_payload.repr(*this);
|
m_orphanWindowMap[create_window_payload.getAddress()] = create_window_payload.repr(*this);
|
||||||
@ -881,7 +915,7 @@ void Workspaces::updateWorkspaceStates() {
|
|||||||
if (updatedWorkspace != updatedWorkspaces.end()) {
|
if (updatedWorkspace != updatedWorkspaces.end()) {
|
||||||
workspace->setOutput((*updatedWorkspace)["monitor"].asString());
|
workspace->setOutput((*updatedWorkspace)["monitor"].asString());
|
||||||
}
|
}
|
||||||
workspace->update(m_format, workspaceIcon);
|
workspace->update(workspaceIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user