shithub: drawterm

Download patch

ref: c53aae4aec0b41d9427d60d78eb4c1ef0e535009
parent: 9d09c9315c3051e7633f7774ab65345804f1e192
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Jan 18 15:13:42 EST 2022

gui-wl: set primary selection

--- a/gui-wl/Makefile
+++ b/gui-wl/Makefile
@@ -4,15 +4,18 @@
 
 XDG_SHELL=/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml
 XDG_DECO=/usr/share/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml
+XDG_PRIMSEL=/usr/share/wayland-protocols/unstable/primary-selection/primary-selection-unstable-v1.xml
 
 HFILES=\
 	xdg-shell-protocol.h\
 	xdg-decoration-protocol.h\
+	xdg-primary-selection-protocol.h\
 	wl-inc.h\
 
 OFILES=\
 	xdg-shell-protocol.$O\
 	xdg-decoration-protocol.$O\
+	xdg-primary-selection-protocol.$O\
 	wl-cb.$O\
 	wl-screen.$O\
 	wl-util.$O\
@@ -28,6 +31,12 @@
 
 xdg-decoration-protocol.h:
 	wayland-scanner client-header < $(XDG_DECO) > $@ || { rm -f $@; exit 1; }
+
+xdg-primary-selection-protocol.c:
+	wayland-scanner private-code < $(XDG_PRIMSEL) > $@ || { rm -f $@; exit 1; }
+
+xdg-primary-selection-protocol.h:
+	wayland-scanner client-header < $(XDG_PRIMSEL) > $@ || { rm -f $@; exit 1; }
 
 default: $(LIB)
 $(LIB): $(HFILES) $(OFILES)
--- a/gui-wl/wl-cb.c
+++ b/gui-wl/wl-cb.c
@@ -10,6 +10,7 @@
 #include <xkbcommon/xkbcommon.h>
 #include "xdg-shell-protocol.h"
 #include "xdg-decoration-protocol.h"
+#include "xdg-primary-selection-protocol.h"
 
 #include "u.h"
 #include "lib.h"
@@ -415,6 +416,44 @@
 };
 
 static void
+primsel_source_handle_send(void *data, struct zwp_primary_selection_source_v1 *source, const char *mime_type, int fd)
+{
+	ulong n;
+	ulong pos;
+	ulong len;
+	Wlwin *wl;
+
+	if(strcmp(mime_type, "text/plain;charset=utf-8") != 0)
+		return;
+
+	wl = data;
+	qlock(&wl->clip.lk);
+	len = strlen(wl->clip.content);
+	for(pos = 0; (n = write(fd, wl->clip.content+pos, len-pos)) > 0 && pos < len; pos += n)
+		;
+	wl->clip.primsel_posted = 0;
+	close(fd);
+	qunlock(&wl->clip.lk);
+}
+
+static void
+primsel_source_handle_cancelled(void *data, struct zwp_primary_selection_source_v1 *source)
+{
+	Wlwin *wl;
+
+	wl = data;
+	qlock(&wl->clip.lk);
+	wl->clip.primsel_posted = 0;
+	qunlock(&wl->clip.lk);
+	zwp_primary_selection_source_v1_destroy(source);
+}
+
+static const struct zwp_primary_selection_source_v1_listener primsel_source_listener = {
+	.send = primsel_source_handle_send,
+	.cancelled = primsel_source_handle_cancelled,
+};
+
+static void
 data_device_handle_data_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer)
 {
 }
@@ -492,6 +531,8 @@
 		wl->data_device_manager = wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3);
 	} else if(strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
 		wl->decoman = wl_registry_bind(registry, name, &zxdg_decoration_manager_v1_interface, 1);
+	} else if(strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
+		wl->primsel = wl_registry_bind(registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
 	}
 }
 
@@ -525,9 +566,10 @@
 	wl_display_roundtrip(wl->display);
 	wl->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 
-	if(wl->shm == nil || wl->compositor == nil || wl->xdg_wm_base == nil || wl->seat == nil || wl->decoman == nil)
+	if(wl->shm == nil || wl->compositor == nil || wl->xdg_wm_base == nil || wl->seat == nil || wl->decoman == nil || wl->primsel == nil)
 		sysfatal("Registration fell short");
 
+	wl->primsel_device = zwp_primary_selection_device_manager_v1_get_device(wl->primsel, wl->seat);
 
 	wl->data_device = wl_data_device_manager_get_data_device(wl->data_device_manager, wl->seat);
 	wl_data_device_add_listener(wl->data_device, &data_device_listener, wl);
@@ -560,20 +602,30 @@
 wlsetsnarf(Wlwin *wl, char *s)
 {
 	struct wl_data_source *source;
+	struct zwp_primary_selection_source_v1 *psource;
 
 	qlock(&wl->clip.lk);
 	free(wl->clip.content);
 	wl->clip.content = strdup(s);
+
 	/* Do we still own the clipboard? */
-	if(wl->clip.posted == 1)
-		goto done;
+	if(wl->clip.posted == 0){
+		source = wl_data_device_manager_create_data_source(wl->data_device_manager);
+		wl_data_source_add_listener(source, &data_source_listener, wl);
+		wl_data_source_offer(source, "text/plain;charset=utf-8");
+		wl_data_device_set_selection(wl->data_device, source, wl->clip.serial);
+		wl->clip.posted = 1;
+	}
 
-	source = wl_data_device_manager_create_data_source(wl->data_device_manager);
-	wl_data_source_add_listener(source, &data_source_listener, wl);
-	wl_data_source_offer(source, "text/plain;charset=utf-8");
-	wl_data_device_set_selection(wl->data_device, source, wl->clip.serial);
-	wl->clip.posted = 1;
-done:
+	/* Primary selection */
+	if(wl->clip.primsel_posted == 0){
+		psource = zwp_primary_selection_device_manager_v1_create_source(wl->primsel);
+		zwp_primary_selection_source_v1_add_listener(psource, &primsel_source_listener, wl);
+		zwp_primary_selection_source_v1_offer(psource, "text/plain;charset=utf-8");
+		zwp_primary_selection_device_v1_set_selection(wl->primsel_device, psource, wl->clip.serial);
+		wl->clip.primsel_posted = 1;
+	}
+
 	qunlock(&wl->clip.lk);
 }
 
--- a/gui-wl/wl-inc.h
+++ b/gui-wl/wl-inc.h
@@ -25,6 +25,7 @@
 	 * Posted stores if we already made
 	 * our round trip */
 	int posted;
+	int primsel_posted;
 };
 
 struct Mouse {
@@ -66,6 +67,9 @@
 	struct xkb_context *xkb_context;
 
 	struct zxdg_decoration_manager_v1 *decoman;
+
+	struct zwp_primary_selection_device_manager_v1 *primsel;
+	struct zwp_primary_selection_device_v1 *primsel_device;
 };
 
 void wlallocbuffer(Wlwin*);