gdk/wayland: Add support for primary-selection-unstable-v1

Additionally to gtk_primary_selection, the gtk-private predecessor,
support the upstream unstable protocol.

This allows the primary selection to work on Kwin and potentially
other compositors, as well as dropping the private version eventually.

Closes https://gitlab.gnome.org/GNOME/gtk/-/issues/2591
This commit is contained in:
Robert Mader
2020-09-26 15:33:59 +02:00
parent d3cd68f11d
commit 5bd8f8c5a3
9 changed files with 238 additions and 66 deletions

View File

@ -61,7 +61,7 @@ m4_define([cairo_required_version], [1.14.0])
m4_define([gdk_pixbuf_required_version], [2.30.0])
m4_define([introspection_required_version], [1.39.0])
m4_define([wayland_required_version], [1.14.91])
m4_define([wayland_protocols_required_version], [1.14])
m4_define([wayland_protocols_required_version], [1.17])
m4_define([epoxy_required_version], [1.4])
m4_define([cloudproviders_required_version], [0.2.5])
m4_define([sysprof_required_version], [3.33.2])

View File

@ -40,7 +40,9 @@ BUILT_SOURCES = \
server-decoration-client-protocol.h \
server-decoration-protocol.c \
gtk-shell-client-protocol.h \
gtk-shell-protocol.c
gtk-shell-protocol.c \
primary-selection-unstable-v1-client-protocol.h \
primary-selection-unstable-v1-protocol.c
nodist_libgdk_wayland_la_SOURCES = \
$(BUILT_SOURCES)

View File

