aboutsummaryrefslogtreecommitdiffstats
path: root/sway/ipc-json.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-30 21:00:10 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-09-05 18:01:43 +1000
commit7586f150c058997d9dde387ea7c091ffa7a3c3c7 (patch)
tree63d19027974c1db62ce3a74ca1d2314eb6d5049b /sway/ipc-json.c
parentMerge pull request #2569 from RyanDwyer/deny-reload-repeat (diff)
downloadsway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.tar.gz
sway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.tar.zst
sway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.zip
Implement type safe arguments and demote sway_container
This commit changes the meaning of sway_container so that it only refers to layout containers and view containers. Workspaces, outputs and the root are no longer known as containers. Instead, root, outputs, workspaces and containers are all a type of node, and containers come in two types: layout containers and view containers. In addition to the above, this implements type safe variables. This means we use specific types such as sway_output and sway_workspace instead of generic containers or nodes. However, it's worth noting that in a few places places (eg. seat focus and transactions) referring to them in a generic way is unavoidable which is why we still use nodes in some places. If you want a TL;DR, look at node.h, as well as the struct definitions for root, output, workspace and container. Note that sway_output now contains a workspaces list, and workspaces now contain a tiling and floating list, and containers now contain a pointer back to the workspace. There are now functions for seat_get_focused_workspace and seat_get_focused_container. The latter will return NULL if a workspace itself is focused. Most other seat functions like seat_get_focus and seat_set_focus now accept and return nodes. In the config->handler_context struct, current_container has been replaced with three pointers: node, container and workspace. node is the same as what current_container was, while workspace is the workspace that the node resides on and container is the actual container, which may be NULL if a workspace itself is focused. The global root_container variable has been replaced with one simply called root, which is a pointer to the sway_root instance. The way outputs are created, enabled, disabled and destroyed has changed. Previously we'd wrap the sway_output in a container when it is enabled, but as we don't have containers any more it needs a different approach. The output_create and output_destroy functions previously created/destroyed the container, but now they create/destroy the sway_output. There is a new function output_disable to disable an output without destroying it. Containers have a new view property. If this is populated then the container is a view container, otherwise it's a layout container. Like before, this property is immutable for the life of the container. Containers have both a `sway_container *parent` and `sway_workspace *workspace`. As we use specific types now, parent cannot point to a workspace so it'll be NULL for containers which are direct children of the workspace. The workspace property is set for all containers, except those which are hidden in the scratchpad as they have no workspace. In some cases we need to refer to workspaces in a container-like way. For example, workspaces have layout and children, but when using specific types this makes it difficult. Likewise, it's difficult for a container to get its parent's layout when the parent could be another container or a workspace. To make it easier, some helper functions have been created: container_parent_layout and container_get_siblings. container_remove_child has been renamed to container_detach and container_replace_child has been renamed to container_replace. `container_handle_fullscreen_reparent(con, old_parent)` has had the old_parent removed. We now unfullscreen the workspace when detaching the container, so this function is simplified and only needs one argument now. container_notify_subtree_changed has been renamed to container_update_representation. This is more descriptive of its purpose. I also wanted to be able to call it with whatever container was changed rather than the container's parent, which makes bubbling up to the workspace easier. There are now state structs per node thing. ie. sway_output_state, sway_workspace_state and sway_container_state. The focus, move and layout commands have been completely refactored to work with the specific types. I considered making these a separate PR, but I'd be backporting my changes only to replace them again, and it's easier just to test everything at once.
Diffstat (limited to 'sway/ipc-json.c')
-rw-r--r--sway/ipc-json.c189
1 files changed, 102 insertions, 87 deletions
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 06cb7e11..9a955991 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -46,18 +46,18 @@ json_object *ipc_json_get_version() {
46 return version; 46 return version;
47} 47}
48 48
49static json_object *ipc_json_create_rect(struct sway_container *c) { 49static json_object *ipc_json_create_rect(struct wlr_box *box) {
50 json_object *rect = json_object_new_object(); 50 json_object *rect = json_object_new_object();
51 51
52 json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); 52 json_object_object_add(rect, "x", json_object_new_int(box->x));
53 json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); 53 json_object_object_add(rect, "y", json_object_new_int(box->y));
54 json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); 54 json_object_object_add(rect, "width", json_object_new_int(box->width));
55 json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); 55 json_object_object_add(rect, "height", json_object_new_int(box->height));
56 56
57 return rect; 57 return rect;
58} 58}
59 59
60static void ipc_json_describe_root(struct sway_container *root, json_object *object) { 60static void ipc_json_describe_root(struct sway_root *root, json_object *object) {
61 json_object_object_add(object, "type", json_object_new_string("root")); 61 json_object_object_add(object, "type", json_object_new_string("root"));
62 json_object_object_add(object, "layout", json_object_new_string("splith")); 62 json_object_object_add(object, "layout", json_object_new_string("splith"));
63} 63}
@@ -84,17 +84,13 @@ static const char *ipc_json_get_output_transform(enum wl_output_transform transf
84 return NULL; 84 return NULL;
85} 85}
86 86
87static void ipc_json_describe_output(struct sway_container *container, 87static void ipc_json_describe_output(struct sway_output *output,
88 json_object *object) { 88 json_object *object) {
89 struct wlr_output *wlr_output = container->sway_output->wlr_output; 89 struct wlr_output *wlr_output = output->wlr_output;
90 json_object_object_add(object, "type", 90 json_object_object_add(object, "type", json_object_new_string("output"));
91 json_object_new_string("output")); 91 json_object_object_add(object, "active", json_object_new_boolean(true));
92 json_object_object_add(object, "active", 92 json_object_object_add(object, "primary", json_object_new_boolean(false));
93 json_object_new_boolean(true)); 93 json_object_object_add(object, "layout", json_object_new_string("output"));
94 json_object_object_add(object, "primary",
95 json_object_new_boolean(false));
96 json_object_object_add(object, "layout",
97 json_object_new_string("output"));
98 json_object_object_add(object, "make", 94 json_object_object_add(object, "make",
99 json_object_new_string(wlr_output->make)); 95 json_object_new_string(wlr_output->make));
100 json_object_object_add(object, "model", 96 json_object_object_add(object, "model",
@@ -109,20 +105,9 @@ static void ipc_json_describe_output(struct sway_container *container,
109 json_object_new_string( 105 json_object_new_string(
110 ipc_json_get_output_transform(wlr_output->transform))); 106 ipc_json_get_output_transform(wlr_output->transform)));
111 107
112 struct sway_seat *seat = input_manager_get_default_seat(input_manager); 108 struct sway_workspace *ws = output_get_active_workspace(output);
113 const char *ws = NULL;
114 if (seat) {
115 struct sway_container *focus =
116 seat_get_focus_inactive(seat, container);
117 if (focus && focus->type != C_WORKSPACE) {
118 focus = container_parent(focus, C_WORKSPACE);
119 }
120 if (focus) {
121 ws = focus->name;
122 }
123 }
124 json_object_object_add(object, "current_workspace", 109 json_object_object_add(object, "current_workspace",
125 json_object_new_string(ws)); 110 json_object_new_string(ws->name));
126 111
127 json_object *modes_array = json_object_new_array(); 112 json_object *modes_array = json_object_new_array();
128 struct wlr_output_mode *mode; 113 struct wlr_output_mode *mode;
@@ -161,60 +146,57 @@ json_object *ipc_json_describe_disabled_output(struct sway_output *output) {
161 return object; 146 return object;
162} 147}
163 148
164static void ipc_json_describe_workspace(struct sway_container *workspace, 149static void ipc_json_describe_workspace(struct sway_workspace *workspace,
165 json_object *object) { 150 json_object *object) {
166 int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1; 151 int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1;
167 152
168 json_object_object_add(object, "num", json_object_new_int(num)); 153 json_object_object_add(object, "num", json_object_new_int(num));
169 json_object_object_add(object, "output", workspace->parent ? 154 json_object_object_add(object, "output", workspace->output ?
170 json_object_new_string(workspace->parent->name) : NULL); 155 json_object_new_string(workspace->output->wlr_output->name) : NULL);
171 json_object_object_add(object, "type", json_object_new_string("workspace")); 156 json_object_object_add(object, "type", json_object_new_string("workspace"));
172 json_object_object_add(object, "urgent", 157 json_object_object_add(object, "urgent",
173 json_object_new_boolean(workspace->sway_workspace->urgent)); 158 json_object_new_boolean(workspace->urgent));
174 json_object_object_add(object, "representation", workspace->formatted_title ? 159 json_object_object_add(object, "representation", workspace->representation ?
175 json_object_new_string(workspace->formatted_title) : NULL); 160 json_object_new_string(workspace->representation) : NULL);
176 161
177 const char *layout = ipc_json_layout_description(workspace->layout); 162 const char *layout = ipc_json_layout_description(workspace->layout);
178 json_object_object_add(object, "layout", json_object_new_string(layout)); 163 json_object_object_add(object, "layout", json_object_new_string(layout));
179 164
180 // Floating 165 // Floating
181 json_object *floating_array = json_object_new_array(); 166 json_object *floating_array = json_object_new_array();
182 list_t *floating = workspace->sway_workspace->floating; 167 for (int i = 0; i < workspace->floating->length; ++i) {
183 for (int i = 0; i < floating->length; ++i) { 168 struct sway_container *floater = workspace->floating->items[i];
184 struct sway_container *floater = floating->items[i];
185 json_object_array_add(floating_array, 169 json_object_array_add(floating_array,
186 ipc_json_describe_container_recursive(floater)); 170 ipc_json_describe_node_recursive(&floater->node));
187 } 171 }
188 json_object_object_add(object, "floating_nodes", floating_array); 172 json_object_object_add(object, "floating_nodes", floating_array);
189} 173}
190 174
191static void ipc_json_describe_view(struct sway_container *c, json_object *object) { 175static void ipc_json_describe_view(struct sway_container *c, json_object *object) {
192 json_object_object_add(object, "name", 176 json_object_object_add(object, "name",
193 c->name ? json_object_new_string(c->name) : NULL); 177 c->title ? json_object_new_string(c->title) : NULL);
194 json_object_object_add(object, "type", json_object_new_string("con")); 178 json_object_object_add(object, "type", json_object_new_string("con"));
195 179
196 if (c->type == C_VIEW) { 180 if (c->view) {
197 const char *app_id = view_get_app_id(c->sway_view); 181 const char *app_id = view_get_app_id(c->view);
198 json_object_object_add(object, "app_id", 182 json_object_object_add(object, "app_id",
199 app_id ? json_object_new_string(app_id) : NULL); 183 app_id ? json_object_new_string(app_id) : NULL);
200 184
201 const char *class = view_get_class(c->sway_view); 185 const char *class = view_get_class(c->view);
202 json_object_object_add(object, "class", 186 json_object_object_add(object, "class",
203 class ? json_object_new_string(class) : NULL); 187 class ? json_object_new_string(class) : NULL);
204 } 188 }
205 189
206 if (c->parent) { 190 json_object_object_add(object, "layout",
207 json_object_object_add(object, "layout", 191 json_object_new_string(ipc_json_layout_description(c->layout)));
208 json_object_new_string(ipc_json_layout_description(c->layout)));
209 }
210 192
211 bool urgent = c->type == C_VIEW ? 193 bool urgent = c->view ?
212 view_is_urgent(c->sway_view) : container_has_urgent_child(c); 194 view_is_urgent(c->view) : container_has_urgent_child(c);
213 json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); 195 json_object_object_add(object, "urgent", json_object_new_boolean(urgent));
214 196
215 if (c->type == C_VIEW) { 197 if (c->view) {
216 json_object *marks = json_object_new_array(); 198 json_object *marks = json_object_new_array();
217 list_t *view_marks = c->sway_view->marks; 199 list_t *view_marks = c->view->marks;
218 for (int i = 0; i < view_marks->length; ++i) { 200 for (int i = 0; i < view_marks->length; ++i) {
219 json_object_array_add(marks, json_object_new_string(view_marks->items[i])); 201 json_object_array_add(marks, json_object_new_string(view_marks->items[i]));
220 } 202 }
@@ -222,64 +204,97 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
222 } 204 }
223} 205}
224 206
225static void focus_inactive_children_iterator(struct sway_container *c, void *data) { 207struct focus_inactive_data {
226 json_object *focus = data; 208 struct sway_node *node;
227 json_object_array_add(focus, json_object_new_int(c->id)); 209 json_object *object;
228} 210};
229 211
230json_object *ipc_json_describe_container(struct sway_container *c) { 212static void focus_inactive_children_iterator(struct sway_node *node,
231 if (!(sway_assert(c, "Container must not be null."))) { 213 void *_data) {
232 return NULL; 214 struct focus_inactive_data *data = _data;
215 if (node_get_parent(node) == data->node) {
216 json_object_array_add(data->object, json_object_new_int(node->id));
233 } 217 }
218}
234 219
220json_object *ipc_json_describe_node(struct sway_node *node) {
235 struct sway_seat *seat = input_manager_get_default_seat(input_manager); 221 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
236 bool focused = seat_get_focus(seat) == c; 222 bool focused = seat_get_focus(seat) == node;
237 223
238 json_object *object = json_object_new_object(); 224 json_object *object = json_object_new_object();
225 char *name = node_get_name(node);
239 226
240 json_object_object_add(object, "id", json_object_new_int((int)c->id)); 227 struct wlr_box box;
228 node_get_box(node, &box);
229 json_object_object_add(object, "id", json_object_new_int((int)node->id));
241 json_object_object_add(object, "name", 230 json_object_object_add(object, "name",
242 c->name ? json_object_new_string(c->name) : NULL); 231 name ? json_object_new_string(name) : NULL);
243 json_object_object_add(object, "rect", ipc_json_create_rect(c)); 232 json_object_object_add(object, "rect", ipc_json_create_rect(&box));
244 json_object_object_add(object, "focused", 233 json_object_object_add(object, "focused", json_object_new_boolean(focused));
245 json_object_new_boolean(focused));
246 234
247 json_object *focus = json_object_new_array(); 235 json_object *focus = json_object_new_array();
248 seat_focus_inactive_children_for_each(seat, c, 236 struct focus_inactive_data data = {
249 focus_inactive_children_iterator, focus); 237 .node = node,
238 .object = focus,
239 };
240 seat_for_each_node(seat, focus_inactive_children_iterator, &data);
250 json_object_object_add(object, "focus", focus); 241 json_object_object_add(object, "focus", focus);
251 242
252 switch (c->type) { 243 switch (node->type) {
253 case C_ROOT: 244 case N_ROOT:
254 ipc_json_describe_root(c, object); 245 ipc_json_describe_root(root, object);
255 break; 246 break;
256 case C_OUTPUT: 247 case N_OUTPUT:
257 ipc_json_describe_output(c, object); 248 ipc_json_describe_output(node->sway_output, object);
258 break; 249 break;
259 case C_CONTAINER: 250 case N_CONTAINER:
260 case C_VIEW: 251 ipc_json_describe_view(node->sway_container, object);
261 ipc_json_describe_view(c, object);
262 break; 252 break;
263 case C_WORKSPACE: 253 case N_WORKSPACE:
264 ipc_json_describe_workspace(c, object); 254 ipc_json_describe_workspace(node->sway_workspace, object);
265 break;
266 case C_TYPES:
267 default:
268 break; 255 break;
269 } 256 }
270 257
271 return object; 258 return object;
272} 259}
273 260
274json_object *ipc_json_describe_container_recursive(struct sway_container *c) { 261json_object *ipc_json_describe_node_recursive(struct sway_node *node) {
275 json_object *object = ipc_json_describe_container(c); 262 json_object *object = ipc_json_describe_node(node);
276 int i; 263 int i;
277 264
278 json_object *children = json_object_new_array(); 265 json_object *children = json_object_new_array();
279 if (c->type != C_VIEW && c->children) { 266 switch (node->type) {
280 for (i = 0; i < c->children->length; ++i) { 267 case N_ROOT:
281 json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); 268 for (i = 0; i < root->outputs->length; ++i) {
269 struct sway_output *output = root->outputs->items[i];
270 json_object_array_add(children,
271 ipc_json_describe_node_recursive(&output->node));
272 }
273 break;
274 case N_OUTPUT:
275 for (i = 0; i < node->sway_output->workspaces->length; ++i) {
276 struct sway_workspace *ws = node->sway_output->workspaces->items[i];
277 json_object_array_add(children,
278 ipc_json_describe_node_recursive(&ws->node));
282 } 279 }
280 break;
281 case N_WORKSPACE:
282 for (i = 0; i < node->sway_workspace->tiling->length; ++i) {
283 struct sway_container *con = node->sway_workspace->tiling->items[i];
284 json_object_array_add(children,
285 ipc_json_describe_node_recursive(&con->node));
286 }
287 break;
288 case N_CONTAINER:
289 if (node->sway_container->children) {
290 for (i = 0; i < node->sway_container->children->length; ++i) {
291 struct sway_container *child =
292 node->sway_container->children->items[i];
293 json_object_array_add(children,
294 ipc_json_describe_node_recursive(&child->node));
295 }
296 }
297 break;
283 } 298 }
284 json_object_object_add(object, "nodes", children); 299 json_object_object_add(object, "nodes", children);
285 300
@@ -329,7 +344,7 @@ json_object *ipc_json_describe_seat(struct sway_seat *seat) {
329 } 344 }
330 345
331 json_object *object = json_object_new_object(); 346 json_object *object = json_object_new_object();
332 struct sway_container *focus = seat_get_focus(seat); 347 struct sway_node *focus = seat_get_focus(seat);
333 348
334 json_object_object_add(object, "name", 349 json_object_object_add(object, "name",
335 json_object_new_string(seat->wlr_seat->name)); 350 json_object_new_string(seat->wlr_seat->name));
@@ -470,13 +485,13 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) {
470 json_object_object_add(json, "colors", colors); 485 json_object_object_add(json, "colors", colors);
471 486
472 // Add outputs if defined 487 // Add outputs if defined
488 json_object *outputs = json_object_new_array();
473 if (bar->outputs && bar->outputs->length > 0) { 489 if (bar->outputs && bar->outputs->length > 0) {
474 json_object *outputs = json_object_new_array();
475 for (int i = 0; i < bar->outputs->length; ++i) { 490 for (int i = 0; i < bar->outputs->length; ++i) {
476 const char *name = bar->outputs->items[i]; 491 const char *name = bar->outputs->items[i];
477 json_object_array_add(outputs, json_object_new_string(name)); 492 json_object_array_add(outputs, json_object_new_string(name));
478 } 493 }
479 json_object_object_add(json, "outputs", outputs);
480 } 494 }
495 json_object_object_add(json, "outputs", outputs);
481 return json; 496 return json;
482} 497}