wayclip

Wayland clipboard utility
git clone git://git.nihaljere.xyz/wayclip
Log | Files | Refs | README | LICENSE

commit acfd22d0149f3cc20b20ecc43abb6881db93abf8
parent 53e0dedb1add9a603e65958999cecce20314a2ff
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Mon, 21 Feb 2022 23:29:41 -0600

add waypaste

Diffstat:
M.gitignore | 1+
MMakefile | 5+++++
Mutil.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Mutil.h | 2++
Mwaycopy.c | 24------------------------
Awaypaste.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 165 insertions(+), 24 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,4 @@ *.o protocol/*.[ch] waycopy +waypaste diff --git a/Makefile b/Makefile @@ -1,6 +1,11 @@ .c.o: $(CC) -Wall -c $< -o $@ +all: waycopy waypaste + +waypaste: protocol/wlr-data-control-unstable-v1-client-protocol.h protocol/wlr-data-control-unstable-v1.o waypaste.o util.o + $(CC) protocol/wlr-data-control-unstable-v1.o waypaste.o util.o -lwayland-client -o waypaste + waycopy: protocol/wlr-data-control-unstable-v1-client-protocol.h protocol/wlr-data-control-unstable-v1.o waycopy.o util.o $(CC) protocol/wlr-data-control-unstable-v1.o waycopy.o util.o -lwayland-client -o waycopy diff --git a/util.c b/util.c @@ -1,5 +1,6 @@ #include <stdlib.h> #include <stdio.h> +#include <unistd.h> #include "util.h" @@ -18,3 +19,55 @@ warn(const char *const error) fprintf(stderr, "%s: warning: %s\n", argv0, error); } +void +copyfile(FILE *out, FILE *in) +{ + char buf[BUFSIZ]; + + size_t rcount, wcount; + do { + rcount = fread(buf, 1, BUFSIZ, in); + wcount = fwrite(buf, 1, rcount, out); + if (rcount < BUFSIZ) { + if (ferror(in)) { + // TODO: print actual error + warn("fread failed"); + } else if (feof(in)) { + break; + } + } + + if (wcount < rcount) { + warn("fwrite failed"); + } + } while (1); +} + +void +copyfd(int out, int in) +{ + char buf[BUFSIZ], *ptr; + + size_t rcount, wcount; + do { + rcount = read(in, buf, BUFSIZ); + if (rcount == -1) { + warn("read failed"); + } + + wcount = 0; + ptr = buf; + while (wcount < rcount) { + ssize_t len = write(out, ptr, rcount); + if (len == -1) { + warn("read failed"); + return; + } + + ptr += len; + wcount += len; + } + if (rcount < BUFSIZ) + break; + } while (1); +} diff --git a/util.h b/util.h @@ -1,2 +1,4 @@ void die(const char *const error); void warn(const char *const error); +void copyfile(FILE *out, FILE *in); +void copyfd(int out, int in); diff --git a/waycopy.c b/waycopy.c @@ -22,30 +22,6 @@ FILE *temp; bool running = 1; void -copyfile(FILE *out, FILE *in) -{ - char buf[BUFSIZ]; - - size_t rcount, wcount; - do { - rcount = fread(buf, 1, BUFSIZ, in); - wcount = fwrite(buf, 1, rcount, out); - if (rcount < BUFSIZ) { - if (ferror(in)) { - // TODO: print actual error - warn("fread failed"); - } else if (feof(in)) { - break; - } - } - - if (wcount < rcount) { - warn("fwrite failed"); - } - } while (1); -} - -void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { if (strcmp(interface, "wl_seat") == 0) { diff --git a/waypaste.c b/waypaste.c @@ -0,0 +1,104 @@ +#include <assert.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <wayland-client.h> +#include <unistd.h> + +#include "protocol/wlr-data-control-unstable-v1-client-protocol.h" +#include "util.h" + +struct zwlr_data_control_manager_v1 *data_control_manager; +struct wl_seat *seat; +struct wl_display *display; +int pipes[2]; + +void +registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) +{ + if (strcmp(interface, "wl_seat") == 0) { + seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); + } else if (strcmp(interface, "zwlr_data_control_manager_v1") == 0) { + data_control_manager = wl_registry_bind(registry, name, &zwlr_data_control_manager_v1_interface, 1); + } +} + +void +registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + .global = registry_global, + .global_remove = registry_global_remove, +}; + +void +offer_offer(void *data, struct zwlr_data_control_offer_v1 *offer, const char *mime_type) +{ + if (strcmp(mime_type, "text/plain") == 0) { + if (pipe(pipes) == -1) + die("failed to create pipe"); + + zwlr_data_control_offer_v1_receive(offer, mime_type, pipes[1]); + wl_display_roundtrip(display); + } else { + return; + } + + copyfd(STDOUT_FILENO, pipes[0]); + close(pipes[0]); + + exit(0); +} + +static const struct zwlr_data_control_offer_v1_listener offer_listener = { + .offer = offer_offer, +}; + +void +control_data_offer(void *data, struct zwlr_data_control_device_v1 *device, struct zwlr_data_control_offer_v1 *offer) +{ + zwlr_data_control_offer_v1_add_listener(offer, &offer_listener, NULL); +} + +void +control_data_selection(void *data, struct zwlr_data_control_device_v1 *device, struct zwlr_data_control_offer_v1 *offer) +{ +} + +static const struct zwlr_data_control_device_v1_listener device_listener = { + .data_offer = control_data_offer, + .selection = control_data_selection, +}; + +int +main() +{ + display = wl_display_connect(NULL); + if (display == NULL) + die("failed to connect to display"); + + struct wl_registry *const registry = wl_display_get_registry(display); + if (registry == NULL) + die("failed to get registry"); + + wl_registry_add_listener(registry, &registry_listener, NULL); + + wl_display_roundtrip(display); + + if (seat == NULL) + die("failed to bind to seat interface"); + + if (data_control_manager == NULL) + die("failed to bind to data_control_manager interface"); + + struct zwlr_data_control_device_v1 *device = zwlr_data_control_manager_v1_get_data_device(data_control_manager, seat); + if (device == NULL) + die("data device is null"); + + zwlr_data_control_device_v1_add_listener(device, &device_listener, NULL); + + wl_display_roundtrip(display); +}