diff options
| -rw-r--r-- | data-device.c | 80 | ||||
| -rw-r--r-- | input_field.c | 18 | ||||
| -rw-r--r-- | registry.c | 5 | ||||
| -rw-r--r-- | seat.c | 1 | ||||
| -rw-r--r-- | state.h | 5 | ||||
| -rw-r--r-- | wayland.h | 1 |
6 files changed, 94 insertions, 16 deletions
diff --git a/data-device.c b/data-device.c new file mode 100644 index 0000000..3d04f1e --- /dev/null +++ b/data-device.c @@ -0,0 +1,80 @@ +#include "wayland.h" +#include <unistd.h> + +struct wl_data_device_listener data_device_listener; + +void setup_data_device(client_state* state) { + state->data_device = wl_data_device_manager_get_data_device(state->data_device_manager, state->seat); + wl_data_device_add_listener(state->data_device, &data_device_listener, state); +} + +static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, + const char *mime_type) { +} + +static const struct wl_data_offer_listener data_offer_listener = { + .offer = data_offer_handle_offer, +}; + +static void data_device_handle_data_offer(void *data, + struct wl_data_device *data_device, struct wl_data_offer *offer) { + // An application has created a new data source + wl_data_offer_add_listener(offer, &data_offer_listener, NULL); +} + +static void data_device_handle_selection(void *data, + struct wl_data_device *data_device, struct wl_data_offer *offer) { + + client_state *state = data; + state->data_offer = offer; + + // free old clipboard + free(state->clipboard); + + // no clipboard contents + if (offer == NULL) { + state->clipboard = ""; + return; + } + + // get contents in fd + int fds[2]; + pipe(fds); + wl_data_offer_receive(offer, "text/plain", fds[1]); + close(fds[1]); + wl_display_roundtrip(state->display); + + // read fd + state->clipboard_size = 64; + state->clipboard = malloc(state->clipboard_size); + size_t current_clip = 0; + while (true) { + ssize_t n = read(fds[0], state->clipboard + current_clip, state->clipboard_size - current_clip); + if (n <= 0) { + break; + } + current_clip += n; + if (current_clip == state->clipboard_size) { + state->clipboard_size *= 2; + state->clipboard = realloc(state->clipboard, state->clipboard_size); + } + } + close(fds[0]); + + state->clipboard_size = current_clip; // we don't need the ACTUAL length of the buffer anymore, just the string :D + // remove newlines + int i, j; + for (i = 0, j = 0; i < state->clipboard_size; i++) { + if (state->clipboard[i] != '\n' && state->clipboard[i] != '\r') { + state->clipboard[j++] = state->clipboard[i]; + } + } + state->clipboard_size = j; + + wl_data_offer_destroy(offer); +} + +struct wl_data_device_listener data_device_listener = { + .data_offer = data_device_handle_data_offer, + .selection = data_device_handle_selection, +}; diff --git a/input_field.c b/input_field.c index a0d5cc6..6b34b1f 100644 --- a/input_field.c +++ b/input_field.c @@ -123,26 +123,14 @@ bool type_key(client_state* state, xkb_keysym_t keysym) { // paste if (keysym == XKB_KEY_v && ctrl) { - FILE* fp = popen("wl-paste --no-newline --type text/plain 2>/dev/null", "r"); - if (!fp) return false; - char* buffer = NULL; - size_t size = 0; - ssize_t len = getdelim(&buffer, &size, '\0', fp); - int status = pclose(fp); - - if (status != 0 || len <= 0) { - free(buffer); - return false; - } - - for (size_t i = 0; i < len; ++i) { - array_add(state->input_buffer, buffer[i]); + for (size_t i = 0; i < state->clipboard_size; ++i) { + array_insert(state->input_buffer, state->cursor_index, state->clipboard[i]); + ++state->cursor_index; } update_text_buffer(state); - free(buffer); return true; } @@ -24,7 +24,7 @@ void global(void *data, struct wl_registry *wl_registry, uint32_t name, const ch state->compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1); } else if (!strcmp(interface, wl_seat_interface.name)) { - state->seat = wl_registry_bind(state->registry, name, &wl_seat_interface, 4); + state->seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4); } else if (!strcmp(interface, zwlr_layer_shell_v1_interface.name)) { state->layer_shell = wl_registry_bind(wl_registry, name, &zwlr_layer_shell_v1_interface, 5); @@ -32,6 +32,9 @@ void global(void *data, struct wl_registry *wl_registry, uint32_t name, const ch else if (!strcmp(interface, wp_cursor_shape_manager_v1_interface.name)) { state->cursor_shape_manager = wl_registry_bind( wl_registry, name, &wp_cursor_shape_manager_v1_interface, 1); } + else if (!strcmp(interface, wl_data_device_manager_interface.name)) { + state->data_device_manager = wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3); + } else { } @@ -12,6 +12,7 @@ void setup_seat(client_state* state) { void capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { client_state* state = data; + setup_data_device(state); if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD && !state->keyboard) { setup_keyboard(state); } @@ -60,6 +60,9 @@ typedef struct { struct zwlr_layer_shell_v1* layer_shell; struct zwlr_layer_surface_v1* layer_surface; struct wl_seat* seat; + struct wl_data_device_manager *data_device_manager; + struct wl_data_device *data_device; + struct wl_data_offer *data_offer; struct wl_keyboard* keyboard; struct wl_pointer* pointer; struct wp_cursor_shape_manager_v1* cursor_shape_manager; @@ -113,6 +116,8 @@ typedef struct { // state uint32_t width, height; + char* clipboard; + size_t clipboard_size; char* input_buffer; item_t* items; item_display_t* filtered_items; @@ -6,6 +6,7 @@ void setup_registry_and_globals(client_state* state); void create_surface(client_state* state); void setup_seat(client_state* state); +void setup_data_device(client_state* state); void setup_pointer(client_state* state); void setup_keyboard(client_state* state); |
