@@ -19,7 +19,9 @@ namespace waybar::modules::dwl {
19
19
/* dwl stuff */
20
20
wl_array tags, layouts;
21
21
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;
23
25
24
26
static void toggle_visibility (void *data, zdwl_ipc_output_v2 *zdwl_output_v2) {
25
27
// Intentionally empty
@@ -87,14 +89,59 @@ static void handle_global_remove(void *data, struct wl_registry *registry, uint3
87
89
88
90
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
89
91
.global_remove = handle_global_remove};
92
+ uint32_t Tags::get_label_position (std::string label) {
93
+ uint32_t i;
94
+ for (i = 0 ; i < num_counts; i++) {
95
+ if (label == tag_labels[i]) {
96
+ return i;
97
+ }
98
+ }
99
+ return UINT32_MAX;
100
+ }
101
+
102
+ void Tags::add_button (uint32_t tag) {
103
+ uint32_t inser_pos = 0 ;
104
+ std::string label = tag_labels[tag];
105
+ std::string added_label;
106
+ uint32_t position = UINT32_MAX;
107
+
108
+ for (auto &added_button : buttons_) {
109
+ added_label = added_button.get_label ();
110
+ position = get_label_position (added_label);
111
+ if (position != UINT32_MAX && position < (tag + 1 )) {
112
+ inser_pos++;
113
+ }
114
+ }
115
+
116
+ buttons_.emplace (buttons_.begin () + (inser_pos), label);
117
+
118
+ auto &button = buttons_[inser_pos];
119
+
120
+ button.set_relief (Gtk::RELIEF_NONE);
121
+ box_.pack_start (button, false , false , 0 );
122
+ for (size_t i = 0 ; i < buttons_.size (); ++i) {
123
+ box_.reorder_child (buttons_[i], i);
124
+ }
125
+
126
+ if (!config_[" disable-click" ].asBool ()) {
127
+ button.signal_clicked ().connect (
128
+ sigc::bind (sigc::mem_fun (*this , &Tags::handle_primary_clicked), 1 << tag));
129
+ button.signal_button_press_event ().connect (
130
+ sigc::bind (sigc::mem_fun (*this , &Tags::handle_button_press), 1 << tag));
131
+ }
132
+ }
90
133
91
134
Tags::Tags (const std::string &id, const waybar::Bar &bar, const Json::Value &config)
92
135
: waybar::AModule(config, " tags" , id, false , false ),
93
136
status_manager_{nullptr },
94
137
seat_{nullptr },
95
138
bar_ (bar),
96
139
box_{bar.orientation , 0 },
140
+ hide_vacant_ (false ),
97
141
output_status_{nullptr } {
142
+ if (config_[" hide-vacant" ].asBool ()) {
143
+ hide_vacant_ = config_[" hide-vacant" ].asBool ();
144
+ }
98
145
struct wl_display *display = Client::inst ()->wl_display ;
99
146
struct wl_registry *registry = wl_display_get_registry (display);
100
147
@@ -118,33 +165,27 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
118
165
event_box_.add (box_);
119
166
120
167
// Default to 9 tags, cap at 32
121
- const uint32_t num_tags =
168
+ num_counts =
122
169
config[" num-tags" ].isUInt () ? std::min<uint32_t >(32 , config_[" num-tags" ].asUInt ()) : 9 ;
123
170
124
- std::vector<std::string> tag_labels (num_tags);
125
- for (uint32_t tag = 0 ; tag < num_tags; ++tag) {
171
+ tag_labels.resize (num_counts);
172
+
173
+ for (uint32_t tag = 0 ; tag < num_counts; ++tag) {
126
174
tag_labels[tag] = std::to_string (tag + 1 );
127
175
}
128
176
const Json::Value custom_labels = config[" tag-labels" ];
129
177
if (custom_labels.isArray () && !custom_labels.empty ()) {
130
- for (uint32_t tag = 0 ; tag < std::min (num_tags , custom_labels.size ()); ++tag) {
178
+ for (uint32_t tag = 0 ; tag < std::min (num_counts , custom_labels.size ()); ++tag) {
131
179
tag_labels[tag] = custom_labels[tag].asString ();
132
180
}
133
181
}
134
182
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));
183
+ if (!hide_vacant_) {
184
+ uint32_t i = 1 ;
185
+ while (i <= num_counts) {
186
+ add_button (num_counts - i);
187
+ i++;
145
188
}
146
- button.show ();
147
- i <<= 1 ;
148
189
}
149
190
150
191
struct wl_output *output = gdk_wayland_monitor_get_wl_output (bar_.output ->monitor ->gobj ());
@@ -179,24 +220,53 @@ bool Tags::handle_button_press(GdkEventButton *event_button, uint32_t tag) {
179
220
}
180
221
181
222
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" );
223
+ bool is_new_button = true ;
224
+ std::string label;
225
+ uint32_t position = UINT32_MAX;
226
+
227
+ for (auto &added_button : buttons_) {
228
+ label = added_button.get_label ();
229
+ position = get_label_position (label);
230
+ if (position != UINT32_MAX && position == tag) {
231
+ is_new_button = false ;
232
+ }
188
233
}
189
234
190
- if (state & TAG_ACTIVE) {
191
- button.get_style_context ()->add_class (" focused" );
192
- } else {
193
- button.get_style_context ()->remove_class (" focused" );
235
+ if (is_new_button && ((state & TAG_ACTIVE) || (state & TAG_URGENT) || clients)) {
236
+ add_button (tag);
194
237
}
195
238
196
- if (state & TAG_URGENT) {
197
- button.get_style_context ()->add_class (" urgent" );
198
- } else {
199
- button.get_style_context ()->remove_class (" urgent" );
239
+ for (auto &button : buttons_) {
240
+ label = button.get_label ();
241
+ position = get_label_position (label);
242
+ if (position == UINT32_MAX || position != tag) continue ;
243
+
244
+ if (clients) {
245
+ button.get_style_context ()->add_class (" occupied" );
246
+ button.set_visible (true );
247
+ } else {
248
+ button.get_style_context ()->remove_class (" occupied" );
249
+ }
250
+
251
+ if (state & TAG_ACTIVE) {
252
+ button.get_style_context ()->add_class (" focused" );
253
+ button.set_visible (true );
254
+ } else {
255
+ button.get_style_context ()->remove_class (" focused" );
256
+ }
257
+
258
+ if (state & TAG_URGENT) {
259
+ button.get_style_context ()->add_class (" urgent" );
260
+ button.set_visible (true );
261
+ } else {
262
+ button.get_style_context ()->remove_class (" urgent" );
263
+ }
264
+
265
+ if (hide_vacant_ && !(state & TAG_ACTIVE) && !(state & TAG_URGENT) && !clients) {
266
+ button.set_visible (false );
267
+ } else {
268
+ button.set_visible (true );
269
+ }
200
270
}
201
271
}
202
272
0 commit comments