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