diff options
author | nyorain <nyorain@gmail.com> | 2017-07-07 15:38:45 +0200 |
---|---|---|
committer | nyorain <nyorain@gmail.com> | 2017-07-07 15:38:45 +0200 |
commit | 02c75ebe37d50ff97c4fd8b6be169ac4e1074b07 (patch) | |
tree | dc5f4295e0b988b2f8746507a2fadfbda7b8d881 /sway/ipc-server.c | |
parent | Make asciidoc (and man pages) optional (diff) | |
download | sway-02c75ebe37d50ff97c4fd8b6be169ac4e1074b07.tar.gz sway-02c75ebe37d50ff97c4fd8b6be169ac4e1074b07.tar.zst sway-02c75ebe37d50ff97c4fd8b6be169ac4e1074b07.zip |
Implement ipc get_clipboard
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r-- | sway/ipc-server.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index dca881fa..5bc64b1f 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -55,6 +55,11 @@ struct get_pixels_request { | |||
55 | struct wlc_geometry geo; | 55 | struct wlc_geometry geo; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct get_clipboard_request { | ||
59 | struct ipc_client *client; | ||
60 | struct wlc_event_source *event_source; | ||
61 | }; | ||
62 | |||
58 | struct sockaddr_un *ipc_user_sockaddr(void); | 63 | struct sockaddr_un *ipc_user_sockaddr(void); |
59 | int ipc_handle_connection(int fd, uint32_t mask, void *data); | 64 | int ipc_handle_connection(int fd, uint32_t mask, void *data); |
60 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); | 65 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); |
@@ -322,6 +327,46 @@ void ipc_get_pixels(wlc_handle output) { | |||
322 | ipc_get_pixel_requests = unhandled; | 327 | ipc_get_pixel_requests = unhandled; |
323 | } | 328 | } |
324 | 329 | ||
330 | static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) | ||
331 | { | ||
332 | assert(data); | ||
333 | struct get_clipboard_request *req = (struct get_clipboard_request*) data; | ||
334 | |||
335 | if (mask & WLC_EVENT_ERROR) { | ||
336 | sway_log(L_ERROR, "Selection data fd error"); | ||
337 | const char *error = "{ \"success\": false, \"error\": " | ||
338 | "\"Could not receive text data from clipboard\" }"; | ||
339 | ipc_send_reply(req->client, error, (uint32_t)strlen(error)); | ||
340 | goto cleanup; | ||
341 | } | ||
342 | |||
343 | if (mask & WLC_EVENT_READABLE) { | ||
344 | char buf[512]; | ||
345 | int ret = read(fd, buf, 511); | ||
346 | if (ret < 0) { | ||
347 | sway_log_errno(L_ERROR, "Reading from selection data fd failed"); | ||
348 | const char *error = "{ \"success\": false, \"error\": " | ||
349 | "\"Could not receive text data from clipboard\" }"; | ||
350 | ipc_send_reply(req->client, error, (uint32_t)strlen(error)); | ||
351 | goto cleanup; | ||
352 | } | ||
353 | |||
354 | buf[ret] = '\0'; | ||
355 | json_object *obj = json_object_new_object(); | ||
356 | json_object_object_add(obj, "success", json_object_new_boolean(true)); | ||
357 | json_object_object_add(obj, "content", json_object_new_string(buf)); | ||
358 | const char *str = json_object_to_json_string(obj); | ||
359 | ipc_send_reply(req->client, str, (uint32_t)strlen(str)); | ||
360 | json_object_put(obj); | ||
361 | } | ||
362 | |||
363 | cleanup: | ||
364 | wlc_event_source_remove(req->event_source); | ||
365 | close(fd); | ||
366 | free(req); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
325 | void ipc_client_handle_command(struct ipc_client *client) { | 370 | void ipc_client_handle_command(struct ipc_client *client) { |
326 | if (!sway_assert(client != NULL, "client != NULL")) { | 371 | if (!sway_assert(client != NULL, "client != NULL")) { |
327 | return; | 372 | return; |
@@ -565,6 +610,70 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
565 | goto exit_cleanup; | 610 | goto exit_cleanup; |
566 | } | 611 | } |
567 | 612 | ||
613 | case IPC_GET_CLIPBOARD: | ||
614 | { | ||
615 | if (!(client->security_policy & IPC_FEATURE_GET_CLIPBOARD)) { | ||
616 | goto exit_denied; | ||
617 | } | ||
618 | |||
619 | size_t size; | ||
620 | bool found = false; | ||
621 | const char **types = wlc_get_selection_types(&size); | ||
622 | if (types == NULL || size == 0) { | ||
623 | const char *error = "{ \"success\": false, \"error\": " | ||
624 | "\"Empty clipboard\" }"; | ||
625 | ipc_send_reply(client, error, (uint32_t)strlen(error)); | ||
626 | goto exit_cleanup; | ||
627 | } | ||
628 | |||
629 | for (size_t i = 0; i < size; ++i) { | ||
630 | if (strcmp(types[i], "text/plain;charset=utf-8") != 0 | ||
631 | && strcmp(types[i], "text/plain") != 0) { | ||
632 | continue; | ||
633 | } | ||
634 | |||
635 | struct get_clipboard_request *req = malloc(sizeof(*req)); | ||
636 | if (!req) { | ||
637 | sway_log(L_ERROR, "Unable to allocate get_clipboard_request"); | ||
638 | goto exit_cleanup; | ||
639 | } | ||
640 | |||
641 | int pipes[2]; | ||
642 | if (pipe(pipes) == -1) { | ||
643 | sway_log_errno(L_ERROR, "pipe call failed"); | ||
644 | free(req); | ||
645 | break; | ||
646 | } | ||
647 | |||
648 | fcntl(pipes[0], F_SETFD, FD_CLOEXEC | O_NONBLOCK); | ||
649 | fcntl(pipes[1], F_SETFD, FD_CLOEXEC | O_NONBLOCK); | ||
650 | if (!wlc_get_selection_data(types[i], pipes[1])) { | ||
651 | close(pipes[0]); | ||
652 | close(pipes[1]); | ||
653 | free(req); | ||
654 | sway_log(L_ERROR, "wlc_get_selection_data failed"); | ||
655 | break; | ||
656 | } | ||
657 | |||
658 | req->client = client; | ||
659 | req->event_source = wlc_event_loop_add_fd(pipes[0], | ||
660 | WLC_EVENT_READABLE | WLC_EVENT_ERROR | WLC_EVENT_HANGUP, | ||
661 | &ipc_selection_data_cb, req); | ||
662 | found = true; | ||
663 | break; | ||
664 | } | ||
665 | |||
666 | if (!found) { | ||
667 | sway_log(L_INFO, "Clipboard has to text data"); | ||
668 | const char *error = "{ \"success\": false, \"error\": " | ||
669 | "\"Could not receive text data from clipboard\" }"; | ||
670 | ipc_send_reply(client, error, (uint32_t)strlen(error)); | ||
671 | } | ||
672 | |||
673 | free(types); | ||
674 | goto exit_cleanup; | ||
675 | } | ||
676 | |||
568 | default: | 677 | default: |
569 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 678 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); |
570 | goto exit_cleanup; | 679 | goto exit_cleanup; |