diff options
Diffstat (limited to 'sway/old/ipc-json.c')
-rw-r--r-- | sway/old/ipc-json.c | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/sway/old/ipc-json.c b/sway/old/ipc-json.c new file mode 100644 index 00000000..1579a2d9 --- /dev/null +++ b/sway/old/ipc-json.c | |||
@@ -0,0 +1,521 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <json-c/json.h> | ||
3 | #include <ctype.h> | ||
4 | #include <string.h> | ||
5 | #include <stdint.h> | ||
6 | #include <libinput.h> | ||
7 | #include <wlr/types/wlr_box.h> | ||
8 | #include <wlr/types/wlr_output.h> | ||
9 | #include "sway/output.h" | ||
10 | #include "sway/container.h" | ||
11 | #include "sway/input.h" | ||
12 | #include "sway/ipc-json.h" | ||
13 | #include "util.h" | ||
14 | |||
15 | static json_object *ipc_json_create_rect(swayc_t *c) { | ||
16 | json_object *rect = json_object_new_object(); | ||
17 | |||
18 | json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); | ||
19 | json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); | ||
20 | |||
21 | struct wlr_box box; | ||
22 | if (c->type == C_OUTPUT) { | ||
23 | wlr_output_effective_resolution(c->_handle.output->wlr_output, | ||
24 | &box.width, &box.height); | ||
25 | } else { | ||
26 | box.width = c->width; | ||
27 | box.width = c->height; | ||
28 | } | ||
29 | |||
30 | json_object_object_add(rect, "width", | ||
31 | json_object_new_int((int32_t)box.width)); | ||
32 | json_object_object_add(rect, "height", | ||
33 | json_object_new_int((int32_t)box.height)); | ||
34 | |||
35 | return rect; | ||
36 | } | ||
37 | |||
38 | static json_object *ipc_json_create_rect_from_geometry(struct wlc_geometry g) { | ||
39 | json_object *rect = json_object_new_object(); | ||
40 | |||
41 | json_object_object_add(rect, "x", json_object_new_int(g.origin.x)); | ||
42 | json_object_object_add(rect, "y", json_object_new_int(g.origin.y)); | ||
43 | json_object_object_add(rect, "width", json_object_new_int(g.size.w)); | ||
44 | json_object_object_add(rect, "height", json_object_new_int(g.size.h)); | ||
45 | |||
46 | return rect; | ||
47 | } | ||
48 | |||
49 | static const char *ipc_json_border_description(swayc_t *c) { | ||
50 | const char *border; | ||
51 | |||
52 | switch (c->border_type) { | ||
53 | case B_PIXEL: | ||
54 | border = "1pixel"; | ||
55 | break; | ||
56 | |||
57 | case B_NORMAL: | ||
58 | border = "normal"; | ||
59 | break; | ||
60 | |||
61 | case B_NONE: // fallthrough | ||
62 | default: | ||
63 | border = "none"; | ||
64 | break; | ||
65 | } | ||
66 | |||
67 | return border; | ||
68 | } | ||
69 | |||
70 | static const char *ipc_json_layout_description(enum swayc_layouts l) { | ||
71 | const char *layout; | ||
72 | |||
73 | switch (l) { | ||
74 | case L_VERT: | ||
75 | layout = "splitv"; | ||
76 | break; | ||
77 | |||
78 | case L_HORIZ: | ||
79 | layout = "splith"; | ||
80 | break; | ||
81 | |||
82 | case L_TABBED: | ||
83 | layout = "tabbed"; | ||
84 | break; | ||
85 | |||
86 | case L_STACKED: | ||
87 | layout = "stacked"; | ||
88 | break; | ||
89 | |||
90 | case L_FLOATING: | ||
91 | layout = "floating"; | ||
92 | break; | ||
93 | |||
94 | case L_NONE: // fallthrough | ||
95 | case L_LAYOUTS: // fallthrough; this should never happen, I'm just trying to silence compiler warnings | ||
96 | default: | ||
97 | layout = "null"; | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | return layout; | ||
102 | } | ||
103 | |||
104 | static float ipc_json_child_percentage(swayc_t *c) { | ||
105 | float percent = 0; | ||
106 | swayc_t *parent = c->parent; | ||
107 | |||
108 | if (parent) { | ||
109 | switch (parent->layout) { | ||
110 | case L_VERT: | ||
111 | percent = c->height / parent->height; | ||
112 | break; | ||
113 | |||
114 | case L_HORIZ: | ||
115 | percent = c->width / parent->width; | ||
116 | break; | ||
117 | |||
118 | case L_STACKED: // fallthrough | ||
119 | case L_TABBED: // fallthrough | ||
120 | percent = 1.0; | ||
121 | break; | ||
122 | |||
123 | default: | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | return percent; | ||
129 | } | ||
130 | |||
131 | static void ipc_json_describe_output(swayc_t *output, json_object *object) { | ||
132 | uint32_t scale = wlc_output_get_scale(output->handle); | ||
133 | json_object_object_add(object, "active", json_object_new_boolean(true)); | ||
134 | json_object_object_add(object, "primary", json_object_new_boolean(false)); | ||
135 | json_object_object_add(object, "layout", json_object_new_string("output")); | ||
136 | json_object_object_add(object, "type", json_object_new_string("output")); | ||
137 | json_object_object_add(object, "current_workspace", | ||
138 | (output->focused) ? json_object_new_string(output->focused->name) : NULL); | ||
139 | json_object_object_add(object, "scale", json_object_new_int(scale)); | ||
140 | } | ||
141 | |||
142 | static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { | ||
143 | int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; | ||
144 | const char *layout = ipc_json_layout_description(workspace->workspace_layout); | ||
145 | |||
146 | json_object_object_add(object, "num", json_object_new_int(num)); | ||
147 | json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); | ||
148 | json_object_object_add(object, "type", json_object_new_string("workspace")); | ||
149 | json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); | ||
150 | } | ||
151 | |||
152 | // window is in the scratchpad ? changed : none | ||
153 | static const char *ipc_json_get_scratchpad_state(swayc_t *c) { | ||
154 | int i; | ||
155 | for (i = 0; i < scratchpad->length; i++) { | ||
156 | if (scratchpad->items[i] == c) { | ||
157 | return "changed"; | ||
158 | } | ||
159 | } | ||
160 | return "none"; // we ignore the fresh value | ||
161 | } | ||
162 | |||
163 | static void ipc_json_describe_view(swayc_t *c, json_object *object) { | ||
164 | json_object *props = json_object_new_object(); | ||
165 | json_object_object_add(object, "type", json_object_new_string((c->is_floating) ? "floating_con" : "con")); | ||
166 | |||
167 | wlc_handle parent = wlc_view_get_parent(c->handle); | ||
168 | json_object_object_add(object, "scratchpad_state", | ||
169 | json_object_new_string(ipc_json_get_scratchpad_state(c))); | ||
170 | |||
171 | json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); | ||
172 | |||
173 | json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) : | ||
174 | c->app_id ? json_object_new_string(c->app_id) : NULL); | ||
175 | json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) : | ||
176 | c->app_id ? json_object_new_string(c->app_id) : NULL); | ||
177 | json_object_object_add(props, "title", (c->name) ? json_object_new_string(c->name) : NULL); | ||
178 | json_object_object_add(props, "transient_for", parent ? json_object_new_int(parent) : NULL); | ||
179 | json_object_object_add(object, "window_properties", props); | ||
180 | |||
181 | json_object_object_add(object, "fullscreen_mode", | ||
182 | json_object_new_int(swayc_is_fullscreen(c) ? 1 : 0)); | ||
183 | json_object_object_add(object, "sticky", json_object_new_boolean(c->sticky)); | ||
184 | json_object_object_add(object, "floating", json_object_new_string( | ||
185 | c->is_floating ? "auto_on" : "auto_off")); // we can't state the cause | ||
186 | |||
187 | json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL); | ||
188 | |||
189 | if (c->parent) { | ||
190 | const char *layout = (c->parent->type == C_CONTAINER) ? | ||
191 | ipc_json_layout_description(c->parent->layout) : "none"; | ||
192 | const char *last_layout = (c->parent->type == C_CONTAINER) ? | ||
193 | ipc_json_layout_description(c->parent->prev_layout) : "none"; | ||
194 | json_object_object_add(object, "layout", | ||
195 | (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); | ||
196 | json_object_object_add(object, "last_split_layout", | ||
197 | (strcmp(last_layout, "null") == 0) ? NULL : json_object_new_string(last_layout)); | ||
198 | json_object_object_add(object, "workspace_layout", | ||
199 | json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout))); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void ipc_json_describe_root(swayc_t *c, json_object *object) { | ||
204 | json_object_object_add(object, "type", json_object_new_string("root")); | ||
205 | json_object_object_add(object, "layout", json_object_new_string("splith")); | ||
206 | } | ||
207 | |||
208 | json_object *ipc_json_describe_container(swayc_t *c) { | ||
209 | float percent = ipc_json_child_percentage(c); | ||
210 | |||
211 | if (!(sway_assert(c, "Container must not be null."))) { | ||
212 | return NULL; | ||
213 | } | ||
214 | |||
215 | json_object *object = json_object_new_object(); | ||
216 | |||
217 | json_object_object_add(object, "id", json_object_new_int((int)c->id)); | ||
218 | json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); | ||
219 | json_object_object_add(object, "rect", ipc_json_create_rect(c)); | ||
220 | json_object_object_add(object, "visible", json_object_new_boolean(c->visible)); | ||
221 | json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus)); | ||
222 | |||
223 | json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c))); | ||
224 | json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry)); | ||
225 | json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry)); | ||
226 | json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry)); | ||
227 | json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL); | ||
228 | json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat | ||
229 | // TODO: make urgency actually work once Sway supports it | ||
230 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
231 | json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness)); | ||
232 | |||
233 | switch (c->type) { | ||
234 | case C_ROOT: | ||
235 | ipc_json_describe_root(c, object); | ||
236 | break; | ||
237 | |||
238 | case C_OUTPUT: | ||
239 | ipc_json_describe_output(c, object); | ||
240 | break; | ||
241 | |||
242 | case C_CONTAINER: // fallthrough | ||
243 | case C_VIEW: | ||
244 | ipc_json_describe_view(c, object); | ||
245 | break; | ||
246 | |||
247 | case C_WORKSPACE: | ||
248 | ipc_json_describe_workspace(c, object); | ||
249 | break; | ||
250 | |||
251 | case C_TYPES: // fallthrough; this should never happen, I'm just trying to silence compiler warnings | ||
252 | default: | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | return object; | ||
257 | } | ||
258 | |||
259 | json_object *ipc_json_describe_input(struct libinput_device *device) { | ||
260 | char* identifier = libinput_dev_unique_id(device); | ||
261 | int vendor = libinput_device_get_id_vendor(device); | ||
262 | int product = libinput_device_get_id_product(device); | ||
263 | const char *name = libinput_device_get_name(device); | ||
264 | double width = -1, height = -1; | ||
265 | int has_size = libinput_device_get_size(device, &width, &height); | ||
266 | |||
267 | json_object *device_object = json_object_new_object(); | ||
268 | json_object_object_add(device_object,"identifier", | ||
269 | identifier ? json_object_new_string(identifier) : NULL); | ||
270 | json_object_object_add(device_object, | ||
271 | "vendor", json_object_new_int(vendor)); | ||
272 | json_object_object_add(device_object, | ||
273 | "product", json_object_new_int(product)); | ||
274 | json_object_object_add(device_object, | ||
275 | "name", json_object_new_string(name)); | ||
276 | if (has_size == 0) { | ||
277 | json_object *size_object = json_object_new_object(); | ||
278 | json_object_object_add(size_object, | ||
279 | "width", json_object_new_double(width)); | ||
280 | json_object_object_add(size_object, | ||
281 | "height", json_object_new_double(height)); | ||
282 | } else { | ||
283 | json_object_object_add(device_object, "size", NULL); | ||
284 | } | ||
285 | |||
286 | struct { | ||
287 | enum libinput_device_capability cap; | ||
288 | const char *name; | ||
289 | // If anyone feels like implementing device-specific IPC output, | ||
290 | // be my guest | ||
291 | json_object *(*describe)(struct libinput_device *); | ||
292 | } caps[] = { | ||
293 | { LIBINPUT_DEVICE_CAP_KEYBOARD, "keyboard", NULL }, | ||
294 | { LIBINPUT_DEVICE_CAP_POINTER, "pointer", NULL }, | ||
295 | { LIBINPUT_DEVICE_CAP_TOUCH, "touch", NULL }, | ||
296 | { LIBINPUT_DEVICE_CAP_TABLET_TOOL, "tablet_tool", NULL }, | ||
297 | { LIBINPUT_DEVICE_CAP_TABLET_PAD, "tablet_pad", NULL }, | ||
298 | { LIBINPUT_DEVICE_CAP_GESTURE, "gesture", NULL }, | ||
299 | #ifdef LIBINPUT_DEVICE_CAP_SWITCH // libinput 1.7.0+ | ||
300 | { LIBINPUT_DEVICE_CAP_SWITCH, "switch", NULL }, | ||
301 | #endif | ||
302 | }; | ||
303 | |||
304 | json_object *_caps = json_object_new_array(); | ||
305 | for (size_t i = 0; i < sizeof(caps) / sizeof(caps[0]); ++i) { | ||
306 | if (libinput_device_has_capability(device, caps[i].cap)) { | ||
307 | json_object_array_add(_caps, json_object_new_string(caps[i].name)); | ||
308 | if (caps[i].describe) { | ||
309 | json_object *desc = caps[i].describe(device); | ||
310 | json_object_object_add(device_object, caps[i].name, desc); | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | json_object_object_add(device_object, "capabilities", _caps); | ||
315 | |||
316 | free(identifier); | ||
317 | return device_object; | ||
318 | } | ||
319 | |||
320 | json_object *ipc_json_get_version() { | ||
321 | int major = 0, minor = 0, patch = 0; | ||
322 | json_object *version = json_object_new_object(); | ||
323 | |||
324 | sscanf(SWAY_VERSION, "%u.%u.%u", &major, &minor, &patch); | ||
325 | |||
326 | json_object_object_add(version, "human_readable", json_object_new_string(SWAY_VERSION)); | ||
327 | json_object_object_add(version, "variant", json_object_new_string("sway")); | ||
328 | json_object_object_add(version, "major", json_object_new_int(major)); | ||
329 | json_object_object_add(version, "minor", json_object_new_int(minor)); | ||
330 | json_object_object_add(version, "patch", json_object_new_int(patch)); | ||
331 | |||
332 | return version; | ||
333 | } | ||
334 | |||
335 | json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | ||
336 | if (!sway_assert(bar, "Bar must not be NULL")) { | ||
337 | return NULL; | ||
338 | } | ||
339 | |||
340 | json_object *json = json_object_new_object(); | ||
341 | json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||
342 | #ifdef ENABLE_TRAY | ||
343 | if (bar->tray_output) { | ||
344 | json_object_object_add(json, "tray_output", json_object_new_string(bar->tray_output)); | ||
345 | } else { | ||
346 | json_object_object_add(json, "tray_output", NULL); | ||
347 | } | ||
348 | if (bar->icon_theme) { | ||
349 | json_object_object_add(json, "icon_theme", json_object_new_string(bar->icon_theme)); | ||
350 | } else { | ||
351 | json_object_object_add(json, "icon_theme", NULL); | ||
352 | } | ||
353 | json_object_object_add(json, "tray_padding", json_object_new_int(bar->tray_padding)); | ||
354 | json_object_object_add(json, "activate_button", json_object_new_int(bar->activate_button)); | ||
355 | json_object_object_add(json, "context_button", json_object_new_int(bar->context_button)); | ||
356 | json_object_object_add(json, "secondary_button", json_object_new_int(bar->secondary_button)); | ||
357 | #endif | ||
358 | json_object_object_add(json, "mode", json_object_new_string(bar->mode)); | ||
359 | json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); | ||
360 | json_object_object_add(json, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); | ||
361 | switch (bar->position) { | ||
362 | case DESKTOP_SHELL_PANEL_POSITION_TOP: | ||
363 | json_object_object_add(json, "position", json_object_new_string("top")); | ||
364 | break; | ||
365 | case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: | ||
366 | json_object_object_add(json, "position", json_object_new_string("bottom")); | ||
367 | break; | ||
368 | case DESKTOP_SHELL_PANEL_POSITION_LEFT: | ||
369 | json_object_object_add(json, "position", json_object_new_string("left")); | ||
370 | break; | ||
371 | case DESKTOP_SHELL_PANEL_POSITION_RIGHT: | ||
372 | json_object_object_add(json, "position", json_object_new_string("right")); | ||
373 | break; | ||
374 | } | ||
375 | json_object_object_add(json, "status_command", json_object_new_string(bar->status_command)); | ||
376 | json_object_object_add(json, "font", json_object_new_string((bar->font) ? bar->font : config->font)); | ||
377 | if (bar->separator_symbol) { | ||
378 | json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); | ||
379 | } | ||
380 | json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); | ||
381 | json_object_object_add(json, "wrap_scroll", json_object_new_boolean(bar->wrap_scroll)); | ||
382 | json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); | ||
383 | json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); | ||
384 | json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); | ||
385 | json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); | ||
386 | json_object_object_add(json, "pango_markup", json_object_new_boolean(bar->pango_markup)); | ||
387 | |||
388 | json_object *colors = json_object_new_object(); | ||
389 | json_object_object_add(colors, "background", json_object_new_string(bar->colors.background)); | ||
390 | json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline)); | ||
391 | json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator)); | ||
392 | |||
393 | if (bar->colors.focused_background) { | ||
394 | json_object_object_add(colors, "focused_background", json_object_new_string(bar->colors.focused_background)); | ||
395 | } else { | ||
396 | json_object_object_add(colors, "focused_background", json_object_new_string(bar->colors.background)); | ||
397 | } | ||
398 | |||
399 | if (bar->colors.focused_statusline) { | ||
400 | json_object_object_add(colors, "focused_statusline", json_object_new_string(bar->colors.focused_statusline)); | ||
401 | } else { | ||
402 | json_object_object_add(colors, "focused_statusline", json_object_new_string(bar->colors.statusline)); | ||
403 | } | ||
404 | |||
405 | if (bar->colors.focused_separator) { | ||
406 | json_object_object_add(colors, "focused_separator", json_object_new_string(bar->colors.focused_separator)); | ||
407 | } else { | ||
408 | json_object_object_add(colors, "focused_separator", json_object_new_string(bar->colors.separator)); | ||
409 | } | ||
410 | |||
411 | json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border)); | ||
412 | json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg)); | ||
413 | json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text)); | ||
414 | |||
415 | json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border)); | ||
416 | json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg)); | ||
417 | json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text)); | ||
418 | |||
419 | json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border)); | ||
420 | json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg)); | ||
421 | json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text)); | ||
422 | |||
423 | json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||
424 | json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||
425 | json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||
426 | |||
427 | if (bar->colors.binding_mode_border) { | ||
428 | json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border)); | ||
429 | } else { | ||
430 | json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||
431 | } | ||
432 | |||
433 | if (bar->colors.binding_mode_bg) { | ||
434 | json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg)); | ||
435 | } else { | ||
436 | json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||
437 | } | ||
438 | |||
439 | if (bar->colors.binding_mode_text) { | ||
440 | json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text)); | ||
441 | } else { | ||
442 | json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||
443 | } | ||
444 | |||
445 | json_object_object_add(json, "colors", colors); | ||
446 | |||
447 | // Add outputs if defined | ||
448 | if (bar->outputs && bar->outputs->length > 0) { | ||
449 | json_object *outputs = json_object_new_array(); | ||
450 | int i; | ||
451 | for (i = 0; i < bar->outputs->length; ++i) { | ||
452 | const char *name = bar->outputs->items[i]; | ||
453 | json_object_array_add(outputs, json_object_new_string(name)); | ||
454 | } | ||
455 | json_object_object_add(json, "outputs", outputs); | ||
456 | } | ||
457 | |||
458 | return json; | ||
459 | } | ||
460 | |||
461 | json_object *ipc_json_describe_container_recursive(swayc_t *c) { | ||
462 | json_object *object = ipc_json_describe_container(c); | ||
463 | int i; | ||
464 | |||
465 | json_object *floating = json_object_new_array(); | ||
466 | if (c->type != C_VIEW && c->floating) { | ||
467 | for (i = 0; i < c->floating->length; ++i) { | ||
468 | swayc_t *item = c->floating->items[i]; | ||
469 | json_object_array_add(floating, ipc_json_describe_container_recursive(item)); | ||
470 | } | ||
471 | } | ||
472 | json_object_object_add(object, "floating_nodes", floating); | ||
473 | |||
474 | json_object *children = json_object_new_array(); | ||
475 | if (c->type != C_VIEW && c->children) { | ||
476 | for (i = 0; i < c->children->length; ++i) { | ||
477 | json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); | ||
478 | } | ||
479 | } | ||
480 | json_object_object_add(object, "nodes", children); | ||
481 | |||
482 | json_object *focus = json_object_new_array(); | ||
483 | if (c->type != C_VIEW) { | ||
484 | if (c->focused) { | ||
485 | json_object_array_add(focus, json_object_new_double(c->focused->id)); | ||
486 | } | ||
487 | if (c->floating) { | ||
488 | for (i = 0; i < c->floating->length; ++i) { | ||
489 | swayc_t *item = c->floating->items[i]; | ||
490 | if (item == c->focused) { | ||
491 | continue; | ||
492 | } | ||
493 | |||
494 | json_object_array_add(focus, json_object_new_double(item->id)); | ||
495 | } | ||
496 | } | ||
497 | if (c->children) { | ||
498 | for (i = 0; i < c->children->length; ++i) { | ||
499 | swayc_t *item = c->children->items[i]; | ||
500 | if (item == c->focused) { | ||
501 | continue; | ||
502 | } | ||
503 | |||
504 | json_object_array_add(focus, json_object_new_double(item->id)); | ||
505 | } | ||
506 | } | ||
507 | } | ||
508 | json_object_object_add(object, "focus", focus); | ||
509 | |||
510 | if (c->type == C_ROOT) { | ||
511 | json_object *scratchpad_json = json_object_new_array(); | ||
512 | if (scratchpad->length > 0) { | ||
513 | for (i = 0; i < scratchpad->length; ++i) { | ||
514 | json_object_array_add(scratchpad_json, ipc_json_describe_container_recursive(scratchpad->items[i])); | ||
515 | } | ||
516 | } | ||
517 | json_object_object_add(object, "scratchpad", scratchpad_json); | ||
518 | } | ||
519 | |||
520 | return object; | ||
521 | } | ||