17
17
namespace waybar ::modules::sway {
18
18
19
19
Window::Window (const std::string& id, const Bar& bar, const Json::Value& config)
20
- : AIconLabel(config, " window" , id, " {title }" , 0 , true ), bar_(bar), windowId_(-1 ) {
20
+ : AIconLabel(config, " window" , id, " {}" , 0 , true ), bar_(bar), windowId_(-1 ) {
21
21
// Icon size
22
22
if (config_[" icon-size" ].isUInt ()) {
23
23
app_icon_size_ = config[" icon-size" ].asUInt ();
@@ -35,6 +35,7 @@ Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
35
35
ipc_.handleEvent ();
36
36
} catch (const std::exception & e) {
37
37
spdlog::error (" Window: {}" , e.what ());
38
+ spdlog::trace (" Window::Window exception" );
38
39
}
39
40
});
40
41
}
@@ -46,12 +47,13 @@ void Window::onCmd(const struct Ipc::ipc_response& res) {
46
47
std::lock_guard<std::mutex> lock (mutex_);
47
48
auto payload = parser_.parse (res.payload );
48
49
auto output = payload[" output" ].isString () ? payload[" output" ].asString () : " " ;
49
- std::tie (app_nb_, windowId_, window_, app_id_, app_class_, shell_) =
50
+ std::tie (app_nb_, floating_count_, windowId_, window_, app_id_, app_class_, shell_, layout_ ) =
50
51
getFocusedNode (payload[" nodes" ], output);
51
52
updateAppIconName ();
52
53
dp.emit ();
53
54
} catch (const std::exception & e) {
54
55
spdlog::error (" Window: {}" , e.what ());
56
+ spdlog::trace (" Window::onCmd exception" );
55
57
}
56
58
}
57
59
@@ -156,27 +158,52 @@ void Window::updateAppIcon() {
156
158
}
157
159
158
160
auto Window::update () -> void {
159
- if (!old_app_id_.empty ()) {
160
- bar_.window .get_style_context ()->remove_class (old_app_id_);
161
- }
161
+ spdlog::trace (" workspace layout {}, tiled count {}, floating count {}" , layout_, app_nb_,
162
+ floating_count_);
163
+
164
+ int mode = 0 ;
162
165
if (app_nb_ == 0 ) {
163
- bar_.window .get_style_context ()->remove_class (" solo" );
164
- if (!bar_.window .get_style_context ()->has_class (" empty" )) {
165
- bar_.window .get_style_context ()->add_class (" empty" );
166
+ if (floating_count_ == 0 ) {
167
+ mode += 1 ;
168
+ } else {
169
+ mode += 4 ;
166
170
}
167
171
} else if (app_nb_ == 1 ) {
168
- bar_.window .get_style_context ()->remove_class (" empty" );
169
- if (!bar_.window .get_style_context ()->has_class (" solo" )) {
170
- bar_.window .get_style_context ()->add_class (" solo" );
172
+ mode += 2 ;
173
+ } else {
174
+ if (layout_ == " tabbed" ) {
175
+ mode += 8 ;
176
+ } else if (layout_ == " stacked" ) {
177
+ mode += 16 ;
178
+ } else {
179
+ mode += 32 ;
171
180
}
172
181
if (!app_id_.empty () && !bar_.window .get_style_context ()->has_class (app_id_)) {
173
182
bar_.window .get_style_context ()->add_class (app_id_);
174
183
old_app_id_ = app_id_;
175
184
}
176
- } else {
177
- bar_.window .get_style_context ()->remove_class (" solo" );
178
- bar_.window .get_style_context ()->remove_class (" empty" );
179
185
}
186
+
187
+ if (!old_app_id_.empty () && ((mode & 2 ) == 0 || old_app_id_ != app_id_) &&
188
+ bar_.window .get_style_context ()->has_class (old_app_id_)) {
189
+ spdlog::trace (" Removing app_id class: {}" , old_app_id_);
190
+ bar_.window .get_style_context ()->remove_class (old_app_id_);
191
+ old_app_id_ = " " ;
192
+ }
193
+
194
+ setClass (" empty" , ((mode & 1 ) > 0 ));
195
+ setClass (" solo" , ((mode & 2 ) > 0 ));
196
+ setClass (" floating" , ((mode & 4 ) > 0 ));
197
+ setClass (" tabbed" , ((mode & 8 ) > 0 ));
198
+ setClass (" stacked" , ((mode & 16 ) > 0 ));
199
+ setClass (" tiled" , ((mode & 32 ) > 0 ));
200
+
201
+ if ((mode & 2 ) > 0 && !app_id_.empty () && !bar_.window .get_style_context ()->has_class (app_id_)) {
202
+ spdlog::trace (" Adding app_id class: {}" , app_id_);
203
+ bar_.window .get_style_context ()->add_class (app_id_);
204
+ old_app_id_ = app_id_;
205
+ }
206
+
180
207
label_.set_markup (fmt::format (
181
208
format_, fmt::arg (" title" , waybar::util::rewriteTitle (window_, config_[" rewrite" ])),
182
209
fmt::arg (" app_id" , app_id_), fmt::arg (" shell" , shell_)));
@@ -190,78 +217,151 @@ auto Window::update() -> void {
190
217
AIconLabel::update ();
191
218
}
192
219
193
- int leafNodesInWorkspace (const Json::Value& node) {
220
+ void Window::setClass (std::string classname, bool enable) {
221
+ if (enable) {
222
+ if (!bar_.window .get_style_context ()->has_class (classname)) {
223
+ bar_.window .get_style_context ()->add_class (classname);
224
+ }
225
+ } else {
226
+ bar_.window .get_style_context ()->remove_class (classname);
227
+ }
228
+ }
229
+
230
+ std::pair<int , int > leafNodesInWorkspace (const Json::Value& node) {
194
231
auto const & nodes = node[" nodes" ];
195
232
auto const & floating_nodes = node[" floating_nodes" ];
196
233
if (nodes.empty () && floating_nodes.empty ()) {
197
- if (node[" type" ] == " workspace" )
198
- return 0 ;
199
- else
200
- return 1 ;
234
+ if (node[" type" ].asString () == " workspace" )
235
+ return {0 , 0 };
236
+ else if (node[" type" ].asString () == " floating_con" ) {
237
+ return {0 , 1 };
238
+ } else {
239
+ return {1 , 0 };
240
+ }
201
241
}
202
242
int sum = 0 ;
203
- if (!nodes.empty ()) {
204
- for (auto const & node : nodes) sum += leafNodesInWorkspace (node);
243
+ int floating_sum = 0 ;
244
+ for (auto const & node : nodes) {
245
+ std::pair all_leaf_nodes = leafNodesInWorkspace (node);
246
+ sum += all_leaf_nodes.first ;
247
+ floating_sum += all_leaf_nodes.second ;
205
248
}
206
- if (!floating_nodes.empty ()) {
207
- for (auto const & node : floating_nodes) sum += leafNodesInWorkspace (node);
249
+ for (auto const & node : floating_nodes) {
250
+ std::pair all_leaf_nodes = leafNodesInWorkspace (node);
251
+ sum += all_leaf_nodes.first ;
252
+ floating_sum += all_leaf_nodes.second ;
208
253
}
209
- return sum;
254
+ return { sum, floating_sum} ;
210
255
}
211
256
212
- std::tuple<std::size_t , int , std::string, std::string, std::string, std::string> gfnWithWorkspace (
213
- const Json::Value& nodes, std::string& output, const Json::Value& config_, const Bar& bar_,
214
- Json::Value& parentWorkspace) {
257
+ std::tuple<std::size_t , int , int , std::string, std::string, std::string, std::string, std::string>
258
+ gfnWithWorkspace (const Json::Value& nodes, std::string& output, const Json::Value& config_,
259
+ const Bar& bar_, Json::Value& parentWorkspace,
260
+ const Json::Value& immediateParent) {
215
261
for (auto const & node : nodes) {
216
- if (node[" output" ].isString ()) {
217
- output = node[" output" ].asString ();
218
- }
219
- // found node
220
- if (node[" focused" ].asBool () && (node[" type" ] == " con" || node[" type" ] == " floating_con" )) {
221
- if ((!config_[" all-outputs" ].asBool () && output == bar_.output ->name ) ||
222
- config_[" all-outputs" ].asBool ()) {
223
- auto app_id = node[" app_id" ].isString () ? node[" app_id" ].asString ()
224
- : node[" window_properties" ][" instance" ].asString ();
225
- const auto app_class = node[" window_properties" ][" class" ].isString ()
226
- ? node[" window_properties" ][" class" ].asString ()
227
- : " " ;
228
-
229
- const auto shell = node[" shell" ].isString () ? node[" shell" ].asString () : " " ;
230
-
231
- int nb = node.size ();
232
- if (parentWorkspace != 0 ) nb = leafNodesInWorkspace (parentWorkspace);
233
- return {nb, node[" id" ].asInt (), Glib::Markup::escape_text (node[" name" ].asString ()),
234
- app_id, app_class, shell};
262
+ if (node[" type" ].asString () == " output" ) {
263
+ if ((!config_[" all-outputs" ].asBool () || config_[" offscreen-css" ].asBool ()) &&
264
+ (node[" name" ].asString () != bar_.output ->name )) {
265
+ continue ;
266
+ }
267
+ output = node[" name" ].asString ();
268
+ } else if (node[" type" ].asString () == " workspace" ) {
269
+ // needs to be a string comparison, because filterWorkspace is the current_workspace
270
+ if (node[" name" ].asString () != immediateParent[" current_workspace" ].asString ()) {
271
+ continue ;
235
272
}
273
+ if (node[" focused" ].asBool ()) {
274
+ std::pair all_leaf_nodes = leafNodesInWorkspace (node);
275
+ return {all_leaf_nodes.first ,
276
+ all_leaf_nodes.second ,
277
+ node[" id" ].asInt (),
278
+ (((all_leaf_nodes.first > 0 ) || (all_leaf_nodes.second > 0 )) &&
279
+ (config_[" show-focused-workspace-name" ].asBool ()))
280
+ ? node[" name" ].asString ()
281
+ : " " ,
282
+ " " ,
283
+ " " ,
284
+ " " ,
285
+ node[" layout" ].asString ()};
286
+ }
287
+ parentWorkspace = node;
288
+ } else if ((node[" type" ].asString () == " con" || node[" type" ].asString () == " floating_con" ) &&
289
+ (node[" focused" ].asBool ())) {
290
+ // found node
291
+ spdlog::trace (" actual output {}, output found {}, node (focused) found {}" , bar_.output ->name ,
292
+ output, node[" name" ].asString ());
293
+ auto app_id = node[" app_id" ].isString () ? node[" app_id" ].asString ()
294
+ : node[" window_properties" ][" instance" ].asString ();
295
+ const auto app_class = node[" window_properties" ][" class" ].isString ()
296
+ ? node[" window_properties" ][" class" ].asString ()
297
+ : " " ;
298
+ const auto shell = node[" shell" ].isString () ? node[" shell" ].asString () : " " ;
299
+ int nb = node.size ();
300
+ int floating_count = 0 ;
301
+ std::string workspace_layout = " " ;
302
+ if (!parentWorkspace.isNull ()) {
303
+ std::pair all_leaf_nodes = leafNodesInWorkspace (parentWorkspace);
304
+ nb = all_leaf_nodes.first ;
305
+ floating_count = all_leaf_nodes.second ;
306
+ workspace_layout = parentWorkspace[" layout" ].asString ();
307
+ }
308
+ return {nb,
309
+ floating_count,
310
+ node[" id" ].asInt (),
311
+ Glib::Markup::escape_text (node[" name" ].asString ()),
312
+ app_id,
313
+ app_class,
314
+ shell,
315
+ workspace_layout};
236
316
}
317
+
237
318
// iterate
238
- if (node[" type" ] == " workspace" ) parentWorkspace = node;
239
- auto [nb, id, name, app_id, app_class, shell] =
240
- gfnWithWorkspace (node[" nodes" ], output, config_, bar_, parentWorkspace);
241
- if (id > -1 && !name.empty ()) {
242
- return {nb, id, name, app_id, app_class, shell};
243
- }
244
- // Search for floating node
245
- std::tie (nb, id, name, app_id, app_class, shell) =
246
- gfnWithWorkspace (node[" floating_nodes" ], output, config_, bar_, parentWorkspace);
247
- if (id > -1 && !name.empty ()) {
248
- return {nb, id, name, app_id, app_class, shell};
319
+ auto [nb, f, id, name, app_id, app_class, shell, workspace_layout] =
320
+ gfnWithWorkspace (node[" nodes" ], output, config_, bar_, parentWorkspace, node);
321
+ auto [nb2, f2, id2, name2, app_id2, app_class2, shell2, workspace_layout2] =
322
+ gfnWithWorkspace (node[" floating_nodes" ], output, config_, bar_, parentWorkspace, node);
323
+
324
+ // if ((id > 0 || ((id2 < 0 || name2.empty()) && id > -1)) && !name.empty()) {
325
+ if ((id > 0 ) || (id2 < 0 && id > -1 )) {
326
+ return {nb, f, id, name, app_id, app_class, shell, workspace_layout};
327
+ } else if (id2 > 0 && !name2.empty ()) {
328
+ return {nb2, f2, id2, name2, app_id2, app_class, shell2, workspace_layout2};
249
329
}
250
330
}
251
- return {0 , -1 , " " , " " , " " , " " };
331
+
332
+ // this only comes into effect when no focused children are present
333
+ if (config_[" all-outputs" ].asBool () && config_[" offscreen-css" ].asBool () &&
334
+ immediateParent[" type" ].asString () == " workspace" ) {
335
+ std::pair all_leaf_nodes = leafNodesInWorkspace (immediateParent);
336
+ // using an empty string as default ensures that no window depending styles are set due to the
337
+ // checks above for !name.empty()
338
+ return {all_leaf_nodes.first ,
339
+ all_leaf_nodes.second ,
340
+ 0 ,
341
+ (all_leaf_nodes.first > 0 || all_leaf_nodes.second > 0 )
342
+ ? config_[" offscreen-css-text" ].asString ()
343
+ : " " ,
344
+ " " ,
345
+ " " ,
346
+ " " ,
347
+ immediateParent[" layout" ].asString ()};
348
+ }
349
+
350
+ return {0 , 0 , -1 , " " , " " , " " , " " , " " };
252
351
}
253
352
254
- std::tuple<std::size_t , int , std::string, std::string, std::string, std::string>
353
+ std::tuple<std::size_t , int , int , std::string, std::string, std::string, std::string, std::string>
255
354
Window::getFocusedNode (const Json::Value& nodes, std::string& output) {
256
- Json::Value placeholder = 0 ;
257
- return gfnWithWorkspace (nodes, output, config_, bar_, placeholder);
355
+ Json::Value placeholder = Json::Value::null ;
356
+ return gfnWithWorkspace (nodes, output, config_, bar_, placeholder, placeholder );
258
357
}
259
358
260
359
void Window::getTree () {
261
360
try {
262
361
ipc_.sendCmd (IPC_GET_TREE);
263
362
} catch (const std::exception & e) {
264
363
spdlog::error (" Window: {}" , e.what ());
364
+ spdlog::trace (" Window::getTree exception" );
265
365
}
266
366
}
267
367
0 commit comments