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



commit 7c114360d0d9b15748999d0c759684dc18bd2cb3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Feb 3 18:39:58 2016 +0100

    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

 src/wayland/meta-wayland-data-device-private.h |    6 +
 src/wayland/meta-wayland-data-device.c         |  363 ++++++++++++++++++++++--
 src/wayland/meta-wayland-data-device.h         |    7 +
 src/wayland/meta-xwayland-selection.c          |   17 +-
 4 files changed, 368 insertions(+), 25 deletions(-)
---
diff --git a/src/wayland/meta-wayland-data-device-private.h b/src/wayland/meta-wayland-data-device-private.h
index 9f5377a..5e65130 100644
--- a/src/wayland/meta-wayland-data-device-private.h
+++ b/src/wayland/meta-wayland-data-device-private.h
@@ -31,4 +31,10 @@ G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
                       META, WAYLAND_DATA_SOURCE_WAYLAND,
                       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 */
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index b0652a0..c6a98ff 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -37,6 +37,8 @@
 #include "meta-wayland-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 | \
                      WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
                      WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
@@ -70,13 +72,24 @@ typedef struct _MetaWaylandDataSourceWayland
   struct wl_resource *resource;
 } MetaWaylandDataSourceWayland;
 
+typedef struct _MetaWaylandDataSourcePrimary
+{
+  MetaWaylandDataSourceWayland parent;
+
+  struct wl_resource *resource;
+} MetaWaylandDataSourcePrimary;
+
 G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
                             G_TYPE_OBJECT);
 G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
                META_TYPE_WAYLAND_DATA_SOURCE);
+G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
+               META_TYPE_WAYLAND_DATA_SOURCE);
 
 static MetaWaylandDataSource *
 meta_wayland_data_source_wayland_new (struct wl_resource *resource);
+static MetaWaylandDataSource *
+meta_wayland_data_source_primary_new (struct wl_resource *resource);
 
 static void
 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,
                                  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
@@ -351,7 +365,8 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
 }
 
 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);
 }
@@ -425,12 +440,43 @@ data_offer_set_actions (struct wl_client   *client,
 static const struct wl_data_offer_interface data_offer_interface = {
   data_offer_accept,
   data_offer_receive,
-  data_offer_destroy,
+  default_destructor,
   data_offer_finish,
   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
 meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source)
 {
   META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source);
@@ -500,6 +546,35 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
   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
 data_source_offer (struct wl_client *client,
                    struct wl_resource *resource, const char *type)
@@ -511,12 +586,6 @@ data_source_offer (struct wl_client *client,
 }
 
 static void
-data_source_destroy (struct wl_client *client, struct wl_resource *resource)
-{
-  wl_resource_destroy (resource);
-}
-
-static void
 data_source_set_actions (struct wl_client   *client,
                          struct wl_resource *resource,
                          uint32_t            dnd_actions)
@@ -557,10 +626,26 @@ data_source_set_actions (struct wl_client   *client,
 
 static struct wl_data_source_interface data_source_interface = {
   data_source_offer,
-  data_source_destroy,
+  default_destructor,
   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 {
   MetaWaylandPointerGrab  generic;
 
@@ -1109,6 +1194,42 @@ meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *
 }
 
 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
 meta_wayland_data_source_finalize (GObject *object)
 {
   MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
@@ -1299,6 +1420,7 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
 
   if (source)
     {
+      meta_wayland_data_source_set_seat (source, seat);
       g_object_weak_ref (G_OBJECT (source),
                          selection_data_source_destroyed,
                          data_device);
@@ -1339,16 +1461,114 @@ data_device_set_selection (struct wl_client *client,
   meta_wayland_data_device_set_selection (data_device, source, serial);
 }
 
+static const struct wl_data_device_interface data_device_interface = {
+  data_device_start_drag,
+  data_device_set_selection,
+  default_destructor,
+};
+
 static void
-data_device_release(struct wl_client *client, struct wl_resource *resource)
+primary_source_destroyed (gpointer  data,
+                          GObject  *object_was_here)
 {
-  wl_resource_destroy(resource);
+  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);
+    }
 }
 
-static const struct wl_data_device_interface data_device_interface = {
-  data_device_start_drag,
-  data_device_set_selection,
-  data_device_release,
+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
@@ -1390,6 +1610,51 @@ static const struct wl_data_device_manager_interface manager_interface = {
 };
 
 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
 bind_manager (struct wl_client *client,
               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);
 }
 
+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
 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,
                        NULL, bind_manager) == NULL)
     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
 meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
 {
   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->primary_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;
 
   data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
-  if (!data_device_resource)
-    return;
+  if (data_device_resource)
+    {
+      source = data_device->selection_data_source;
+      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);
+        }
+    }
 
