wayland: Implement the (so far internal) primary selection protocol

Add an additional MetaWaylandDataSource implementation for primary selection
sources, and methods to set primary selection offers. Primary selection
sets altogether a different channel than the clipboard selection, those don't
cross in any way.

Also, the bridge for the X11 PRIMARY selection atom has been added, which
adds all the necessary handling to translate primary selection both ways
with wayland and X11 applications.

https://bugzilla.gnome.org/show_bug.cgi?id=762560
This commit is contained in:
Carlos Garnacho 2016-02-03 18:39:58 +01:00
parent c6aad6e735
commit 7c114360d0
4 changed files with 370 additions and 27 deletions

View File

@ -31,4 +31,10 @@ G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
META, WAYLAND_DATA_SOURCE_WAYLAND, META, WAYLAND_DATA_SOURCE_WAYLAND,
MetaWaylandDataSource); MetaWaylandDataSource);
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
meta_wayland_data_source_primary,
META, WAYLAND_DATA_SOURCE_PRIMARY,
MetaWaylandDataSourceWayland);
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */ #endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */

View File

@ -37,6 +37,8 @@
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
#include "meta-dnd-actor-private.h" #include "meta-dnd-actor-private.h"
#include "gtk-primary-selection-server-protocol.h"
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \ #define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
@ -70,13 +72,24 @@ typedef struct _MetaWaylandDataSourceWayland
struct wl_resource *resource; struct wl_resource *resource;
} MetaWaylandDataSourceWayland; } MetaWaylandDataSourceWayland;
typedef struct _MetaWaylandDataSourcePrimary
{
MetaWaylandDataSourceWayland parent;
struct wl_resource *resource;
} MetaWaylandDataSourcePrimary;
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source, G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
G_TYPE_OBJECT); G_TYPE_OBJECT);
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland, G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
META_TYPE_WAYLAND_DATA_SOURCE); META_TYPE_WAYLAND_DATA_SOURCE);
G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
META_TYPE_WAYLAND_DATA_SOURCE);
static MetaWaylandDataSource * static MetaWaylandDataSource *
meta_wayland_data_source_wayland_new (struct wl_resource *resource); meta_wayland_data_source_wayland_new (struct wl_resource *resource);
static MetaWaylandDataSource *
meta_wayland_data_source_primary_new (struct wl_resource *resource);
static void static void
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was); drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was);
@ -160,7 +173,8 @@ static void
meta_wayland_data_source_target (MetaWaylandDataSource *source, meta_wayland_data_source_target (MetaWaylandDataSource *source,
const char *mime_type) const char *mime_type)
{ {
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type); if (META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target)
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type);
} }
void void
@ -351,7 +365,8 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
} }
static void static void
data_offer_destroy (struct wl_client *client, struct wl_resource *resource) default_destructor (struct wl_client *client,
struct wl_resource *resource)
{ {
wl_resource_destroy (resource); wl_resource_destroy (resource);
} }
@ -425,11 +440,42 @@ data_offer_set_actions (struct wl_client *client,
static const struct wl_data_offer_interface data_offer_interface = { static const struct wl_data_offer_interface data_offer_interface = {
data_offer_accept, data_offer_accept,
data_offer_receive, data_offer_receive,
data_offer_destroy, default_destructor,
data_offer_finish, data_offer_finish,
data_offer_set_actions, data_offer_set_actions,
}; };
static void
primary_offer_receive (struct wl_client *client, struct wl_resource *resource,
const char *mime_type, int32_t fd)
{
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
MetaWaylandDataSource *source = offer->source;
MetaWaylandSeat *seat;
if (!offer->source)
{
close (fd);
return;
}
seat = meta_wayland_data_source_get_seat (source);
if (wl_resource_get_client (offer->resource) !=
meta_wayland_keyboard_get_focus_client (&seat->keyboard))
{
close (fd);
return;
}
meta_wayland_data_source_send (offer->source, mime_type, fd);
}
static const struct gtk_primary_selection_offer_interface primary_offer_interface = {
primary_offer_receive,
default_destructor,
};
static void static void
meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source) meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source)
{ {
@ -500,6 +546,35 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
return offer->resource; return offer->resource;
} }
static struct wl_resource *
meta_wayland_data_source_send_primary_offer (MetaWaylandDataSource *source,
struct wl_resource *target)
{
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
char **p;
offer->source = source;
g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source);
offer->resource = wl_resource_create (wl_resource_get_client (target),
&gtk_primary_selection_offer_interface,
wl_resource_get_version (target), 0);
wl_resource_set_implementation (offer->resource,
&primary_offer_interface,
offer,
destroy_data_offer);
gtk_primary_selection_device_send_data_offer (target, offer->resource);
wl_array_for_each (p, &priv->mime_types)
gtk_primary_selection_offer_send_offer (offer->resource, *p);
meta_wayland_data_source_set_current_offer (source, offer);
return offer->resource;
}
static void static void
data_source_offer (struct wl_client *client, data_source_offer (struct wl_client *client,
struct wl_resource *resource, const char *type) struct wl_resource *resource, const char *type)
@ -510,12 +585,6 @@ data_source_offer (struct wl_client *client,
wl_resource_post_no_memory (resource); wl_resource_post_no_memory (resource);
} }
static void
data_source_destroy (struct wl_client *client, struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void static void
data_source_set_actions (struct wl_client *client, data_source_set_actions (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
@ -557,10 +626,26 @@ data_source_set_actions (struct wl_client *client,
static struct wl_data_source_interface data_source_interface = { static struct wl_data_source_interface data_source_interface = {
data_source_offer, data_source_offer,
data_source_destroy, default_destructor,
data_source_set_actions data_source_set_actions
}; };
static void
primary_source_offer (struct wl_client *client,
struct wl_resource *resource,
const char *type)
{
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
if (!meta_wayland_data_source_add_mime_type (source, type))
wl_resource_post_no_memory (resource);
}
static struct gtk_primary_selection_source_interface primary_source_interface = {
primary_source_offer,
default_destructor,
};
struct _MetaWaylandDragGrab { struct _MetaWaylandDragGrab {
MetaWaylandPointerGrab generic; MetaWaylandPointerGrab generic;
@ -1108,6 +1193,42 @@ meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *
data_source_class->drag_finished = meta_wayland_source_drag_finished; data_source_class->drag_finished = meta_wayland_source_drag_finished;
} }
static void
meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
const gchar *mime_type,
gint fd)
{
MetaWaylandDataSourcePrimary *source_primary;
source_primary = META_WAYLAND_DATA_SOURCE_PRIMARY (source);
gtk_primary_selection_source_send_send (source_primary->resource,
mime_type, fd);
}
static void
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
{
MetaWaylandDataSourcePrimary *source_primary;
source_primary = META_WAYLAND_DATA_SOURCE_PRIMARY (source);
gtk_primary_selection_source_send_cancelled (source_primary->resource);
}
static void
meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
{
}
static void
meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
{
MetaWaylandDataSourceClass *data_source_class =
META_WAYLAND_DATA_SOURCE_CLASS (klass);
data_source_class->send = meta_wayland_data_source_primary_send;
data_source_class->cancel = meta_wayland_data_source_primary_cancel;
}
static void static void
meta_wayland_data_source_finalize (GObject *object) meta_wayland_data_source_finalize (GObject *object)
{ {
@ -1299,6 +1420,7 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (source) if (source)
{ {
meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source), g_object_weak_ref (G_OBJECT (source),
selection_data_source_destroyed, selection_data_source_destroyed,
data_device); data_device);
@ -1339,16 +1461,114 @@ data_device_set_selection (struct wl_client *client,
meta_wayland_data_device_set_selection (data_device, source, serial); meta_wayland_data_device_set_selection (data_device, source, serial);
} }
static void
data_device_release(struct wl_client *client, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static const struct wl_data_device_interface data_device_interface = { static const struct wl_data_device_interface data_device_interface = {
data_device_start_drag, data_device_start_drag,
data_device_set_selection, data_device_set_selection,
data_device_release, default_destructor,
};
static void
primary_source_destroyed (gpointer data,
GObject *object_was_here)
{
MetaWaylandDataDevice *data_device = data;
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_client *focus_client = NULL;
data_device->primary_data_source = NULL;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client)
{
struct wl_resource *data_device_resource;
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
if (data_device_resource)
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
}
}
void
meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource, *offer;
struct wl_client *focus_client;
if (META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source))
{
struct wl_resource *resource;
resource = META_WAYLAND_DATA_SOURCE_PRIMARY (source)->resource;
if (wl_resource_get_client (resource) !=
meta_wayland_keyboard_get_focus_client (&seat->keyboard))
return;
}
if (data_device->primary_data_source &&
data_device->primary_serial - serial < UINT32_MAX / 2)
return;
if (data_device->primary_data_source)
{
meta_wayland_data_source_cancel (data_device->primary_data_source);
g_object_weak_unref (G_OBJECT (data_device->primary_data_source),
primary_source_destroyed,
data_device);
}
data_device->primary_data_source = source;
data_device->primary_serial = serial;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
if (data_device_resource)
{
if (data_device->primary_data_source)
{
offer = meta_wayland_data_source_send_primary_offer (data_device->primary_data_source,
data_device_resource);
gtk_primary_selection_device_send_selection (data_device_resource, offer);
}
else
{
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
}
}
}
if (source)
{
meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source),
primary_source_destroyed,
data_device);
}
wl_signal_emit (&data_device->primary_ownership_signal, source);
}
static void
primary_device_set_selection (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *source_resource,
uint32_t serial)
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandDataSource *source;
source = wl_resource_get_user_data (source_resource);
meta_wayland_data_device_set_primary (data_device, source, serial);
}
static const struct gtk_primary_selection_device_interface primary_device_interface = {
primary_device_set_selection,
default_destructor,
}; };
static void static void
@ -1389,6 +1609,51 @@ static const struct wl_data_device_manager_interface manager_interface = {
get_data_device get_data_device
}; };
static void
destroy_primary_source (struct wl_resource *resource)
{
MetaWaylandDataSourcePrimary *source = wl_resource_get_user_data (resource);
source->resource = NULL;
g_object_unref (source);
}
static void
primary_device_manager_create_source (struct wl_client *client,
struct wl_resource *manager_resource,
guint32 id)
{
struct wl_resource *source_resource;
source_resource =
wl_resource_create (client, &gtk_primary_selection_source_interface,
wl_resource_get_version (manager_resource),
id);
meta_wayland_data_source_primary_new (source_resource);
}
static void
primary_device_manager_get_device (struct wl_client *client,
struct wl_resource *manager_resource,
guint32 id,
struct wl_resource *seat_resource)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
struct wl_resource *cr;
cr = wl_resource_create (client, &gtk_primary_selection_device_interface,
wl_resource_get_version (manager_resource), id);
wl_resource_set_implementation (cr, &primary_device_interface,
&seat->data_device, unbind_resource);
wl_list_insert (&seat->data_device.primary_resource_list, wl_resource_get_link (cr));
}
static const struct gtk_primary_selection_device_manager_interface primary_manager_interface = {
primary_device_manager_create_source,
primary_device_manager_get_device,
default_destructor,
};
static void static void
bind_manager (struct wl_client *client, bind_manager (struct wl_client *client,
void *data, guint32 version, guint32 id) void *data, guint32 version, guint32 id)
@ -1398,6 +1663,19 @@ bind_manager (struct wl_client *client,
wl_resource_set_implementation (resource, &manager_interface, NULL, NULL); wl_resource_set_implementation (resource, &manager_interface, NULL, NULL);
} }
static void
bind_primary_manager (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create (client, &gtk_primary_selection_device_manager_interface,
version, id);
wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL);
}
void void
meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor) meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
{ {
@ -1406,13 +1684,20 @@ meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
META_WL_DATA_DEVICE_MANAGER_VERSION, META_WL_DATA_DEVICE_MANAGER_VERSION,
NULL, bind_manager) == NULL) NULL, bind_manager) == NULL)
g_error ("Could not create data_device"); g_error ("Could not create data_device");
if (wl_global_create (compositor->wayland_display,
&gtk_primary_selection_device_manager_interface,
1, NULL, bind_primary_manager) == NULL)
g_error ("Could not create data_device");
} }
void void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device) meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
{ {
wl_list_init (&data_device->resource_list); wl_list_init (&data_device->resource_list);
wl_list_init (&data_device->primary_resource_list);
wl_signal_init (&data_device->selection_ownership_signal); wl_signal_init (&data_device->selection_ownership_signal);
wl_signal_init (&data_device->primary_ownership_signal);
wl_signal_init (&data_device->dnd_ownership_signal); wl_signal_init (&data_device->dnd_ownership_signal);
} }
@ -1435,17 +1720,34 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
return; return;
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client); data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (!data_device_resource) if (data_device_resource)
return;
source = data_device->selection_data_source;
if (source)
{ {
offer = meta_wayland_data_source_send_offer (source, data_device_resource); source = data_device->selection_data_source;
wl_data_device_send_selection (data_device_resource, offer); if (source)
{
offer = meta_wayland_data_source_send_offer (source, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
}
else
{
wl_data_device_send_selection (data_device_resource, NULL);
}
}
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
if (data_device_resource)
{
source = data_device->primary_data_source;
if (source)
{
offer = meta_wayland_data_source_send_primary_offer (source, data_device_resource);
gtk_primary_selection_device_send_selection (data_device_resource, offer);
}
else
{
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
}
} }
else
wl_data_device_send_selection (data_device_resource, NULL);
} }
gboolean gboolean
@ -1486,6 +1788,19 @@ meta_wayland_data_source_wayland_new (struct wl_resource *resource)
return META_WAYLAND_DATA_SOURCE (source_wayland); return META_WAYLAND_DATA_SOURCE (source_wayland);
} }
static MetaWaylandDataSource *
meta_wayland_data_source_primary_new (struct wl_resource *resource)
{
MetaWaylandDataSourcePrimary *source_primary =
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
source_primary->resource = resource;
wl_resource_set_implementation (resource, &primary_source_interface,
source_primary, destroy_primary_source);
return META_WAYLAND_DATA_SOURCE (source_primary);
}
gboolean gboolean
meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type) const gchar *mime_type)

