@@ -24,6 +24,24 @@ int Workspaces::convertWorkspaceNameToNum(std::string name) {
24
24
return -1 ;
25
25
}
26
26
27
+ int Workspaces::windowRewritePriorityFunction (std::string const &window_rule) {
28
+ // Rules that match against title are prioritized
29
+ // Rules that don't specify if they're matching against either title or class are deprioritized
30
+ bool const hasTitle = window_rule.find (" title" ) != std::string::npos;
31
+ bool const hasClass = window_rule.find (" class" ) != std::string::npos;
32
+
33
+ if (hasTitle && hasClass) {
34
+ return 3 ;
35
+ }
36
+ if (hasTitle) {
37
+ return 2 ;
38
+ }
39
+ if (hasClass) {
40
+ return 1 ;
41
+ }
42
+ return 0 ;
43
+ }
44
+
27
45
Workspaces::Workspaces (const std::string &id, const Bar &bar, const Json::Value &config)
28
46
: AModule(config, " workspaces" , id, false , !config[" disable-scroll" ].asBool()),
29
47
bar_ (bar),
@@ -39,10 +57,25 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
39
57
}
40
58
box_.get_style_context ()->add_class (MODULE_CLASS);
41
59
event_box_.add (box_);
60
+ if (config_[" format-window-separator" ].isString ()) {
61
+ m_formatWindowSeperator = config_[" format-window-separator" ].asString ();
62
+ } else {
63
+ m_formatWindowSeperator = " " ;
64
+ }
65
+ const Json::Value &windowRewrite = config[" window-rewrite" ];
66
+
67
+ const Json::Value &windowRewriteDefaultConfig = config[" window-rewrite-default" ];
68
+ m_windowRewriteDefault =
69
+ windowRewriteDefaultConfig.isString () ? windowRewriteDefaultConfig.asString () : " ?" ;
70
+
71
+ m_windowRewriteRules = waybar::util::RegexCollection (
72
+ windowRewrite, m_windowRewriteDefault,
73
+ [this ](std::string &window_rule) { return windowRewritePriorityFunction (window_rule); });
42
74
ipc_.subscribe (R"( ["workspace"])" );
75
+ ipc_.subscribe (R"( ["window"])" );
43
76
ipc_.signal_event .connect (sigc::mem_fun (*this , &Workspaces::onEvent));
44
77
ipc_.signal_cmd .connect (sigc::mem_fun (*this , &Workspaces::onCmd));
45
- ipc_.sendCmd (IPC_GET_WORKSPACES );
78
+ ipc_.sendCmd (IPC_GET_TREE );
46
79
if (config[" enable-bar-scroll" ].asBool ()) {
47
80
auto &window = const_cast <Bar &>(bar_).window ;
48
81
window.add_events (Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
@@ -60,26 +93,33 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
60
93
61
94
void Workspaces::onEvent (const struct Ipc ::ipc_response &res) {
62
95
try {
63
- ipc_.sendCmd (IPC_GET_WORKSPACES );
96
+ ipc_.sendCmd (IPC_GET_TREE );
64
97
} catch (const std::exception &e) {
65
98
spdlog::error (" Workspaces: {}" , e.what ());
66
99
}
67
100
}
68
101
69
102
void Workspaces::onCmd (const struct Ipc ::ipc_response &res) {
70
- if (res.type == IPC_GET_WORKSPACES ) {
103
+ if (res.type == IPC_GET_TREE ) {
71
104
try {
72
105
{
73
106
std::lock_guard<std::mutex> lock (mutex_);
74
107
auto payload = parser_.parse (res.payload );
75
108
workspaces_.clear ();
76
- std::copy_if (payload.begin (), payload.end (), std::back_inserter (workspaces_),
109
+ std::vector<Json::Value> outputs;
110
+ std::copy_if (payload[" nodes" ].begin (), payload[" nodes" ].end (), std::back_inserter (outputs),
77
111
[&](const auto &workspace) {
78
112
return !config_[" all-outputs" ].asBool ()
79
- ? workspace[" output " ].asString () == bar_.output ->name
113
+ ? workspace[" name " ].asString () == bar_.output ->name
80
114
: true ;
81
115
});
82
116
117
+ for (auto &output : outputs) {
118
+ std::copy (output[" nodes" ].begin (), output[" nodes" ].end (),
119
+ std::back_inserter (workspaces_));
120
+ std::copy (output[" floating_nodes" ].begin (), output[" floating_nodes" ].end (),
121
+ std::back_inserter (workspaces_));
122
+ }
83
123
if (config_[" persistent_workspaces" ].isObject ()) {
84
124
spdlog::warn (
85
125
" persistent_workspaces is deprecated. Please change config to use "
@@ -204,6 +244,38 @@ bool Workspaces::filterButtons() {
204
244
return needReorder;
205
245
}
206
246
247
+ bool Workspaces::hasFlag (const Json::Value &node, const std::string &flag) {
248
+ if (node[flag].asBool ()) {
249
+ return true ;
250
+ }
251
+
252
+ if (std::any_of (node[" nodes" ].begin (), node[" nodes" ].end (), [&](auto const &e) { return hasFlag (e, flag); })) {
253
+ return true ;
254
+ }
255
+ return false ;
256
+ }
257
+
258
+ void Workspaces::updateWindows (const Json::Value &node, std::string &windows) {
259
+ auto format = config_[" window-format" ].asString ();
260
+ if ((node[" type" ].asString () == " con" || node[" type" ].asString () == " floating_con" ) && node[" name" ].isString ()) {
261
+ std::string title = g_markup_escape_text (node[" name" ].asString ().c_str (), -1 );
262
+ std::string windowClass = node[" app_id" ].asString ();
263
+ std::string windowReprKey = fmt::format (" class<{}> title<{}>" , windowClass, title);
264
+ std::string window = m_windowRewriteRules.get (windowReprKey);
265
+ // allow result to have formatting
266
+ window =
267
+ fmt::format (fmt::runtime (window), fmt::arg (" name" , title), fmt::arg (" class" , windowClass));
268
+ windows.append (window);
269
+ windows.append (m_formatWindowSeperator);
270
+ }
271
+ for (const Json::Value &child : node[" nodes" ]) {
272
+ updateWindows (child, windows);
273
+ }
274
+ for (const Json::Value &child : node[" floating_nodes" ]) {
275
+ updateWindows (child, windows);
276
+ }
277
+ }
278
+
207
279
auto Workspaces::update () -> void {
208
280
std::lock_guard<std::mutex> lock (mutex_);
209
281
bool needReorder = filterButtons ();
@@ -213,22 +285,25 @@ auto Workspaces::update() -> void {
213
285
needReorder = true ;
214
286
}
215
287
auto &button = bit == buttons_.end () ? addButton (*it) : bit->second ;
216
- if ((*it)[" focused" ].asBool ()) {
288
+ if (needReorder) {
289
+ box_.reorder_child (button, it - workspaces_.begin ());
290
+ }
291
+ if (hasFlag ((*it), " focused" )) {
217
292
button.get_style_context ()->add_class (" focused" );
218
293
} else {
219
294
button.get_style_context ()->remove_class (" focused" );
220
295
}
221
- if (( *it)[ " visible" ]. asBool ( )) {
296
+ if (hasFlag (( *it), " visible" )) {
222
297
button.get_style_context ()->add_class (" visible" );
223
298
} else {
224
299
button.get_style_context ()->remove_class (" visible" );
225
300
}
226
- if (( *it)[ " urgent" ]. asBool ( )) {
301
+ if (hasFlag (( *it), " urgent" )) {
227
302
button.get_style_context ()->add_class (" urgent" );
228
303
} else {
229
304
button.get_style_context ()->remove_class (" urgent" );
230
305
}
231
- if (( *it)[ " target_output" ]. isString ( )) {
306
+ if (hasFlag (( *it), " target_output" )) {
232
307
button.get_style_context ()->add_class (" persistent" );
233
308
} else {
234
309
button.get_style_context ()->remove_class (" persistent" );
@@ -242,16 +317,19 @@ auto Workspaces::update() -> void {
242
317
} else {
243
318
button.get_style_context ()->remove_class (" current_output" );
244
319
}
245
- if (needReorder) {
246
- box_.reorder_child (button, it - workspaces_.begin ());
247
- }
248
320
std::string output = (*it)[" name" ].asString ();
321
+ std::string windows = " " ;
322
+ if (config_[" window-format" ].isString ()) {
323
+ updateWindows ((*it), windows);
324
+ }
249
325
if (config_[" format" ].isString ()) {
250
326
auto format = config_[" format" ].asString ();
251
- output = fmt::format (fmt::runtime (format), fmt::arg (" icon" , getIcon (output, *it)),
252
- fmt::arg (" value" , output), fmt::arg (" name" , trimWorkspaceName (output)),
253
- fmt::arg (" index" , (*it)[" num" ].asString ()),
254
- fmt::arg (" output" , (*it)[" output" ].asString ()));
327
+ output = fmt::format (
328
+ fmt::runtime (format), fmt::arg (" icon" , getIcon (output, *it)), fmt::arg (" value" , output),
329
+ fmt::arg (" name" , trimWorkspaceName (output)), fmt::arg (" index" , (*it)[" num" ].asString ()),
330
+ fmt::arg (" windows" ,
331
+ windows.substr (0 , windows.length () - m_formatWindowSeperator.length ())),
332
+ fmt::arg (" output" , (*it)[" output" ].asString ()));
255
333
}
256
334
if (!config_[" disable-markup" ].asBool ()) {
257
335
static_cast <Gtk::Label *>(button.get_children ()[0 ])->set_markup (output);
0 commit comments