diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-10-22 10:37:30 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2017-11-11 09:08:50 -0500 |
commit | 7c448b408126aef0561be0761871f968921d7db0 (patch) | |
tree | 055716519b975eca17b2e27254217acd1b801c20 /sway/ipc-server.c | |
parent | Find and link to wlroots (diff) | |
download | sway-7c448b408126aef0561be0761871f968921d7db0.tar.gz sway-7c448b408126aef0561be0761871f968921d7db0.tar.zst sway-7c448b408126aef0561be0761871f968921d7db0.zip |
Fire up the wlroots backend and run the event loop
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r-- | sway/ipc-server.c | 389 |
1 files changed, 22 insertions, 367 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index b560b930..9ba736d8 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <sys/socket.h> | 10 | #include <sys/socket.h> |
11 | #include <sys/un.h> | 11 | #include <sys/un.h> |
12 | #include <stdbool.h> | 12 | #include <stdbool.h> |
13 | #include <wlc/wlc-render.h> | ||
14 | #include <unistd.h> | 13 | #include <unistd.h> |
15 | #include <stdlib.h> | 14 | #include <stdlib.h> |
16 | #include <sys/ioctl.h> | 15 | #include <sys/ioctl.h> |
@@ -31,21 +30,22 @@ struct ucred { | |||
31 | #include "sway/config.h" | 30 | #include "sway/config.h" |
32 | #include "sway/commands.h" | 31 | #include "sway/commands.h" |
33 | #include "sway/input.h" | 32 | #include "sway/input.h" |
33 | #include "sway/server.h" | ||
34 | #include "stringop.h" | 34 | #include "stringop.h" |
35 | #include "log.h" | 35 | #include "log.h" |
36 | #include "list.h" | 36 | #include "list.h" |
37 | #include "util.h" | 37 | #include "util.h" |
38 | 38 | ||
39 | static int ipc_socket = -1; | 39 | static int ipc_socket = -1; |
40 | static struct wlc_event_source *ipc_event_source = NULL; | 40 | static struct wl_event_source *ipc_event_source = NULL; |
41 | static struct sockaddr_un *ipc_sockaddr = NULL; | 41 | static struct sockaddr_un *ipc_sockaddr = NULL; |
42 | static list_t *ipc_client_list = NULL; | 42 | static list_t *ipc_client_list = NULL; |
43 | 43 | ||
44 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; | 44 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; |
45 | 45 | ||
46 | struct ipc_client { | 46 | struct ipc_client { |
47 | struct wlc_event_source *event_source; | 47 | struct wl_event_source *event_source; |
48 | struct wlc_event_source *writable_event_source; | 48 | struct wl_event_source *writable_event_source; |
49 | int fd; | 49 | int fd; |
50 | uint32_t payload_length; | 50 | uint32_t payload_length; |
51 | uint32_t security_policy; | 51 | uint32_t security_policy; |
@@ -58,25 +58,6 @@ struct ipc_client { | |||
58 | 58 | ||
59 | static list_t *ipc_get_pixel_requests = NULL; | 59 | static list_t *ipc_get_pixel_requests = NULL; |
60 | 60 | ||
61 | struct get_pixels_request { | ||
62 | struct ipc_client *client; | ||
63 | wlc_handle output; | ||
64 | struct wlc_geometry geo; | ||
65 | }; | ||
66 | |||
67 | struct get_clipboard_request { | ||
68 | struct ipc_client *client; | ||
69 | json_object *json; | ||
70 | int fd; | ||
71 | struct wlc_event_source *fd_event_source; | ||
72 | struct wlc_event_source *timer_event_source; | ||
73 | char *type; | ||
74 | unsigned int *pending; | ||
75 | char *buf; | ||
76 | size_t buf_size; | ||
77 | size_t buf_position; | ||
78 | }; | ||
79 | |||
80 | struct sockaddr_un *ipc_user_sockaddr(void); | 61 | struct sockaddr_un *ipc_user_sockaddr(void); |
81 | int ipc_handle_connection(int fd, uint32_t mask, void *data); | 62 | int ipc_handle_connection(int fd, uint32_t mask, void *data); |
82 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); | 63 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); |
@@ -118,12 +99,13 @@ void ipc_init(void) { | |||
118 | ipc_client_list = create_list(); | 99 | ipc_client_list = create_list(); |
119 | ipc_get_pixel_requests = create_list(); | 100 | ipc_get_pixel_requests = create_list(); |
120 | 101 | ||
121 | ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); | 102 | ipc_event_source = wl_event_loop_add_fd(server.wl_event_loop, ipc_socket, |
103 | WL_EVENT_READABLE, ipc_handle_connection, NULL); | ||
122 | } | 104 | } |
123 | 105 | ||
124 | void ipc_terminate(void) { | 106 | void ipc_terminate(void) { |
125 | if (ipc_event_source) { | 107 | if (ipc_event_source) { |
126 | wlc_event_source_remove(ipc_event_source); | 108 | wl_event_source_remove(ipc_event_source); |
127 | } | 109 | } |
128 | close(ipc_socket); | 110 | close(ipc_socket); |
129 | unlink(ipc_sockaddr->sun_path); | 111 | unlink(ipc_sockaddr->sun_path); |
@@ -176,7 +158,7 @@ static pid_t get_client_pid(int client_fd) { | |||
176 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { | 158 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { |
177 | (void) fd; (void) data; | 159 | (void) fd; (void) data; |
178 | sway_log(L_DEBUG, "Event on IPC listening socket"); | 160 | sway_log(L_DEBUG, "Event on IPC listening socket"); |
179 | assert(mask == WLC_EVENT_READABLE); | 161 | assert(mask == WL_EVENT_READABLE); |
180 | 162 | ||
181 | int client_fd = accept(ipc_socket, NULL, NULL); | 163 | int client_fd = accept(ipc_socket, NULL, NULL); |
182 | if (client_fd == -1) { | 164 | if (client_fd == -1) { |
@@ -207,7 +189,8 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
207 | client->payload_length = 0; | 189 | client->payload_length = 0; |
208 | client->fd = client_fd; | 190 | client->fd = client_fd; |
209 | client->subscribed_events = 0; | 191 | client->subscribed_events = 0; |
210 | client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); | 192 | client->event_source = wl_event_loop_add_fd(server.wl_event_loop, client_fd, |
193 | WL_EVENT_READABLE, ipc_client_handle_readable, client); | ||
211 | client->writable_event_source = NULL; | 194 | client->writable_event_source = NULL; |
212 | 195 | ||
213 | client->write_buffer_size = 128; | 196 | client->write_buffer_size = 128; |
@@ -234,13 +217,13 @@ static const int ipc_header_size = sizeof(ipc_magic)+8; | |||
234 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | 217 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { |
235 | struct ipc_client *client = data; | 218 | struct ipc_client *client = data; |
236 | 219 | ||
237 | if (mask & WLC_EVENT_ERROR) { | 220 | if (mask & WL_EVENT_ERROR) { |
238 | sway_log(L_ERROR, "IPC Client socket error, removing client"); | 221 | sway_log(L_ERROR, "IPC Client socket error, removing client"); |
239 | ipc_client_disconnect(client); | 222 | ipc_client_disconnect(client); |
240 | return 0; | 223 | return 0; |
241 | } | 224 | } |
242 | 225 | ||
243 | if (mask & WLC_EVENT_HANGUP) { | 226 | if (mask & WL_EVENT_HANGUP) { |
244 | sway_log(L_DEBUG, "Client %d hung up", client->fd); | 227 | sway_log(L_DEBUG, "Client %d hung up", client->fd); |
245 | ipc_client_disconnect(client); | 228 | ipc_client_disconnect(client); |
246 | return 0; | 229 | return 0; |
@@ -296,13 +279,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
296 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | 279 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { |
297 | struct ipc_client *client = data; | 280 | struct ipc_client *client = data; |
298 | 281 | ||
299 | if (mask & WLC_EVENT_ERROR) { | 282 | if (mask & WL_EVENT_ERROR) { |
300 | sway_log(L_ERROR, "IPC Client socket error, removing client"); | 283 | sway_log(L_ERROR, "IPC Client socket error, removing client"); |
301 | ipc_client_disconnect(client); | 284 | ipc_client_disconnect(client); |
302 | return 0; | 285 | return 0; |
303 | } | 286 | } |
304 | 287 | ||
305 | if (mask & WLC_EVENT_HANGUP) { | 288 | if (mask & WL_EVENT_HANGUP) { |
306 | sway_log(L_DEBUG, "Client %d hung up", client->fd); | 289 | sway_log(L_DEBUG, "Client %d hung up", client->fd); |
307 | ipc_client_disconnect(client); | 290 | ipc_client_disconnect(client); |
308 | return 0; | 291 | return 0; |
@@ -328,7 +311,7 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | |||
328 | client->write_buffer_len -= written; | 311 | client->write_buffer_len -= written; |
329 | 312 | ||
330 | if (client->write_buffer_len == 0 && client->writable_event_source) { | 313 | if (client->write_buffer_len == 0 && client->writable_event_source) { |
331 | wlc_event_source_remove(client->writable_event_source); | 314 | wl_event_source_remove(client->writable_event_source); |
332 | client->writable_event_source = NULL; | 315 | client->writable_event_source = NULL; |
333 | } | 316 | } |
334 | 317 | ||
@@ -345,9 +328,9 @@ void ipc_client_disconnect(struct ipc_client *client) { | |||
345 | } | 328 | } |
346 | 329 | ||
347 | sway_log(L_INFO, "IPC Client %d disconnected", client->fd); | 330 | sway_log(L_INFO, "IPC Client %d disconnected", client->fd); |
348 | wlc_event_source_remove(client->event_source); | 331 | wl_event_source_remove(client->event_source); |
349 | if (client->writable_event_source) { | 332 | if (client->writable_event_source) { |
350 | wlc_event_source_remove(client->writable_event_source); | 333 | wl_event_source_remove(client->writable_event_source); |
351 | } | 334 | } |
352 | int i = 0; | 335 | int i = 0; |
353 | while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; | 336 | while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; |
@@ -365,165 +348,6 @@ bool output_by_name_test(swayc_t *view, void *data) { | |||
365 | return !strcmp(name, view->name); | 348 | return !strcmp(name, view->name); |
366 | } | 349 | } |
367 | 350 | ||
368 | void ipc_get_pixels(wlc_handle output) { | ||
369 | if (ipc_get_pixel_requests->length == 0) { | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | list_t *unhandled = create_list(); | ||
374 | |||
375 | struct get_pixels_request *req; | ||
376 | int i; | ||
377 | for (i = 0; i < ipc_get_pixel_requests->length; ++i) { | ||
378 | req = ipc_get_pixel_requests->items[i]; | ||
379 | if (req->output != output) { | ||
380 | list_add(unhandled, req); | ||
381 | continue; | ||
382 | } | ||
383 | |||
384 | const struct wlc_size *size = &req->geo.size; | ||
385 | struct wlc_geometry g_out; | ||
386 | char response_header[9]; | ||
387 | memset(response_header, 0, sizeof(response_header)); | ||
388 | char *data = malloc(sizeof(response_header) + size->w * size->h * 4); | ||
389 | if (!data) { | ||
390 | sway_log(L_ERROR, "Unable to allocate pixels for get_pixels"); | ||
391 | ipc_client_disconnect(req->client); | ||
392 | free(req); | ||
393 | continue; | ||
394 | } | ||
395 | wlc_pixels_read(WLC_RGBA8888, &req->geo, &g_out, data + sizeof(response_header)); | ||
396 | |||
397 | response_header[0] = 1; | ||
398 | uint32_t *_size = (uint32_t *)(response_header + 1); | ||
399 | _size[0] = g_out.size.w; | ||
400 | _size[1] = g_out.size.h; | ||
401 | size_t len = sizeof(response_header) + (g_out.size.w * g_out.size.h * 4); | ||
402 | memcpy(data, response_header, sizeof(response_header)); | ||
403 | ipc_send_reply(req->client, data, len); | ||
404 | free(data); | ||
405 | // free the request since it has been handled | ||
406 | free(req); | ||
407 | } | ||
408 | |||
409 | // free old list of pixel requests and set new list to all unhandled | ||
410 | // requests (request for another output). | ||
411 | list_free(ipc_get_pixel_requests); | ||
412 | ipc_get_pixel_requests = unhandled; | ||
413 | } | ||
414 | |||
415 | static bool is_text_target(const char *target) { | ||
416 | return (strncmp(target, "text/", 5) == 0 | ||
417 | || strcmp(target, "UTF8_STRING") == 0 | ||
418 | || strcmp(target, "STRING") == 0 | ||
419 | || strcmp(target, "TEXT") == 0 | ||
420 | || strcmp(target, "COMPOUND_TEXT") == 0); | ||
421 | } | ||
422 | |||
423 | static void release_clipboard_request(struct get_clipboard_request *req) { | ||
424 | if (--(*req->pending) == 0) { | ||
425 | const char *str = json_object_to_json_string(req->json); | ||
426 | ipc_send_reply(req->client, str, (uint32_t)strlen(str)); | ||
427 | json_object_put(req->json); | ||
428 | } | ||
429 | |||
430 | free(req->type); | ||
431 | free(req->buf); | ||
432 | wlc_event_source_remove(req->fd_event_source); | ||
433 | wlc_event_source_remove(req->timer_event_source); | ||
434 | close(req->fd); | ||
435 | free(req); | ||
436 | } | ||
437 | |||
438 | static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) { | ||
439 | assert(data); | ||
440 | struct get_clipboard_request *req = (struct get_clipboard_request *)data; | ||
441 | |||
442 | if (mask & WLC_EVENT_ERROR) { | ||
443 | sway_log(L_ERROR, "Selection data fd error"); | ||
444 | goto error; | ||
445 | } | ||
446 | |||
447 | if (mask & WLC_EVENT_READABLE) { | ||
448 | static const unsigned int max_size = 8192 * 1024; | ||
449 | int amt = 0; | ||
450 | |||
451 | do { | ||
452 | int size = req->buf_size - req->buf_position; | ||
453 | int amt = read(fd, req->buf + req->buf_position, size - 1); | ||
454 | if (amt < 0) { | ||
455 | if (errno == EAGAIN) { | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | sway_log_errno(L_INFO, "Failed to read from clipboard data fd"); | ||
460 | goto release; | ||
461 | } | ||
462 | |||
463 | req->buf_position += amt; | ||
464 | if (req->buf_position >= req->buf_size - 1) { | ||
465 | if (req->buf_size >= max_size) { | ||
466 | sway_log(L_ERROR, "get_clipbard: selection data too large"); | ||
467 | goto error; | ||
468 | } | ||
469 | char *next = realloc(req->buf, req->buf_size *= 2); | ||
470 | if (!next) { | ||
471 | sway_log_errno(L_ERROR, "get_clipboard: realloc data buffer failed"); | ||
472 | goto error; | ||
473 | } | ||
474 | |||
475 | req->buf = next; | ||
476 | } | ||
477 | } while(amt != 0); | ||
478 | |||
479 | req->buf[req->buf_position] = '\0'; | ||
480 | |||
481 | json_object *obj = json_object_new_object(); | ||
482 | json_object_object_add(obj, "success", json_object_new_boolean(true)); | ||
483 | if (is_text_target(req->type)) { | ||
484 | json_object_object_add(obj, "content", json_object_new_string(req->buf)); | ||
485 | json_object_object_add(req->json, req->type, obj); | ||
486 | } else { | ||
487 | size_t outlen; | ||
488 | char *b64 = b64_encode(req->buf, req->buf_position, &outlen); | ||
489 | json_object_object_add(obj, "content", json_object_new_string(b64)); | ||
490 | free(b64); | ||
491 | |||
492 | char *type = malloc(strlen(req->type) + 8); | ||
493 | strcat(type, ";base64"); | ||
494 | json_object_object_add(req->json, type, obj); | ||
495 | free(type); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | goto release; | ||
500 | |||
501 | error:; | ||
502 | json_object *obj = json_object_new_object(); | ||
503 | json_object_object_add(obj, "success", json_object_new_boolean(false)); | ||
504 | json_object_object_add(obj, "error", | ||
505 | json_object_new_string("Failed to retrieve data")); | ||
506 | json_object_object_add(req->json, req->type, obj); | ||
507 | |||
508 | release: | ||
509 | release_clipboard_request(req); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int ipc_selection_timer_cb(void *data) { | ||
514 | assert(data); | ||
515 | struct get_clipboard_request *req = (struct get_clipboard_request *)data; | ||
516 | |||
517 | sway_log(L_INFO, "get_clipbard: timeout for type %s", req->type); | ||
518 | json_object *obj = json_object_new_object(); | ||
519 | json_object_object_add(obj, "success", json_object_new_boolean(false)); | ||
520 | json_object_object_add(obj, "error", json_object_new_string("Timeout")); | ||
521 | json_object_object_add(req->json, req->type, obj); | ||
522 | |||
523 | release_clipboard_request(req); | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | // greedy wildcard (only "*") matching | 351 | // greedy wildcard (only "*") matching |
528 | bool mime_type_matches(const char *mime_type, const char *pattern) { | 352 | bool mime_type_matches(const char *mime_type, const char *pattern) { |
529 | const char *wildcard = NULL; | 353 | const char *wildcard = NULL; |
@@ -553,125 +377,6 @@ bool mime_type_matches(const char *mime_type, const char *pattern) { | |||
553 | return (*mime_type == *pattern); | 377 | return (*mime_type == *pattern); |
554 | } | 378 | } |
555 | 379 | ||
556 | void ipc_get_clipboard(struct ipc_client *client, char *buf) { | ||
557 | size_t size; | ||
558 | const char **types = wlc_get_selection_types(&size); | ||
559 | if (client->payload_length == 0) { | ||
560 | json_object *obj = json_object_new_array(); | ||
561 | for (size_t i = 0; i < size; ++i) { | ||
562 | json_object_array_add(obj, json_object_new_string(types[i])); | ||
563 | } | ||
564 | |||
565 | const char *str = json_object_to_json_string(obj); | ||
566 | ipc_send_reply(client, str, strlen(str)); | ||
567 | json_object_put(obj); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | unescape_string(buf); | ||
572 | strip_quotes(buf); | ||
573 | list_t *requested = split_string(buf, " "); | ||
574 | json_object *json = json_object_new_object(); | ||
575 | unsigned int *pending = malloc(sizeof(unsigned int)); | ||
576 | *pending = 0; | ||
577 | |||
578 | for (size_t l = 0; l < (size_t) requested->length; ++l) { | ||
579 | const char *pattern = requested->items[l]; | ||
580 | bool found = false; | ||
581 | for (size_t i = 0; i < size; ++i) { | ||
582 | if (!mime_type_matches(types[i], pattern)) { | ||
583 | continue; | ||
584 | } | ||
585 | |||
586 | found = true; | ||
587 | |||
588 | struct get_clipboard_request *req = malloc(sizeof(*req)); | ||
589 | if (!req) { | ||
590 | sway_log(L_ERROR, "get_clipboard: request malloc failed"); | ||
591 | goto data_error; | ||
592 | } | ||
593 | |||
594 | int pipes[2]; | ||
595 | if (pipe(pipes) == -1) { | ||
596 | sway_log_errno(L_ERROR, "get_clipboard: pipe call failed"); | ||
597 | free(req); | ||
598 | goto data_error; | ||
599 | } | ||
600 | |||
601 | fcntl(pipes[0], F_SETFD, FD_CLOEXEC | O_NONBLOCK); | ||
602 | fcntl(pipes[1], F_SETFD, FD_CLOEXEC | O_NONBLOCK); | ||
603 | |||
604 | if (!wlc_get_selection_data(types[i], pipes[1])) { | ||
605 | close(pipes[0]); | ||
606 | close(pipes[1]); | ||
607 | free(req); | ||
608 | sway_log(L_ERROR, "get_clipboard: failed to retrieve " | ||
609 | "selection data"); | ||
610 | goto data_error; | ||
611 | } | ||
612 | |||
613 | if (!(req->buf = malloc(512))) { | ||
614 | close(pipes[0]); | ||
615 | close(pipes[1]); | ||
616 | free(req); | ||
617 | sway_log_errno(L_ERROR, "get_clipboard: buf malloc failed"); | ||
618 | goto data_error; | ||
619 | } | ||
620 | |||
621 | (*pending)++; | ||
622 | |||
623 | req->client = client; | ||
624 | req->type = strdup(types[i]); | ||
625 | req->json = json; | ||
626 | req->pending = pending; | ||
627 | req->buf_position = 0; | ||
628 | req->buf_size = 512; | ||
629 | req->fd = pipes[0]; | ||
630 | req->timer_event_source = wlc_event_loop_add_timer(ipc_selection_timer_cb, req); | ||
631 | req->fd_event_source = wlc_event_loop_add_fd(pipes[0], | ||
632 | WLC_EVENT_READABLE | WLC_EVENT_ERROR | WLC_EVENT_HANGUP, | ||
633 | &ipc_selection_data_cb, req); | ||
634 | |||
635 | wlc_event_source_timer_update(req->timer_event_source, 30000); | ||
636 | |||
637 | // NOTE: remove this goto to enable retrieving multiple | ||
638 | // targets at once. The whole implementation is already | ||
639 | // made for it. The only reason it was disabled | ||
640 | // at the time of writing is that neither wlc's xselection | ||
641 | // implementation nor (apparently) gtk on wayland supports | ||
642 | // multiple send requests at the same time which makes | ||
643 | // every request except the last one fail (and therefore | ||
644 | // return empty data) | ||
645 | goto cleanup; | ||
646 | } | ||
647 | |||
648 | if (!found) { | ||
649 | sway_log(L_INFO, "Invalid clipboard type %s requested", pattern); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | if (*pending == 0) { | ||
654 | static const char *error_empty = "{ \"success\": false, \"error\": " | ||
655 | "\"No matching types found\" }"; | ||
656 | ipc_send_reply(client, error_empty, (uint32_t)strlen(error_empty)); | ||
657 | free(json); | ||
658 | free(pending); | ||
659 | } | ||
660 | |||
661 | goto cleanup; | ||
662 | |||
663 | data_error:; | ||
664 | static const char *error_json = "{ \"success\": false, \"error\": " | ||
665 | "\"Failed to create clipboard data request\" }"; | ||
666 | ipc_send_reply(client, error_json, (uint32_t)strlen(error_json)); | ||
667 | free(json); | ||
668 | free(pending); | ||
669 | |||
670 | cleanup: | ||
671 | list_free(requested); | ||
672 | free(types); | ||
673 | } | ||
674 | |||
675 | void ipc_client_handle_command(struct ipc_client *client) { | 380 | void ipc_client_handle_command(struct ipc_client *client) { |
676 | if (!sway_assert(client != NULL, "client != NULL")) { | 381 | if (!sway_assert(client != NULL, "client != NULL")) { |
677 | return; | 382 | return; |
@@ -830,52 +535,6 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
830 | goto exit_cleanup; | 535 | goto exit_cleanup; |
831 | } | 536 | } |
832 | 537 | ||
833 | case IPC_SWAY_GET_PIXELS: | ||
834 | { | ||
835 | char response_header[9]; | ||
836 | memset(response_header, 0, sizeof(response_header)); | ||
837 | |||
838 | json_object *obj = json_tokener_parse(buf); | ||
839 | json_object *o, *x, *y, *w, *h; | ||
840 | |||
841 | json_object_object_get_ex(obj, "output", &o); | ||
842 | json_object_object_get_ex(obj, "x", &x); | ||
843 | json_object_object_get_ex(obj, "y", &y); | ||
844 | json_object_object_get_ex(obj, "w", &w); | ||
845 | json_object_object_get_ex(obj, "h", &h); | ||
846 | |||
847 | struct wlc_geometry g = { | ||
848 | .origin = { | ||
849 | .x = json_object_get_int(x), | ||
850 | .y = json_object_get_int(y) | ||
851 | }, | ||
852 | .size = { | ||
853 | .w = json_object_get_int(w), | ||
854 | .h = json_object_get_int(h) | ||
855 | } | ||
856 | }; | ||
857 | |||
858 | swayc_t *output = swayc_by_test(&root_container, output_by_name_test, (void *)json_object_get_string(o)); | ||
859 | json_object_put(obj); | ||
860 | |||
861 | if (!output) { | ||
862 | sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); | ||
863 | ipc_send_reply(client, response_header, sizeof(response_header)); | ||
864 | goto exit_cleanup; | ||
865 | } | ||
866 | struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); | ||
867 | if (!req) { | ||
868 | sway_log(L_ERROR, "Unable to allocate get_pixels request"); | ||
869 | goto exit_cleanup; | ||
870 | } | ||
871 | req->client = client; | ||
872 | req->output = output->handle; | ||
873 | req->geo = g; | ||
874 | list_add(ipc_get_pixel_requests, req); | ||
875 | wlc_output_schedule_render(output->handle); | ||
876 | goto exit_cleanup; | ||
877 | } | ||
878 | |||
879 | case IPC_GET_BAR_CONFIG: | 538 | case IPC_GET_BAR_CONFIG: |
880 | { | 539 | { |
881 | if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { | 540 | if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { |
@@ -917,14 +576,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
917 | } | 576 | } |
918 | 577 | ||
919 | case IPC_GET_CLIPBOARD: | 578 | case IPC_GET_CLIPBOARD: |
920 | { | 579 | // TODO WLR |
921 | if (!(client->security_policy & IPC_FEATURE_GET_CLIPBOARD)) { | 580 | break; |
922 | goto exit_denied; | ||
923 | } | ||
924 | |||
925 | ipc_get_clipboard(client, buf); | ||
926 | goto exit_cleanup; | ||
927 | } | ||
928 | 581 | ||
929 | default: | 582 | default: |
930 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 583 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); |
@@ -977,7 +630,9 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
977 | client->write_buffer_len += payload_length; | 630 | client->write_buffer_len += payload_length; |
978 | 631 | ||
979 | if (!client->writable_event_source) { | 632 | if (!client->writable_event_source) { |
980 | client->writable_event_source = wlc_event_loop_add_fd(client->fd, WLC_EVENT_WRITABLE, ipc_client_handle_writable, client); | 633 | client->writable_event_source = wl_event_loop_add_fd( |
634 | server.wl_event_loop, client->fd, WL_EVENT_WRITABLE, | ||
635 | ipc_client_handle_writable, client); | ||
981 | } | 636 | } |
982 | 637 | ||
983 | sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); | 638 | sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); |