diff options
Diffstat (limited to 'sway/ipc-json.c')
-rw-r--r-- | sway/ipc-json.c | 655 |
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" | |
11 | static 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 | |||
14 | static 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)); | 32 | json_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 | ||
31 | static json_object *ipc_json_create_rect_from_geometry(struct wlc_geometry g) { | 47 | static 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 | ||
42 | static const char *ipc_json_border_description(swayc_t *c) { | 58 | static 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 | ||
63 | static const char *ipc_json_layout_description(enum swayc_layouts l) { | 63 | static 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 | ||
97 | static float ipc_json_child_percentage(swayc_t *c) { | 85 | static 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 | |||
124 | static 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 | ||
135 | static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { | 141 | static 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); |
146 | static 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 | ||
156 | static void ipc_json_describe_view(swayc_t *c, json_object *object) { | 155 | static 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 | ||
196 | static void ipc_json_describe_root(swayc_t *c, json_object *object) { | 169 | static 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 | ||
201 | json_object *ipc_json_describe_container(swayc_t *c) { | 174 | json_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 | ||
252 | json_object *ipc_json_describe_input(struct libinput_device *device) { | 218 | json_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 | ||
313 | json_object *ipc_json_get_version() { | 233 | static 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); | 249 | json_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 | ||
328 | json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | 270 | json_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 | |||
454 | json_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 | } | ||