View File

@ -55,15 +55,19 @@ struct _MetaWaylandDataSourceClass
struct _MetaWaylandDataDevice struct _MetaWaylandDataDevice
{ {
uint32_t selection_serial; uint32_t selection_serial;
uint32_t primary_serial;
MetaWaylandDataSource *selection_data_source; MetaWaylandDataSource *selection_data_source;
MetaWaylandDataSource *dnd_data_source; MetaWaylandDataSource *dnd_data_source;
MetaWaylandDataSource *primary_data_source;
struct wl_listener selection_data_source_listener; struct wl_listener selection_data_source_listener;
struct wl_list resource_list; struct wl_list resource_list;
struct wl_list primary_resource_list;
MetaWaylandDragGrab *current_grab; MetaWaylandDragGrab *current_grab;
struct wl_client *focus_client; struct wl_client *focus_client;
struct wl_signal selection_ownership_signal; struct wl_signal selection_ownership_signal;
struct wl_signal dnd_ownership_signal; struct wl_signal dnd_ownership_signal;
struct wl_signal primary_ownership_signal;
}; };
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor); void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
@ -80,6 +84,9 @@ void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_de
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source, MetaWaylandDataSource *source,
guint32 serial); guint32 serial);
void meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial);
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type); const gchar *mime_type);

