diff options
Diffstat (limited to 'sway/ipc-server.c')
| -rw-r--r-- | sway/ipc-server.c | 90 | 
1 files changed, 90 insertions, 0 deletions
| diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 4c0953e8..156de380 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -240,6 +240,57 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {  	return 0;  } +static void ipc_send_event(const char *json_string, enum ipc_command_type event) { +	static struct { +		enum ipc_command_type event; +		enum ipc_feature feature; +	} security_mappings[] = { +		{ IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE }, +		{ IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT }, +		{ IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, +		{ IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, +		{ IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, +		{ IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } +	}; + +	uint32_t security_mask = 0; +	for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) { +		if (security_mappings[i].event == event) { +			security_mask = security_mappings[i].feature; +			break; +		} +	} + +	int i; +	struct ipc_client *client; +	for (i = 0; i < ipc_client_list->length; i++) { +		client = ipc_client_list->items[i]; +		if (!(client->security_policy & security_mask)) { +			continue; +		} +		if ((client->subscribed_events & event_mask(event)) == 0) { +			continue; +		} +		client->current_command = event; +		if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { +			wlr_log_errno(L_INFO, "Unable to send reply to IPC client"); +			ipc_client_disconnect(client); +		} +	} +} + +void ipc_event_window(swayc_t *window, const char *change) { +	wlr_log(L_DEBUG, "Sending window::%s event", change); +	json_object *obj = json_object_new_object(); +	json_object_object_add(obj, "change", json_object_new_string(change)); +	json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); + +	const char *json_string = json_object_to_json_string(obj); +	ipc_send_event(json_string, IPC_EVENT_WINDOW); + +	json_object_put(obj); // free +} +  int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {  	struct ipc_client *client = data; @@ -361,6 +412,45 @@ void ipc_client_handle_command(struct ipc_client *client) {  		goto exit_cleanup;  	} +	case IPC_SUBSCRIBE: +	{ +		// TODO: Check if they're permitted to use these events +		struct json_object *request = json_tokener_parse(buf); +		if (request == NULL) { +			ipc_send_reply(client, "{\"success\": false}", 18); +			wlr_log_errno(L_INFO, "Failed to read request"); +			goto exit_cleanup; +		} + +		// parse requested event types +		for (size_t i = 0; i < json_object_array_length(request); i++) { +			const char *event_type = json_object_get_string(json_object_array_get_idx(request, i)); +			if (strcmp(event_type, "workspace") == 0) { +				client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE); +			} else if (strcmp(event_type, "barconfig_update") == 0) { +				client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE); +			} else if (strcmp(event_type, "mode") == 0) { +				client->subscribed_events |= event_mask(IPC_EVENT_MODE); +			} else if (strcmp(event_type, "window") == 0) { +				client->subscribed_events |= event_mask(IPC_EVENT_WINDOW); +			} else if (strcmp(event_type, "modifier") == 0) { +				client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER); +			} else if (strcmp(event_type, "binding") == 0) { +				client->subscribed_events |= event_mask(IPC_EVENT_BINDING); +			} else { +				ipc_send_reply(client, "{\"success\": false}", 18); +				json_object_put(request); +				wlr_log_errno(L_INFO, "Failed to parse request"); +				goto exit_cleanup; +			} +		} + +		json_object_put(request); + +		ipc_send_reply(client, "{\"success\": true}", 17); +		goto exit_cleanup; +	} +  	case IPC_GET_INPUTS:  	{  		json_object *inputs = json_object_new_array(); | 
