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