|
|
|
@ -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();
|
|
|
|
|