-  source = data_device->selection_data_source;
-  if (source)
+  data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
+  if (data_device_resource)
     {
-      offer = meta_wayland_data_source_send_offer (source, data_device_resource);
-      wl_data_device_send_selection (data_device_resource, offer);
+      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
@@ -1486,6 +1788,19 @@ meta_wayland_data_source_wayland_new (struct wl_resource *resource)
   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
 meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
                                         const gchar           *mime_type)
diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h
index cdb4f05..f48b135 100644
--- a/src/wayland/meta-wayland-data-device.h
+++ b/src/wayland/meta-wayland-data-device.h
@@ -55,15 +55,19 @@ struct _MetaWaylandDataSourceClass
 struct _MetaWaylandDataDevice
 {
   uint32_t selection_serial;
+  uint32_t primary_serial;
   MetaWaylandDataSource *selection_data_source;
   MetaWaylandDataSource *dnd_data_source;
+  MetaWaylandDataSource *primary_data_source;
   struct wl_listener selection_data_source_listener;
   struct wl_list resource_list;
+  struct wl_list primary_resource_list;
   MetaWaylandDragGrab *current_grab;
   struct wl_client *focus_client;
 
   struct wl_signal selection_ownership_signal;
   struct wl_signal dnd_ownership_signal;
+  struct wl_signal primary_ownership_signal;
 };
 
 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,
                                                   MetaWaylandDataSource *source,
                                                   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,
                                                   const gchar           *mime_type);
diff --git a/src/wayland/meta-xwayland-selection.c b/src/wayland/meta-xwayland-selection.c
index 5d3405a..42354a7 100644
--- a/src/wayland/meta-xwayland-selection.c
+++ b/src/wayland/meta-xwayland-selection.c
@@ -91,6 +91,7 @@ struct _MetaWaylandDataSourceXWayland
 
 struct _MetaXWaylandSelection {
   MetaSelectionBridge clipboard;
+  MetaSelectionBridge primary;
   MetaDndBridge dnd;
 };
 
@@ -396,6 +397,8 @@ atom_to_selection_bridge (MetaWaylandCompositor *compositor,
 
   if (selection_atom == selection_data->clipboard.selection_atom)
     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)
     return &selection_data->dnd.selection;
   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"))
     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])
     return data_device->dnd_data_source;
   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,
                                                   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
     g_object_unref (data_source);
@@ -1529,7 +1539,8 @@ meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *c
   if (!selection)
     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)
         {
@@ -1712,6 +1723,9 @@ meta_xwayland_init_selection (void)
   init_selection_bridge (&manager->selection_data->clipboard,
                          gdk_x11_get_xatom_by_name ("CLIPBOARD"),
                          &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,
                          xdnd_atoms[ATOM_DND_SELECTION],
                          &compositor->seat->data_device.dnd_ownership_signal);
@@ -1730,6 +1744,7 @@ meta_xwayland_shutdown_selection (void)
 
   meta_xwayland_shutdown_dnd (manager);
   shutdown_selection_bridge (&selection->clipboard);
+  shutdown_selection_bridge (&selection->primary);
   shutdown_selection_bridge (&selection->dnd.selection);
 
   g_slice_free (MetaXWaylandSelection, selection);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]