Merge pull request #1387 from lbonn/ipc-work
ipc: various fixes for i3 compat
This commit is contained in:
commit
43161a7e17
|
@ -458,7 +458,11 @@ struct cmd_results *handle_command(char *_exec, enum command_context context) {
|
||||||
if (!containers) {
|
if (!containers) {
|
||||||
current_container = get_focused_container(&root_container);
|
current_container = get_focused_container(&root_container);
|
||||||
} else if (containers->length == 0) {
|
} else if (containers->length == 0) {
|
||||||
break;
|
if (results) {
|
||||||
|
free_cmd_results(results);
|
||||||
|
}
|
||||||
|
results = cmd_results_new(CMD_FAILURE, argv[0], "No matching container");
|
||||||
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
current_container = (swayc_t *)containers->items[i];
|
current_container = (swayc_t *)containers->items[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,12 @@
|
||||||
|
|
||||||
enum criteria_type { // *must* keep in sync with criteria_strings[]
|
enum criteria_type { // *must* keep in sync with criteria_strings[]
|
||||||
CRIT_CLASS,
|
CRIT_CLASS,
|
||||||
|
CRIT_CON_ID,
|
||||||
CRIT_CON_MARK,
|
CRIT_CON_MARK,
|
||||||
|
CRIT_FLOATING,
|
||||||
CRIT_ID,
|
CRIT_ID,
|
||||||
CRIT_INSTANCE,
|
CRIT_INSTANCE,
|
||||||
|
CRIT_TILING,
|
||||||
CRIT_TITLE,
|
CRIT_TITLE,
|
||||||
CRIT_URGENT,
|
CRIT_URGENT,
|
||||||
CRIT_WINDOW_ROLE,
|
CRIT_WINDOW_ROLE,
|
||||||
|
@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
|
||||||
|
|
||||||
static const char * const criteria_strings[CRIT_LAST] = {
|
static const char * const criteria_strings[CRIT_LAST] = {
|
||||||
[CRIT_CLASS] = "class",
|
[CRIT_CLASS] = "class",
|
||||||
|
[CRIT_CON_ID] = "con_id",
|
||||||
[CRIT_CON_MARK] = "con_mark",
|
[CRIT_CON_MARK] = "con_mark",
|
||||||
|
[CRIT_FLOATING] = "floating",
|
||||||
[CRIT_ID] = "id",
|
[CRIT_ID] = "id",
|
||||||
[CRIT_INSTANCE] = "instance",
|
[CRIT_INSTANCE] = "instance",
|
||||||
|
[CRIT_TILING] = "tiling",
|
||||||
[CRIT_TITLE] = "title",
|
[CRIT_TITLE] = "title",
|
||||||
[CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
|
[CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
|
||||||
[CRIT_WINDOW_ROLE] = "window_role",
|
[CRIT_WINDOW_ROLE] = "window_role",
|
||||||
|
@ -108,6 +114,7 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
|
||||||
|
|
||||||
char **argv = *buf = calloc(max_tokens, sizeof(char*));
|
char **argv = *buf = calloc(max_tokens, sizeof(char*));
|
||||||
argv[0] = base; // this needs to be freed by caller
|
argv[0] = base; // this needs to be freed by caller
|
||||||
|
bool quoted = true;
|
||||||
|
|
||||||
*argc = 1; // uneven = name, even = value
|
*argc = 1; // uneven = name, even = value
|
||||||
while (*head && *argc < max_tokens) {
|
while (*head && *argc < max_tokens) {
|
||||||
|
@ -128,7 +135,8 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
|
||||||
if (*(namep) == ' ') {
|
if (*(namep) == ' ') {
|
||||||
namep = strrchr(namep, ' ') + 1;
|
namep = strrchr(namep, ' ') + 1;
|
||||||
}
|
}
|
||||||
argv[(*argc)++] = namep;
|
argv[*argc] = namep;
|
||||||
|
*argc += 1;
|
||||||
}
|
}
|
||||||
} else if (*head == '"') {
|
} else if (*head == '"') {
|
||||||
if (*argc % 2 != 0) {
|
if (*argc % 2 != 0) {
|
||||||
|
@ -137,21 +145,38 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
|
||||||
"Found quoted value where it was not expected");
|
"Found quoted value where it was not expected");
|
||||||
} else if (!valp) { // value starts here
|
} else if (!valp) { // value starts here
|
||||||
valp = head + 1;
|
valp = head + 1;
|
||||||
|
quoted = true;
|
||||||
} else {
|
} else {
|
||||||
// value ends here
|
// value ends here
|
||||||
argv[(*argc)++] = valp;
|
argv[*argc] = valp;
|
||||||
|
*argc += 1;
|
||||||
*head = '\0';
|
*head = '\0';
|
||||||
valp = NULL;
|
valp = NULL;
|
||||||
namep = head + 1;
|
namep = head + 1;
|
||||||
}
|
}
|
||||||
} else if (*argc % 2 == 0 && !valp && *head != ' ') {
|
} else if (*argc % 2 == 0 && *head != ' ') {
|
||||||
// We're expecting a quoted value, haven't found one yet, and this
|
// parse unquoted values
|
||||||
// is not an empty space.
|
if (!valp) {
|
||||||
return strdup("Unable to parse criteria: "
|
quoted = false;
|
||||||
"Names must be unquoted, values must be quoted");
|
valp = head; // value starts here
|
||||||
|
}
|
||||||
|
} else if (valp && !quoted && *head == ' ') {
|
||||||
|
// value ends here
|
||||||
|
argv[*argc] = valp;
|
||||||
|
*argc += 1;
|
||||||
|
*head = '\0';
|
||||||
|
valp = NULL;
|
||||||
|
namep = head + 1;
|
||||||
}
|
}
|
||||||
head++;
|
head++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// catch last unquoted value if needed
|
||||||
|
if (valp && !quoted && !*head) {
|
||||||
|
argv[*argc] = valp;
|
||||||
|
*argc += 1;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +288,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CRIT_CON_ID: {
|
||||||
|
char *endptr;
|
||||||
|
size_t crit_id = strtoul(crit->raw, &endptr, 10);
|
||||||
|
|
||||||
|
if (*endptr == 0 && cont->id == crit_id) {
|
||||||
|
++matches;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CRIT_CON_MARK:
|
case CRIT_CON_MARK:
|
||||||
if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
|
if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
|
||||||
// Make sure it isn't matching the NUL string
|
// Make sure it isn't matching the NUL string
|
||||||
|
@ -271,6 +305,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CRIT_FLOATING:
|
||||||
|
if (cont->is_floating) {
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CRIT_ID:
|
case CRIT_ID:
|
||||||
if (!cont->app_id) {
|
if (!cont->app_id) {
|
||||||
// ignore
|
// ignore
|
||||||
|
@ -290,6 +329,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CRIT_TILING:
|
||||||
|
if (!cont->is_floating) {
|
||||||
|
matches++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CRIT_TITLE:
|
case CRIT_TITLE:
|
||||||
if (!cont->name) {
|
if (!cont->name) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|
|
@ -557,6 +557,8 @@ static void handle_view_destroyed(wlc_handle handle) {
|
||||||
parent->fullscreen = NULL;
|
parent->fullscreen = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipc_event_window(parent, "close");
|
||||||
|
|
||||||
// Destroy empty workspaces
|
// Destroy empty workspaces
|
||||||
if (parent->type == C_WORKSPACE &&
|
if (parent->type == C_WORKSPACE &&
|
||||||
parent->children->length == 0 &&
|
parent->children->length == 0 &&
|
||||||
|
@ -567,7 +569,6 @@ static void handle_view_destroyed(wlc_handle handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
arrange_windows(parent, -1, -1);
|
arrange_windows(parent, -1, -1);
|
||||||
ipc_event_window(parent, "close");
|
|
||||||
} else {
|
} else {
|
||||||
// Is it unmanaged?
|
// Is it unmanaged?
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -138,7 +138,6 @@ static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object)
|
||||||
|
|
||||||
json_object_object_add(object, "num", json_object_new_int(num));
|
json_object_object_add(object, "num", json_object_new_int(num));
|
||||||
json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL);
|
json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL);
|
||||||
json_object_object_add(object, "urgent", json_object_new_boolean(false));
|
|
||||||
json_object_object_add(object, "type", json_object_new_string("workspace"));
|
json_object_object_add(object, "type", json_object_new_string("workspace"));
|
||||||
json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
|
json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
|
||||||
}
|
}
|
||||||
|
@ -156,7 +155,6 @@ static const char *ipc_json_get_scratchpad_state(swayc_t *c) {
|
||||||
|
|
||||||
static void ipc_json_describe_view(swayc_t *c, json_object *object) {
|
static void ipc_json_describe_view(swayc_t *c, json_object *object) {
|
||||||
json_object *props = json_object_new_object();
|
json_object *props = json_object_new_object();
|
||||||
float percent = ipc_json_child_percentage(c);
|
|
||||||
const char *layout = (c->parent->type == C_CONTAINER) ?
|
const char *layout = (c->parent->type == C_CONTAINER) ?
|
||||||
ipc_json_layout_description(c->parent->layout) : "none";
|
ipc_json_layout_description(c->parent->layout) : "none";
|
||||||
const char *last_layout = (c->parent->type == C_CONTAINER) ?
|
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) {
|
||||||
|
|
||||||
json_object_object_add(object, "scratchpad_state",
|
json_object_object_add(object, "scratchpad_state",
|
||||||
json_object_new_string(ipc_json_get_scratchpad_state(c)));
|
json_object_new_string(ipc_json_get_scratchpad_state(c)));
|
||||||
json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL);
|
|
||||||
// TODO: make urgency actually work once Sway supports it
|
|
||||||
json_object_object_add(object, "urgent", json_object_new_boolean(false));
|
|
||||||
json_object_object_add(object, "layout",
|
json_object_object_add(object, "layout",
|
||||||
(strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
|
(strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
|
||||||
json_object_object_add(object, "last_split_layout",
|
json_object_object_add(object, "last_split_layout",
|
||||||
|
@ -177,17 +172,8 @@ static void ipc_json_describe_view(swayc_t *c, json_object *object) {
|
||||||
json_object_object_add(object, "workspace_layout",
|
json_object_object_add(object, "workspace_layout",
|
||||||
json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout)));
|
json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout)));
|
||||||
|
|
||||||
json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c)));
|
|
||||||
json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness));
|
|
||||||
|
|
||||||
json_object_object_add(object, "rect", ipc_json_create_rect(c));
|
|
||||||
json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry));
|
|
||||||
json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry));
|
|
||||||
json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry));
|
|
||||||
|
|
||||||
json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL);
|
json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL);
|
||||||
|
|
||||||
json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat
|
|
||||||
json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) :
|
json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) :
|
||||||
c->app_id ? json_object_new_string(c->app_id) : NULL);
|
c->app_id ? json_object_new_string(c->app_id) : NULL);
|
||||||
json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) :
|
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) {
|
||||||
json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL);
|
json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ipc_json_describe_root(swayc_t *c, json_object *object) {
|
||||||
|
json_object_object_add(object, "type", json_object_new_string("root"));
|
||||||
|
json_object_object_add(object, "layout", json_object_new_string("splith"));
|
||||||
|
}
|
||||||
|
|
||||||
json_object *ipc_json_describe_container(swayc_t *c) {
|
json_object *ipc_json_describe_container(swayc_t *c) {
|
||||||
|
float percent = ipc_json_child_percentage(c);
|
||||||
|
|
||||||
if (!(sway_assert(c, "Container must not be null."))) {
|
if (!(sway_assert(c, "Container must not be null."))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -218,9 +211,19 @@ json_object *ipc_json_describe_container(swayc_t *c) {
|
||||||
json_object_object_add(object, "visible", json_object_new_boolean(c->visible));
|
json_object_object_add(object, "visible", json_object_new_boolean(c->visible));
|
||||||
json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus));
|
json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus));
|
||||||
|
|
||||||
|
json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c)));
|
||||||
|
json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry));
|
||||||
|
json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry));
|
||||||
|
json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry));
|
||||||
|
json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL);
|
||||||
|
json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat
|
||||||
|
// TODO: make urgency actually work once Sway supports it
|
||||||
|
json_object_object_add(object, "urgent", json_object_new_boolean(false));
|
||||||
|
json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness));
|
||||||
|
|
||||||
switch (c->type) {
|
switch (c->type) {
|
||||||
case C_ROOT:
|
case C_ROOT:
|
||||||
json_object_object_add(object, "type", json_object_new_string("root"));
|
ipc_json_describe_root(c, object);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case C_OUTPUT:
|
case C_OUTPUT:
|
||||||
|
@ -451,21 +454,50 @@ json_object *ipc_json_describe_container_recursive(swayc_t *c) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
json_object *floating = json_object_new_array();
|
json_object *floating = json_object_new_array();
|
||||||
if (c->type != C_VIEW && c->floating && c->floating->length > 0) {
|
if (c->type != C_VIEW && c->floating) {
|
||||||
for (i = 0; i < c->floating->length; ++i) {
|
for (i = 0; i < c->floating->length; ++i) {
|
||||||
json_object_array_add(floating, ipc_json_describe_container_recursive(c->floating->items[i]));
|
swayc_t *item = c->floating->items[i];
|
||||||
|
json_object_array_add(floating, ipc_json_describe_container_recursive(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json_object_object_add(object, "floating_nodes", floating);
|
json_object_object_add(object, "floating_nodes", floating);
|
||||||
|
|
||||||
json_object *children = json_object_new_array();
|
json_object *children = json_object_new_array();
|
||||||
if (c->type != C_VIEW && c->children && c->children->length > 0) {
|
if (c->type != C_VIEW && c->children) {
|
||||||
for (i = 0; i < c->children->length; ++i) {
|
for (i = 0; i < c->children->length; ++i) {
|
||||||
json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i]));
|
json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json_object_object_add(object, "nodes", children);
|
json_object_object_add(object, "nodes", children);
|
||||||
|
|
||||||
|
json_object *focus = json_object_new_array();
|
||||||
|
if (c->type != C_VIEW) {
|
||||||
|
if (c->focused) {
|
||||||
|
json_object_array_add(focus, json_object_new_double(c->focused->id));
|
||||||
|
}
|
||||||
|
if (c->floating) {
|
||||||
|
for (i = 0; i < c->floating->length; ++i) {
|
||||||
|
swayc_t *item = c->floating->items[i];
|
||||||
|
if (item == c->focused) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_array_add(focus, json_object_new_double(item->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c->children) {
|
||||||
|
for (i = 0; i < c->children->length; ++i) {
|
||||||
|
swayc_t *item = c->children->items[i];
|
||||||
|
if (item == c->focused) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_array_add(focus, json_object_new_double(item->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
json_object_object_add(object, "focus", focus);
|
||||||
|
|
||||||
if (c->type == C_ROOT) {
|
if (c->type == C_ROOT) {
|
||||||
json_object *scratchpad_json = json_object_new_array();
|
json_object *scratchpad_json = json_object_new_array();
|
||||||
if (scratchpad->length > 0) {
|
if (scratchpad->length > 0) {
|
||||||
|
|
|
@ -792,11 +792,7 @@ void ipc_event_window(swayc_t *window, const char *change) {
|
||||||
sway_log(L_DEBUG, "Sending window::%s event", change);
|
sway_log(L_DEBUG, "Sending window::%s event", change);
|
||||||
json_object *obj = json_object_new_object();
|
json_object *obj = json_object_new_object();
|
||||||
json_object_object_add(obj, "change", json_object_new_string(change));
|
json_object_object_add(obj, "change", json_object_new_string(change));
|
||||||
if (strcmp(change, "close") == 0 || !window) {
|
json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
|
||||||
json_object_object_add(obj, "container", NULL);
|
|
||||||
} else {
|
|
||||||
json_object_object_add(obj, "container", ipc_json_describe_container(window));
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *json_string = json_object_to_json_string(obj);
|
const char *json_string = json_object_to_json_string(obj);
|
||||||
ipc_send_event(json_string, IPC_EVENT_WINDOW);
|
ipc_send_event(json_string, IPC_EVENT_WINDOW);
|
||||||
|
|
Loading…
Reference in a new issue