mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-01 22:58:40 -04:00
Add proof-of-concept selection support to terminal
Next will be to support mouse selections so we can copy and paste something more interesting than just 'selection data'.
This commit is contained in:
parent
67cac8a565
commit
58eec36f68
3 changed files with 216 additions and 0 deletions
|
|
@ -390,6 +390,11 @@ struct terminal {
|
||||||
struct terminal_color color_table[256];
|
struct terminal_color color_table[256];
|
||||||
cairo_font_extents_t extents;
|
cairo_font_extents_t extents;
|
||||||
cairo_scaled_font_t *font_normal, *font_bold;
|
cairo_scaled_font_t *font_normal, *font_bold;
|
||||||
|
|
||||||
|
uint32_t tag;
|
||||||
|
struct wl_selection *selection;
|
||||||
|
struct wl_selection_offer *selection_offer;
|
||||||
|
uint32_t selection_offer_has_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create default tab stops, every 8 characters */
|
/* Create default tab stops, every 8 characters */
|
||||||
|
|
@ -1872,6 +1877,88 @@ terminal_data(struct terminal *terminal, const char *data, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
selection_listener_send(void *data, struct wl_selection *selection,
|
||||||
|
const char *mime_type, int fd)
|
||||||
|
{
|
||||||
|
struct terminal *terminal = data;
|
||||||
|
static const char msg[] = "selection data";
|
||||||
|
|
||||||
|
fprintf(stderr, "selection send, fd is %d\n", fd);
|
||||||
|
write(fd, msg, sizeof msg);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selection_listener_cancelled(void *data, struct wl_selection *selection)
|
||||||
|
{
|
||||||
|
struct terminal *terminal = data;
|
||||||
|
|
||||||
|
fprintf(stderr, "selection cancelled\n");
|
||||||
|
wl_selection_destroy(selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_selection_listener selection_listener = {
|
||||||
|
selection_listener_send,
|
||||||
|
selection_listener_cancelled
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
selection_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
|
||||||
|
{
|
||||||
|
struct terminal *terminal = data;
|
||||||
|
char buffer[256];
|
||||||
|
unsigned int len;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = g_io_channel_unix_get_fd(source);
|
||||||
|
len = read(fd, buffer, sizeof buffer);
|
||||||
|
fprintf(stderr, "read %d bytes: %.*s\n", len, len, buffer);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
g_source_remove(terminal->tag);
|
||||||
|
|
||||||
|
g_io_channel_unref(source);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handle_bound_key(struct terminal *terminal,
|
||||||
|
struct input *input, uint32_t sym, uint32_t time)
|
||||||
|
{
|
||||||
|
struct wl_shell *shell;
|
||||||
|
GIOChannel *channel;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
switch (sym) {
|
||||||
|
case XK_C:
|
||||||
|
shell = display_get_shell(terminal->display);
|
||||||
|
terminal->selection = wl_shell_create_selection(shell);
|
||||||
|
wl_selection_add_listener(terminal->selection,
|
||||||
|
&selection_listener, terminal);
|
||||||
|
wl_selection_offer(terminal->selection, "text/plain");
|
||||||
|
wl_selection_activate(terminal->selection,
|
||||||
|
input_get_input_device(input), time);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
case XK_V:
|
||||||
|
if (input_offers_mime_type(input, "text/plain")) {
|
||||||
|
fd = input_receive_mime_type(input, "text/plain");
|
||||||
|
channel = g_io_channel_unix_new(fd);
|
||||||
|
terminal->tag = g_io_add_watch(channel, G_IO_IN,
|
||||||
|
selection_io_func,
|
||||||
|
terminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
case XK_X:
|
||||||
|
/* cut selection; terminal doesn't do cut */
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
key_handler(struct window *window, struct input *input, uint32_t time,
|
key_handler(struct window *window, struct input *input, uint32_t time,
|
||||||
uint32_t key, uint32_t sym, uint32_t state, void *data)
|
uint32_t key, uint32_t sym, uint32_t state, void *data)
|
||||||
|
|
|
||||||
120
clients/window.c
120
clients/window.c
|
|
@ -118,6 +118,7 @@ struct input {
|
||||||
struct wl_input_device *input_device;
|
struct wl_input_device *input_device;
|
||||||
struct window *pointer_focus;
|
struct window *pointer_focus;
|
||||||
struct window *keyboard_focus;
|
struct window *keyboard_focus;
|
||||||
|
struct selection_offer *offer;
|
||||||
uint32_t current_pointer_image;
|
uint32_t current_pointer_image;
|
||||||
uint32_t modifiers;
|
uint32_t modifiers;
|
||||||
int32_t x, y, sx, sy;
|
int32_t x, y, sx, sy;
|
||||||
|
|
@ -1317,6 +1318,117 @@ display_add_input(struct display *d, uint32_t id)
|
||||||
wl_input_device_set_user_data(input->input_device, input);
|
wl_input_device_set_user_data(input->input_device, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct selection_offer {
|
||||||
|
struct display *display;
|
||||||
|
struct wl_selection_offer *offer;
|
||||||
|
struct wl_array types;
|
||||||
|
struct input *input;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
input_offers_mime_type(struct input *input, const char *type)
|
||||||
|
{
|
||||||
|
struct selection_offer *offer = input->offer;
|
||||||
|
char **p, **end;
|
||||||
|
|
||||||
|
if (offer == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
end = offer->types.data + offer->types.size;
|
||||||
|
for (p = offer->types.data; p < end; p++)
|
||||||
|
if (strcmp(*p, type) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
input_receive_mime_type(struct input *input, const char *type)
|
||||||
|
{
|
||||||
|
struct selection_offer *offer = input->offer;
|
||||||
|
int p[2];
|
||||||
|
|
||||||
|
pipe(p);
|
||||||
|
/* FIXME: A number of things can go wrong here: the object may
|
||||||
|
* not be the current selection offer any more (which could
|
||||||
|
* still work, but the source may have gone away or just
|
||||||
|
* destroyed its wl_selection) or the offer may not have the
|
||||||
|
* requested type after all (programmer/client error,
|
||||||
|
* typically) */
|
||||||
|
wl_selection_offer_receive(offer->offer, type, p[1]);
|
||||||
|
close(p[1]);
|
||||||
|
|
||||||
|
return p[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selection_offer_offer(void *data,
|
||||||
|
struct wl_selection_offer *selection_offer,
|
||||||
|
const char *type)
|
||||||
|
{
|
||||||
|
struct selection_offer *offer = data;
|
||||||
|
|
||||||
|
char **p;
|
||||||
|
|
||||||
|
p = wl_array_add(&offer->types, sizeof *p);
|
||||||
|
if (p)
|
||||||
|
*p = strdup(type);
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
selection_offer_keyboard_focus(void *data,
|
||||||
|
struct wl_selection_offer *selection_offer,
|
||||||
|
struct wl_input_device *input_device)
|
||||||
|
{
|
||||||
|
struct selection_offer *offer = data;
|
||||||
|
struct input *input;
|
||||||
|
char **p, **end;
|
||||||
|
|
||||||
|
if (input_device == NULL) {
|
||||||
|
printf("selection offer retracted %p\n", selection_offer);
|
||||||
|
input = offer->input;
|
||||||
|
input->offer = NULL;
|
||||||
|
wl_selection_offer_destroy(selection_offer);
|
||||||
|
wl_array_release(&offer->types);
|
||||||
|
free(offer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input = wl_input_device_get_user_data(input_device);
|
||||||
|
printf("new selection offer %p:", selection_offer);
|
||||||
|
|
||||||
|
offer->input = input;
|
||||||
|
input->offer = offer;
|
||||||
|
end = offer->types.data + offer->types.size;
|
||||||
|
for (p = offer->types.data; p < end; p++)
|
||||||
|
printf(" %s", *p);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_selection_offer_listener selection_offer_listener = {
|
||||||
|
selection_offer_offer,
|
||||||
|
selection_offer_keyboard_focus
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_selection_offer(struct display *d, uint32_t id)
|
||||||
|
{
|
||||||
|
struct selection_offer *offer;
|
||||||
|
|
||||||
|
offer = malloc(sizeof *offer);
|
||||||
|
if (offer == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
offer->offer = wl_selection_offer_create(d->display, id);
|
||||||
|
offer->display = d;
|
||||||
|
wl_array_init(&offer->types);
|
||||||
|
offer->input = NULL;
|
||||||
|
|
||||||
|
wl_selection_offer_add_listener(offer->offer,
|
||||||
|
&selection_offer_listener, offer);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
display_handle_global(struct wl_display *display, uint32_t id,
|
display_handle_global(struct wl_display *display, uint32_t id,
|
||||||
const char *interface, uint32_t version, void *data)
|
const char *interface, uint32_t version, void *data)
|
||||||
|
|
@ -1338,6 +1450,8 @@ display_handle_global(struct wl_display *display, uint32_t id,
|
||||||
wl_drm_add_listener(d->drm, &drm_listener, d);
|
wl_drm_add_listener(d->drm, &drm_listener, d);
|
||||||
} else if (strcmp(interface, "shm") == 0) {
|
} else if (strcmp(interface, "shm") == 0) {
|
||||||
d->shm = wl_shm_create(display, id);
|
d->shm = wl_shm_create(display, id);
|
||||||
|
} else if (strcmp(interface, "selection_offer") == 0) {
|
||||||
|
add_selection_offer(d, id);
|
||||||
} else if (d->global_handler) {
|
} else if (d->global_handler) {
|
||||||
d->global_handler(d, interface, id, version);
|
d->global_handler(d, interface, id, version);
|
||||||
}
|
}
|
||||||
|
|
@ -1534,6 +1648,12 @@ display_get_egl_display(struct display *d)
|
||||||
return d->dpy;
|
return d->dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wl_shell *
|
||||||
|
display_get_shell(struct display *display)
|
||||||
|
{
|
||||||
|
return display->shell;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
display_run(struct display *d)
|
display_run(struct display *d)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,9 @@ display_get_display(struct display *display);
|
||||||
struct wl_compositor *
|
struct wl_compositor *
|
||||||
display_get_compositor(struct display *display);
|
display_get_compositor(struct display *display);
|
||||||
|
|
||||||
|
struct wl_shell *
|
||||||
|
display_get_shell(struct display *display);
|
||||||
|
|
||||||
#ifdef EGL_NO_DISPLAY
|
#ifdef EGL_NO_DISPLAY
|
||||||
EGLDisplay
|
EGLDisplay
|
||||||
display_get_egl_display(struct display *d);
|
display_get_egl_display(struct display *d);
|
||||||
|
|
@ -243,4 +246,10 @@ input_get_modifiers(struct input *input);
|
||||||
struct wl_input_device *
|
struct wl_input_device *
|
||||||
input_get_input_device(struct input *input);
|
input_get_input_device(struct input *input);
|
||||||
|
|
||||||
|
int
|
||||||
|
input_offers_mime_type(struct input *input, const char *type);
|
||||||
|
int
|
||||||
|
input_receive_mime_type(struct input *input, const char *type);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue