aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-10-08 10:02:52 -0400
committerLibravatar GitHub <noreply@github.com>2017-10-08 10:02:52 -0400
commit43161a7e178b59b6bff3f210f46e21e8bf67e066 (patch)
tree8550777f6cffe2f692831b5edb77c45c2867adc5
parentMerge pull request #1385 from lbonn/sec-no-hidden (diff)
parentipc/window-event: fill "container" on close events (diff)
downloadsway-43161a7e178b59b6bff3f210f46e21e8bf67e066.tar.gz
sway-43161a7e178b59b6bff3f210f46e21e8bf67e066.tar.zst
sway-43161a7e178b59b6bff3f210f46e21e8bf67e066.zip
Merge pull request #1387 from lbonn/ipc-work
ipc: various fixes for i3 compat
-rw-r--r--sway/commands.c6
-rw-r--r--sway/criteria.c58
-rw-r--r--sway/handlers.c3
-rw-r--r--sway/ipc-json.c68
-rw-r--r--sway/ipc-server.c6
5 files changed, 109 insertions, 32 deletions
diff --git a/sway/commands.c b/sway/commands.c
index d55d9a96..c7dbf731 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -458,7 +458,11 @@ struct cmd_results *handle_command(char *_exec, enum command_context context) {
458 if (!containers) { 458 if (!containers) {
459 current_container = get_focused_container(&root_container); 459 current_container = get_focused_container(&root_container);
460 } else if (containers->length == 0) { 460 } else if (containers->length == 0) {
461 break; 461 if (results) {
462 free_cmd_results(results);
463 }
464 results = cmd_results_new(CMD_FAILURE, argv[0], "No matching container");
465 goto cleanup;
462 } else { 466 } else {
463 current_container = (swayc_t *)containers->items[i]; 467 current_container = (swayc_t *)containers->items[i];
464 } 468 }
diff --git a/sway/criteria.c b/sway/criteria.c
index 04683f66..f5fe40cb 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -12,9 +12,12 @@
12 12
13enum criteria_type { // *must* keep in sync with criteria_strings[] 13enum criteria_type { // *must* keep in sync with criteria_strings[]
14 CRIT_CLASS, 14 CRIT_CLASS,
15 CRIT_CON_ID,
15 CRIT_CON_MARK, 16 CRIT_CON_MARK,
17 CRIT_FLOATING,
16 CRIT_ID, 18 CRIT_ID,
17 CRIT_INSTANCE, 19 CRIT_INSTANCE,
20 CRIT_TILING,
18 CRIT_TITLE, 21 CRIT_TITLE,
19 CRIT_URGENT, 22 CRIT_URGENT,
20 CRIT_WINDOW_ROLE, 23 CRIT_WINDOW_ROLE,
@@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
25 28
26static const char * const criteria_strings[CRIT_LAST] = { 29static const char * const criteria_strings[CRIT_LAST] = {
27 [CRIT_CLASS] = "class", 30 [CRIT_CLASS] = "class",
31 [CRIT_CON_ID] = "con_id",
28 [CRIT_CON_MARK] = "con_mark", 32 [CRIT_CON_MARK] = "con_mark",
33 [CRIT_FLOATING] = "floating",
29 [CRIT_ID] = "id", 34 [CRIT_ID] = "id",
30 [CRIT_INSTANCE] = "instance", 35 [CRIT_INSTANCE] = "instance",
36 [CRIT_TILING] = "tiling",
31 [CRIT_TITLE] = "title", 37 [CRIT_TITLE] = "title",
32 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... 38 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
33 [CRIT_WINDOW_ROLE] = "window_role", 39 [CRIT_WINDOW_ROLE] = "window_role",
@@ -108,6 +114,7 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
108 114
109 char **argv = *buf = calloc(max_tokens, sizeof(char*)); 115 char **argv = *buf = calloc(max_tokens, sizeof(char*));
110 argv[0] = base; // this needs to be freed by caller 116 argv[0] = base; // this needs to be freed by caller
117 bool quoted = true;
111 118
112 *argc = 1; // uneven = name, even = value 119 *argc = 1; // uneven = name, even = value
113 while (*head && *argc < max_tokens) { 120 while (*head && *argc < max_tokens) {
@@ -128,7 +135,8 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
128 if (*(namep) == ' ') { 135 if (*(namep) == ' ') {
129 namep = strrchr(namep, ' ') + 1; 136 namep = strrchr(namep, ' ') + 1;
130 } 137 }
131 argv[(*argc)++] = namep; 138 argv[*argc] = namep;
139 *argc += 1;
132 } 140 }
133 } else if (*head == '"') { 141 } else if (*head == '"') {
134 if (*argc % 2 != 0) { 142 if (*argc % 2 != 0) {
@@ -137,21 +145,38 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
137 "Found quoted value where it was not expected"); 145 "Found quoted value where it was not expected");
138 } else if (!valp) { // value starts here 146 } else if (!valp) { // value starts here
139 valp = head + 1; 147 valp = head + 1;
148 quoted = true;
140 } else { 149 } else {
141 // value ends here 150 // value ends here
142 argv[(*argc)++] = valp; 151 argv[*argc] = valp;
152 *argc += 1;
143 *head = '\0'; 153 *head = '\0';
144 valp = NULL; 154 valp = NULL;
145 namep = head + 1; 155 namep = head + 1;
146 } 156 }
147 } else if (*argc % 2 == 0 && !valp && *head != ' ') { 157 } else if (*argc % 2 == 0 && *head != ' ') {
148 // We're expecting a quoted value, haven't found one yet, and this 158 // parse unquoted values
149 // is not an empty space. 159 if (!valp) {
150 return strdup("Unable to parse criteria: " 160 quoted = false;
151 "Names must be unquoted, values must be quoted"); 161 valp = head; // value starts here
162 }
163 } else if (valp && !quoted && *head == ' ') {
164 // value ends here
165 argv[*argc] = valp;
166 *argc += 1;
167 *head = '\0';
168 valp = NULL;
169 namep = head + 1;
152 } 170 }
153 head++; 171 head++;
154 } 172 }
173
174 // catch last unquoted value if needed
175 if (valp && !quoted && !*head) {
176 argv[*argc] = valp;
177 *argc += 1;
178 }
179
155 return NULL; 180 return NULL;
156} 181}
157 182
@@ -263,6 +288,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
263 matches++; 288 matches++;
264 } 289 }
265 break; 290 break;
291 case CRIT_CON_ID: {
292 char *endptr;
293 size_t crit_id = strtoul(crit->raw, &endptr, 10);
294
295 if (*endptr == 0 && cont->id == crit_id) {
296 ++matches;
297 }
298 break;
299 }
266 case CRIT_CON_MARK: 300 case CRIT_CON_MARK:
267 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { 301 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
268 // Make sure it isn't matching the NUL string 302 // Make sure it isn't matching the NUL string
@@ -271,6 +305,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
271 } 305 }
272 } 306 }
273 break; 307 break;
308 case CRIT_FLOATING:
309 if (cont->is_floating) {
310 matches++;
311 }
312 break;
274 case CRIT_ID: 313 case CRIT_ID:
275 if (!cont->app_id) { 314 if (!cont->app_id) {
276 // ignore 315 // ignore
@@ -290,6 +329,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
290 matches++; 329 matches++;
291 } 330 }
292 break; 331 break;
332 case CRIT_TILING:
333 if (!cont->is_floating) {
334 matches++;
335 }
336 break;
293 case CRIT_TITLE: 337 case CRIT_TITLE:
294 if (!cont->name) { 338 if (!cont->name) {
295 // ignore 339 // ignore
diff --git a/sway/handlers.c b/sway/handlers.c
index 4a2298cd..db0c5e24 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -557,6 +557,8 @@ static void handle_view_destroyed(wlc_handle handle) {
557 parent->fullscreen = NULL; 557 parent->fullscreen = NULL;
558 } 558 }
559 559
560 ipc_event_window(parent, "close");
561
560 // Destroy empty workspaces 562 // Destroy empty workspaces
561 if (parent->type == C_WORKSPACE && 563 if (parent->type == C_WORKSPACE &&
562 parent->children->length == 0 && 564 parent->children->length == 0 &&
@@ -567,7 +569,6 @@ static void handle_view_destroyed(wlc_handle handle) {
567 } 569 }
568 570
569 arrange_windows(parent, -1, -1); 571 arrange_windows(parent, -1, -1);
570 ipc_event_window(parent, "close");
571 } else { 572 } else {
572 // Is it unmanaged? 573 // Is it unmanaged?
573 int i; 574 int i;
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 31de53f0..94768aa4 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -138,7 +138,6 @@ static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object)
138 138
139 json_object_object_add(object, "num", json_object_new_int(num)); 139 json_object_object_add(object, "num", json_object_new_int(num));
140 json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); 140 json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL);
141 json_object_object_add(object, "urgent", json_object_new_boolean(false));
142 json_object_object_add(object, "type", json_object_new_string("workspace")); 141 json_object_object_add(object, "type", json_object_new_string("workspace"));
143 json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); 142 json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
144} 143}
@@ -156,7 +155,6 @@ static const char *ipc_json_get_scratchpad_state(swayc_t *c) {
156 155
157static void ipc_json_describe_view(swayc_t *c, json_object *object) { 156static void ipc_json_describe_view(swayc_t *c, json_object *object) {
158 json_object *props = json_object_new_object(); 157 json_object *props = json_object_new_object();
159 float percent = ipc_json_child_percentage(c);
160 const char *layout = (c->parent->type == C_CONTAINER) ? 158 const char *layout = (c->parent->type == C_CONTAINER) ?
161 ipc_json_layout_description(c->parent->layout) : "none"; 159 ipc_json_layout_description(c->parent->layout) : "none";
162 const char *last_layout = (c->parent->type == C_CONTAINER) ? 160 const char *last_layout = (c->parent->type == C_CONTAINER) ?
@@ -167,9 +165,6 @@ static void ipc_json_describe_view(swayc_t *c, json_object *object) {
167 165
168 json_object_object_add(object, "scratchpad_state", 166 json_object_object_add(object, "scratchpad_state",
169 json_object_new_string(ipc_json_get_scratchpad_state(c))); 167 json_object_new_string(ipc_json_get_scratchpad_state(c)));
170 json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL);
171 // TODO: make urgency actually work once Sway supports it
172 json_object_object_add(object, "urgent", json_object_new_boolean(false));
173 json_object_object_add(object, "layout", 168 json_object_object_add(object, "layout",
174 (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); 169 (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
175 json_object_object_add(object, "last_split_layout", 170 json_object_object_add(object, "last_split_layout",
@@ -177,17 +172,8 @@ static void ipc_json_describe_view(swayc_t *c, json_object *object) {
177 json_object_object_add(object, "workspace_layout", 172 json_object_object_add(object, "workspace_layout",
178 json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout))); 173 json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout)));
179 174
180 json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c)));
181 json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness));
182
183 json_object_object_add(object, "rect", ipc_json_create_rect(c));
184 json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry));
185 json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry));
186 json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry));
187
188 json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); 175 json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL);
189 176
190 json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat
191 json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) : 177 json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) :
192 c->app_id ? json_object_new_string(c->app_id) : NULL); 178 c->app_id ? json_object_new_string(c->app_id) : NULL);
193 json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) : 179 json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) :
@@ -205,7 +191,14 @@ static void ipc_json_describe_view(swayc_t *c, json_object *object) {
205 json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL); 191 json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL);
206} 192}
207 193
194static void ipc_json_describe_root(swayc_t *c, json_object *object) {
195 json_object_object_add(object, "type", json_object_new_string("root"));
196 json_object_object_add(object, "layout", json_object_new_string("splith"));
197}
198
208json_object *ipc_json_describe_container(swayc_t *c) { 199json_object *ipc_json_describe_container(swayc_t *c) {
200 float percent = ipc_json_child_percentage(c);
201
209 if (!(sway_assert(c, "Container must not be null."))) { 202 if (!(sway_assert(c, "Container must not be null."))) {
210 return NULL; 203 return NULL;
211 } 204 }
@@ -218,9 +211,19 @@ json_object *ipc_json_describe_container(swayc_t *c) {
218 json_object_object_add(object, "visible", json_object_new_boolean(c->visible)); 211 json_object_object_add(object, "visible", json_object_new_boolean(c->visible));
219 json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus)); 212 json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus));
220 213
214 json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c)));
215 json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry));
216 json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry));
217 json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry));
218 json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL);
219 json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat
220 // TODO: make urgency actually work once Sway supports it
221 json_object_object_add(object, "urgent", json_object_new_boolean(false));
222 json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness));
223
221 switch (c->type) { 224 switch (c->type) {
222 case C_ROOT: 225 case C_ROOT:
223 json_object_object_add(object, "type", json_object_new_string("root")); 226 ipc_json_describe_root(c, object);
224 break; 227 break;
225 228
226 case C_OUTPUT: 229 case C_OUTPUT:
@@ -451,21 +454,50 @@ json_object *ipc_json_describe_container_recursive(swayc_t *c) {
451 int i; 454 int i;
452 455
453 json_object *floating = json_object_new_array(); 456 json_object *floating = json_object_new_array();
454 if (c->type != C_VIEW && c->floating && c->floating->length > 0) { 457 if (c->type != C_VIEW && c->floating) {
455 for (i = 0; i < c->floating->length; ++i) { 458 for (i = 0; i < c->floating->length; ++i) {
456 json_object_array_add(floating, ipc_json_describe_container_recursive(c->floating->items[i])); 459 swayc_t *item = c->floating->items[i];
460 json_object_array_add(floating, ipc_json_describe_container_recursive(item));
457 } 461 }
458 } 462 }
459 json_object_object_add(object, "floating_nodes", floating); 463 json_object_object_add(object, "floating_nodes", floating);
460 464
461 json_object *children = json_object_new_array(); 465 json_object *children = json_object_new_array();
462 if (c->type != C_VIEW && c->children && c->children->length > 0) { 466 if (c->type != C_VIEW && c->children) {
463 for (i = 0; i < c->children->length; ++i) { 467 for (i = 0; i < c->children->length; ++i) {
464 json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); 468 json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i]));
465 } 469 }
466 } 470 }
467 json_object_object_add(object, "nodes", children); 471 json_object_object_add(object, "nodes", children);
468 472
473 json_object *focus = json_object_new_array();
474 if (c->type != C_VIEW) {
475 if (c->focused) {
476 json_object_array_add(focus, json_object_new_double(c->focused->id));
477 }
478 if (c->floating) {
479 for (i = 0; i < c->floating->length; ++i) {
480 swayc_t *item = c->floating->items[i];
481 if (item == c->focused) {
482 continue;
483 }
484
485 json_object_array_add(focus, json_object_new_double(item->id));
486 }
487 }
488 if (c->children) {
489 for (i = 0; i < c->children->length; ++i) {
490 swayc_t *item = c->children->items[i];
491 if (item == c->focused) {
492 continue;
493 }
494
495 json_object_array_add(focus, json_object_new_double(item->id));
496 }
497 }
498 }
499 json_object_object_add(object, "focus", focus);
500
469 if (c->type == C_ROOT) { 501 if (c->type == C_ROOT) {
470 json_object *scratchpad_json = json_object_new_array(); 502 json_object *scratchpad_json = json_object_new_array();
471 if (scratchpad->length > 0) { 503 if (scratchpad->length > 0) {
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 26d0be65..9122d548 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -792,11 +792,7 @@ void ipc_event_window(swayc_t *window, const char *change) {
792 sway_log(L_DEBUG, "Sending window::%s event", change); 792 sway_log(L_DEBUG, "Sending window::%s event", change);
793 json_object *obj = json_object_new_object(); 793 json_object *obj = json_object_new_object();
794 json_object_object_add(obj, "change", json_object_new_string(change)); 794 json_object_object_add(obj, "change", json_object_new_string(change));
795 if (strcmp(change, "close") == 0 || !window) { 795 json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
796 json_object_object_add(obj, "container", NULL);
797 } else {
798 json_object_object_add(obj, "container", ipc_json_describe_container(window));
799 }
800 796
801 const char *json_string = json_object_to_json_string(obj); 797 const char *json_string = json_object_to_json_string(obj);
802 ipc_send_event(json_string, IPC_EVENT_WINDOW); 798 ipc_send_event(json_string, IPC_EVENT_WINDOW);