aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/ipc-server.h3
-rw-r--r--sway/ipc-server.c90
-rw-r--r--sway/tree/container.c12
3 files changed, 102 insertions, 3 deletions
diff --git a/include/sway/ipc-server.h b/include/sway/ipc-server.h
index b85ff535..bcf1c433 100644
--- a/include/sway/ipc-server.h
+++ b/include/sway/ipc-server.h
@@ -1,6 +1,7 @@
1#ifndef _SWAY_IPC_SERVER_H 1#ifndef _SWAY_IPC_SERVER_H
2#define _SWAY_IPC_SERVER_H 2#define _SWAY_IPC_SERVER_H
3#include <sys/socket.h> 3#include <sys/socket.h>
4#include "sway/container.h"
4#include "ipc.h" 5#include "ipc.h"
5 6
6struct sway_server; 7struct sway_server;
@@ -9,4 +10,6 @@ void ipc_init(struct sway_server *server);
9void ipc_terminate(void); 10void ipc_terminate(void);
10struct sockaddr_un *ipc_user_sockaddr(void); 11struct sockaddr_un *ipc_user_sockaddr(void);
11 12
13void ipc_event_window(swayc_t *window, const char *change);
14
12#endif 15#endif
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) {
240 return 0; 240 return 0;
241} 241}
242 242
243static void ipc_send_event(const char *json_string, enum ipc_command_type event) {
244 static struct {
245 enum ipc_command_type event;
246 enum ipc_feature feature;
247 } security_mappings[] = {
248 { IPC_EVENT_WORKSPACE, IPC_FEATURE_EVENT_WORKSPACE },
249 { IPC_EVENT_OUTPUT, IPC_FEATURE_EVENT_OUTPUT },
250 { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE },
251 { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW },
252 { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING },
253 { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT }
254 };
255
256 uint32_t security_mask = 0;
257 for (size_t i = 0; i < sizeof(security_mappings) / sizeof(security_mappings[0]); ++i) {
258 if (security_mappings[i].event == event) {
259 security_mask = security_mappings[i].feature;
260 break;
261 }
262 }
263
264 int i;
265 struct ipc_client *client;
266 for (i = 0; i < ipc_client_list->length; i++) {
267 client = ipc_client_list->items[i];
268 if (!(client->security_policy & security_mask)) {
269 continue;
270 }
271 if ((client->subscribed_events & event_mask(event)) == 0) {
272 continue;
273 }
274 client->current_command = event;
275 if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
276 wlr_log_errno(L_INFO, "Unable to send reply to IPC client");
277 ipc_client_disconnect(client);
278 }
279 }
280}
281
282void ipc_event_window(swayc_t *window, const char *change) {
283 wlr_log(L_DEBUG, "Sending window::%s event", change);
284 json_object *obj = json_object_new_object();
285 json_object_object_add(obj, "change", json_object_new_string(change));
286 json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
287
288 const char *json_string = json_object_to_json_string(obj);
289 ipc_send_event(json_string, IPC_EVENT_WINDOW);
290
291 json_object_put(obj); // free
292}
293
243int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { 294int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
244 struct ipc_client *client = data; 295 struct ipc_client *client = data;
245 296
@@ -361,6 +412,45 @@ void ipc_client_handle_command(struct ipc_client *client) {
361 goto exit_cleanup; 412 goto exit_cleanup;
362 } 413 }
363 414
415 case IPC_SUBSCRIBE:
416 {
417 // TODO: Check if they're permitted to use these events
418 struct json_object *request = json_tokener_parse(buf);
419 if (request == NULL) {
420 ipc_send_reply(client, "{\"success\": false}", 18);
421 wlr_log_errno(L_INFO, "Failed to read request");
422 goto exit_cleanup;
423 }
424
425 // parse requested event types
426 for (size_t i = 0; i < json_object_array_length(request); i++) {
427 const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
428 if (strcmp(event_type, "workspace") == 0) {
429 client->subscribed_events |= event_mask(IPC_EVENT_WORKSPACE);
430 } else if (strcmp(event_type, "barconfig_update") == 0) {
431 client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
432 } else if (strcmp(event_type, "mode") == 0) {
433 client->subscribed_events |= event_mask(IPC_EVENT_MODE);
434 } else if (strcmp(event_type, "window") == 0) {
435 client->subscribed_events |= event_mask(IPC_EVENT_WINDOW);
436 } else if (strcmp(event_type, "modifier") == 0) {
437 client->subscribed_events |= event_mask(IPC_EVENT_MODIFIER);
438 } else if (strcmp(event_type, "binding") == 0) {
439 client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
440 } else {
441 ipc_send_reply(client, "{\"success\": false}", 18);
442 json_object_put(request);
443 wlr_log_errno(L_INFO, "Failed to parse request");
444 goto exit_cleanup;
445 }
446 }
447
448 json_object_put(request);
449
450 ipc_send_reply(client, "{\"success\": true}", 17);
451 goto exit_cleanup;
452 }
453
364 case IPC_GET_INPUTS: 454 case IPC_GET_INPUTS:
365 { 455 {
366 json_object *inputs = json_object_new_array(); 456 json_object *inputs = json_object_new_array();
diff --git a/sway/tree/container.c b/sway/tree/container.c
index fafbdb03..b424dd0a 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -15,6 +15,7 @@
15#include "sway/server.h" 15#include "sway/server.h"
16#include "sway/view.h" 16#include "sway/view.h"
17#include "sway/workspace.h" 17#include "sway/workspace.h"
18#include "sway/ipc-server.h"
18#include "log.h" 19#include "log.h"
19 20
20static list_t *bfs_queue; 21static list_t *bfs_queue;
@@ -32,6 +33,11 @@ static list_t *get_bfs_queue() {
32 return bfs_queue; 33 return bfs_queue;
33} 34}
34 35
36static void notify_new_container(swayc_t *container) {
37 wl_signal_emit(&root_container.sway_root->events.new_container, container);
38 ipc_event_window(container, "new");
39}
40
35swayc_t *swayc_by_test(swayc_t *container, 41swayc_t *swayc_by_test(swayc_t *container,
36 bool (*test)(swayc_t *view, void *data), void *data) { 42 bool (*test)(swayc_t *view, void *data), void *data) {
37 if (!container->children) { 43 if (!container->children) {
@@ -175,7 +181,7 @@ swayc_t *new_output(struct sway_output *sway_output) {
175 } 181 }
176 182
177 free(ws_name); 183 free(ws_name);
178 wl_signal_emit(&root_container.sway_root->events.new_container, output); 184 notify_new_container(output);
179 return output; 185 return output;
180} 186}
181 187
@@ -197,7 +203,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) {
197 203
198 add_child(output, workspace); 204 add_child(output, workspace);
199 sort_workspaces(output); 205 sort_workspaces(output);
200 wl_signal_emit(&root_container.sway_root->events.new_container, workspace); 206 notify_new_container(workspace);
201 return workspace; 207 return workspace;
202} 208}
203 209
@@ -222,7 +228,7 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) {
222 // Regular case, create as sibling of current container 228 // Regular case, create as sibling of current container
223 add_sibling(sibling, swayc); 229 add_sibling(sibling, swayc);
224 } 230 }
225 wl_signal_emit(&root_container.sway_root->events.new_container, swayc); 231 notify_new_container(swayc);
226 return swayc; 232 return swayc;
227} 233}
228 234