ref: c53aae4aec0b41d9427d60d78eb4c1ef0e535009
parent: 9d09c9315c3051e7633f7774ab65345804f1e192
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Jan 18 16: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*);