ipc: add function hooks to ipc_json_describe_node*

This makes it easier to have an alternative json output for
compatibility purposes, and is preparative work for serving
a mimicked i3 output on I3SOCK.

Signed-off-by: Franklin "Snaipe" Mathieu <me@snai.pe>
This commit is contained in:
Franklin "Snaipe" Mathieu 2018-10-28 16:37:33 +00:00
parent 91c1a52595
commit 822b5897ad
6 changed files with 107 additions and 77 deletions

View file

@ -4,16 +4,27 @@
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
typedef void (*ipc_json_descriptor)(struct sway_node *, json_object *);
typedef ipc_json_descriptor ipc_json_descriptor_map[NUM_NODE_TYPES];
json_object *ipc_json_success(void); json_object *ipc_json_success(void);
json_object *ipc_json_failure(const char *error); json_object *ipc_json_failure(const char *error);
json_object *ipc_json_get_version(void); json_object *ipc_json_get_version(void);
json_object *ipc_json_describe_disabled_output(struct sway_output *o); json_object *ipc_json_describe_disabled_output(struct sway_output *o);
json_object *ipc_json_describe_node(struct sway_node *node); json_object *ipc_json_describe_node(struct sway_node *node,
json_object *ipc_json_describe_node_recursive(struct sway_node *node); const ipc_json_descriptor_map *desc);
json_object *ipc_json_describe_node_recursive(struct sway_node *node,
const ipc_json_descriptor_map *desc);
json_object *ipc_json_describe_input(struct sway_input_device *device); json_object *ipc_json_describe_input(struct sway_input_device *device);
json_object *ipc_json_describe_seat(struct sway_seat *seat); json_object *ipc_json_describe_seat(struct sway_seat *seat);
json_object *ipc_json_describe_bar_config(struct bar_config *bar); json_object *ipc_json_describe_bar_config(struct bar_config *bar);
void ipc_json_describe_container(struct sway_container *c, json_object *object);
void ipc_json_describe_view_common(struct sway_container *c, json_object *object);
void ipc_json_describe_output(struct sway_node *node, json_object *object);
void ipc_json_describe_root(struct sway_node *node, json_object *object);
void ipc_json_describe_workspace(struct sway_node *node, json_object *object);
#endif #endif

View file

