aboutsummaryrefslogtreecommitdiff
path: root/data-device.c
diff options
context:
space:
mode:
authorJack Jamison <jackqjamison@gmail.com>2025-10-23 13:58:43 -0400
committerJack Jamison <jackqjamison@gmail.com>2025-10-23 13:58:43 -0400
commit6933f5438f303cd90346ae779af141f910a4a1b1 (patch)
treeedd477d1d42f35bdcbc13e5dc0aef9b1c44899e6 /data-device.c
parent9d8db4146d025e3a967700414a9fc68fa186045e (diff)
clipboard with wl-paste
Diffstat (limited to 'data-device.c')
-rw-r--r--data-device.c80
1 files changed, 80 insertions, 0 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,
+};