parent
							
								
									7144fb9fc3
								
							
						
					
					
						commit
						15a324b0d3
					
				| @ -0,0 +1,13 @@ | ||||
| #ifndef _SWAY_IPC_JSON_H | ||||
| #define _SWAY_IPC_JSON_H | ||||
| 
 | ||||
| #include <json-c/json.h> | ||||
| #include "config.h" | ||||
| #include "container.h" | ||||
| 
 | ||||
| json_object *ipc_json_get_version(); | ||||
| json_object *ipc_json_describe_bar_config(struct bar_config *bar); | ||||
| json_object *ipc_json_describe_container(swayc_t *c); | ||||
| json_object *ipc_json_describe_container_recursive(swayc_t *c); | ||||
| 
 | ||||
| #endif | ||||
| @ -0,0 +1,326 @@ | ||||
| #include <json-c/json.h> | ||||
| #include <ctype.h> | ||||
| #include <string.h> | ||||
| #include "container.h" | ||||
| #include "util.h" | ||||
| #include "ipc-json.h" | ||||
| 
 | ||||
| static json_object *ipc_json_create_rect(swayc_t *c) { | ||||
| 	json_object *rect = json_object_new_object(); | ||||
| 
 | ||||
| 	json_object_object_add(rect, "x", json_object_new_int((int32_t)c->x)); | ||||
| 	json_object_object_add(rect, "y", json_object_new_int((int32_t)c->y)); | ||||
| 	json_object_object_add(rect, "width", json_object_new_int((int32_t)c->width)); | ||||
| 	json_object_object_add(rect, "height", json_object_new_int((int32_t)c->height)); | ||||
| 
 | ||||
| 	return rect; | ||||
| } | ||||
| 
 | ||||
