diff options
author | Drew DeVault <sir@cmpwn.com> | 2016-07-04 16:03:23 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-04 16:03:23 -0400 |
commit | 33c923be731c0bb1c399bf3bd1011aa969e591d8 (patch) | |
tree | 93c374e26425460bfa7ad1bc1528a1b9b5725a8e | |
parent | Merge pull request #734 from jplatte/patch-1 (diff) | |
parent | Merge branch 'master' into get-tree-command (diff) | |
download | sway-33c923be731c0bb1c399bf3bd1011aa969e591d8.tar.gz sway-33c923be731c0bb1c399bf3bd1011aa969e591d8.tar.zst sway-33c923be731c0bb1c399bf3bd1011aa969e591d8.zip |
Merge pull request #735 from zandrmartin/get-tree-command
implement `get_tree` command
-rw-r--r-- | include/ipc-json.h | 13 | ||||
-rw-r--r-- | sway/CMakeLists.txt | 1 | ||||
-rw-r--r-- | sway/container.c | 28 | ||||
-rw-r--r-- | sway/ipc-json.c | 326 | ||||
-rw-r--r-- | sway/ipc-server.c | 168 | ||||
-rw-r--r-- | sway/layout.c | 1 |
6 files changed, 385 insertions, 152 deletions
diff --git a/include/ipc-json.h b/include/ipc-json.h new file mode 100644 index 00000000..f90d801e --- /dev/null +++ b/include/ipc-json.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef _SWAY_IPC_JSON_H | ||
2 | #define _SWAY_IPC_JSON_H | ||
3 | |||
4 | #include <json-c/json.h> | ||
5 | #include "config.h" | ||
6 | #include "container.h" | ||
7 | |||
8 | json_object *ipc_json_get_version(); | ||
9 | json_object *ipc_json_describe_bar_config(struct bar_config *bar); | ||
10 | json_object *ipc_json_describe_container(swayc_t *c); | ||
11 | json_object *ipc_json_describe_container_recursive(swayc_t *c); | ||
12 | |||
13 | #endif | ||
diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 73df3b1b..be63c944 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt | |||
@@ -21,6 +21,7 @@ add_executable(sway | |||
21 | handlers.c | 21 | handlers.c |
22 | input.c | 22 | input.c |
23 | input_state.c | 23 | input_state.c |
24 | ipc-json.c | ||
24 | ipc-server.c | 25 | ipc-server.c |
25 | layout.c | 26 | layout.c |
26 | main.c | 27 | main.c |
diff --git a/sway/container.c b/sway/container.c index 21538ab4..a7e46571 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -75,6 +75,30 @@ static void free_swayc(swayc_t *cont) { | |||
75 | free(cont); | 75 | free(cont); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void update_root_geometry() { | ||
79 | int width = 0; | ||
80 | int height = 0; | ||
81 | swayc_t *child; | ||
82 | int child_width; | ||
83 | int child_height; | ||
84 | |||
85 | for (int i = 0; i < root_container.children->length; ++i) { | ||
86 | child = root_container.children->items[i]; | ||
87 | child_width = child->width + child->x; | ||
88 | child_height = child->height + child->y; | ||
89 | if (child_width > width) { | ||
90 | width = child_width; | ||
91 | } | ||
92 | |||
93 | if (child_height > height) { | ||
94 | height = child_height; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | root_container.width = width; | ||
99 | root_container.height = height; | ||
100 | } | ||
101 | |||
78 | // New containers | 102 | // New containers |
79 | 103 | ||
80 | swayc_t *new_output(wlc_handle handle) { | 104 | swayc_t *new_output(wlc_handle handle) { |
@@ -167,6 +191,7 @@ swayc_t *new_output(wlc_handle handle) { | |||
167 | } | 191 | } |
168 | 192 | ||
169 | free(ws_name); | 193 | free(ws_name); |
194 | update_root_geometry(); | ||
170 | return output; | 195 | return output; |
171 | } | 196 | } |
172 | 197 | ||
@@ -361,7 +386,7 @@ void floating_view_sane_size(swayc_t *view) { | |||
361 | view->desired_width = config->floating_maximum_width; | 386 | view->desired_width = config->floating_maximum_width; |
362 | } | 387 | } |
363 | 388 | ||
364 | sway_log(L_DEBUG, "Sane values for view to %d x %d @ %.f, %.f", | 389 | sway_log(L_DEBUG, "Sane values for view to %d x %d @ %.f, %.f", |
365 | view->desired_width, view->desired_height, view->x, view->y); | 390 | view->desired_width, view->desired_height, view->x, view->y); |
366 | 391 | ||
367 | return; | 392 | return; |
@@ -393,6 +418,7 @@ swayc_t *destroy_output(swayc_t *output) { | |||
393 | } | 418 | } |
394 | sway_log(L_DEBUG, "OUTPUT: Destroying output '%" PRIuPTR "'", output->handle); | 419 | sway_log(L_DEBUG, "OUTPUT: Destroying output '%" PRIuPTR "'", output->handle); |
395 | free_swayc(output); | 420 | free_swayc(output); |
421 | update_root_geometry(); | ||
396 | return &root_container; | 422 | return &root_container; |
397 | } | 423 | } |
398 | 424 | ||
diff --git a/sway/ipc-json.c b/sway/ipc-json.c new file mode 100644 index 00000000..69412023 --- /dev/null +++ b/sway/ipc-json.c | |||
@@ -0,0 +1,326 @@ | |||
1 | #include <json-c/json.h> | ||
2 | #include <ctype.h> | ||
3 | #include <string.h> | ||
4 | #include "container.h" | ||
5 | #include "util.h" | ||
6 | #include "ipc-json.h" | ||
7 | |||
8 | static json_object *ipc_json_create_rect(swayc_t *c) { | ||
9 | json_object *rect = json_object_new_object(); | ||
10 | |||
11 | json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); | ||
12 | json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); | ||
13 | json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); | ||
14 | json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); | ||
15 | |||
16 | return rect; | ||
17 | } | ||
18 | |||
19 | static const char *ipc_json_border_description(swayc_t *c) { | ||
20 | const char *border; | ||
21 | |||
22 | switch (c->border_type) { | ||
23 | case B_PIXEL: | ||
24 | border = "1pixel"; | ||
25 | break; | ||
26 | |||
27 | case B_NORMAL: | ||
28 | border = "normal"; | ||
29 | break; | ||
30 | |||
31 | case B_NONE: // fallthrough | ||
32 | default: | ||
33 | border = "none"; | ||
34 | break; | ||
35 | } | ||
36 | |||
37 | return border; | ||
38 | } | ||
39 | |||
40 | static const char *ipc_json_layout_description(swayc_t *c) { | ||
41 | const char *layout; | ||
42 | |||
43 | switch (c->layout) { | ||
44 | case L_VERT: | ||
45 | layout = "splitv"; | ||
46 | break; | ||
47 | |||
48 | case L_HORIZ: | ||
49 | layout = "splith"; | ||
50 | break; | ||
51 | |||
52 | case L_TABBED: | ||
53 | layout = "tabbed"; | ||
54 | break; | ||
55 | |||
56 | case L_STACKED: | ||
57 | layout = "stacked"; | ||
58 | break; | ||
59 | |||
60 | case L_FLOATING: | ||
61 | layout = "floating"; | ||
62 | break; | ||
63 | |||
64 | case L_NONE: // fallthrough | ||
65 | case L_LAYOUTS: // fallthrough; this should never happen, I'm just trying to silence compiler warnings | ||
66 | default: | ||
67 | layout = "null"; | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | return layout; | ||
72 | } | ||
73 | |||
74 | static float ipc_json_child_percentage(swayc_t *c) { | ||
75 | float percent = 0; | ||
76 | swayc_t *parent = c->parent; | ||
77 | |||
78 | if (parent) { | ||
79 | switch (parent->layout) { | ||
80 | case L_VERT: | ||
81 | percent = c->height / parent->height; | ||
82 | break; | ||
83 | |||
84 | case L_HORIZ: | ||
85 | percent = c->width / parent->width; | ||
86 | break; | ||
87 | |||
88 | case L_STACKED: // fallthrough | ||
89 | case L_TABBED: // fallthrough | ||
90 | percent = 1.0; | ||
91 | break; | ||
92 | |||
93 | default: | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | return percent; | ||
99 | } | ||
100 | |||
101 | static void ipc_json_describe_output(swayc_t *output, json_object *object) { | ||
102 | json_object_object_add(object, "active", json_object_new_boolean(true)); | ||
103 | json_object_object_add(object, "primary", json_object_new_boolean(false)); | ||
104 | json_object_object_add(object, "layout", json_object_new_string("output")); | ||
105 | json_object_object_add(object, "type", json_object_new_string("output")); | ||
106 | json_object_object_add(object, "current_workspace", | ||
107 | (output->focused) ? json_object_new_string(output->focused->name) : NULL); | ||
108 | } | ||
109 | |||
110 | static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { | ||
111 | int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; | ||
112 | bool focused = root_container.focused == workspace->parent && workspace->parent->focused == workspace; | ||
113 | |||
114 | json_object_object_add(object, "num", json_object_new_int(num)); | ||
115 | json_object_object_add(object, "visible", json_object_new_boolean(workspace->visible)); | ||
116 | json_object_object_add(object, "focused", json_object_new_boolean(focused)); | ||
117 | json_object_object_add(object, "output", json_object_new_string((workspace->parent) ? workspace->parent->name : "null")); | ||
118 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
119 | json_object_object_add(object, "type", json_object_new_string("workspace")); | ||
120 | json_object_object_add(object, "layout", json_object_new_string(ipc_json_layout_description(workspace))); | ||
121 | } | ||
122 | |||
123 | static void ipc_json_describe_view(swayc_t *view, json_object *object) { | ||
124 | float percent = ipc_json_child_percentage(view); | ||
125 | |||
126 | json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(view))); | ||
127 | json_object_object_add(object, "current_border_width", json_object_new_int(view->border_thickness)); | ||
128 | json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : json_object_new_string("null")); | ||
129 | // TODO: make urgency actually work once Sway supports it | ||
130 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
131 | json_object_object_add(object, "focused", json_object_new_boolean(view->is_focused)); | ||
132 | json_object_object_add(object, "type", json_object_new_string((view->is_floating) ? "floating_con" : "con")); | ||
133 | json_object_object_add(object, "layout", json_object_new_string(ipc_json_layout_description(view))); | ||
134 | |||
135 | if (view->class) { | ||
136 | json_object_object_add(object, "class", json_object_new_string(view->class)); | ||
137 | } | ||
138 | |||
139 | if (view->app_id) { | ||
140 | json_object_object_add(object, "app_id", json_object_new_string(view->app_id)); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | json_object *ipc_json_describe_container(swayc_t *c) { | ||
145 | if (!(sway_assert(c, "Container must not be null."))) { | ||
146 | return NULL; | ||
147 | } | ||
148 | |||
149 | json_object *object = json_object_new_object(); | ||
150 | |||
151 | json_object_object_add(object, "id", json_object_new_int((int64_t)&c)); | ||
152 | json_object_object_add(object, "name", json_object_new_string(c->name)); | ||
153 | json_object_object_add(object, "rect", ipc_json_create_rect(c)); | ||
154 | |||
155 | switch (c->type) { | ||
156 | case C_ROOT: | ||
157 | json_object_object_add(object, "type", json_object_new_string("root")); | ||
158 | break; | ||
159 | |||
160 | case C_OUTPUT: | ||
161 | ipc_json_describe_output(c, object); | ||
162 | break; | ||
163 | |||
164 | case C_CONTAINER: // fallthrough | ||
165 | case C_VIEW: | ||
166 | ipc_json_describe_view(c, object); | ||
167 | break; | ||
168 | |||
169 | case C_WORKSPACE: | ||
170 | ipc_json_describe_workspace(c, object); | ||
171 | break; | ||
172 | |||
173 | case C_TYPES: // fallthrough; this should never happen, I'm just trying to silence compiler warnings | ||
174 | default: | ||
175 | break; | ||
176 | } | ||
177 | |||
178 | return object; | ||
179 | } | ||
180 | |||
181 | json_object *ipc_json_get_version() { | ||
182 | json_object *version = json_object_new_object(); | ||
183 | |||
184 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE | ||
185 | char *full_version = calloc(strlen(SWAY_GIT_VERSION) + strlen(SWAY_GIT_BRANCH) + strlen(SWAY_VERSION_DATE) + 20, 1); | ||
186 | strcat(full_version, SWAY_GIT_VERSION); | ||
187 | strcat(full_version, " ("); | ||
188 | strcat(full_version, SWAY_VERSION_DATE); | ||
189 | strcat(full_version, ", branch \""); | ||
190 | strcat(full_version, SWAY_GIT_BRANCH); | ||
191 | strcat(full_version, "\")"); | ||
192 | |||
193 | json_object_object_add(version, "human_readable", json_object_new_string(full_version)); | ||
194 | json_object_object_add(version, "variant", json_object_new_string("sway")); | ||
195 | // Todo once we actually release a version | ||
196 | json_object_object_add(version, "major", json_object_new_int(0)); | ||
197 | json_object_object_add(version, "minor", json_object_new_int(0)); | ||
198 | json_object_object_add(version, "patch", json_object_new_int(1)); | ||
199 | #else | ||
200 | json_object_object_add(version, "human_readable", json_object_new_string("version not found")); | ||
201 | json_object_object_add(version, "major", json_object_new_int(0)); | ||
202 | json_object_object_add(version, "minor", json_object_new_int(0)); | ||
203 | json_object_object_add(version, "patch", json_object_new_int(0)); | ||
204 | #endif | ||
205 | |||
206 | return version; | ||
207 | } | ||
208 | |||
209 | json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | ||
210 | if (!sway_assert(bar, "Bar must not be NULL")) { | ||
211 | return NULL; | ||
212 | } | ||
213 | |||
214 | json_object *json = json_object_new_object(); | ||
215 | json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||
216 | json_object_object_add(json, "tray_output", NULL); | ||
217 | json_object_object_add(json, "mode", json_object_new_string(bar->mode)); | ||
218 | json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); | ||
219 | json_object_object_add(json, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); | ||
220 | switch (bar->position) { | ||
221 | case DESKTOP_SHELL_PANEL_POSITION_TOP: | ||
222 | json_object_object_add(json, "position", json_object_new_string("top")); | ||
223 | break; | ||
224 | case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: | ||
225 | json_object_object_add(json, "position", json_object_new_string("bottom")); | ||
226 | break; | ||
227 | case DESKTOP_SHELL_PANEL_POSITION_LEFT: | ||
228 | json_object_object_add(json, "position", json_object_new_string("left")); | ||
229 | break; | ||
230 | case DESKTOP_SHELL_PANEL_POSITION_RIGHT: | ||
231 | json_object_object_add(json, "position", json_object_new_string("right")); | ||
232 | break; | ||
233 | } | ||
234 | json_object_object_add(json, "status_command", json_object_new_string(bar->status_command)); | ||
235 | json_object_object_add(json, "font", json_object_new_string((bar->font) ? bar->font : config->font)); | ||
236 | if (bar->separator_symbol) { | ||
237 | json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); | ||
238 | } | ||
239 | json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); | ||
240 | json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); | ||
241 | json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); | ||
242 | json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); | ||
243 | json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); | ||
244 | json_object_object_add(json, "pango_markup", json_object_new_boolean(bar->pango_markup)); | ||
245 | |||
246 | json_object *colors = json_object_new_object(); | ||
247 | json_object_object_add(colors, "background", json_object_new_string(bar->colors.background)); | ||
248 | json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline)); | ||
249 | json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator)); | ||
250 | |||
251 | json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border)); | ||
252 | json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg)); | ||
253 | json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text)); | ||
254 | |||
255 | json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border)); | ||
256 | json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg)); | ||
257 | json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text)); | ||
258 | |||
259 | json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border)); | ||
260 | json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg)); | ||
261 | json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text)); | ||
262 | |||
263 | json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||
264 | json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||
265 | json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||
266 | |||
267 | json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border)); | ||
268 | json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg)); | ||
269 | json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text)); | ||
270 | |||
271 | json_object_object_add(json, "colors", colors); | ||
272 | |||
273 | // Add outputs if defined | ||
274 | if (bar->outputs && bar->outputs->length > 0) { | ||
275 | json_object *outputs = json_object_new_array(); | ||
276 | int i; | ||
277 | for (i = 0; i < bar->outputs->length; ++i) { | ||
278 | const char *name = bar->outputs->items[i]; | ||
279 | json_object_array_add(outputs, json_object_new_string(name)); | ||
280 | } | ||
281 | json_object_object_add(json, "outputs", outputs); | ||
282 | } | ||
283 | |||
284 | return json; | ||
285 | } | ||
286 | |||
287 | json_object *ipc_json_describe_container_recursive(swayc_t *c) { | ||
288 | json_object *object = ipc_json_describe_container(c); | ||
289 | int i; | ||
290 | |||
291 | json_object *floating = json_object_new_array(); | ||
292 | if (c->floating && c->floating->length > 0) { | ||
293 | for (i = 0; i < c->floating->length; ++i) { | ||
294 | json_object_array_add(floating, ipc_json_describe_container_recursive(c->floating->items[i])); | ||
295 | } | ||
296 | } | ||
297 | json_object_object_add(object, "floating_nodes", floating); | ||
298 | |||
299 | json_object *children = json_object_new_array(); | ||
300 | if (c->children && c->children->length > 0) { | ||
301 | for (i = 0; i < c->children->length; ++i) { | ||
302 | json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); | ||
303 | } | ||
304 | } | ||
305 | json_object_object_add(object, "nodes", children); | ||
306 | |||
307 | json_object *unmanaged = json_object_new_array(); | ||
308 | if (c->unmanaged && c->unmanaged->length > 0) { | ||
309 | for (i = 0; i < c->unmanaged->length; ++i) { | ||
310 | json_object_array_add(unmanaged, ipc_json_describe_container_recursive(c->unmanaged->items[i])); | ||
311 | } | ||
312 | } | ||
313 | json_object_object_add(object, "unmanaged_nodes", unmanaged); | ||
314 | |||
315 | if (c->type == C_ROOT) { | ||
316 | json_object *scratchpad_json = json_object_new_array(); | ||
317 | if (scratchpad->length > 0) { | ||
318 | for (i = 0; i < scratchpad->length; ++i) { | ||
319 | json_object_array_add(scratchpad_json, ipc_json_describe_container_recursive(scratchpad->items[i])); | ||
320 | } | ||
321 | } | ||
322 | json_object_object_add(object, "scratchpad", scratchpad_json); | ||
323 | } | ||
324 | |||
325 | return object; | ||
326 | } | ||
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 484d7e51..0729bfd5 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -10,10 +10,10 @@ | |||
10 | #include <stdlib.h> | 10 | #include <stdlib.h> |
11 | #include <sys/ioctl.h> | 11 | #include <sys/ioctl.h> |
12 | #include <fcntl.h> | 12 | #include <fcntl.h> |
13 | #include <ctype.h> | ||
14 | #include <json-c/json.h> | 13 | #include <json-c/json.h> |
15 | #include <list.h> | 14 | #include <list.h> |
16 | #include <libinput.h> | 15 | #include <libinput.h> |
16 | #include "ipc-json.h" | ||
17 | #include "ipc-server.h" | 17 | #include "ipc-server.h" |
18 | #include "log.h" | 18 | #include "log.h" |
19 | #include "config.h" | 19 | #include "config.h" |
@@ -53,7 +53,6 @@ void ipc_client_handle_command(struct ipc_client *client); | |||
53 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); | 53 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); |
54 | void ipc_get_workspaces_callback(swayc_t *workspace, void *data); | 54 | void ipc_get_workspaces_callback(swayc_t *workspace, void *data); |
55 | void ipc_get_outputs_callback(swayc_t *container, void *data); | 55 | void ipc_get_outputs_callback(swayc_t *container, void *data); |
56 | json_object *ipc_json_describe_bar_config(struct bar_config *bar); | ||
57 | 56 | ||
58 | void ipc_init(void) { | 57 | void ipc_init(void) { |
59 | ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); | 58 | ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); |
@@ -399,33 +398,21 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
399 | goto exit_cleanup; | 398 | goto exit_cleanup; |
400 | } | 399 | } |
401 | 400 | ||
401 | case IPC_GET_TREE: | ||
402 | { | ||
403 | json_object *tree = ipc_json_describe_container_recursive(&root_container); | ||
404 | const char *json_string = json_object_to_json_string(tree); | ||
405 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | ||
406 | json_object_put(tree); | ||
407 | goto exit_cleanup; | ||
408 | } | ||
409 | |||
402 | case IPC_GET_VERSION: | 410 | case IPC_GET_VERSION: |
403 | { | 411 | { |
404 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE | 412 | json_object *version = ipc_json_get_version(); |
405 | char *full_version = calloc(strlen(SWAY_GIT_VERSION) + strlen(SWAY_GIT_BRANCH) + strlen(SWAY_VERSION_DATE) + 20, 1); | 413 | const char *json_string = json_object_to_json_string(version); |
406 | strcat(full_version, SWAY_GIT_VERSION); | ||
407 | strcat(full_version, " ("); | ||
408 | strcat(full_version, SWAY_VERSION_DATE); | ||
409 | strcat(full_version, ", branch \""); | ||
410 | strcat(full_version, SWAY_GIT_BRANCH); | ||
411 | strcat(full_version, "\")"); | ||
412 | json_object *json = json_object_new_object(); | ||
413 | json_object_object_add(json, "human_readable", json_object_new_string(full_version)); | ||
414 | json_object_object_add(json, "variant", json_object_new_string("sway")); | ||
415 | // Todo once we actually release a version | ||
416 | json_object_object_add(json, "major", json_object_new_int(0)); | ||
417 | json_object_object_add(json, "minor", json_object_new_int(0)); | ||
418 | json_object_object_add(json, "patch", json_object_new_int(1)); | ||
419 | #else | ||
420 | json_object_object_add(json, "human_readable", json_object_new_string("version not found")); | ||
421 | json_object_object_add(json, "major", json_object_new_int(0)); | ||
422 | json_object_object_add(json, "minor", json_object_new_int(0)); | ||
423 | json_object_object_add(json, "patch", json_object_new_int(0)); | ||
424 | #endif | ||
425 | const char *json_string = json_object_to_json_string(json); | ||
426 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 414 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); |
427 | json_object_put(json); // free | 415 | json_object_put(version); // free |
428 | free(full_version); | ||
429 | goto exit_cleanup; | 416 | goto exit_cleanup; |
430 | } | 417 | } |
431 | 418 | ||
@@ -518,137 +505,16 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
518 | return true; | 505 | return true; |
519 | } | 506 | } |
520 | 507 | ||
521 | json_object *ipc_json_describe_workspace(swayc_t *workspace) { | ||
522 | if (!sway_assert(workspace, "Workspace must not be NULL")) { | ||
523 | return NULL; | ||
524 | } | ||
525 | |||
526 | int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1; | ||
527 | json_object *object = json_object_new_object(); | ||
528 | json_object *rect = json_object_new_object(); | ||
529 | json_object_object_add(rect, "x", json_object_new_int((int32_t) workspace->x)); | ||
530 | json_object_object_add(rect, "y", json_object_new_int((int32_t) workspace->y)); | ||
531 | json_object_object_add(rect, "width", json_object_new_int((int32_t) workspace->width)); | ||
532 | json_object_object_add(rect, "height", json_object_new_int((int32_t) workspace->height)); | ||
533 | |||
534 | json_object_object_add(object, "num", json_object_new_int(num)); | ||
535 | json_object_object_add(object, "name", json_object_new_string(workspace->name)); | ||
536 | json_object_object_add(object, "visible", json_object_new_boolean(workspace->visible)); | ||
537 | bool focused = root_container.focused == workspace->parent && workspace->parent->focused == workspace; | ||
538 | json_object_object_add(object, "focused", json_object_new_boolean(focused)); | ||
539 | json_object_object_add(object, "rect", rect); | ||
540 | json_object_object_add(object, "output", json_object_new_string(workspace->parent ? workspace->parent->name : "null")); | ||
541 | json_object_object_add(object, "urgent", json_object_new_boolean(false)); | ||
542 | |||
543 | return object; | ||
544 | } | ||
545 | |||
546 | void ipc_get_workspaces_callback(swayc_t *workspace, void *data) { | 508 | void ipc_get_workspaces_callback(swayc_t *workspace, void *data) { |
547 | if (workspace->type == C_WORKSPACE) { | 509 | if (workspace->type == C_WORKSPACE) { |
548 | json_object_array_add((json_object *)data, ipc_json_describe_workspace(workspace)); | 510 | json_object_array_add((json_object *)data, ipc_json_describe_container(workspace)); |
549 | } | 511 | } |
550 | } | 512 | } |
551 | 513 | ||
552 | json_object *ipc_json_describe_output(swayc_t *output) { | ||
553 | json_object *object = json_object_new_object(); | ||
554 | json_object *rect = json_object_new_object(); | ||
555 | json_object_object_add(rect, "x", json_object_new_int((int32_t) output->x)); | ||
556 | json_object_object_add(rect, "y", json_object_new_int((int32_t) output->y)); | ||
557 | json_object_object_add(rect, "width", json_object_new_int((int32_t) output->width)); | ||
558 | json_object_object_add(rect, "height", json_object_new_int((int32_t) output->height)); | ||
559 | |||
560 | json_object_object_add(object, "name", json_object_new_string(output->name)); | ||
561 | json_object_object_add(object, "active", json_object_new_boolean(true)); | ||
562 | json_object_object_add(object, "primary", json_object_new_boolean(false)); | ||
563 | json_object_object_add(object, "rect", rect); | ||
564 | json_object_object_add(object, "current_workspace", | ||
565 | output->focused ? json_object_new_string(output->focused->name) : NULL); | ||
566 | |||
567 | return object; | ||
568 | } | ||
569 | |||
570 | void ipc_get_outputs_callback(swayc_t *container, void *data) { | 514 | void ipc_get_outputs_callback(swayc_t *container, void *data) { |
571 | if (container->type == C_OUTPUT) { | 515 | if (container->type == C_OUTPUT) { |
572 | json_object_array_add((json_object *)data, ipc_json_describe_output(container)); | 516 | json_object_array_add((json_object *)data, ipc_json_describe_container(container)); |
573 | } | ||
574 | } | ||
575 | |||
576 | json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | ||
577 | if (!sway_assert(bar, "Bar must not be NULL")) { | ||
578 | return NULL; | ||
579 | } | ||
580 | |||
581 | json_object *json = json_object_new_object(); | ||
582 | json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||
583 | json_object_object_add(json, "tray_output", NULL); | ||
584 | json_object_object_add(json, "mode", json_object_new_string(bar->mode)); | ||
585 | json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); | ||
586 | json_object_object_add(json, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); | ||
587 | switch (bar->position) { | ||
588 | case DESKTOP_SHELL_PANEL_POSITION_TOP: | ||
589 | json_object_object_add(json, "position", json_object_new_string("top")); | ||
590 | break; | ||
591 | case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: | ||
592 | json_object_object_add(json, "position", json_object_new_string("bottom")); | ||
593 | break; | ||
594 | case DESKTOP_SHELL_PANEL_POSITION_LEFT: | ||
595 | json_object_object_add(json, "position", json_object_new_string("left")); | ||
596 | break; | ||
597 | case DESKTOP_SHELL_PANEL_POSITION_RIGHT: | ||
598 | json_object_object_add(json, "position", json_object_new_string("right")); | ||
599 | break; | ||
600 | } | ||
601 | json_object_object_add(json, "status_command", json_object_new_string(bar->status_command)); | ||
602 | json_object_object_add(json, "font", json_object_new_string(bar->font ? bar->font : config->font)); | ||
603 | if (bar->separator_symbol) { | ||
604 | json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); | ||
605 | } | ||
606 | json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); | ||
607 | json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); | ||
608 | json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); | ||
609 | json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); | ||
610 | json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); | ||
611 | json_object_object_add(json, "pango_markup", json_object_new_boolean(bar->pango_markup)); | ||
612 | |||
613 | json_object *colors = json_object_new_object(); | ||
614 | json_object_object_add(colors, "background", json_object_new_string(bar->colors.background)); | ||
615 | json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline)); | ||
616 | json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator)); | ||
617 | |||
618 | json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border)); | ||
619 | json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg)); | ||
620 | json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text)); | ||
621 | |||
622 | json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border)); | ||
623 | json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg)); | ||
624 | json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text)); | ||
625 | |||
626 | json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border)); | ||
627 | json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg)); | ||
628 | json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text)); | ||
629 | |||
630 | json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||
631 | json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||
632 | json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||
633 | |||
634 | json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border)); | ||
635 | json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg)); | ||
636 | json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text)); | ||
637 | |||
638 | json_object_object_add(json, "colors", colors); | ||
639 | |||
640 | // Add outputs if defined | ||
641 | if (bar->outputs && bar->outputs->length > 0) { | ||
642 | json_object *outputs = json_object_new_array(); | ||
643 | int i; | ||
644 | for (i = 0; i < bar->outputs->length; ++i) { | ||
645 | const char *name = bar->outputs->items[i]; | ||
646 | json_object_array_add(outputs, json_object_new_string(name)); | ||
647 | } | ||
648 | json_object_object_add(json, "outputs", outputs); | ||
649 | } | 517 | } |
650 | |||
651 | return json; | ||
652 | } | 518 | } |
653 | 519 | ||
654 | void ipc_send_event(const char *json_string, enum ipc_command_type event) { | 520 | void ipc_send_event(const char *json_string, enum ipc_command_type event) { |
@@ -672,14 +538,14 @@ void ipc_event_workspace(swayc_t *old, swayc_t *new, const char *change) { | |||
672 | json_object_object_add(obj, "change", json_object_new_string(change)); | 538 | json_object_object_add(obj, "change", json_object_new_string(change)); |
673 | if (strcmp("focus", change) == 0) { | 539 | if (strcmp("focus", change) == 0) { |
674 | if (old) { | 540 | if (old) { |
675 | json_object_object_add(obj, "old", ipc_json_describe_workspace(old)); | 541 | json_object_object_add(obj, "old", ipc_json_describe_container(old)); |
676 | } else { | 542 | } else { |
677 | json_object_object_add(obj, "old", NULL); | 543 | json_object_object_add(obj, "old", NULL); |
678 | } | 544 | } |
679 | } | 545 | } |
680 | 546 | ||
681 | if (new) { | 547 | if (new) { |
682 | json_object_object_add(obj, "current", ipc_json_describe_workspace(new)); | 548 | json_object_object_add(obj, "current", ipc_json_describe_container(new)); |
683 | } else { | 549 | } else { |
684 | json_object_object_add(obj, "current", NULL); | 550 | json_object_object_add(obj, "current", NULL); |
685 | } | 551 | } |
diff --git a/sway/layout.c b/sway/layout.c index 952bcf1c..27760f35 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -23,6 +23,7 @@ int min_sane_w = 100; | |||
23 | void init_layout(void) { | 23 | void init_layout(void) { |
24 | root_container.type = C_ROOT; | 24 | root_container.type = C_ROOT; |
25 | root_container.layout = L_NONE; | 25 | root_container.layout = L_NONE; |
26 | root_container.name = strdup("root"); | ||
26 | root_container.children = create_list(); | 27 | root_container.children = create_list(); |
27 | root_container.handle = -1; | 28 | root_container.handle = -1; |
28 | root_container.visible = true; | 29 | root_container.visible = true; |