@ -31,4 +31,6 @@ json_object *ipc_sway_send_tick(struct ipc_client *client,
json_object *ipc_sway_subscribe(struct ipc_client *client, json_object *ipc_sway_subscribe(struct ipc_client *client,
enum ipc_command_type *type, char *buf); enum ipc_command_type *type, char *buf);
extern const ipc_json_descriptor_map ipc_json_sway_descriptors;
#endif #endif

View file

@ -17,6 +17,8 @@ enum sway_node_type {
N_CONTAINER, N_CONTAINER,
}; };
#define NUM_NODE_TYPES ((size_t)(N_CONTAINER + 1))
struct sway_node { struct sway_node {
enum sway_node_type type; enum sway_node_type type;
union { union {

View file

@ -6,6 +6,7 @@
#include "log.h" #include "log.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/ipc-json.h" #include "sway/ipc-json.h"
#include "sway/ipc-sway.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
@ -168,12 +169,13 @@ static json_object *ipc_json_create_node(int id, char *name,
return object; return object;
} }
static void ipc_json_describe_root(struct sway_root *root, json_object *object) { void ipc_json_describe_root(struct sway_node *node, json_object *object) {
json_object_object_add(object, "type", json_object_new_string("root")); json_object_object_add(object, "type", json_object_new_string("root"));
} }
static void ipc_json_describe_output(struct sway_output *output, void ipc_json_describe_output(struct sway_node *node,
json_object *object) { json_object *object) {
struct sway_output *output = node->sway_output;
struct wlr_output *wlr_output = output->wlr_output; struct wlr_output *wlr_output = output->wlr_output;
json_object_object_add(object, "type", json_object_new_string("output")); json_object_object_add(object, "type", json_object_new_string("output"));
json_object_object_add(object, "active", json_object_new_boolean(true)); json_object_object_add(object, "active", json_object_new_boolean(true));
@ -308,7 +310,8 @@ static json_object *ipc_json_describe_scratchpad_output(void) {
struct sway_container *container = root->scratchpad->items[i]; struct sway_container *container = root->scratchpad->items[i];
if (container_is_scratchpad_hidden(container)) { if (container_is_scratchpad_hidden(container)) {
json_object_array_add(floating_array, json_object_array_add(floating_array,
ipc_json_describe_node_recursive(&container->node)); ipc_json_describe_node_recursive(&container->node,
&ipc_json_sway_descriptors));
} }
} }
json_object_object_add(workspace, "floating_nodes", floating_array); json_object_object_add(workspace, "floating_nodes", floating_array);
@ -331,8 +334,9 @@ static json_object *ipc_json_describe_scratchpad_output(void) {
return output; return output;
} }
static void ipc_json_describe_workspace(struct sway_workspace *workspace, void ipc_json_describe_workspace(struct sway_node *node,
json_object *object) { json_object *object) {
struct sway_workspace *workspace = node->sway_workspace;
int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1; int num = isdigit(workspace->name[0]) ? atoi(workspace->name) : -1;
json_object_object_add(object, "num", json_object_new_int(num)); json_object_object_add(object, "num", json_object_new_int(num));
@ -356,7 +360,8 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace,
for (int i = 0; i < workspace->floating->length; ++i) { for (int i = 0; i < workspace->floating->length; ++i) {
struct sway_container *floater = workspace->floating->items[i]; struct sway_container *floater = workspace->floating->items[i];
json_object_array_add(floating_array, json_object_array_add(floating_array,
ipc_json_describe_node_recursive(&floater->node)); ipc_json_describe_node_recursive(&floater->node,
&ipc_json_sway_descriptors));
} }
json_object_object_add(object, "floating_nodes", floating_array); json_object_object_add(object, "floating_nodes", floating_array);
} }
@ -398,13 +403,9 @@ static void get_deco_rect(struct sway_container *c, struct wlr_box *deco_rect) {
} }
} }
static void ipc_json_describe_view(struct sway_container *c, json_object *object) { void ipc_json_describe_view_common(struct sway_container *c, json_object *object) {
json_object_object_add(object, "pid", json_object_new_int(c->view->pid)); json_object_object_add(object, "pid", json_object_new_int(c->view->pid));
const char *app_id = view_get_app_id(c->view);
json_object_object_add(object, "app_id",
app_id ? json_object_new_string(app_id) : NULL);
bool visible = view_is_visible(c->view); bool visible = view_is_visible(c->view);
json_object_object_add(object, "visible", json_object_new_boolean(visible)); json_object_object_add(object, "visible", json_object_new_boolean(visible));
@ -427,42 +428,9 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
struct wlr_box geometry = {0, 0, c->view->natural_width, c->view->natural_height}; struct wlr_box geometry = {0, 0, c->view->natural_width, c->view->natural_height};
json_object_object_add(object, "geometry", ipc_json_create_rect(&geometry)); json_object_object_add(object, "geometry", ipc_json_create_rect(&geometry));
#if HAVE_XWAYLAND
if (c->view->type == SWAY_VIEW_XWAYLAND) {
json_object_object_add(object, "window",
json_object_new_int(view_get_x11_window_id(c->view)));
json_object *window_props = json_object_new_object();
const char *class = view_get_class(c->view);
if (class) {
json_object_object_add(window_props, "class", json_object_new_string(class));
}
const char *instance = view_get_instance(c->view);
if (instance) {
json_object_object_add(window_props, "instance", json_object_new_string(instance));
}
if (c->title) {
json_object_object_add(window_props, "title", json_object_new_string(c->title));
} }
// the transient_for key is always present in i3's output void ipc_json_describe_container(struct sway_container *c, json_object *object) {
uint32_t parent_id = view_get_x11_parent_id(c->view);
json_object_object_add(window_props, "transient_for",
parent_id ? json_object_new_int(parent_id) : NULL);
const char *role = view_get_window_role(c->view);
if (role) {
json_object_object_add(window_props, "window_role", json_object_new_string(role));
}
json_object_object_add(object, "window_properties", window_props);
}
#endif
}
static void ipc_json_describe_container(struct sway_container *c, json_object *object) {
json_object_object_add(object, "name", json_object_object_add(object, "name",
c->title ? json_object_new_string(c->title) : NULL); c->title ? json_object_new_string(c->title) : NULL);
json_object_object_add(object, "type", json_object_object_add(object, "type",
@ -507,10 +475,6 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o
struct wlr_box deco_box = {0, 0, 0, 0}; struct wlr_box deco_box = {0, 0, 0, 0};
get_deco_rect(c, &deco_box); get_deco_rect(c, &deco_box);
json_object_object_add(object, "deco_rect", ipc_json_create_rect(&deco_box)); json_object_object_add(object, "deco_rect", ipc_json_create_rect(&deco_box));
if (c->view) {
ipc_json_describe_view(c, object);
}
} }
struct focus_inactive_data { struct focus_inactive_data {
@ -541,7 +505,8 @@ static void focus_inactive_children_iterator(struct sway_node *node,
json_object_array_add(focus, json_object_new_int(node->id)); json_object_array_add(focus, json_object_new_int(node->id));
} }
json_object *ipc_json_describe_node(struct sway_node *node) { json_object *ipc_json_describe_node(struct sway_node *node,
const ipc_json_descriptor_map *desc) {
struct sway_seat *seat = input_manager_get_default_seat(); struct sway_seat *seat = input_manager_get_default_seat();
bool focused = seat_get_focus(seat) == node; bool focused = seat_get_focus(seat) == node;
char *name = node_get_name(node); char *name = node_get_name(node);
@ -569,26 +534,15 @@ json_object *ipc_json_describe_node(struct sway_node *node) {
json_object *object = ipc_json_create_node( json_object *object = ipc_json_create_node(
(int)node->id, name, focused, focus, &box); (int)node->id, name, focused, focus, &box);
switch (node->type) { if ((*desc)[node->type]) {
case N_ROOT: (*desc)[node->type](node, object);
ipc_json_describe_root(root, object);
break;
case N_OUTPUT:
ipc_json_describe_output(node->sway_output, object);
break;
case N_CONTAINER:
ipc_json_describe_container(node->sway_container, object);
break;
case N_WORKSPACE:
ipc_json_describe_workspace(node->sway_workspace, object);
break;
} }
return object; return object;
} }
json_object *ipc_json_describe_node_recursive(struct sway_node *node) { json_object *ipc_json_describe_node_recursive(struct sway_node *node,
json_object *object = ipc_json_describe_node(node); const ipc_json_descriptor_map *desc) {
json_object *object = ipc_json_describe_node(node, desc);
int i; int i;
json_object *children = json_object_new_array(); json_object *children = json_object_new_array();
@ -599,21 +553,21 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) {
for (i = 0; i < root->outputs->length; ++i) { for (i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
json_object_array_add(children, json_object_array_add(children,
ipc_json_describe_node_recursive(&output->node)); ipc_json_describe_node_recursive(&output->node, desc));
} }
break; break;
case N_OUTPUT: case N_OUTPUT:
for (i = 0; i < node->sway_output->workspaces->length; ++i) { for (i = 0; i < node->sway_output->workspaces->length; ++i) {
struct sway_workspace *ws = node->sway_output->workspaces->items[i]; struct sway_workspace *ws = node->sway_output->workspaces->items[i];
json_object_array_add(children, json_object_array_add(children,
ipc_json_describe_node_recursive(&ws->node)); ipc_json_describe_node_recursive(&ws->node, desc));
} }
break; break;
case N_WORKSPACE: case N_WORKSPACE:
for (i = 0; i < node->sway_workspace->tiling->length; ++i) { for (i = 0; i < node->sway_workspace->tiling->length; ++i) {
struct sway_container *con = node->sway_workspace->tiling->items[i]; struct sway_container *con = node->sway_workspace->tiling->items[i];
json_object_array_add(children, json_object_array_add(children,
ipc_json_describe_node_recursive(&con->node)); ipc_json_describe_node_recursive(&con->node, desc));
} }
break; break;
case N_CONTAINER: case N_CONTAINER:
@ -622,7 +576,8 @@ json_object *ipc_json_describe_node_recursive(struct sway_node *node) {
struct sway_container *child = struct sway_container *child =
node->sway_container->children->items[i]; node->sway_container->children->items[i];
json_object_array_add(children, json_object_array_add(children,
ipc_json_describe_node_recursive(&child->node)); ipc_json_describe_node_recursive(&child->node,
desc));
} }
} }
break; break;

View file

@ -18,6 +18,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/ipc-json.h" #include "sway/ipc-json.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
#include "sway/ipc-sway.h"
#include "sway/server.h" #include "sway/server.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/input/keyboard.h" #include "sway/input/keyboard.h"
@ -291,14 +292,14 @@ void ipc_event_workspace(struct sway_workspace *old,
json_object_object_add(obj, "change", json_object_new_string(change)); json_object_object_add(obj, "change", json_object_new_string(change));
if (old) { if (old) {
json_object_object_add(obj, "old", json_object_object_add(obj, "old",
ipc_json_describe_node_recursive(&old->node)); ipc_json_describe_node_recursive(&old->node, &ipc_json_sway_descriptors));
} else { } else {
json_object_object_add(obj, "old", NULL); json_object_object_add(obj, "old", NULL);
} }
if (new) { if (new) {
json_object_object_add(obj, "current", json_object_object_add(obj, "current",
ipc_json_describe_node_recursive(&new->node)); ipc_json_describe_node_recursive(&new->node, &ipc_json_sway_descriptors));
} else { } else {
json_object_object_add(obj, "current", NULL); json_object_object_add(obj, "current", NULL);
} }
@ -316,7 +317,7 @@ void ipc_event_window(struct sway_container *window, const char *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));
json_object_object_add(obj, "container", json_object_object_add(obj, "container",
ipc_json_describe_node_recursive(&window->node)); ipc_json_describe_node_recursive(&window->node, &ipc_json_sway_descriptors));
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);

View file

@ -1,9 +1,11 @@
#include <json-c/json.h> #include <json-c/json.h>
#include <stdbool.h> #include <stdbool.h>
#include "sway/config.h"
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/desktop/transaction.h" #include "sway/desktop/transaction.h"
#include "sway/ipc-json.h" #include "sway/ipc-json.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
#include "sway/ipc-sway.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
#include "log.h" #include "log.h"
@ -47,7 +49,8 @@ json_object *ipc_sway_get_outputs(struct ipc_client *client,
json_object *outputs = json_object_new_array(); json_object *outputs = json_object_new_array();
for (int i = 0; i < root->outputs->length; ++i) { for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
json_object *output_json = ipc_json_describe_node(&output->node); json_object *output_json = ipc_json_describe_node(&output->node,
&ipc_json_sway_descriptors);
// override the default focused indicator because it's set // override the default focused indicator because it's set
// differently for the get_outputs reply // differently for the get_outputs reply
@ -75,7 +78,8 @@ json_object *ipc_sway_get_outputs(struct ipc_client *client,
static void ipc_get_workspaces_callback(struct sway_workspace *workspace, static void ipc_get_workspaces_callback(struct sway_workspace *workspace,
void *data) { void *data) {
json_object *workspace_json = ipc_json_describe_node(&workspace->node); json_object *workspace_json = ipc_json_describe_node(&workspace->node,
&ipc_json_sway_descriptors);
// override the default focused indicator because // override the default focused indicator because
// it's set differently for the get_workspaces reply // it's set differently for the get_workspaces reply
struct sway_seat *seat = input_manager_get_default_seat(); struct sway_seat *seat = input_manager_get_default_seat();
@ -176,7 +180,7 @@ json_object *ipc_sway_get_seats(struct ipc_client *client,
json_object *ipc_sway_get_tree(struct ipc_client *client, json_object *ipc_sway_get_tree(struct ipc_client *client,
enum ipc_command_type *type, char *buf) { enum ipc_command_type *type, char *buf) {
return ipc_json_describe_node_recursive(&root->node); return ipc_json_describe_node_recursive(&root->node, &ipc_json_sway_descriptors);
} }
static void ipc_get_marks_callback(struct sway_container *con, void *data) { static void ipc_get_marks_callback(struct sway_container *con, void *data) {
@ -249,6 +253,61 @@ json_object *ipc_sway_sync(struct ipc_client *client,
return ipc_json_failure(NULL); return ipc_json_failure(NULL);
} }
static void ipc_sway_json_describe_view(struct sway_container *c, json_object *object) {
const char *app_id = view_get_app_id(c->view);
json_object_object_add(object, "app_id",
app_id ? json_object_new_string(app_id) : NULL);
#if HAVE_XWAYLAND
if (c->view->type == SWAY_VIEW_XWAYLAND) {
json_object_object_add(object, "window",
json_object_new_int(view_get_x11_window_id(c->view)));
json_object *window_props = json_object_new_object();
const char *class = view_get_class(c->view);
if (class) {
json_object_object_add(window_props, "class", json_object_new_string(class));
}
const char *instance = view_get_instance(c->view);
if (instance) {
json_object_object_add(window_props, "instance", json_object_new_string(instance));
}
if (c->title) {
json_object_object_add(window_props, "title", json_object_new_string(c->title));
}
// the transient_for key is always present in i3's output
uint32_t parent_id = view_get_x11_parent_id(c->view);
json_object_object_add(window_props, "transient_for",
parent_id ? json_object_new_int(parent_id) : NULL);
const char *role = view_get_window_role(c->view);
if (role) {
json_object_object_add(window_props, "window_role", json_object_new_string(role));
}
json_object_object_add(object, "window_properties", window_props);
}
#endif
}
static void ipc_sway_json_describe_container(struct sway_node *node, json_object *object) {
struct sway_container *c = node->sway_container;
ipc_json_describe_container(node->sway_container, object);
if (c->view) {
ipc_json_describe_view_common(node->sway_container, object);
ipc_sway_json_describe_view(node->sway_container, object);
}
}
const ipc_json_descriptor_map ipc_json_sway_descriptors = {
[N_ROOT] = ipc_json_describe_root,
[N_WORKSPACE] = ipc_json_describe_workspace,
[N_OUTPUT] = ipc_json_describe_output,
[N_CONTAINER] = ipc_sway_json_describe_container,
};
static const ipc_handler sway_commands[] = { static const ipc_handler sway_commands[] = {
[IPC_COMMAND] = ipc_sway_command, [IPC_COMMAND] = ipc_sway_command,
[IPC_GET_BAR_CONFIG] = ipc_sway_get_bar_config, [IPC_GET_BAR_CONFIG] = ipc_sway_get_bar_config,