| static const char *ipc_json_border_description(swayc_t *c) { | ||||
| 	const char *border; | ||||
| 
 | ||||
| 	switch (c->border_type) { | ||||
| 	case B_PIXEL: | ||||
| 		border = "1pixel"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case B_NORMAL: | ||||
| 		border = "normal"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case B_NONE: // fallthrough
 | ||||
| 	default: | ||||
| 		border = "none"; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return border; | ||||
| } | ||||
| 
 | ||||
| static const char *ipc_json_layout_description(swayc_t *c) { | ||||
| 	const char *layout; | ||||
| 
 | ||||
| 	switch (c->layout) { | ||||
| 	case L_VERT: | ||||
| 		layout = "splitv"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case L_HORIZ: | ||||
| 		layout = "splith"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case L_TABBED: | ||||
| 		layout = "tabbed"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case L_STACKED: | ||||
| 		layout = "stacked"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case L_FLOATING: | ||||
| 		layout = "floating"; | ||||
| 		break; | ||||
| 
 | ||||
| 	case L_NONE: // fallthrough
 | ||||
| 	case L_LAYOUTS: // fallthrough; this should never happen, I'm just trying to silence compiler warnings
 | ||||
| 	default: | ||||
| 		layout = "null"; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return layout; | ||||
| } | ||||
| 
 | ||||
| static float ipc_json_child_percentage(swayc_t *c) { | ||||
| 	float percent = 0; | ||||
| 	swayc_t *parent = c->parent; | ||||
| 
 | ||||
| 	if (parent) { | ||||
| 		switch (parent->layout) { | ||||
| 		case L_VERT: | ||||
| 			percent = c->height / parent->height; | ||||
| 			break; | ||||
| 
 | ||||
| 		case L_HORIZ: | ||||
| 			percent = c->width / parent->width; | ||||
| 			break; | ||||
| 
 | ||||
| 		case L_STACKED: // fallthrough
 | ||||
| 		case L_TABBED: // fallthrough
 | ||||
| 			percent = 1.0; | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return percent; | ||||
| } | ||||
| 
 | ||||
| static void ipc_json_describe_output(swayc_t *output, json_object *object) { | ||||
| 	json_object_object_add(object, "active", json_object_new_boolean(true)); | ||||
| 	json_object_object_add(object, "primary", json_object_new_boolean(false)); | ||||
| 	json_object_object_add(object, "layout", json_object_new_string("output")); | ||||
| 	json_object_object_add(object, "type", json_object_new_string("output")); | ||||
| 	json_object_object_add(object, "current_workspace", | ||||
| 		(output->focused) ? json_object_new_string(output->focused->name) : NULL); | ||||
| } | ||||
| 
 | ||||
| static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { | ||||
| 	int num = (isdigit(workspace->name[0])) ? atoi(workspace->name) : -1; | ||||
| 	bool focused = root_container.focused == workspace->parent && workspace->parent->focused == workspace; | ||||
| 
 | ||||
| 	json_object_object_add(object, "num", json_object_new_int(num)); | ||||
| 	json_object_object_add(object, "visible", json_object_new_boolean(workspace->visible)); | ||||
| 	json_object_object_add(object, "focused", json_object_new_boolean(focused)); | ||||
| 	json_object_object_add(object, "output", json_object_new_string((workspace->parent) ? 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, "layout", json_object_new_string(ipc_json_layout_description(workspace))); | ||||
| } | ||||
| 
 | ||||
| static void ipc_json_describe_view(swayc_t *view, json_object *object) { | ||||
| 	float percent = ipc_json_child_percentage(view); | ||||
| 
 | ||||
| 	json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(view))); | ||||
| 	json_object_object_add(object, "current_border_width", json_object_new_int(view->border_thickness)); | ||||
| 	json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : json_object_new_string("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, "focused", json_object_new_boolean(view->is_focused)); | ||||
| 	json_object_object_add(object, "type", json_object_new_string((view->is_floating) ? "floating_con" : "con")); | ||||
| 	json_object_object_add(object, "layout", json_object_new_string(ipc_json_layout_description(view))); | ||||
| 
 | ||||
| 	if (view->class) { | ||||
| 		json_object_object_add(object, "class", json_object_new_string(view->class)); | ||||
| 	} | ||||
| 
 | ||||
| 	if (view->app_id) { | ||||
| 		json_object_object_add(object, "app_id", json_object_new_string(view->app_id)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| json_object *ipc_json_describe_container(swayc_t *c) { | ||||
| 	if (!(sway_assert(c, "Container must not be null."))) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	json_object *object = json_object_new_object(); | ||||
| 
 | ||||
| 	json_object_object_add(object, "id", json_object_new_int((int64_t)&c)); | ||||
| 	json_object_object_add(object, "name", json_object_new_string(c->name)); | ||||
| 	json_object_object_add(object, "rect", ipc_json_create_rect(c)); | ||||
| 
 | ||||
| 	switch (c->type) { | ||||
| 	case C_ROOT: | ||||
| 		json_object_object_add(object, "type", json_object_new_string("root")); | ||||
| 		break; | ||||
| 
 | ||||
| 	case C_OUTPUT: | ||||
| 		ipc_json_describe_output(c, object); | ||||
| 		break; | ||||
| 
 | ||||
| 	case C_CONTAINER: // fallthrough
 | ||||
| 	case C_VIEW: | ||||
| 		ipc_json_describe_view(c, object); | ||||
| 		break; | ||||
| 
 | ||||
| 	case C_WORKSPACE: | ||||
| 		ipc_json_describe_workspace(c, object); | ||||
| 		break; | ||||
| 
 | ||||
| 	case C_TYPES: // fallthrough; this should never happen, I'm just trying to silence compiler warnings
 | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return object; | ||||
| } | ||||
| 
 | ||||
| json_object *ipc_json_get_version() { | ||||
| 	json_object *version = json_object_new_object(); | ||||
| 
 | ||||
| #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE | ||||
| 	char *full_version = calloc(strlen(SWAY_GIT_VERSION) + strlen(SWAY_GIT_BRANCH) + strlen(SWAY_VERSION_DATE) + 20, 1); | ||||
| 	strcat(full_version, SWAY_GIT_VERSION); | ||||
| 	strcat(full_version, " ("); | ||||
| 	strcat(full_version, SWAY_VERSION_DATE); | ||||
| 	strcat(full_version, ", branch \""); | ||||
| 	strcat(full_version, SWAY_GIT_BRANCH); | ||||
| 	strcat(full_version, "\")"); | ||||
| 
 | ||||
| 	json_object_object_add(version, "human_readable", json_object_new_string(full_version)); | ||||
| 	json_object_object_add(version, "variant", json_object_new_string("sway")); | ||||
| 	// Todo once we actually release a version
 | ||||
| 	json_object_object_add(version, "major", json_object_new_int(0)); | ||||
| 	json_object_object_add(version, "minor", json_object_new_int(0)); | ||||
| 	json_object_object_add(version, "patch", json_object_new_int(1)); | ||||
| #else | ||||
| 	json_object_object_add(version, "human_readable", json_object_new_string("version not found")); | ||||
| 	json_object_object_add(version, "major", json_object_new_int(0)); | ||||
| 	json_object_object_add(version, "minor", json_object_new_int(0)); | ||||
| 	json_object_object_add(version, "patch", json_object_new_int(0)); | ||||
| #endif | ||||
| 
 | ||||
| 	return version; | ||||
| } | ||||
| 
 | ||||
| json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | ||||
| 	if (!sway_assert(bar, "Bar must not be NULL")) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	json_object *json = json_object_new_object(); | ||||
| 	json_object_object_add(json, "id", json_object_new_string(bar->id)); | ||||
| 	json_object_object_add(json, "tray_output", NULL); | ||||
| 	json_object_object_add(json, "mode", json_object_new_string(bar->mode)); | ||||
| 	json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); | ||||
| 	json_object_object_add(json, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); | ||||
| 	switch (bar->position) { | ||||
| 	case DESKTOP_SHELL_PANEL_POSITION_TOP: | ||||
| 		json_object_object_add(json, "position", json_object_new_string("top")); | ||||
| 		break; | ||||
| 	case DESKTOP_SHELL_PANEL_POSITION_BOTTOM: | ||||
| 		json_object_object_add(json, "position", json_object_new_string("bottom")); | ||||
| 		break; | ||||
| 	case DESKTOP_SHELL_PANEL_POSITION_LEFT: | ||||
| 		json_object_object_add(json, "position", json_object_new_string("left")); | ||||
| 		break; | ||||
| 	case DESKTOP_SHELL_PANEL_POSITION_RIGHT: | ||||
| 		json_object_object_add(json, "position", json_object_new_string("right")); | ||||
| 		break; | ||||
| 	} | ||||
| 	json_object_object_add(json, "status_command", json_object_new_string(bar->status_command)); | ||||
| 	json_object_object_add(json, "font", json_object_new_string((bar->font) ? bar->font : config->font)); | ||||
| 	if (bar->separator_symbol) { | ||||
| 		json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); | ||||
| 	} | ||||
| 	json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); | ||||
| 	json_object_object_add(json, "workspace_buttons", json_object_new_boolean(bar->workspace_buttons)); | ||||
| 	json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); | ||||
| 	json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); | ||||
| 	json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); | ||||
| 	json_object_object_add(json, "pango_markup", json_object_new_boolean(bar->pango_markup)); | ||||
| 
 | ||||
| 	json_object *colors = json_object_new_object(); | ||||
| 	json_object_object_add(colors, "background", json_object_new_string(bar->colors.background)); | ||||
| 	json_object_object_add(colors, "statusline", json_object_new_string(bar->colors.statusline)); | ||||
| 	json_object_object_add(colors, "separator", json_object_new_string(bar->colors.separator)); | ||||
| 
 | ||||
| 	json_object_object_add(colors, "focused_workspace_border", json_object_new_string(bar->colors.focused_workspace_border)); | ||||
| 	json_object_object_add(colors, "focused_workspace_bg", json_object_new_string(bar->colors.focused_workspace_bg)); | ||||
| 	json_object_object_add(colors, "focused_workspace_text", json_object_new_string(bar->colors.focused_workspace_text)); | ||||
| 
 | ||||
| 	json_object_object_add(colors, "inactive_workspace_border", json_object_new_string(bar->colors.inactive_workspace_border)); | ||||
| 	json_object_object_add(colors, "inactive_workspace_bg", json_object_new_string(bar->colors.inactive_workspace_bg)); | ||||
| 	json_object_object_add(colors, "inactive_workspace_text", json_object_new_string(bar->colors.inactive_workspace_text)); | ||||
| 
 | ||||
| 	json_object_object_add(colors, "active_workspace_border", json_object_new_string(bar->colors.active_workspace_border)); | ||||
| 	json_object_object_add(colors, "active_workspace_bg", json_object_new_string(bar->colors.active_workspace_bg)); | ||||
| 	json_object_object_add(colors, "active_workspace_text", json_object_new_string(bar->colors.active_workspace_text)); | ||||
| 
 | ||||
| 	json_object_object_add(colors, "urgent_workspace_border", json_object_new_string(bar->colors.urgent_workspace_border)); | ||||
| 	json_object_object_add(colors, "urgent_workspace_bg", json_object_new_string(bar->colors.urgent_workspace_bg)); | ||||
| 	json_object_object_add(colors, "urgent_workspace_text", json_object_new_string(bar->colors.urgent_workspace_text)); | ||||
| 
 | ||||
| 	json_object_object_add(colors, "binding_mode_border", json_object_new_string(bar->colors.binding_mode_border)); | ||||
| 	json_object_object_add(colors, "binding_mode_bg", json_object_new_string(bar->colors.binding_mode_bg)); | ||||
| 	json_object_object_add(colors, "binding_mode_text", json_object_new_string(bar->colors.binding_mode_text)); | ||||
| 
 | ||||
| 	json_object_object_add(json, "colors", colors); | ||||
| 
 | ||||
| 	// Add outputs if defined
 | ||||
| 	if (bar->outputs && bar->outputs->length > 0) { | ||||
| 		json_object *outputs = json_object_new_array(); | ||||
| 		int i; | ||||
| 		for (i = 0; i < bar->outputs->length; ++i) { | ||||
| 			const char *name = bar->outputs->items[i]; | ||||
| 			json_object_array_add(outputs, json_object_new_string(name)); | ||||
| 		} | ||||
| 		json_object_object_add(json, "outputs", outputs); | ||||
| 	} | ||||
| 
 | ||||
| 	return json; | ||||
| } | ||||
| 
 | ||||
| json_object *ipc_json_describe_container_recursive(swayc_t *c) { | ||||
| 	json_object *object = ipc_json_describe_container(c); | ||||
| 	int i; | ||||
| 
 | ||||
| 	json_object *floating = json_object_new_array(); | ||||
| 	if (c->floating && c->floating->length > 0) { | ||||
| 		for (i = 0; i < c->floating->length; ++i) { | ||||
| 			json_object_array_add(floating, ipc_json_describe_container_recursive(c->floating->items[i])); | ||||
| 		} | ||||
| 	} | ||||
| 	json_object_object_add(object, "floating_nodes", floating); | ||||
| 
 | ||||
| 	json_object *children = json_object_new_array(); | ||||
| 	if (c->children && c->children->length > 0) { | ||||
| 		for (i = 0; i < c->children->length; ++i) { | ||||
| 			json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); | ||||
| 		} | ||||
| 	} | ||||
| 	json_object_object_add(object, "nodes", children); | ||||
| 
 | ||||
| 	json_object *unmanaged = json_object_new_array(); | ||||
| 	if (c->unmanaged && c->unmanaged->length > 0) { | ||||
| 		for (i = 0; i < c->unmanaged->length; ++i) { | ||||
| 			json_object_array_add(unmanaged, ipc_json_describe_container_recursive(c->unmanaged->items[i])); | ||||
| 		} | ||||
| 	} | ||||
| 	json_object_object_add(object, "unmanaged_nodes", unmanaged); | ||||
| 
 | ||||
| 	if (c->type == C_ROOT) { | ||||
| 		json_object *scratchpad_json = json_object_new_array(); | ||||
| 		if (scratchpad->length > 0) { | ||||
| 			for (i = 0; i < scratchpad->length; ++i) { | ||||
| 				json_object_array_add(scratchpad_json, ipc_json_describe_container_recursive(scratchpad->items[i])); | ||||
| 			} | ||||
| 		} | ||||
| 		json_object_object_add(object, "scratchpad", unmanaged); | ||||
| 	} | ||||
| 
 | ||||
| 	return object; | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue