diff --git a/input.c b/input.c index 951397d3..934fc5af 100644 --- a/input.c +++ b/input.c @@ -161,6 +161,11 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, selection_to_clipboard(term, serial); found_map = true; } + + else if (sym == XKB_KEY_V) { + selection_from_clipboard(term, serial); + found_map = true; + } } for (size_t i = 0; i < sizeof(key_map) / sizeof(key_map[0]) && !found_map; i++) { diff --git a/selection.c b/selection.c index 99688e01..29d4cb46 100644 --- a/selection.c +++ b/selection.c @@ -2,6 +2,7 @@ #include #include +#include #define LOG_MODULE "selection" #define LOG_ENABLE_DBG 0 @@ -257,6 +258,44 @@ selection_to_clipboard(struct terminal *term, uint32_t serial) clipboard->serial = serial; } +void +selection_from_clipboard(struct terminal *term, uint32_t serial) +{ + struct clipboard *clipboard = &term->selection.clipboard; + if (clipboard->data_offer == NULL) + return; + + wl_data_offer_accept(clipboard->data_offer, serial, "text/plain"); + wl_data_offer_accept(clipboard->data_offer, serial, "text/plain;charset=utf-8"); + + int fds[2]; + + if (pipe2(fds, O_CLOEXEC) == -1) { + LOG_ERRNO("failed to create pipe"); + return; + } + + int read_fd = fds[0]; + int write_fd = fds[1]; + + wl_data_offer_receive(clipboard->data_offer, "text/plain;charset=utf-8", write_fd); + wl_display_roundtrip(term->wl.display); + + char text[4096]; + ssize_t amount = read(read_fd, text, sizeof(text)); + + close(read_fd); + close(write_fd); + + if (term->bracketed_paste) + write(term->ptmx, "\033[200~", 6); + + write(term->ptmx, text, amount); + + if (term->bracketed_paste) + write(term->ptmx, "\033[201~", 6); +} + static void offer(void *data, struct wl_data_offer *wl_data_offer, const char *mime_type) { @@ -320,7 +359,8 @@ selection(void *data, struct wl_data_device *wl_data_device, wl_data_offer_destroy(clipboard->data_offer); clipboard->data_offer = id; - wl_data_offer_add_listener(id, &data_offer_listener, term); + if (id != NULL) + wl_data_offer_add_listener(id, &data_offer_listener, term); } const struct wl_data_device_listener data_device_listener = { diff --git a/selection.h b/selection.h index 81eb3174..41fc5bbb 100644 --- a/selection.h +++ b/selection.h @@ -10,4 +10,6 @@ void selection_start(struct terminal *term, int col, int row); void selection_update(struct terminal *term, int col, int row); void selection_finalize(struct terminal *term); void selection_cancel(struct terminal *term); + void selection_to_clipboard(struct terminal *term, uint32_t serial); +void selection_from_clipboard(struct terminal *term, uint32_t serial);