hyprland/workspaces: implement 'active_only' option and visible class
parent
116aa5cdbd
commit
04b39ea64e
|
@ -14,9 +14,11 @@
|
|||
|
||||
namespace waybar::modules::hyprland {
|
||||
|
||||
class Workspaces;
|
||||
|
||||
class Workspace {
|
||||
public:
|
||||
explicit Workspace(const Json::Value& workspace_data);
|
||||
explicit Workspace(const Json::Value& workspace_data, Workspaces& workspace_manager);
|
||||
std::string& select_icon(std::map<std::string, std::string>& icons_map);
|
||||
Gtk::Button& button() { return button_; };
|
||||
|
||||
|
@ -26,6 +28,7 @@ class Workspace {
|
|||
bool active() const { return active_; };
|
||||
bool is_special() const { return is_special_; };
|
||||
bool is_persistent() const { return is_persistent_; };
|
||||
bool is_visible() const { return is_visible_; };
|
||||
bool is_empty() const { return windows_ == 0; };
|
||||
bool is_urgent() const { return is_urgent_; };
|
||||
|
||||
|
@ -33,12 +36,15 @@ class Workspace {
|
|||
void set_active(bool value = true) { active_ = value; };
|
||||
void set_persistent(bool value = true) { is_persistent_ = value; };
|
||||
void set_urgent(bool value = true) { is_urgent_ = value; };
|
||||
void set_visible(bool value = true) { is_visible_ = value; };
|
||||
void set_windows(uint value) { windows_ = value; };
|
||||
void set_name(std::string value) { name_ = value; };
|
||||
|
||||
void update(const std::string& format, const std::string& icon);
|
||||
|
||||
private:
|
||||
Workspaces& workspace_manager_;
|
||||
|
||||
int id_;
|
||||
std::string name_;
|
||||
std::string output_;
|
||||
|
@ -47,6 +53,7 @@ class Workspace {
|
|||
bool is_special_ = false;
|
||||
bool is_persistent_ = false;
|
||||
bool is_urgent_ = false;
|
||||
bool is_visible_ = false;
|
||||
|
||||
Gtk::Button button_;
|
||||
Gtk::Box content_;
|
||||
|
@ -62,6 +69,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||
|
||||
auto all_outputs() const -> bool { return all_outputs_; }
|
||||
auto show_special() const -> bool { return show_special_; }
|
||||
auto active_only() const -> bool { return active_only_; }
|
||||
|
||||
auto get_bar_output() const -> std::string { return bar_.output->name; }
|
||||
|
||||
|
@ -75,6 +83,7 @@ class Workspaces : public AModule, public EventHandler {
|
|||
|
||||
bool all_outputs_ = false;
|
||||
bool show_special_ = false;
|
||||
bool active_only_ = false;
|
||||
|
||||
void fill_persistent_workspaces();
|
||||
void create_persistent_workspaces();
|
||||
|
|
|
@ -24,13 +24,18 @@ Addressed by *hyprland/workspaces*
|
|||
*show-special*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to true special workspaces will be shown.
|
||||
If set to true, special workspaces will be shown.
|
||||
|
||||
*all-outputs*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to false workspaces group will be shown only in assigned output. Otherwise all workspace groups are shown.
|
||||
|
||||
*active-only*: ++
|
||||
typeof: bool ++
|
||||
default: false ++
|
||||
If set to true, only the active workspace will be shown.
|
||||
|
||||
# FORMAT REPLACEMENTS
|
||||
|
||||
*{id}*: id of workspace assigned by compositor
|
||||
|
@ -43,10 +48,11 @@ Addressed by *hyprland/workspaces*
|
|||
|
||||
Additional to workspace name matching, the following *format-icons* can be set.
|
||||
|
||||
- *default*: Will be shown, when no string match is found.
|
||||
- *default*: Will be shown, when no string match is found and none of the below conditions have defined icons.
|
||||
- *active*: Will be shown, when workspace is active
|
||||
- *special*: Will be shown on non-active special workspaces
|
||||
- *empty*: Will be shown on empty persistent workspaces
|
||||
- *empty*: Will be shown on non-active, non-special empty persistent workspaces
|
||||
- *visible*: Will be shown on workspaces that are visible but not active. For example: this is useful if you want your visible workspaces on other monitors to have the same look as active.
|
||||
- *persistent*: Will be shown on non-empty persistent workspaces
|
||||
|
||||
# EXAMPLES
|
||||
|
@ -95,6 +101,7 @@ Additional to workspace name matching, the following *format-icons* can be set.
|
|||
- *#workspaces button*
|
||||
- *#workspaces button.active*
|
||||
- *#workspaces button.empty*
|
||||
- *#workspaces button.visible*
|
||||
- *#workspaces button.persistent*
|
||||
- *#workspaces button.special*
|
||||
- *#workspaces button.urgent*
|
||||
|
|
|
@ -38,6 +38,11 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
|||
show_special_ = config_show_special.asBool();
|
||||
}
|
||||
|
||||
auto config_active_only = config_["active-only"];
|
||||
if (config_active_only.isBool()) {
|
||||
active_only_ = config_active_only.asBool();
|
||||
}
|
||||
|
||||
box_.set_name("workspaces");
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
|
@ -75,11 +80,29 @@ auto Workspaces::update() -> void {
|
|||
|
||||
workspaces_to_create_.clear();
|
||||
|
||||
// get all active workspaces
|
||||
auto monitors = gIPC->getSocket1JsonReply("monitors");
|
||||
std::vector<std::string> visible_workspaces;
|
||||
for (Json::Value &monitor : monitors) {
|
||||
auto ws = monitor["activeWorkspace"];
|
||||
if (ws.isObject() && (ws["name"].isString())) {
|
||||
visible_workspaces.push_back(ws["name"].asString());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &workspace : workspaces_) {
|
||||
// active
|
||||
workspace->set_active(workspace->name() == active_workspace_name_);
|
||||
if (workspace->name() == active_workspace_name_ && workspace.get()->is_urgent()) {
|
||||
// disable urgency if workspace is active
|
||||
if (workspace->name() == active_workspace_name_ && workspace->is_urgent()) {
|
||||
workspace->set_urgent(false);
|
||||
}
|
||||
|
||||
// visible
|
||||
workspace->set_visible(std::find(visible_workspaces.begin(), visible_workspaces.end(),
|
||||
workspace->name()) != visible_workspaces.end());
|
||||
|
||||
// set workspace icon
|
||||
std::string &workspace_icon = icons_map_[""];
|
||||
if (with_icon_) {
|
||||
workspace_icon = workspace->select_icon(icons_map_);
|
||||
|
@ -103,9 +126,10 @@ void Workspaces::onEvent(const std::string &ev) {
|
|||
} else if (eventName == "createworkspace") {
|
||||
const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces");
|
||||
for (Json::Value workspace_json : workspaces_json) {
|
||||
if (workspace_json["name"].asString() == payload &&
|
||||
std::string name = workspace_json["name"].asString();
|
||||
if (name == payload &&
|
||||
(all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) &&
|
||||
(show_special() || !workspace_json["name"].asString().starts_with("special"))) {
|
||||
(show_special() || !name.starts_with("special"))) {
|
||||
workspaces_to_create_.push_back(workspace_json);
|
||||
break;
|
||||
}
|
||||
|
@ -120,8 +144,8 @@ void Workspaces::onEvent(const std::string &ev) {
|
|||
if (bar_.output->name == new_output) { // TODO: implement this better
|
||||
const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces");
|
||||
for (Json::Value workspace_json : workspaces_json) {
|
||||
if (workspace_json["name"].asString() == workspace &&
|
||||
bar_.output->name == workspace_json["monitor"].asString()) {
|
||||
std::string name = workspace_json["name"].asString();
|
||||
if (name == workspace && bar_.output->name == workspace_json["monitor"].asString()) {
|
||||
workspaces_to_create_.push_back(workspace_json);
|
||||
break;
|
||||
}
|
||||
|
@ -154,15 +178,15 @@ void Workspaces::update_window_count() {
|
|||
auto workspace_json = std::find_if(
|
||||
workspaces_json.begin(), workspaces_json.end(),
|
||||
[&](Json::Value const &x) { return x["name"].asString() == workspace->name(); });
|
||||
uint32_t count = 0;
|
||||
if (workspace_json != workspaces_json.end()) {
|
||||
try {
|
||||
workspace->set_windows((*workspace_json)["windows"].asUInt());
|
||||
count = (*workspace_json)["windows"].asUInt();
|
||||
} catch (const std::exception &e) {
|
||||
spdlog::error("Failed to update window count: {}", e.what());
|
||||
}
|
||||
} else {
|
||||
workspace->set_windows(0);
|
||||
}
|
||||
workspace->set_windows(count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,7 +205,7 @@ void Workspaces::create_workspace(Json::Value &value) {
|
|||
}
|
||||
|
||||
// create new workspace
|
||||
workspaces_.emplace_back(std::make_unique<Workspace>(value));
|
||||
workspaces_.emplace_back(std::make_unique<Workspace>(value, *this));
|
||||
Gtk::Button &new_workspace_button = workspaces_.back()->button();
|
||||
box_.pack_start(new_workspace_button, false, false);
|
||||
sort_workspaces();
|
||||
|
@ -207,7 +231,7 @@ void Workspaces::remove_workspace(std::string name) {
|
|||
}
|
||||
|
||||
void Workspaces::fill_persistent_workspaces() {
|
||||
if (config_["persistent_workspaces"].isObject() && !all_outputs()) {
|
||||
if (config_["persistent_workspaces"].isObject()) {
|
||||
const Json::Value persistent_workspaces = config_["persistent_workspaces"];
|
||||
const std::vector<std::string> keys = persistent_workspaces.getMemberNames();
|
||||
|
||||
|
@ -297,8 +321,9 @@ void Workspaces::init() {
|
|||
const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces");
|
||||
for (Json::Value workspace_json : workspaces_json) {
|
||||
if ((all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) &&
|
||||
(!workspace_json["name"].asString().starts_with("special") || show_special()))
|
||||
(!workspace_json["name"].asString().starts_with("special") || show_special())) {
|
||||
create_workspace(workspace_json);
|
||||
}
|
||||
}
|
||||
|
||||
update_window_count();
|
||||
|
@ -314,8 +339,9 @@ Workspaces::~Workspaces() {
|
|||
std::lock_guard<std::mutex> lg(mutex_);
|
||||
}
|
||||
|
||||
Workspace::Workspace(const Json::Value &workspace_data)
|
||||
: id_(workspace_data["id"].asInt()),
|
||||
Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_manager)
|
||||
: workspace_manager_(workspace_manager),
|
||||
id_(workspace_data["id"].asInt()),
|
||||
name_(workspace_data["name"].asString()),
|
||||
output_(workspace_data["monitor"].asString()), // TODO:allow using monitor desc
|
||||
windows_(workspace_data["windows"].asInt()),
|
||||
|
@ -350,12 +376,26 @@ void add_or_remove_class(const Glib::RefPtr<Gtk::StyleContext> &context, bool co
|
|||
}
|
||||
|
||||
void Workspace::update(const std::string &format, const std::string &icon) {
|
||||
// clang-format off
|
||||
if (this->workspace_manager_.active_only() && \
|
||||
!this->active() && \
|
||||
!this->is_persistent() && \
|
||||
!this->is_visible() && \
|
||||
!this->is_special()) {
|
||||
// clang-format on
|
||||
// if active_only is true, hide if not active, persistent, visible or special
|
||||
button_.hide();
|
||||
return;
|
||||
}
|
||||
button_.show();
|
||||
|
||||
auto style_context = button_.get_style_context();
|
||||
add_or_remove_class(style_context, active(), "active");
|
||||
add_or_remove_class(style_context, is_special(), "special");
|
||||
add_or_remove_class(style_context, is_empty(), "empty");
|
||||
add_or_remove_class(style_context, is_persistent(), "persistent");
|
||||
add_or_remove_class(style_context, is_urgent(), "urgent");
|
||||
add_or_remove_class(style_context, is_visible(), "visible");
|
||||
|
||||
label_.set_markup(fmt::format(fmt::runtime(format), fmt::arg("id", id()),
|
||||
fmt::arg("name", name()), fmt::arg("icon", icon)));
|
||||
|
@ -420,6 +460,13 @@ std::string &Workspace::select_icon(std::map<std::string, std::string> &icons_ma
|
|||
return named_icon_it->second;
|
||||
}
|
||||
|
||||
if (is_visible()) {
|
||||
auto visible_icon_it = icons_map.find("visible");
|
||||
if (visible_icon_it != icons_map.end()) {
|
||||
return visible_icon_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_empty()) {
|
||||
auto empty_icon_it = icons_map.find("empty");
|
||||
if (empty_icon_it != icons_map.end()) {
|
||||
|
|
Loading…
Reference in New Issue