Merge pull request #1611 from acrisci/ipc-new-window

Ipc new window
This commit is contained in:
Drew DeVault 2018-02-27 20:17:08 -05:00 committed by GitHub
commit 8a97d3a494
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 3 deletions

View file

@ -1,6 +1,7 @@
#ifndef _SWAY_IPC_SERVER_H #ifndef _SWAY_IPC_SERVER_H
#define _SWAY_IPC_SERVER_H #define _SWAY_IPC_SERVER_H
#include <sys/socket.h> #include <sys/socket.h>
#include "sway/container.h"
#include "ipc.h" #include "ipc.h"
struct sway_server; struct sway_server;
@ -9,4 +10,6 @@ void ipc_init(struct sway_server *server);
void ipc_terminate(void); void ipc_terminate(void);
struct sockaddr_un *ipc_user_sockaddr(void); struct sockaddr_un *ipc_user_sockaddr(void);
void ipc_event_window(swayc_t *window, const char *change);
#endif #endif

View file

@ -240,6 +240,57 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
return 0; 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) { int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
struct ipc_client *client = data; struct ipc_client *client = data;
@ -361,6 +412,45 @@ void ipc_client_handle_command(struct ipc_client *client) {
goto exit_cleanup; 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: case IPC_GET_INPUTS:
{ {
json_object *inputs = json_object_new_array(); json_object *inputs = json_object_new_array();

View file

@ -15,6 +15,7 @@
#include "sway/server.h" #include "sway/server.h"
#include "sway/view.h" #include "sway/view.h"
#include "sway/workspace.h" #include "sway/workspace.h"
#include "sway/ipc-server.h"
#include "log.h" #include "log.h"
static list_t *bfs_queue; static list_t *bfs_queue;
@ -32,6 +33,11 @@ static list_t *get_bfs_queue() {
return bfs_queue; return bfs_queue;
} }
static void notify_new_container(swayc_t *container) {
wl_signal_emit(&root_container.sway_root->events.new_container, container);
ipc_event_window(container, "new");
}
swayc_t *swayc_by_test(swayc_t *container, swayc_t *swayc_by_test(swayc_t *container,
bool (*test)(swayc_t *view, void *data), void *data) { bool (*test)(swayc_t *view, void *data), void *data) {
if (!container->children) { if (!container->children) {
@ -175,7 +181,7 @@ swayc_t *new_output(struct sway_output *sway_output) {
} }
free(ws_name); free(ws_name);
wl_signal_emit(&root_container.sway_root->events.new_container, output); notify_new_container(output);
return output; return output;
} }
@ -197,7 +203,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) {
add_child(output, workspace); add_child(output, workspace);
sort_workspaces(output); sort_workspaces(output);
wl_signal_emit(&root_container.sway_root->events.new_container, workspace); notify_new_container(workspace);
return workspace; return workspace;
} }
@ -222,7 +228,7 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) {
// Regular case, create as sibling of current container // Regular case, create as sibling of current container
add_sibling(sibling, swayc); add_sibling(sibling, swayc);
} }
wl_signal_emit(&root_container.sway_root->events.new_container, swayc); notify_new_container(swayc);
return swayc; return swayc;
} }