Skip to content

Commit c998b41

Browse files
committed
feat: add hide-vacant option to dwl/tags module
1 parent 8490a1d commit c998b41

File tree

3 files changed

+113
-31
lines changed

3 files changed

+113
-31
lines changed

include/modules/dwl/tags.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class Tags : public waybar::AModule {
2020

2121
void handle_primary_clicked(uint32_t tag);
2222
bool handle_button_press(GdkEventButton *event_button, uint32_t tag);
23+
uint32_t get_label_position(std::string label);
24+
void add_button(uint32_t tag);
2325

2426
struct zdwl_ipc_manager_v2 *status_manager_;
2527
struct wl_seat *seat_;
@@ -28,6 +30,7 @@ class Tags : public waybar::AModule {
2830
const waybar::Bar &bar_;
2931
Gtk::Box box_;
3032
std::vector<Gtk::Button> buttons_;
33+
bool hide_vacant_;
3134
struct zdwl_ipc_output_v2 *output_status_;
3235
};
3336

man/waybar-dwl-tags.5.scd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ Addressed by *dwl/tags*
2121
typeof: array ++
2222
The label to display for each tag.
2323

24+
*hide-vacant*: ++
25+
typeof: bool ++
26+
default: false ++
27+
If set to true, tags without clients and that are not active will be hidden.
28+
2429
*disable-click*: ++
2530
typeof: bool ++
2631
default: false ++

src/modules/dwl/tags.cpp

Lines changed: 105 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ namespace waybar::modules::dwl {
1919
/* dwl stuff */
2020
wl_array tags, layouts;
2121

22-
static uint num_tags = 0;
22+
static uint32_t num_tags = 0;
23+
static uint32_t num_counts = 0;
24+
std::vector<std::string> tag_labels;
25+
2326

2427
static void toggle_visibility(void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
2528
// Intentionally empty
@@ -87,14 +90,59 @@ static void handle_global_remove(void *data, struct wl_registry *registry, uint3
8790

8891
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
8992
.global_remove = handle_global_remove};
93+
uint32_t Tags::get_label_position(std::string label) {
94+
uint32_t i;
95+
for(i=0;i< num_counts;i++) {
96+
if(label == tag_labels[i]) {
97+
return i;
98+
}
99+
}
100+
return UINT32_MAX;
101+
}
102+
103+
void Tags::add_button(uint32_t tag) {
104+
uint32_t inser_pos = 0;
105+
std::string label = tag_labels[tag];
106+
std::string added_label;
107+
uint32_t position = UINT32_MAX;
108+
109+
for (auto &added_button : buttons_) {
110+
added_label = added_button.get_label();
111+
position = get_label_position(added_label);
112+
if(position != UINT32_MAX && position < (tag + 1)) {
113+
inser_pos++;
114+
}
115+
}
116+
117+
buttons_.emplace(buttons_.begin() + (inser_pos), label);
118+
119+
auto &button = buttons_[inser_pos];
120+
121+
button.set_relief(Gtk::RELIEF_NONE);
122+
box_.pack_start(button, false, false, 0);
123+
for (size_t i = 0; i < buttons_.size(); ++i) {
124+
box_.reorder_child(buttons_[i], i);
125+
}
126+
127+
if (!config_["disable-click"].asBool()) {
128+
button.signal_clicked().connect(
129+
sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), 1<<tag));
130+
button.signal_button_press_event().connect(
131+
sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), 1<<tag));
132+
}
133+
}
90134