@ -237,7 +237,8 @@ struct _GdkWaylandSeat
uint32_t keyboard_time;
uint32_t keyboard_key_serial;
struct gtk_primary_selection_device *primary_data_device;
struct gtk_primary_selection_device *gtk_primary_data_device;
struct zwp_primary_selection_device_v1 *zwp_primary_data_device_v1;
struct wl_data_device *data_device;
GdkDragContext *drop_context;
@ -1308,23 +1309,43 @@ static const struct wl_data_device_listener data_device_listener = {
};
static void
primary_selection_data_offer (void *data,
struct gtk_primary_selection_device *gtk_primary_selection_device,
struct gtk_primary_selection_offer *gtk_primary_offer)
primary_selection_data_offer (void *data,
gpointer primary_selection_device,
gpointer primary_offer)
{
GdkWaylandSeat *seat = data;
GDK_NOTE (EVENTS,
g_message ("primary selection offer, device %p, data offer %p",
gtk_primary_selection_device, gtk_primary_offer));
primary_selection_device, primary_offer));
gdk_wayland_selection_ensure_primary_offer (seat->display, gtk_primary_offer);
gdk_wayland_selection_ensure_primary_offer (seat->display, primary_offer);
}
static void
primary_selection_selection (void *data,
struct gtk_primary_selection_device *gtk_primary_selection_device,
struct gtk_primary_selection_offer *gtk_primary_offer)
gtk_primary_selection_data_offer (void *data,
struct gtk_primary_selection_device *primary_selection_device,
struct gtk_primary_selection_offer *primary_offer)
{
primary_selection_data_offer (data,
(gpointer) primary_selection_device,
(gpointer) primary_offer);
}
static void
zwp_primary_selection_v1_data_offer (void *data,
struct zwp_primary_selection_device_v1 *primary_selection_device,
struct zwp_primary_selection_offer_v1 *primary_offer)
{
primary_selection_data_offer (data,
(gpointer) primary_selection_device,
(gpointer) primary_offer);
}
static void
primary_selection_selection (void *data,
gpointer primary_selection_device,
gpointer primary_offer)
{
GdkWaylandSeat *seat = data;
GdkAtom selection;
@ -1334,16 +1355,41 @@ primary_selection_selection (void *data,
GDK_NOTE (EVENTS,
g_message ("primary selection selection, device %p, data offer %p",
gtk_primary_selection_device, gtk_primary_offer));
primary_selection_device, primary_offer));
selection = gdk_atom_intern_static_string ("PRIMARY");
gdk_wayland_selection_set_offer (seat->display, selection, gtk_primary_offer);
gdk_wayland_selection_set_offer (seat->display, selection, primary_offer);
emit_selection_owner_change (seat->keyboard_focus, selection);
}
static const struct gtk_primary_selection_device_listener primary_selection_device_listener = {
primary_selection_data_offer,
primary_selection_selection,
static void
gtk_primary_selection_selection (void *data,
struct gtk_primary_selection_device *primary_selection_device,
struct gtk_primary_selection_offer *primary_offer)
{
primary_selection_selection (data,
(gpointer) primary_selection_device,
(gpointer) primary_offer);
}
static void
zwp_primary_selection_v1_selection (void *data,
struct zwp_primary_selection_device_v1 *primary_selection_device,
struct zwp_primary_selection_offer_v1 *primary_offer)
{
primary_selection_selection (data,
(gpointer) primary_selection_device,
(gpointer) primary_offer);
}
static const struct gtk_primary_selection_device_listener gtk_primary_device_listener = {
gtk_primary_selection_data_offer,
gtk_primary_selection_selection,
};
static const struct zwp_primary_selection_device_v1_listener zwp_primary_device_v1_listener = {
zwp_primary_selection_v1_data_offer,
zwp_primary_selection_v1_selection,
};
static GdkDevice * get_scroll_device (GdkWaylandSeat *seat,
@ -5078,13 +5124,23 @@ _gdk_wayland_device_manager_add_seat (GdkDeviceManager *device_manager,
wl_seat_add_listener (seat->wl_seat, &seat_listener, seat);
wl_seat_set_user_data (seat->wl_seat, seat);
if (display_wayland->primary_selection_manager)
if (display_wayland->zwp_primary_selection_manager_v1)
{
seat->primary_data_device =
gtk_primary_selection_device_manager_get_device (display_wayland->primary_selection_manager,
seat->zwp_primary_data_device_v1 =
zwp_primary_selection_device_manager_v1_get_device (display_wayland->zwp_primary_selection_manager_v1,
seat->wl_seat);
zwp_primary_selection_device_v1_add_listener (seat->zwp_primary_data_device_v1,
&zwp_primary_device_v1_listener,
seat);
}
else if (display_wayland->gtk_primary_selection_manager)
{
seat->gtk_primary_data_device =
gtk_primary_selection_device_manager_get_device (display_wayland->gtk_primary_selection_manager,
seat->wl_seat);
gtk_primary_selection_device_add_listener (seat->primary_data_device,
&primary_selection_device_listener, seat);
gtk_primary_selection_device_add_listener (seat->gtk_primary_data_device,
&gtk_primary_device_listener,
seat);
}
seat->data_device =
@ -5355,8 +5411,8 @@ gdk_wayland_seat_set_selection (GdkSeat *seat,
}
void
gdk_wayland_seat_set_primary (GdkSeat *seat,
struct gtk_primary_selection_source *source)
gdk_wayland_seat_set_primary (GdkSeat *seat,
gpointer source)
{
GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
GdkWaylandDisplay *display_wayland;
@ -5366,8 +5422,16 @@ gdk_wayland_seat_set_primary (GdkSeat *seat,
{
display_wayland = GDK_WAYLAND_DISPLAY (gdk_seat_get_display (seat));
serial = _gdk_wayland_display_get_serial (display_wayland);
gtk_primary_selection_device_set_selection (wayland_seat->primary_data_device,
source, serial);
if (wayland_seat->zwp_primary_data_device_v1)
{
zwp_primary_selection_device_v1_set_selection (wayland_seat->zwp_primary_data_device_v1,
source, serial);
}
else if (wayland_seat->gtk_primary_data_device)
{
gtk_primary_selection_device_set_selection (wayland_seat->gtk_primary_data_device,
source, serial);
}
}
}

View File

@ -476,10 +476,16 @@ gdk_registry_handle_global (void *data,
}
else if (strcmp (interface, "gtk_primary_selection_device_manager") == 0)
{
display_wayland->primary_selection_manager =
display_wayland->gtk_primary_selection_manager =
wl_registry_bind(display_wayland->wl_registry, id,
&gtk_primary_selection_device_manager_interface, 1);
}
else if (strcmp (interface, "zwp_primary_selection_device_manager_v1") == 0)
{
display_wayland->zwp_primary_selection_manager_v1 =
wl_registry_bind(display_wayland->wl_registry, id,
&zwp_primary_selection_device_manager_v1_interface, 1);
}
else if (strcmp (interface, "zwp_tablet_manager_v2") == 0)
{
display_wayland->tablet_manager =

View File

@ -35,6 +35,7 @@
#include <gdk/wayland/keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h>
#include <gdk/wayland/server-decoration-client-protocol.h>
#include <gdk/wayland/xdg-output-unstable-v1-client-protocol.h>
#include <gdk/wayland/primary-selection-unstable-v1-client-protocol.h>
#include <glib.h>
#include <gdk/gdkkeys.h>
@ -88,7 +89,8 @@ struct _GdkWaylandDisplay
struct wl_data_device_manager *data_device_manager;
struct wl_subcompositor *subcompositor;
struct zwp_pointer_gestures_v1 *pointer_gestures;
struct gtk_primary_selection_device_manager *primary_selection_manager;
struct gtk_primary_selection_device_manager *gtk_primary_selection_manager;
struct zwp_primary_selection_device_manager_v1 *zwp_primary_selection_manager_v1;
struct zwp_tablet_manager_v2 *tablet_manager;
struct zxdg_exporter_v1 *xdg_exporter;
struct zxdg_importer_v1 *xdg_importer;

View File

@ -191,8 +191,8 @@ struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_devic
void gdk_wayland_seat_set_selection (GdkSeat *seat,
struct wl_data_source *source);
void gdk_wayland_seat_set_primary (GdkSeat *seat,
struct gtk_primary_selection_source *source);
void gdk_wayland_seat_set_primary (GdkSeat *seat,
gpointer source);
GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
@ -249,8 +249,8 @@ void gdk_wayland_selection_free (GdkWaylandSelection *selection);
void gdk_wayland_selection_ensure_offer (GdkDisplay *display,
struct wl_data_offer *wl_offer);
void gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
struct gtk_primary_selection_offer *wp_offer);
void gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
gpointer wp_offer);
void gdk_wayland_selection_set_offer (GdkDisplay *display,
GdkAtom selection,

View File

@ -104,7 +104,7 @@ struct _GdkWaylandSelection
GArray *source_targets;
GdkAtom requested_target;
struct gtk_primary_selection_source *primary_source;
gpointer primary_source;
GdkWindow *primary_owner;
struct wl_data_source *clipboard_source;
@ -434,6 +434,18 @@ gdk_wayland_selection_new (void)
return selection;
}
static void
primary_selection_source_destroy (gpointer primary_source)
{
GdkDisplay *display = gdk_display_get_default ();
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
if (display_wayland->zwp_primary_selection_manager_v1)
zwp_primary_selection_source_v1_destroy (primary_source);
else if (display_wayland->gtk_primary_selection_manager)
gtk_primary_selection_source_destroy (primary_source);
}
void
gdk_wayland_selection_free (GdkWaylandSelection *selection)
{
@ -448,7 +460,7 @@ gdk_wayland_selection_free (GdkWaylandSelection *selection)
g_ptr_array_unref (selection->stored_selections);
if (selection->primary_source)
gtk_primary_selection_source_destroy (selection->primary_source);
primary_selection_source_destroy (selection->primary_source);
if (selection->clipboard_source)
wl_data_source_destroy (selection->clipboard_source);
if (selection->dnd_source)
@ -546,27 +558,47 @@ static const struct wl_data_offer_listener data_offer_listener = {
};
static void
primary_offer_offer (void *data,
struct gtk_primary_selection_offer *gtk_offer,
const char *type)
primary_offer_offer (void *data,
gpointer offer,
const char *type)
{
GdkWaylandSelection *selection = data;
DataOfferData *info;
GdkAtom atom = gdk_atom_intern (type, FALSE);
info = g_hash_table_lookup (selection->offers, gtk_offer);
info = g_hash_table_lookup (selection->offers, offer);
if (!info || g_list_find (info->targets, atom))
return;
GDK_NOTE (EVENTS,
g_message ("primary offer offer, offer %p, type = %s", gtk_offer, type));
g_message ("primary offer offer, offer %p, type = %s", offer, type));
info->targets = g_list_prepend (info->targets, atom);
}
static const struct gtk_primary_selection_offer_listener primary_offer_listener = {
primary_offer_offer,
static void
gtk_primary_offer_offer (void *data,
struct gtk_primary_selection_offer *offer,
const char *type)
{
primary_offer_offer (data, (gpointer) offer, type);
}
static void
zwp_primary_offer_v1_offer (void *data,
struct zwp_primary_selection_offer_v1 *offer,
const char *type)
{
primary_offer_offer (data, (gpointer) offer, type);
}
static const struct gtk_primary_selection_offer_listener gtk_primary_offer_listener = {
gtk_primary_offer_offer,
};
static const struct zwp_primary_selection_offer_v1_listener zwp_primary_offer_listener_v1 = {
zwp_primary_offer_v1_offer,
};
SelectionData *
@ -604,9 +636,10 @@ gdk_wayland_selection_ensure_offer (GdkDisplay *display,
}
void
gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
struct gtk_primary_selection_offer *gtk_offer)
gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
gpointer gtk_offer)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
DataOfferData *info;
@ -614,12 +647,24 @@ gdk_wayland_selection_ensure_primary_offer (GdkDisplay *
if (!info)
{
info = data_offer_data_new (gtk_offer,
(GDestroyNotify) gtk_primary_selection_offer_destroy);
g_hash_table_insert (selection->offers, gtk_offer, info);
gtk_primary_selection_offer_add_listener (gtk_offer,
&primary_offer_listener,
selection);
if (display_wayland->zwp_primary_selection_manager_v1)
{
info = data_offer_data_new (gtk_offer,
(GDestroyNotify) zwp_primary_selection_offer_v1_destroy);
g_hash_table_insert (selection->offers, gtk_offer, info);
zwp_primary_selection_offer_v1_add_listener (gtk_offer,
&zwp_primary_offer_listener_v1,
selection);
}
else if (display_wayland->gtk_primary_selection_manager)
{
info = data_offer_data_new (gtk_offer,
(GDestroyNotify) gtk_primary_selection_offer_destroy);
g_hash_table_insert (selection->offers, gtk_offer, info);
gtk_primary_selection_offer_add_listener (gtk_offer,
&gtk_primary_offer_listener,
selection);
}
}
}
@ -1138,10 +1183,10 @@ static const struct wl_data_source_listener data_source_listener = {
};
static void
primary_source_send (void *data,
struct gtk_primary_selection_source *source,
const char *mime_type,
int32_t fd)
primary_source_send (void *data,
gpointer source,
const char *mime_type,
int32_t fd)
{
GdkWaylandSelection *wayland_selection = data;
@ -1163,8 +1208,26 @@ primary_source_send (void *data,
}
static void
primary_source_cancelled (void *data,
struct gtk_primary_selection_source *source)
gtk_primary_source_send (void *data,
struct gtk_primary_selection_source *source,
const char *mime_type,
int32_t fd)
{
primary_source_send (data, (gpointer) source, mime_type, fd);
}
static void
zwp_primary_source_v1_send (void *data,
struct zwp_primary_selection_source_v1 *source,
const char *mime_type,
int32_t fd)
{
primary_source_send (data, (gpointer) source, mime_type, fd);
}
static void
primary_source_cancelled (void *data,
gpointer source)
{
GdkDisplay *display;
GdkAtom atom;
@ -1180,9 +1243,28 @@ primary_source_cancelled (void *data,
gdk_wayland_selection_unset_data_source (display, atom);
}
static const struct gtk_primary_selection_source_listener primary_source_listener = {
primary_source_send,
primary_source_cancelled,
static void
gtk_primary_source_cancelled (void *data,
struct gtk_primary_selection_source *source)
{
primary_source_cancelled (data, source);
}
static void
zwp_primary_source_v1_cancelled (void *data,
struct zwp_primary_selection_source_v1 *source)
{
primary_source_cancelled (data, source);
}
static const struct gtk_primary_selection_source_listener gtk_primary_source_listener = {
gtk_primary_source_send,
gtk_primary_source_cancelled,
};
static const struct zwp_primary_selection_source_v1_listener zwp_primary_source_v1_listener = {
zwp_primary_source_v1_send,
zwp_primary_source_v1_cancelled,
};
struct wl_data_source *
@ -1204,11 +1286,11 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
{
if (wayland_selection->primary_source &&
(!owner || owner == wayland_selection->primary_owner))
return (gpointer) wayland_selection->primary_source;
return wayland_selection->primary_source;
if (wayland_selection->primary_source)
{
gtk_primary_selection_source_destroy (wayland_selection->primary_source);
primary_selection_source_destroy (wayland_selection->primary_source);
wayland_selection->primary_source = NULL;
}
}
@ -1234,11 +1316,18 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
if (selection == atoms[ATOM_PRIMARY])
{
if (display_wayland->primary_selection_manager)
if (display_wayland->zwp_primary_selection_manager_v1)
{
source = gtk_primary_selection_device_manager_create_source (display_wayland->primary_selection_manager);
source = zwp_primary_selection_device_manager_v1_create_source (display_wayland->zwp_primary_selection_manager_v1);
zwp_primary_selection_source_v1_add_listener (source,
&zwp_primary_source_v1_listener,
wayland_selection);
}
else if (display_wayland->gtk_primary_selection_manager)
{
source = gtk_primary_selection_device_manager_create_source (display_wayland->gtk_primary_selection_manager);
gtk_primary_selection_source_add_listener (source,
&primary_source_listener,
&gtk_primary_source_listener,
wayland_selection);
}
}
@ -1278,7 +1367,7 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display,
{
if (wayland_selection->primary_source)
{
gtk_primary_selection_source_destroy (wayland_selection->primary_source);
primary_selection_source_destroy (wayland_selection->primary_source);
wayland_selection->primary_source = NULL;
}
}
@ -1449,6 +1538,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
GdkAtom target,
guint32 time)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
const SelectionData *selection_data;
SelectionBuffer *buffer_data;
@ -1514,9 +1604,16 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL);
if (selection == atoms[ATOM_PRIMARY])
gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]);
{
if (display_wayland->zwp_primary_selection_manager_v1)
zwp_primary_selection_offer_v1_receive (offer, mimetype, pipe_fd[1]);
else if (display_wayland->gtk_primary_selection_manager)
gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]);
}
else
wl_data_offer_receive (offer, mimetype, pipe_fd[1]);
{
wl_data_offer_receive (offer, mimetype, pipe_fd[1]);
}
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);

View File

@ -56,6 +56,7 @@ proto_sources = [
['keyboard-shortcuts-inhibit', 'unstable', 'v1', ],
['server-decoration', 'private' ],
['xdg-output', 'unstable', 'v1', ],
['primary-selection', 'unstable', 'v1', ],
]
gdk_wayland_gen_headers = []

View File

@ -30,7 +30,7 @@ atk_req = '>= 2.15.1'
cairo_req = '>= 1.14.0'
gdk_pixbuf_req = '>= 2.30.0'
introspection_req = '>= 1.39.0'
wayland_proto_req = '>= 1.14'
wayland_proto_req = '>= 1.17'
wayland_req = '>= 1.14.91'
epoxy_req = '>= 1.4'
cloudproviders_req = '>= 0.2.5'