View File

@ -91,6 +91,7 @@ struct _MetaWaylandDataSourceXWayland
struct _MetaXWaylandSelection { struct _MetaXWaylandSelection {
MetaSelectionBridge clipboard; MetaSelectionBridge clipboard;
MetaSelectionBridge primary;
MetaDndBridge dnd; MetaDndBridge dnd;
}; };
@ -396,6 +397,8 @@ atom_to_selection_bridge (MetaWaylandCompositor *compositor,
if (selection_atom == selection_data->clipboard.selection_atom) if (selection_atom == selection_data->clipboard.selection_atom)
return &selection_data->clipboard; return &selection_data->clipboard;
else if (selection_atom == selection_data->primary.selection_atom)
return &selection_data->primary;
else if (selection_atom == selection_data->dnd.selection.selection_atom) else if (selection_atom == selection_data->dnd.selection.selection_atom)
return &selection_data->dnd.selection; return &selection_data->dnd.selection;
else else
@ -530,6 +533,8 @@ data_device_get_active_source_for_atom (MetaWaylandDataDevice *data_device,
{ {
if (selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD")) if (selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
return data_device->selection_data_source; return data_device->selection_data_source;
else if (selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
return data_device->primary_data_source;
else if (selection_atom == xdnd_atoms[ATOM_DND_SELECTION]) else if (selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
return data_device->dnd_data_source; return data_device->dnd_data_source;
else else
@ -1058,6 +1063,11 @@ meta_xwayland_selection_get_x11_targets (MetaWaylandCompositor *compositor,
meta_wayland_data_device_set_selection (&compositor->seat->data_device, data_source, meta_wayland_data_device_set_selection (&compositor->seat->data_device, data_source,
wl_display_next_serial (compositor->wayland_display)); wl_display_next_serial (compositor->wayland_display));
} }
else if (selection->selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
{
meta_wayland_data_device_set_primary (&compositor->seat->data_device, data_source,
wl_display_next_serial (compositor->wayland_display));
}
} }
else else
g_object_unref (data_source); g_object_unref (data_source);
@ -1529,7 +1539,8 @@ meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *c
if (!selection) if (!selection)
return FALSE; return FALSE;
if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD")) if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD") ||
selection->selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
{ {
if (event->owner == None) if (event->owner == None)
{ {
@ -1712,6 +1723,9 @@ meta_xwayland_init_selection (void)
init_selection_bridge (&manager->selection_data->clipboard, init_selection_bridge (&manager->selection_data->clipboard,
gdk_x11_get_xatom_by_name ("CLIPBOARD"), gdk_x11_get_xatom_by_name ("CLIPBOARD"),
&compositor->seat->data_device.selection_ownership_signal); &compositor->seat->data_device.selection_ownership_signal);
init_selection_bridge (&manager->selection_data->primary,
gdk_x11_get_xatom_by_name ("PRIMARY"),
&compositor->seat->data_device.primary_ownership_signal);
init_selection_bridge (&manager->selection_data->dnd.selection, init_selection_bridge (&manager->selection_data->dnd.selection,
xdnd_atoms[ATOM_DND_SELECTION], xdnd_atoms[ATOM_DND_SELECTION],
&compositor->seat->data_device.dnd_ownership_signal); &compositor->seat->data_device.dnd_ownership_signal);
@ -1730,6 +1744,7 @@ meta_xwayland_shutdown_selection (void)
meta_xwayland_shutdown_dnd (manager); meta_xwayland_shutdown_dnd (manager);
shutdown_selection_bridge (&selection->clipboard); shutdown_selection_bridge (&selection->clipboard);
shutdown_selection_bridge (&selection->primary);
shutdown_selection_bridge (&selection->dnd.selection); shutdown_selection_bridge (&selection->dnd.selection);
g_slice_free (MetaXWaylandSelection, selection); g_slice_free (MetaXWaylandSelection, selection);