aboutsummaryrefslogtreecommitdiffstats
path: root/sway/ipc-json.c
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-11-18 11:22:02 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2017-11-18 11:22:02 -0500
commit733993a651c71f7e2198d505960d6bbd31e0e107 (patch)
treee51732c5872b624e73355f9e5b3f762101f3cd0d /sway/ipc-json.c
parentInitial (awful) pass on xdg shell support (diff)
downloadsway-733993a651c71f7e2198d505960d6bbd31e0e107.tar.gz
sway-733993a651c71f7e2198d505960d6bbd31e0e107.tar.zst
sway-733993a651c71f7e2198d505960d6bbd31e0e107.zip
Move everything to sway/old/
Diffstat (limited to 'sway/ipc-json.c')
-rw-r--r--sway/ipc-json.c521
1 files changed, 0 insertions, 521 deletions
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
deleted file mode 100644
index 1579a2d9..00000000
--- a/sway/ipc-json.c
+++ /dev/null
@@ -1,521 +0,0 @@
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
15static 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
38static 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
49static 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
70static 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
104static 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
131static 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
142static 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
153static 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
163static 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
203static 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
208json_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
259json_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
320json_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
335json_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
461json_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}