mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
selection: add support for pasting *from* primary
This commit is contained in:
parent
e56066feef
commit
703aeecb95
5 changed files with 124 additions and 6 deletions
29
main.c
29
main.c
|
|
@ -131,6 +131,11 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
term->wl.data_device_manager = wl_registry_bind(
|
||||
term->wl.registry, name, &wl_data_device_manager_interface, 1);
|
||||
}
|
||||
|
||||
else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
|
||||
term->wl.primary_selection_device_manager = wl_registry_bind(
|
||||
term->wl.registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -403,12 +408,22 @@ main(int argc, char *const *argv)
|
|||
"(wl_data_device_manager not implemented by server)");
|
||||
goto out;
|
||||
}
|
||||
if (term.wl.primary_selection_device_manager == NULL) {
|
||||
LOG_ERR("no primary selection available");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Clipboard */
|
||||
term.wl.data_device = wl_data_device_manager_get_data_device(
|
||||
term.wl.data_device_manager, term.wl.seat);
|
||||
wl_data_device_add_listener(term.wl.data_device, &data_device_listener, &term);
|
||||
|
||||
/* Primary selection */
|
||||
term.wl.primary_selection_device = zwp_primary_selection_device_manager_v1_get_device(
|
||||
term.wl.primary_selection_device_manager, term.wl.seat);
|
||||
zwp_primary_selection_device_v1_add_listener(
|
||||
term.wl.primary_selection_device, &primary_selection_device_listener, &term);
|
||||
|
||||
/* Cursor */
|
||||
term.wl.pointer.surface = wl_compositor_create_surface(term.wl.compositor);
|
||||
if (term.wl.pointer.surface == NULL) {
|
||||
|
|
@ -623,11 +638,6 @@ out:
|
|||
wl_surface_destroy(term.wl.pointer.surface);
|
||||
if (term.wl.keyboard != NULL)
|
||||
wl_keyboard_destroy(term.wl.keyboard);
|
||||
if (term.selection.primary.data_source != NULL)
|
||||
wl_data_source_destroy(term.selection.primary.data_source);
|
||||
if (term.selection.primary.data_offer != NULL)
|
||||
wl_data_offer_destroy(term.selection.primary.data_offer);
|
||||
free(term.selection.primary.text);
|
||||
if (term.selection.clipboard.data_source != NULL)
|
||||
wl_data_source_destroy(term.selection.clipboard.data_source);
|
||||
if (term.selection.clipboard.data_offer != NULL)
|
||||
|
|
@ -637,6 +647,15 @@ out:
|
|||
wl_data_device_destroy(term.wl.data_device);
|
||||
if (term.wl.data_device_manager != NULL)
|
||||
wl_data_device_manager_destroy(term.wl.data_device_manager);
|
||||
if (term.selection.primary.data_source != NULL)
|
||||
zwp_primary_selection_source_v1_destroy(term.selection.primary.data_source);
|
||||
if (term.selection.primary.data_offer != NULL)
|
||||
zwp_primary_selection_offer_v1_destroy(term.selection.primary.data_offer);
|
||||
free(term.selection.primary.text);
|
||||
if (term.wl.primary_selection_device != NULL)
|
||||
zwp_primary_selection_device_v1_destroy(term.wl.primary_selection_device);
|
||||
if (term.wl.primary_selection_device_manager != NULL)
|
||||
zwp_primary_selection_device_manager_v1_destroy(term.wl.primary_selection_device_manager);
|
||||
if (term.wl.seat != NULL)
|
||||
wl_seat_destroy(term.wl.seat);
|
||||
if (term.wl.surface != NULL)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ wl_proto_src = []
|
|||
foreach prot : [
|
||||
#'external/wlr-layer-shell-unstable-v1.xml',
|
||||
wayland_protocols_datadir + '/stable/xdg-shell/xdg-shell.xml',
|
||||
wayland_protocols_datadir + '/unstable/primary-selection/primary-selection-unstable-v1.xml',
|
||||
#wayland_protocols_datadir + '/unstable/xdg-output/xdg-output-unstable-v1.xml']
|
||||
]
|
||||
|
||||
|
|
|
|||
86
selection.c
86
selection.c
|
|
@ -342,6 +342,49 @@ void
|
|||
selection_from_primary(struct terminal *term)
|
||||
{
|
||||
LOG_WARN("selection from PRIMARY");
|
||||
struct primary *primary = &term->selection.primary;
|
||||
if (primary->data_offer == NULL)
|
||||
return;
|
||||
|
||||
/* Prepare a pipe the other client can write its selection to us */
|
||||
int fds[2];
|
||||
if (pipe2(fds, O_CLOEXEC) == -1) {
|
||||
LOG_ERRNO("failed to create pipe");
|
||||
return;
|
||||
}
|
||||
|
||||
int read_fd = fds[0];
|
||||
int write_fd = fds[1];
|
||||
|
||||
/* Give write-end of pipe to other client */
|
||||
zwp_primary_selection_offer_v1_receive(
|
||||
primary->data_offer, "text/plain;charset=utf-8", write_fd);
|
||||
wl_display_roundtrip(term->wl.display);
|
||||
|
||||
/* Don't keep our copy of the write-end open (or we'll never get EOF) */
|
||||
close(write_fd);
|
||||
|
||||
if (term->bracketed_paste)
|
||||
write(term->ptmx, "\033[200~", 6);
|
||||
|
||||
/* Read until EOF */
|
||||
while (true) {
|
||||
char text[256];
|
||||
ssize_t amount = read(read_fd, text, sizeof(text));
|
||||
|
||||
if (amount == -1) {
|
||||
LOG_ERRNO("failed to read clipboard data: %d", errno);
|
||||
break;
|
||||
} else if (amount == 0)
|
||||
break;
|
||||
|
||||
write(term->ptmx, text, amount);
|
||||
}
|
||||
|
||||
if (term->bracketed_paste)
|
||||
write(term->ptmx, "\033[201~", 6);
|
||||
|
||||
close(read_fd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -420,3 +463,46 @@ const struct wl_data_device_listener data_device_listener = {
|
|||
.drop = &drop,
|
||||
.selection = &selection,
|
||||
};
|
||||
|
||||
static void
|
||||
primary_offer(void *data,
|
||||
struct zwp_primary_selection_offer_v1 *zwp_primary_selection_offer,
|
||||
const char *mime_type)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener = {
|
||||
.offer = &primary_offer,
|
||||
};
|
||||
|
||||
static void
|
||||
primary_data_offer(void *data,
|
||||
struct zwp_primary_selection_device_v1 *zwp_primary_selection_device,
|
||||
struct zwp_primary_selection_offer_v1 *offer)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
primary_selection(void *data,
|
||||
struct zwp_primary_selection_device_v1 *zwp_primary_selection_device,
|
||||
struct zwp_primary_selection_offer_v1 *id)
|
||||
{
|
||||
/* Selection offer from other client, for primary */
|
||||
|
||||
struct terminal *term = data;
|
||||
struct primary *primary = &term->selection.primary;
|
||||
|
||||
if (primary->data_offer != NULL)
|
||||
zwp_primary_selection_offer_v1_destroy(primary->data_offer);
|
||||
|
||||
primary->data_offer = id;
|
||||
if (id != NULL) {
|
||||
zwp_primary_selection_offer_v1_add_listener(
|
||||
id, &primary_selection_offer_listener, term);
|
||||
}
|
||||
}
|
||||
|
||||
const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
|
||||
.data_offer = &primary_data_offer,
|
||||
.selection = &primary_selection,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "terminal.h"
|
||||
|
||||
extern const struct wl_data_device_listener data_device_listener;
|
||||
extern const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener;
|
||||
|
||||
void selection_start(struct terminal *term, int col, int row);
|
||||
void selection_update(struct terminal *term, int col, int row);
|
||||
|
|
|
|||
13
terminal.h
13
terminal.h
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
#include <cairo.h>
|
||||
#include <wayland-client.h>
|
||||
#include <primary-selection-unstable-v1.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
|
||||
|
||||
#include "tllist.h"
|
||||
|
||||
#define likely(c) __builtin_expect(!!(c), 1)
|
||||
|
|
@ -25,6 +27,8 @@ struct wayland {
|
|||
struct wl_seat *seat;
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct wl_data_device *data_device;
|
||||
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
||||
struct zwp_primary_selection_device_v1 *primary_selection_device;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct {
|
||||
struct wl_pointer *pointer;
|
||||
|
|
@ -193,6 +197,13 @@ struct clipboard {
|
|||
uint32_t serial;
|
||||
};
|
||||
|
||||
struct primary {
|
||||
struct zwp_primary_selection_source_v1 *data_source;
|
||||
struct zwp_primary_selection_offer_v1 *data_offer;
|
||||
char *text;
|
||||
uint32_t serial;
|
||||
};
|
||||
|
||||
struct terminal {
|
||||
pid_t slave;
|
||||
int ptmx;
|
||||
|
|
@ -240,8 +251,8 @@ struct terminal {
|
|||
struct {
|
||||
struct coord start;
|
||||
struct coord end;
|
||||
struct clipboard primary;
|
||||
struct clipboard clipboard;
|
||||
struct primary primary;
|
||||
} selection;
|
||||
|
||||
struct grid normal;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue