diff options
Diffstat (limited to 'sway/ipc-json.c')
-rw-r--r-- | sway/ipc-json.c | 380 |
1 files changed, 268 insertions, 112 deletions
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index fceee84d..81ca3483 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -1,7 +1,12 @@ | |||
1 | #include <ctype.h> | ||
2 | #include <float.h> | ||
1 | #include <json.h> | 3 | #include <json.h> |
2 | #include <libevdev/libevdev.h> | 4 | #include <libevdev/libevdev.h> |
3 | #include <stdio.h> | 5 | #include <stdio.h> |
4 | #include <ctype.h> | 6 | #include <wlr/config.h> |
7 | #include <wlr/types/wlr_content_type_v1.h> | ||
8 | #include <wlr/types/wlr_output.h> | ||
9 | #include <xkbcommon/xkbcommon.h> | ||
5 | #include "config.h" | 10 | #include "config.h" |
6 | #include "log.h" | 11 | #include "log.h" |
7 | #include "sway/config.h" | 12 | #include "sway/config.h" |
@@ -13,16 +18,30 @@ | |||
13 | #include "sway/input/input-manager.h" | 18 | #include "sway/input/input-manager.h" |
14 | #include "sway/input/cursor.h" | 19 | #include "sway/input/cursor.h" |
15 | #include "sway/input/seat.h" | 20 | #include "sway/input/seat.h" |
16 | #include <wlr/backend/libinput.h> | ||
17 | #include <wlr/types/wlr_box.h> | ||
18 | #include <wlr/types/wlr_output.h> | ||
19 | #include <xkbcommon/xkbcommon.h> | ||
20 | #include "wlr-layer-shell-unstable-v1-protocol.h" | 21 | #include "wlr-layer-shell-unstable-v1-protocol.h" |
21 | #include "sway/desktop/idle_inhibit_v1.h" | 22 | #include "sway/desktop/idle_inhibit_v1.h" |
22 | 23 | ||
24 | #if WLR_HAS_LIBINPUT_BACKEND | ||
25 | #include <wlr/backend/libinput.h> | ||
26 | #endif | ||
27 | |||
23 | static const int i3_output_id = INT32_MAX; | 28 | static const int i3_output_id = INT32_MAX; |
24 | static const int i3_scratch_id = INT32_MAX - 1; | 29 | static const int i3_scratch_id = INT32_MAX - 1; |
25 | 30 | ||
31 | static const char *ipc_json_node_type_description(enum sway_node_type node_type) { | ||
32 | switch (node_type) { | ||
33 | case N_ROOT: | ||
34 | return "root"; | ||
35 | case N_OUTPUT: | ||
36 | return "output"; | ||
37 | case N_WORKSPACE: | ||
38 | return "workspace"; | ||
39 | case N_CONTAINER: | ||
40 | return "con"; | ||
41 | } | ||
42 | return "none"; | ||
43 | } | ||
44 | |||
26 | static const char *ipc_json_layout_description(enum sway_container_layout l) { | 45 | static const char *ipc_json_layout_description(enum sway_container_layout l) { |
27 | switch (l) { | 46 | switch (l) { |
28 | case L_VERT: | 47 | case L_VERT: |
@@ -98,12 +117,43 @@ static const char *ipc_json_output_adaptive_sync_status_description( | |||
98 | return "disabled"; | 117 | return "disabled"; |
99 | case WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED: | 118 | case WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED: |
100 | return "enabled"; | 119 | return "enabled"; |
101 | case WLR_OUTPUT_ADAPTIVE_SYNC_UNKNOWN: | ||
102 | return "unknown"; | ||
103 | } | 120 | } |
104 | return NULL; | 121 | return NULL; |
105 | } | 122 | } |
106 | 123 | ||
124 | static const char *ipc_json_output_mode_aspect_ratio_description( | ||
125 | enum wlr_output_mode_aspect_ratio aspect_ratio) { | ||
126 | switch (aspect_ratio) { | ||
127 | case WLR_OUTPUT_MODE_ASPECT_RATIO_NONE: | ||
128 | return "none"; | ||
129 | case WLR_OUTPUT_MODE_ASPECT_RATIO_4_3: | ||
130 | return "4:3"; | ||
131 | case WLR_OUTPUT_MODE_ASPECT_RATIO_16_9: | ||
132 | return "16:9"; | ||
133 | case WLR_OUTPUT_MODE_ASPECT_RATIO_64_27: | ||
134 | return "64:27"; | ||
135 | case WLR_OUTPUT_MODE_ASPECT_RATIO_256_135: | ||
136 | return "256:135"; | ||
137 | } | ||
138 | return NULL; | ||
139 | } | ||
140 | |||
141 | static json_object *ipc_json_output_mode_description( | ||
142 | const struct wlr_output_mode *mode) { | ||
143 | const char *pic_ar = | ||
144 | ipc_json_output_mode_aspect_ratio_description(mode->picture_aspect_ratio); | ||
145 | json_object *mode_object = json_object_new_object(); | ||
146 | json_object_object_add(mode_object, "width", | ||
147 | json_object_new_int(mode->width)); | ||
148 | json_object_object_add(mode_object, "height", | ||
149 | json_object_new_int(mode->height)); | ||
150 | json_object_object_add(mode_object, "refresh", | ||
151 | json_object_new_int(mode->refresh)); | ||
152 | json_object_object_add(mode_object, "picture_aspect_ratio", | ||
153 | json_object_new_string(pic_ar)); | ||
154 | return mode_object; | ||
155 | } | ||
156 | |||
107 | #if HAVE_XWAYLAND | 157 | #if HAVE_XWAYLAND |
108 | static const char *ipc_json_xwindow_type_description(struct sway_view *view) { | 158 | static const char *ipc_json_xwindow_type_description(struct sway_view *view) { |
109 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; | 159 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; |
@@ -156,6 +206,20 @@ static const char *ipc_json_user_idle_inhibitor_description(enum sway_idle_inhib | |||
156 | return NULL; | 206 | return NULL; |
157 | } | 207 | } |
158 | 208 | ||
209 | static const char *ipc_json_content_type_description(enum wp_content_type_v1_type type) { | ||
210 | switch (type) { | ||
211 | case WP_CONTENT_TYPE_V1_TYPE_NONE: | ||
212 | return "none"; | ||
213 | case WP_CONTENT_TYPE_V1_TYPE_PHOTO: | ||
214 | return "photo"; | ||
215 | case WP_CONTENT_TYPE_V1_TYPE_VIDEO: | ||
216 | return "video"; | ||
217 | case WP_CONTENT_TYPE_V1_TYPE_GAME: | ||
218 | return "game"; | ||
219 | } | ||
220 | return NULL; | ||
221 | } | ||
222 | |||
159 | json_object *ipc_json_get_version(void) { | 223 | json_object *ipc_json_get_version(void) { |
160 | int major = 0, minor = 0, patch = 0; | 224 | int major = 0, minor = 0, patch = 0; |
161 | json_object *version = json_object_new_object(); | 225 | json_object *version = json_object_new_object(); |
@@ -189,16 +253,22 @@ static json_object *ipc_json_create_empty_rect(void) { | |||
189 | return ipc_json_create_rect(&empty); | 253 | return ipc_json_create_rect(&empty); |
190 | } | 254 | } |
191 | 255 | ||
192 | static json_object *ipc_json_create_node(int id, char *name, | 256 | static json_object *ipc_json_create_node(int id, const char* type, char *name, |
193 | bool focused, json_object *focus, struct wlr_box *box) { | 257 | bool focused, json_object *focus, struct wlr_box *box) { |
194 | json_object *object = json_object_new_object(); | 258 | json_object *object = json_object_new_object(); |
195 | 259 | ||
196 | json_object_object_add(object, "id", json_object_new_int(id)); | 260 | json_object_object_add(object, "id", json_object_new_int(id)); |
197 | json_object_object_add(object, "name", | 261 | json_object_object_add(object, "type", json_object_new_string(type)); |
198 | name ? json_object_new_string(name) : NULL); | 262 | json_object_object_add(object, "orientation", |
199 | json_object_object_add(object, "rect", ipc_json_create_rect(box)); | 263 | json_object_new_string( |
264 | ipc_json_orientation_description(L_HORIZ))); | ||
265 | json_object_object_add(object, "percent", NULL); | ||
266 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
267 | json_object_object_add(object, "marks", json_object_new_array()); | ||
200 | json_object_object_add(object, "focused", json_object_new_boolean(focused)); | 268 | json_object_object_add(object, "focused", json_object_new_boolean(focused)); |
201 | json_object_object_add(object, "focus", focus); | 269 | json_object_object_add(object, "layout", |
270 | json_object_new_string( | ||
271 | ipc_json_layout_description(L_HORIZ))); | ||
202 | 272 | ||
203 | // set default values to be compatible with i3 | 273 | // set default values to be compatible with i3 |
204 | json_object_object_add(object, "border", | 274 | json_object_object_add(object, "border", |
@@ -206,49 +276,68 @@ static json_object *ipc_json_create_node(int id, char *name, | |||
206 | ipc_json_border_description(B_NONE))); | 276 | ipc_json_border_description(B_NONE))); |
207 | json_object_object_add(object, "current_border_width", | 277 | json_object_object_add(object, "current_border_width", |
208 | json_object_new_int(0)); | 278 | json_object_new_int(0)); |
209 | json_object_object_add(object, "layout", | 279 | json_object_object_add(object, "rect", ipc_json_create_rect(box)); |
210 | json_object_new_string( | ||
211 | ipc_json_layout_description(L_HORIZ))); | ||
212 | json_object_object_add(object, "orientation", | ||
213 | json_object_new_string( | ||
214 | ipc_json_orientation_description(L_HORIZ))); | ||
215 | json_object_object_add(object, "percent", NULL); | ||
216 | json_object_object_add(object, "window_rect", ipc_json_create_empty_rect()); | ||
217 | json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect()); | 280 | json_object_object_add(object, "deco_rect", ipc_json_create_empty_rect()); |
281 | json_object_object_add(object, "window_rect", ipc_json_create_empty_rect()); | ||
218 | json_object_object_add(object, "geometry", ipc_json_create_empty_rect()); | 282 | json_object_object_add(object, "geometry", ipc_json_create_empty_rect()); |
283 | json_object_object_add(object, "name", | ||
284 | name ? json_object_new_string(name) : NULL); | ||
219 | json_object_object_add(object, "window", NULL); | 285 | json_object_object_add(object, "window", NULL); |
220 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
221 | json_object_object_add(object, "marks", json_object_new_array()); | ||
222 | json_object_object_add(object, "fullscreen_mode", json_object_new_int(0)); | ||
223 | json_object_object_add(object, "nodes", json_object_new_array()); | 286 | json_object_object_add(object, "nodes", json_object_new_array()); |
224 | json_object_object_add(object, "floating_nodes", json_object_new_array()); | 287 | json_object_object_add(object, "floating_nodes", json_object_new_array()); |
288 | json_object_object_add(object, "focus", focus); | ||
289 | json_object_object_add(object, "fullscreen_mode", json_object_new_int(0)); | ||
225 | json_object_object_add(object, "sticky", json_object_new_boolean(false)); | 290 | json_object_object_add(object, "sticky", json_object_new_boolean(false)); |
291 | json_object_object_add(object, "floating", NULL); | ||
292 | json_object_object_add(object, "scratchpad_state", NULL); | ||
226 | 293 | ||
227 | return object; | 294 | return object; |
228 | } | 295 | } |
229 | 296 | ||
230 | static void ipc_json_describe_root(struct sway_root *root, json_object *object) { | 297 | static void ipc_json_describe_wlr_output(struct wlr_output *wlr_output, json_object *object) { |
231 | json_object_object_add(object, "type", json_object_new_string("root")); | 298 | json_object_object_add(object, "primary", json_object_new_boolean(false)); |
299 | json_object_object_add(object, "make", | ||
300 | json_object_new_string(wlr_output->make ? wlr_output->make : "Unknown")); | ||
301 | json_object_object_add(object, "model", | ||
302 | json_object_new_string(wlr_output->model ? wlr_output->model : "Unknown")); | ||
303 | json_object_object_add(object, "serial", | ||
304 | json_object_new_string(wlr_output->serial ? wlr_output->serial : "Unknown")); | ||
305 | |||
306 | json_object *modes_array = json_object_new_array(); | ||
307 | struct wlr_output_mode *mode; | ||
308 | wl_list_for_each(mode, &wlr_output->modes, link) { | ||
309 | json_object *mode_object = json_object_new_object(); | ||
310 | json_object_object_add(mode_object, "width", | ||
311 | json_object_new_int(mode->width)); | ||
312 | json_object_object_add(mode_object, "height", | ||
313 | json_object_new_int(mode->height)); | ||
314 | json_object_object_add(mode_object, "refresh", | ||
315 | json_object_new_int(mode->refresh)); | ||
316 | json_object_array_add(modes_array, mode_object); | ||
317 | } | ||
318 | json_object_object_add(object, "modes", modes_array); | ||
232 | } | 319 | } |
233 | 320 | ||
234 | static void ipc_json_describe_output(struct sway_output *output, | 321 | static void ipc_json_describe_output(struct sway_output *output, |
235 | json_object *object) { | 322 | json_object *object) { |
323 | ipc_json_describe_wlr_output(output->wlr_output, object); | ||
324 | } | ||
325 | |||
326 | static void ipc_json_describe_enabled_output(struct sway_output *output, | ||
327 | json_object *object) { | ||
328 | ipc_json_describe_output(output, object); | ||
329 | |||
236 | struct wlr_output *wlr_output = output->wlr_output; | 330 | struct wlr_output *wlr_output = output->wlr_output; |
237 | json_object_object_add(object, "type", json_object_new_string("output")); | 331 | json_object_object_add(object, "non_desktop", json_object_new_boolean(false)); |
238 | json_object_object_add(object, "active", json_object_new_boolean(true)); | 332 | json_object_object_add(object, "active", json_object_new_boolean(true)); |
239 | json_object_object_add(object, "dpms", | 333 | json_object_object_add(object, "dpms", |
240 | json_object_new_boolean(wlr_output->enabled)); | 334 | json_object_new_boolean(wlr_output->enabled)); |
241 | json_object_object_add(object, "primary", json_object_new_boolean(false)); | 335 | json_object_object_add(object, "power", |
336 | json_object_new_boolean(wlr_output->enabled)); | ||
242 | json_object_object_add(object, "layout", json_object_new_string("output")); | 337 | json_object_object_add(object, "layout", json_object_new_string("output")); |
243 | json_object_object_add(object, "orientation", | 338 | json_object_object_add(object, "orientation", |
244 | json_object_new_string( | 339 | json_object_new_string( |
245 | ipc_json_orientation_description(L_NONE))); | 340 | ipc_json_orientation_description(L_NONE))); |
246 | json_object_object_add(object, "make", | ||
247 | json_object_new_string(wlr_output->make)); | ||
248 | json_object_object_add(object, "model", | ||
249 | json_object_new_string(wlr_output->model)); | ||
250 | json_object_object_add(object, "serial", | ||
251 | json_object_new_string(wlr_output->serial)); | ||
252 | json_object_object_add(object, "scale", | 341 | json_object_object_add(object, "scale", |
253 | json_object_new_double(wlr_output->scale)); | 342 | json_object_new_double(wlr_output->scale)); |
254 | json_object_object_add(object, "scale_filter", | 343 | json_object_object_add(object, "scale_filter", |
@@ -273,25 +362,26 @@ static void ipc_json_describe_output(struct sway_output *output, | |||
273 | json_object *modes_array = json_object_new_array(); | 362 | json_object *modes_array = json_object_new_array(); |
274 | struct wlr_output_mode *mode; | 363 | struct wlr_output_mode *mode; |
275 | wl_list_for_each(mode, &wlr_output->modes, link) { | 364 | wl_list_for_each(mode, &wlr_output->modes, link) { |
276 | json_object *mode_object = json_object_new_object(); | 365 | json_object *mode_object = |
277 | json_object_object_add(mode_object, "width", | 366 | ipc_json_output_mode_description(mode); |
278 | json_object_new_int(mode->width)); | ||
279 | json_object_object_add(mode_object, "height", | ||
280 | json_object_new_int(mode->height)); | ||
281 | json_object_object_add(mode_object, "refresh", | ||
282 | json_object_new_int(mode->refresh)); | ||
283 | json_object_array_add(modes_array, mode_object); | 367 | json_object_array_add(modes_array, mode_object); |
284 | } | 368 | } |
285 | 369 | ||
286 | json_object_object_add(object, "modes", modes_array); | 370 | json_object_object_add(object, "modes", modes_array); |
287 | 371 | ||
288 | json_object *current_mode_object = json_object_new_object(); | 372 | json_object *current_mode_object; |
289 | json_object_object_add(current_mode_object, "width", | 373 | if (wlr_output->current_mode != NULL) { |
290 | json_object_new_int(wlr_output->width)); | 374 | current_mode_object = |
291 | json_object_object_add(current_mode_object, "height", | 375 | ipc_json_output_mode_description(wlr_output->current_mode); |
292 | json_object_new_int(wlr_output->height)); | 376 | } else { |
293 | json_object_object_add(current_mode_object, "refresh", | 377 | current_mode_object = json_object_new_object(); |
294 | json_object_new_int(wlr_output->refresh)); | 378 | json_object_object_add(current_mode_object, "width", |
379 | json_object_new_int(wlr_output->width)); | ||
380 | json_object_object_add(current_mode_object, "height", | ||
381 | json_object_new_int(wlr_output->height)); | ||
382 | json_object_object_add(current_mode_object, "refresh", | ||
383 | json_object_new_int(wlr_output->refresh)); | ||
384 | } | ||
295 | json_object_object_add(object, "current_mode", current_mode_object); | 385 | json_object_object_add(object, "current_mode", current_mode_object); |
296 | 386 | ||
297 | struct sway_node *parent = node_get_parent(&output->node); | 387 | struct sway_node *parent = node_get_parent(&output->node); |
@@ -315,33 +405,15 @@ json_object *ipc_json_describe_disabled_output(struct sway_output *output) { | |||
315 | 405 | ||
316 | json_object *object = json_object_new_object(); | 406 | json_object *object = json_object_new_object(); |
317 | 407 | ||
408 | ipc_json_describe_output(output, object); | ||
409 | |||
410 | json_object_object_add(object, "non_desktop", json_object_new_boolean(false)); | ||
318 | json_object_object_add(object, "type", json_object_new_string("output")); | 411 | json_object_object_add(object, "type", json_object_new_string("output")); |
319 | json_object_object_add(object, "name", | 412 | json_object_object_add(object, "name", |
320 | json_object_new_string(wlr_output->name)); | 413 | json_object_new_string(wlr_output->name)); |
321 | json_object_object_add(object, "active", json_object_new_boolean(false)); | 414 | json_object_object_add(object, "active", json_object_new_boolean(false)); |
322 | json_object_object_add(object, "dpms", json_object_new_boolean(false)); | 415 | json_object_object_add(object, "dpms", json_object_new_boolean(false)); |
323 | json_object_object_add(object, "primary", json_object_new_boolean(false)); | 416 | json_object_object_add(object, "power", json_object_new_boolean(false)); |
324 | json_object_object_add(object, "make", | ||
325 | json_object_new_string(wlr_output->make)); | ||
326 | json_object_object_add(object, "model", | ||
327 | json_object_new_string(wlr_output->model)); | ||
328 | json_object_object_add(object, "serial", | ||
329 | json_object_new_string(wlr_output->serial)); | ||
330 | |||
331 | json_object *modes_array = json_object_new_array(); | ||
332 | struct wlr_output_mode *mode; | ||
333 | wl_list_for_each(mode, &wlr_output->modes, link) { | ||
334 | json_object *mode_object = json_object_new_object(); | ||
335 | json_object_object_add(mode_object, "width", | ||
336 | json_object_new_int(mode->width)); | ||
337 | json_object_object_add(mode_object, "height", | ||
338 | json_object_new_int(mode->height)); | ||
339 | json_object_object_add(mode_object, "refresh", | ||
340 | json_object_new_int(mode->refresh)); | ||
341 | json_object_array_add(modes_array, mode_object); | ||
342 | } | ||
343 | |||
344 | json_object_object_add(object, "modes", modes_array); | ||
345 | 417 | ||
346 | json_object_object_add(object, "current_workspace", NULL); | 418 | json_object_object_add(object, "current_workspace", NULL); |
347 | 419 | ||
@@ -357,6 +429,21 @@ json_object *ipc_json_describe_disabled_output(struct sway_output *output) { | |||
357 | return object; | 429 | return object; |
358 | } | 430 | } |
359 | 431 | ||
432 | json_object *ipc_json_describe_non_desktop_output(struct sway_output_non_desktop *output) { | ||
433 | struct wlr_output *wlr_output = output->wlr_output; | ||
434 | |||
435 | json_object *object = json_object_new_object(); | ||
436 | |||
437 | ipc_json_describe_wlr_output(wlr_output, object); | ||
438 | |||
439 | json_object_object_add(object, "non_desktop", json_object_new_boolean(true)); | ||
440 | json_object_object_add(object, "type", json_object_new_string("output")); | ||
441 | json_object_object_add(object, "name", | ||
442 | json_object_new_string(wlr_output->name)); | ||
443 | |||
444 | return object; | ||
445 | } | ||
446 | |||
360 | static json_object *ipc_json_describe_scratchpad_output(void) { | 447 | static json_object *ipc_json_describe_scratchpad_output(void) { |
361 | struct wlr_box box; | 448 | struct wlr_box box; |
362 | root_get_box(root, &box); | 449 | root_get_box(root, &box); |
@@ -369,11 +456,9 @@ static json_object *ipc_json_describe_scratchpad_output(void) { | |||
369 | json_object_new_int(container->node.id)); | 456 | json_object_new_int(container->node.id)); |
370 | } | 457 | } |
371 | 458 | ||
372 | json_object *workspace = ipc_json_create_node(i3_scratch_id, | 459 | json_object *workspace = ipc_json_create_node(i3_scratch_id, "workspace", |
373 | "__i3_scratch", false, workspace_focus, &box); | 460 | "__i3_scratch", false, workspace_focus, &box); |
374 | json_object_object_add(workspace, "fullscreen_mode", json_object_new_int(1)); | 461 | json_object_object_add(workspace, "fullscreen_mode", json_object_new_int(1)); |
375 | json_object_object_add(workspace, "type", | ||
376 | json_object_new_string("workspace")); | ||
377 | 462 | ||
378 | // List all hidden scratchpad containers as floating nodes | 463 | // List all hidden scratchpad containers as floating nodes |
379 | json_object *floating_array = json_object_new_array(); | 464 | json_object *floating_array = json_object_new_array(); |
@@ -390,10 +475,8 @@ static json_object *ipc_json_describe_scratchpad_output(void) { | |||
390 | json_object *output_focus = json_object_new_array(); | 475 | json_object *output_focus = json_object_new_array(); |
391 | json_object_array_add(output_focus, json_object_new_int(i3_scratch_id)); | 476 | json_object_array_add(output_focus, json_object_new_int(i3_scratch_id)); |
392 | 477 | ||
393 | json_object *output = ipc_json_create_node(i3_output_id, | 478 | json_object *output = ipc_json_create_node(i3_output_id, "output", |
394 | "__i3", false, output_focus, &box); | 479 | "__i3", false, output_focus, &box); |
395 | json_object_object_add(output, "type", | ||
396 | json_object_new_string("output")); | ||
397 | json_object_object_add(output, "layout", | 480 | json_object_object_add(output, "layout", |
398 | json_object_new_string("output")); | 481 | json_object_new_string("output")); |
399 | 482 | ||
@@ -423,7 +506,6 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace, | |||
423 | json_object_object_add(object, "fullscreen_mode", json_object_new_int(1)); | 506 | json_object_object_add(object, "fullscreen_mode", json_object_new_int(1)); |
424 | json_object_object_add(object, "output", workspace->output ? | 507 | json_object_object_add(object, "output", workspace->output ? |
425 | json_object_new_string(workspace->output->wlr_output->name) : NULL); | 508 | json_object_new_string(workspace->output->wlr_output->name) : NULL); |
426 | json_object_object_add(object, "type", json_object_new_string("workspace")); | ||
427 | json_object_object_add(object, "urgent", | 509 | json_object_object_add(object, "urgent", |
428 | json_object_new_boolean(workspace->urgent)); | 510 | json_object_new_boolean(workspace->urgent)); |
429 | json_object_object_add(object, "representation", workspace->representation ? | 511 | json_object_object_add(object, "representation", workspace->representation ? |
@@ -448,30 +530,32 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace, | |||
448 | 530 | ||
449 | static void get_deco_rect(struct sway_container *c, struct wlr_box *deco_rect) { | 531 | static void get_deco_rect(struct sway_container *c, struct wlr_box *deco_rect) { |
450 | enum sway_container_layout parent_layout = container_parent_layout(c); | 532 | enum sway_container_layout parent_layout = container_parent_layout(c); |
451 | bool tab_or_stack = parent_layout == L_TABBED || parent_layout == L_STACKED; | 533 | list_t *siblings = container_get_siblings(c); |
534 | bool tab_or_stack = (parent_layout == L_TABBED || parent_layout == L_STACKED) | ||
535 | && ((siblings && siblings->length > 1) || !config->hide_lone_tab); | ||
452 | if (((!tab_or_stack || container_is_floating(c)) && | 536 | if (((!tab_or_stack || container_is_floating(c)) && |
453 | c->current.border != B_NORMAL) || | 537 | c->current.border != B_NORMAL) || |
454 | c->fullscreen_mode != FULLSCREEN_NONE || | 538 | c->pending.fullscreen_mode != FULLSCREEN_NONE || |
455 | c->workspace == NULL) { | 539 | c->pending.workspace == NULL) { |
456 | deco_rect->x = deco_rect->y = deco_rect->width = deco_rect->height = 0; | 540 | deco_rect->x = deco_rect->y = deco_rect->width = deco_rect->height = 0; |
457 | return; | 541 | return; |
458 | } | 542 | } |
459 | 543 | ||
460 | if (c->parent) { | 544 | if (c->pending.parent) { |
461 | deco_rect->x = c->x - c->parent->x; | 545 | deco_rect->x = c->pending.x - c->pending.parent->pending.x; |
462 | deco_rect->y = c->y - c->parent->y; | 546 | deco_rect->y = c->pending.y - c->pending.parent->pending.y; |
463 | } else { | 547 | } else { |
464 | deco_rect->x = c->x - c->workspace->x; | 548 | deco_rect->x = c->pending.x - c->pending.workspace->x; |
465 | deco_rect->y = c->y - c->workspace->y; | 549 | deco_rect->y = c->pending.y - c->pending.workspace->y; |
466 | } | 550 | } |
467 | deco_rect->width = c->width; | 551 | deco_rect->width = c->pending.width; |
468 | deco_rect->height = container_titlebar_height(); | 552 | deco_rect->height = container_titlebar_height(); |
469 | 553 | ||
470 | if (!container_is_floating(c)) { | 554 | if (!container_is_floating(c)) { |
471 | if (parent_layout == L_TABBED) { | 555 | if (parent_layout == L_TABBED) { |
472 | deco_rect->width = c->parent | 556 | deco_rect->width = c->pending.parent |
473 | ? c->parent->width / c->parent->children->length | 557 | ? c->pending.parent->pending.width / c->pending.parent->pending.children->length |
474 | : c->workspace->width / c->workspace->tiling->length; | 558 | : c->pending.workspace->width / c->pending.workspace->tiling->length; |
475 | deco_rect->x += deco_rect->width * container_sibling_index(c); | 559 | deco_rect->x += deco_rect->width * container_sibling_index(c); |
476 | } else if (parent_layout == L_STACKED) { | 560 | } else if (parent_layout == L_STACKED) { |
477 | if (!c->view) { | 561 | if (!c->view) { |
@@ -494,10 +578,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
494 | json_object_object_add(object, "visible", json_object_new_boolean(visible)); | 578 | json_object_object_add(object, "visible", json_object_new_boolean(visible)); |
495 | 579 | ||
496 | struct wlr_box window_box = { | 580 | struct wlr_box window_box = { |
497 | c->content_x - c->x, | 581 | c->pending.content_x - c->pending.x, |
498 | (c->current.border == B_PIXEL) ? c->current.border_thickness : 0, | 582 | (c->current.border == B_PIXEL) ? c->pending.content_y - c->pending.y : 0, |
499 | c->content_width, | 583 | c->pending.content_width, |
500 | c->content_height | 584 | c->pending.content_height |
501 | }; | 585 | }; |
502 | 586 | ||
503 | json_object_object_add(object, "window_rect", ipc_json_create_rect(&window_box)); | 587 | json_object_object_add(object, "window_rect", ipc_json_create_rect(&window_box)); |
@@ -539,6 +623,16 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
539 | 623 | ||
540 | json_object_object_add(object, "idle_inhibitors", idle_inhibitors); | 624 | json_object_object_add(object, "idle_inhibitors", idle_inhibitors); |
541 | 625 | ||
626 | enum wp_content_type_v1_type content_type = WP_CONTENT_TYPE_V1_TYPE_NONE; | ||
627 | if (c->view->surface != NULL) { | ||
628 | content_type = wlr_surface_get_content_type_v1(server.content_type_manager_v1, | ||
629 | c->view->surface); | ||
630 | } | ||
631 | if (content_type != WP_CONTENT_TYPE_V1_TYPE_NONE) { | ||
632 | json_object_object_add(object, "content_type", | ||
633 | json_object_new_string(ipc_json_content_type_description(content_type))); | ||
634 | } | ||
635 | |||
542 | #if HAVE_XWAYLAND | 636 | #if HAVE_XWAYLAND |
543 | if (c->view->type == SWAY_VIEW_XWAYLAND) { | 637 | if (c->view->type == SWAY_VIEW_XWAYLAND) { |
544 | json_object_object_add(object, "window", | 638 | json_object_object_add(object, "window", |
@@ -583,24 +677,35 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
583 | static void ipc_json_describe_container(struct sway_container *c, json_object *object) { | 677 | static void ipc_json_describe_container(struct sway_container *c, json_object *object) { |
584 | json_object_object_add(object, "name", | 678 | json_object_object_add(object, "name", |
585 | c->title ? json_object_new_string(c->title) : NULL); | 679 | c->title ? json_object_new_string(c->title) : NULL); |
586 | json_object_object_add(object, "type", | 680 | bool floating = container_is_floating(c); |
587 | json_object_new_string(container_is_floating(c) ? "floating_con" : "con")); | 681 | if (floating) { |
682 | json_object_object_add(object, "type", | ||
683 | json_object_new_string("floating_con")); | ||
684 | } | ||
588 | 685 | ||
589 | json_object_object_add(object, "layout", | 686 | json_object_object_add(object, "layout", |
590 | json_object_new_string( | 687 | json_object_new_string( |
591 | ipc_json_layout_description(c->layout))); | 688 | ipc_json_layout_description(c->pending.layout))); |
592 | 689 | ||
593 | json_object_object_add(object, "orientation", | 690 | json_object_object_add(object, "orientation", |
594 | json_object_new_string( | 691 | json_object_new_string( |
595 | ipc_json_orientation_description(c->layout))); | 692 | ipc_json_orientation_description(c->pending.layout))); |
596 | 693 | ||
597 | bool urgent = c->view ? | 694 | bool urgent = c->view ? |
598 | view_is_urgent(c->view) : container_has_urgent_child(c); | 695 | view_is_urgent(c->view) : container_has_urgent_child(c); |
599 | json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); | 696 | json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); |
600 | json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky)); | 697 | json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky)); |
601 | 698 | ||
699 | // sway doesn't track the floating reason, so we can't use "auto_on" or "user_off" | ||
700 | json_object_object_add(object, "floating", | ||
701 | json_object_new_string(floating ? "user_on" : "auto_off")); | ||
702 | |||
602 | json_object_object_add(object, "fullscreen_mode", | 703 | json_object_object_add(object, "fullscreen_mode", |
603 | json_object_new_int(c->fullscreen_mode)); | 704 | json_object_new_int(c->pending.fullscreen_mode)); |
705 | |||
706 | // sway doesn't track if window was resized in scratchpad, so we can't use "changed" | ||
707 | json_object_object_add(object, "scratchpad_state", | ||
708 | json_object_new_string(!c->scratchpad ? "none" : "fresh")); | ||
604 | 709 | ||
605 | struct sway_node *parent = node_get_parent(&c->node); | 710 | struct sway_node *parent = node_get_parent(&c->node); |
606 | struct wlr_box parent_box = {0, 0, 0, 0}; | 711 | struct wlr_box parent_box = {0, 0, 0, 0}; |
@@ -610,8 +715,8 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o | |||
610 | } | 715 | } |
611 | 716 | ||
612 | if (parent_box.width != 0 && parent_box.height != 0) { | 717 | if (parent_box.width != 0 && parent_box.height != 0) { |
613 | double percent = ((double)c->width / parent_box.width) | 718 | double percent = ((double)c->pending.width / parent_box.width) |
614 | * ((double)c->height / parent_box.height); | 719 | * ((double)c->pending.height / parent_box.height); |
615 | json_object_object_add(object, "percent", json_object_new_double(percent)); | 720 | json_object_object_add(object, "percent", json_object_new_double(percent)); |
616 | } | 721 | } |
617 | 722 | ||
@@ -692,15 +797,14 @@ json_object *ipc_json_describe_node(struct sway_node *node) { | |||
692 | }; | 797 | }; |
693 | seat_for_each_node(seat, focus_inactive_children_iterator, &data); | 798 | seat_for_each_node(seat, focus_inactive_children_iterator, &data); |
694 | 799 | ||
695 | json_object *object = ipc_json_create_node( | 800 | json_object *object = ipc_json_create_node((int)node->id, |
696 | (int)node->id, name, focused, focus, &box); | 801 | ipc_json_node_type_description(node->type), name, focused, focus, &box); |
697 | 802 | ||
698 | switch (node->type) { | 803 | switch (node->type) { |
699 | case N_ROOT: | 804 | case N_ROOT: |
700 | ipc_json_describe_root(root, object); | ||
701 | break; | 805 | break; |
702 | case N_OUTPUT: | 806 | case N_OUTPUT: |
703 | ipc_json_describe_output(node->sway_output, object); | 807 | ipc_json_describe_enabled_output(node->sway_output, object); |
704 | break; | 808 | break; |
705 | case N_CONTAINER: | 809 | case N_CONTAINER: |
706 | ipc_json_describe_container(node->sway_container, object); | 810 | ipc_json_describe_container(node->sway_container, object); |
@@ -743,10 +847,10 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) { | |||
743 | } | 847 | } |
744 | break; | 848 | break; |
745 | case N_CONTAINER: | 849 | case N_CONTAINER: |
746 | if (node->sway_container->children) { | 850 | if (node->sway_container->pending.children) { |
747 | for (i = 0; i < node->sway_container->children->length; ++i) { | 851 | for (i = 0; i < node->sway_container->pending.children->length; ++i) { |
748 | struct sway_container *child = | 852 | struct sway_container *child = |
749 | node->sway_container->children->items[i]; | 853 | node->sway_container->pending.children->items[i]; |
750 | json_object_array_add(children, | 854 | json_object_array_add(children, |
751 | ipc_json_describe_node_recursive(&child->node)); | 855 | ipc_json_describe_node_recursive(&child->node)); |
752 | } | 856 | } |
@@ -758,6 +862,7 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) { | |||
758 | return object; | 862 | return object; |
759 | } | 863 | } |
760 | 864 | ||
865 | #if WLR_HAS_LIBINPUT_BACKEND | ||
761 | static json_object *describe_libinput_device(struct libinput_device *device) { | 866 | static json_object *describe_libinput_device(struct libinput_device *device) { |
762 | json_object *object = json_object_new_object(); | 867 | json_object *object = json_object_new_object(); |
763 | 868 | ||
@@ -841,6 +946,11 @@ static json_object *describe_libinput_device(struct libinput_device *device) { | |||
841 | case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE: | 946 | case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE: |
842 | accel_profile = "adaptive"; | 947 | accel_profile = "adaptive"; |
843 | break; | 948 | break; |
949 | #if HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM | ||
950 | case LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM: | ||
951 | accel_profile = "custom"; | ||
952 | break; | ||
953 | #endif | ||
844 | } | 954 | } |
845 | json_object_object_add(object, "accel_profile", | 955 | json_object_object_add(object, "accel_profile", |
846 | json_object_new_string(accel_profile)); | 956 | json_object_new_string(accel_profile)); |
@@ -920,6 +1030,17 @@ static json_object *describe_libinput_device(struct libinput_device *device) { | |||
920 | uint32_t button = libinput_device_config_scroll_get_button(device); | 1030 | uint32_t button = libinput_device_config_scroll_get_button(device); |
921 | json_object_object_add(object, "scroll_button", | 1031 | json_object_object_add(object, "scroll_button", |
922 | json_object_new_int(button)); | 1032 | json_object_new_int(button)); |
1033 | const char *lock = "unknown"; | ||
1034 | switch (libinput_device_config_scroll_get_button_lock(device)) { | ||
1035 | case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED: | ||
1036 | lock = "enabled"; | ||
1037 | break; | ||
1038 | case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED: | ||
1039 | lock = "disabled"; | ||
1040 | break; | ||
1041 | } | ||
1042 | json_object_object_add(object, "scroll_button_lock", | ||
1043 | json_object_new_string(lock)); | ||
923 | } | 1044 | } |
924 | } | 1045 | } |
925 | 1046 | ||
@@ -936,6 +1057,19 @@ static json_object *describe_libinput_device(struct libinput_device *device) { | |||
936 | json_object_object_add(object, "dwt", json_object_new_string(dwt)); | 1057 | json_object_object_add(object, "dwt", json_object_new_string(dwt)); |
937 | } | 1058 | } |
938 | 1059 | ||
1060 | if (libinput_device_config_dwtp_is_available(device)) { | ||
1061 | const char *dwtp = "unknown"; | ||
1062 | switch (libinput_device_config_dwtp_get_enabled(device)) { | ||
1063 | case LIBINPUT_CONFIG_DWTP_ENABLED: | ||
1064 | dwtp = "enabled"; | ||
1065 | break; | ||
1066 | case LIBINPUT_CONFIG_DWTP_DISABLED: | ||
1067 | dwtp = "disabled"; | ||
1068 | break; | ||
1069 | } | ||
1070 | json_object_object_add(object, "dwtp", json_object_new_string(dwtp)); | ||
1071 | } | ||
1072 | |||
939 | if (libinput_device_config_calibration_has_matrix(device)) { | 1073 | if (libinput_device_config_calibration_has_matrix(device)) { |
940 | float matrix[6]; | 1074 | float matrix[6]; |
941 | libinput_device_config_calibration_get_matrix(device, matrix); | 1075 | libinput_device_config_calibration_get_matrix(device, matrix); |
@@ -950,6 +1084,7 @@ static json_object *describe_libinput_device(struct libinput_device *device) { | |||
950 | 1084 | ||
951 | return object; | 1085 | return object; |
952 | } | 1086 | } |
1087 | #endif | ||
953 | 1088 | ||
954 | json_object *ipc_json_describe_input(struct sway_input_device *device) { | 1089 | json_object *ipc_json_describe_input(struct sway_input_device *device) { |
955 | if (!(sway_assert(device, "Device must not be null"))) { | 1090 | if (!(sway_assert(device, "Device must not be null"))) { |
@@ -962,19 +1097,21 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { | |||
962 | json_object_new_string(device->identifier)); | 1097 | json_object_new_string(device->identifier)); |
963 | json_object_object_add(object, "name", | 1098 | json_object_object_add(object, "name", |
964 | json_object_new_string(device->wlr_device->name)); | 1099 | json_object_new_string(device->wlr_device->name)); |
965 | json_object_object_add(object, "vendor", | ||
966 | json_object_new_int(device->wlr_device->vendor)); | ||
967 | json_object_object_add(object, "product", | ||
968 | json_object_new_int(device->wlr_device->product)); | ||
969 | json_object_object_add(object, "type", | 1100 | json_object_object_add(object, "type", |
970 | json_object_new_string( | 1101 | json_object_new_string( |
971 | input_device_get_type(device))); | 1102 | input_device_get_type(device))); |
972 | 1103 | ||
973 | if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { | 1104 | if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { |
974 | struct wlr_keyboard *keyboard = device->wlr_device->keyboard; | 1105 | struct wlr_keyboard *keyboard = |
1106 | wlr_keyboard_from_input_device(device->wlr_device); | ||
975 | struct xkb_keymap *keymap = keyboard->keymap; | 1107 | struct xkb_keymap *keymap = keyboard->keymap; |
976 | struct xkb_state *state = keyboard->xkb_state; | 1108 | struct xkb_state *state = keyboard->xkb_state; |
977 | 1109 | ||
1110 | json_object_object_add(object, "repeat_delay", | ||
1111 | json_object_new_int(keyboard->repeat_info.delay)); | ||
1112 | json_object_object_add(object, "repeat_rate", | ||
1113 | json_object_new_int(keyboard->repeat_info.rate)); | ||
1114 | |||
978 | json_object *layouts_arr = json_object_new_array(); | 1115 | json_object *layouts_arr = json_object_new_array(); |
979 | json_object_object_add(object, "xkb_layout_names", layouts_arr); | 1116 | json_object_object_add(object, "xkb_layout_names", layouts_arr); |
980 | 1117 | ||
@@ -996,12 +1133,29 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { | |||
996 | } | 1133 | } |
997 | } | 1134 | } |
998 | 1135 | ||
1136 | if (device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { | ||
1137 | struct input_config *ic = input_device_get_config(device); | ||
1138 | float scroll_factor = 1.0f; | ||
1139 | if (ic != NULL && !isnan(ic->scroll_factor) && | ||
1140 | ic->scroll_factor != FLT_MIN) { | ||
1141 | scroll_factor = ic->scroll_factor; | ||
1142 | } | ||
1143 | json_object_object_add(object, "scroll_factor", | ||
1144 | json_object_new_double(scroll_factor)); | ||
1145 | } | ||
1146 | |||
1147 | #if WLR_HAS_LIBINPUT_BACKEND | ||
999 | if (wlr_input_device_is_libinput(device->wlr_device)) { | 1148 | if (wlr_input_device_is_libinput(device->wlr_device)) { |
1000 | struct libinput_device *libinput_dev; | 1149 | struct libinput_device *libinput_dev; |
1001 | libinput_dev = wlr_libinput_get_device_handle(device->wlr_device); | 1150 | libinput_dev = wlr_libinput_get_device_handle(device->wlr_device); |
1002 | json_object_object_add(object, "libinput", | 1151 | json_object_object_add(object, "libinput", |
1003 | describe_libinput_device(libinput_dev)); | 1152 | describe_libinput_device(libinput_dev)); |
1153 | json_object_object_add(object, "vendor", | ||
1154 | json_object_new_int(libinput_device_get_id_vendor(libinput_dev))); | ||
1155 | json_object_object_add(object, "product", | ||
1156 | json_object_new_int(libinput_device_get_id_product(libinput_dev))); | ||
1004 | } | 1157 | } |
1158 | #endif | ||
1005 | 1159 | ||
1006 | return object; | 1160 | return object; |
1007 | } | 1161 | } |
@@ -1109,7 +1263,9 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | |||
1109 | json_object_object_add(json, "verbose", | 1263 | json_object_object_add(json, "verbose", |
1110 | json_object_new_boolean(bar->verbose)); | 1264 | json_object_new_boolean(bar->verbose)); |
1111 | json_object_object_add(json, "pango_markup", | 1265 | json_object_object_add(json, "pango_markup", |
1112 | json_object_new_boolean(bar->pango_markup)); | 1266 | json_object_new_boolean(bar->pango_markup == PANGO_MARKUP_DEFAULT |
1267 | ? config->pango_markup | ||
1268 | : bar->pango_markup)); | ||
1113 | 1269 | ||
1114 | json_object *colors = json_object_new_object(); | 1270 | json_object *colors = json_object_new_object(); |
1115 | json_object_object_add(colors, "background", | 1271 | json_object_object_add(colors, "background", |