91135
Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &config)
92136
: waybar::AModule(config, "tags", id, false, false),
93137
status_manager_{nullptr},
94138
seat_{nullptr},
95139
bar_(bar),
96140
box_{bar.orientation, 0},
141+
hide_vacant_(false),
97142
output_status_{nullptr} {
143+
if (config_["hide-vacant"].asBool()) {
144+
hide_vacant_ = config_["hide-vacant"].asBool();
145+
}
98146
struct wl_display *display = Client::inst()->wl_display;
99147
struct wl_registry *registry = wl_display_get_registry(display);
100148

@@ -118,33 +166,27 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
118166
event_box_.add(box_);
119167

120168
// Default to 9 tags, cap at 32
121-
const uint32_t num_tags =
169+
num_counts =
122170
config["num-tags"].isUInt() ? std::min<uint32_t>(32, config_["num-tags"].asUInt()) : 9;
171+
172+
tag_labels.resize(num_counts);
123173

124-
std::vector<std::string> tag_labels(num_tags);
125-
for (uint32_t tag = 0; tag < num_tags; ++tag) {
174+
for (uint32_t tag = 0; tag < num_counts; ++tag) {
126175
tag_labels[tag] = std::to_string(tag + 1);
127176
}
128177
const Json::Value custom_labels = config["tag-labels"];
129178
if (custom_labels.isArray() && !custom_labels.empty()) {
130-
for (uint32_t tag = 0; tag < std::min(num_tags, custom_labels.size()); ++tag) {
179+
for (uint32_t tag = 0; tag < std::min(num_counts, custom_labels.size()); ++tag) {
131180
tag_labels[tag] = custom_labels[tag].asString();
132181
}
133182
}
134183

135-
uint32_t i = 1;
136-
for (const auto &tag_label : tag_labels) {
137-
Gtk::Button &button = buttons_.emplace_back(tag_label);
138-
button.set_relief(Gtk::RELIEF_NONE);
139-
box_.pack_start(button, false, false, 0);
140-
if (!config_["disable-click"].asBool()) {
141-
button.signal_clicked().connect(
142-
sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), i));
143-
button.signal_button_press_event().connect(
144-
sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), i));
184+
if (!hide_vacant_) {
185+
uint32_t i = 1;
186+
while (i <= num_counts) {
187+
add_button(num_counts-i);
188+
i++;
145189
}
146-
button.show();
147-
i <<= 1;
148190
}
149191

150192
struct wl_output *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj());
@@ -179,24 +221,56 @@ bool Tags::handle_button_press(GdkEventButton *event_button, uint32_t tag) {
179221
}
180222

181223
void Tags::handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) {
182-
// First clear all occupied state
183-
auto &button = buttons_[tag];
184-
if (clients) {
185-
button.get_style_context()->add_class("occupied");
186-
} else {
187-
button.get_style_context()->remove_class("occupied");
224+
225+
bool is_new_button = true;
226+
std::string added_label,label;
227+
uint32_t position = UINT32_MAX;
228+
229+
for (auto &added_button : buttons_) {
230+
added_label = added_button.get_label();
231+
position = get_label_position(added_label);
232+
if(position != UINT32_MAX && position == tag) {
233+
is_new_button = false;
234+
}
188235
}
189236

190-
if (state & TAG_ACTIVE) {
191-
button.get_style_context()->add_class("focused");
192-
} else {
193-
button.get_style_context()->remove_class("focused");
237+
if(is_new_button && ((state & TAG_ACTIVE) || (state & TAG_URGENT) || clients)) {
238+
add_button(tag);
194239
}
195240

196-
if (state & TAG_URGENT) {
197-
button.get_style_context()->add_class("urgent");
198-
} else {
199-
button.get_style_context()->remove_class("urgent");
241+
for (auto &button : buttons_) {
242+
243+
label = button.get_label();
244+
position = get_label_position(label);
245+
if(position == UINT32_MAX || position != tag)
246+
continue;
247+
248+
if (clients) {
249+
button.get_style_context()->add_class("occupied");
250+
button.set_visible(true);
251+
} else {
252+
button.get_style_context()->remove_class("occupied");
253+
}
254+
255+
if (state & TAG_ACTIVE) {
256+
button.get_style_context()->add_class("focused");
257+
button.set_visible(true);
258+
} else {
259+
button.get_style_context()->remove_class("focused");
260+
}
261+
262+
if (state & TAG_URGENT) {
263+
button.get_style_context()->add_class("urgent");
264+
button.set_visible(true);
265+
} else {
266+
button.get_style_context()->remove_class("urgent");
267+
}
268+
269+
if (hide_vacant_ && !(state & TAG_ACTIVE) && !(state & TAG_URGENT) && !clients) {
270+
button.set_visible(false);
271+
} else {
272+
button.set_visible(true);
273+
}
200274
}
201275
}
202276

0 commit comments

Comments
 (0)