[gtk+] wayland: Add primary clipboard subclass



commit ff577e6c2cc3cacfb7e3d504bafffa20ae45733b
Author: Benjamin Otte <otte redhat com>
Date:   Sun Dec 3 05:39:08 2017 +0100

    wayland: Add primary clipboard subclass
    
    I decided to put this in a custom subclass, because then I could keep
    the whole gtk primary protocol self-contained.
    
    The other option would have been reusing GdkWaylandClipboard, but that
    didn't seem worth it, especially because that code needs to interact
    with the DND machinery, while the primary doesn't.

 gdk/wayland/gdkdevice-wayland.c    |   65 +------
 gdk/wayland/gdkprimary-wayland.c   |  398 ++++++++++++++++++++++++++++++++++++
 gdk/wayland/gdkprimary-wayland.h   |   41 ++++
 gdk/wayland/gdkprivate-wayland.h   |    3 -
 gdk/wayland/gdkselection-wayland.c |  188 +----------------
 gdk/wayland/meson.build            |    1 +
 6 files changed, 454 insertions(+), 242 deletions(-)
---
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index ca2ea3e..4f0641f 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -34,6 +34,7 @@
 #include "gdkdeviceprivate.h"
 #include "gdkdevicepadprivate.h"
 #include "gdkdevicetoolprivate.h"
+#include "gdkprimary-wayland.h"
 #include "gdkseatprivate.h"
 #include "pointer-gestures-unstable-v1-client-protocol.h"
 #include "tablet-unstable-v2-client-protocol.h"
@@ -233,7 +234,6 @@ struct _GdkWaylandSeat
 
   GdkClipboard *clipboard;
   GdkClipboard *primary_clipboard;
-  struct gtk_primary_selection_device *primary_data_device;
   struct wl_data_device *data_device;
   GdkDragContext *drop_context;
 
@@ -1211,45 +1211,6 @@ static const struct wl_data_device_listener data_device_listener = {
   data_device_selection
 };
 
-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)
-{
-  GdkWaylandSeat *seat = data;
-
-  GDK_NOTE (EVENTS,
-            g_message ("primary selection offer, device %p, data offer %p",
-                       gtk_primary_selection_device, gtk_primary_offer));
-
-  gdk_wayland_selection_ensure_primary_offer (seat->display, gtk_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)
-{
-  GdkWaylandSeat *seat = data;
-  GdkAtom selection;
-
-  if (!seat->keyboard_focus)
-    return;
-
-  GDK_NOTE (EVENTS,
-            g_message ("primary selection selection, device %p, data offer %p",
-                       gtk_primary_selection_device, gtk_primary_offer));
-
-  selection = gdk_atom_intern_static_string ("PRIMARY");
-  gdk_wayland_selection_set_offer (seat->display, selection, gtk_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 GdkDevice * get_scroll_device (GdkWaylandSeat              *seat,
                                       enum wl_pointer_axis_source  source);
 
@@ -4796,12 +4757,7 @@ _gdk_wayland_display_create_seat (GdkWaylandDisplay *display_wayland,
 
   if (display_wayland->primary_selection_manager)
     {
-      seat->primary_data_device =
-        gtk_primary_selection_device_manager_get_device (display_wayland->primary_selection_manager,
-                                                         seat->wl_seat);
-      gtk_primary_selection_device_add_listener (seat->primary_data_device,
-                                                 &primary_selection_device_listener, seat);
-      seat->primary_clipboard = gdk_wayland_clipboard_new (display);
+      seat->primary_clipboard = gdk_wayland_primary_new (seat);
     }
   else
     {
@@ -5016,23 +4972,6 @@ gdk_wayland_device_set_selection (GdkDevice             *gdk_device,
                                 _gdk_wayland_display_get_serial (display_wayland));
 }
 
-void
-gdk_wayland_seat_set_primary (GdkSeat                             *seat,
-                              struct gtk_primary_selection_source *source)
-{
-  GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
-  GdkWaylandDisplay *display_wayland;
-  guint32 serial;
-
-  if (source)
-    {
-      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);
-    }
-}
-
 /**
  * gdk_wayland_seat_get_wl_seat:
  * @device: (type GdkWaylandDevice): a #GdkDevice
diff --git a/gdk/wayland/gdkprimary-wayland.c b/gdk/wayland/gdkprimary-wayland.c
new file mode 100644
index 0000000..b83f41a
--- /dev/null
+++ b/gdk/wayland/gdkprimary-wayland.c
@@ -0,0 +1,398 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gdkprimary-wayland.h"
+
+#include "gdkclipboardprivate.h"
+#include "gdkcontentformats.h"
+#include "gdkintl.h"
+#include "gdkprivate-wayland.h"
+#include "gdk-private.h"
+
+#include <glib-unix.h>
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+
+typedef struct _GdkWaylandPrimaryClass GdkWaylandPrimaryClass;
+
+struct _GdkWaylandPrimary
+{
+  GdkClipboard parent;
+
+  struct gtk_primary_selection_device *primary_data_device;
+
+  struct gtk_primary_selection_offer *pending;
+  GdkContentFormatsBuilder *pending_builder;
+
+  struct gtk_primary_selection_offer *offer;
+  GdkContentFormats *offer_formats;
+
+  struct gtk_primary_selection_source *source;
+};
+
+struct _GdkWaylandPrimaryClass
+{
+  GdkClipboardClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkWaylandPrimary, gdk_wayland_primary, GDK_TYPE_CLIPBOARD)
+
+static void
+gdk_wayland_primary_discard_pending (GdkWaylandPrimary *cb)
+{
+  if (cb->pending_builder)
+    {
+      GdkContentFormats *ignore = gdk_content_formats_builder_free (cb->pending_builder);
+      gdk_content_formats_unref (ignore);
+      cb->pending_builder = NULL;
+    }
+  g_clear_pointer (&cb->pending, (GDestroyNotify) gtk_primary_selection_offer_destroy);
+}
+
+static void
+gdk_wayland_primary_discard_offer (GdkWaylandPrimary *cb)
+{
+  g_clear_pointer (&cb->offer_formats, gdk_content_formats_unref);
+  g_clear_pointer (&cb->offer, (GDestroyNotify) gtk_primary_selection_offer_destroy);
+}
+
+static void
+gdk_wayland_primary_discard_source (GdkWaylandPrimary *cb)
+{
+  g_clear_pointer (&cb->source, (GDestroyNotify) wl_data_source_destroy);
+}
+
+static void
+gdk_wayland_primary_finalize (GObject *object)
+{
+  GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (object);
+
+  gdk_wayland_primary_discard_pending (cb);
+  gdk_wayland_primary_discard_offer (cb);
+  gdk_wayland_primary_discard_source (cb);
+  
+  G_OBJECT_CLASS (gdk_wayland_primary_parent_class)->finalize (object);
+}
+
+static void
+gdk_wayland_primary_claim_remote (GdkWaylandPrimary                  *cb,
+                                  struct gtk_primary_selection_offer *offer,
+                                  GdkContentFormats                  *formats)
+{
+  g_return_if_fail (GDK_IS_WAYLAND_PRIMARY (cb));
+
+  if (cb->source)
+    {
+      GDK_NOTE (CLIPBOARD, g_printerr ("%p: Ignoring clipboard offer for self\n", cb));
+      return;
+    }
+
+  gdk_wayland_primary_discard_offer (cb);
+
+  GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats);
+                       g_printerr ("%p: remote clipboard claim for %s\n", cb, s);
+                       g_free (s); );
+  cb->offer_formats = formats;
+  cb->offer = offer;
+
+  gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb),
+                              cb->offer_formats);
+}
+
+static void
+primary_offer_offer (void                               *data,
+                     struct gtk_primary_selection_offer *offer,
+                     const char                         *type)
+{
+  GdkWaylandPrimary *cb = data;
+
+  if (cb->pending != offer)
+    {
+      GDK_NOTE (SELECTION, g_printerr ("%p: offer for unknown selection %p of %s\n",
+                                       cb, offer, type));
+      return;
+    }
+
+  gdk_content_formats_builder_add_mime_type (cb->pending_builder, type);
+}
+
+static const struct gtk_primary_selection_offer_listener primary_offer_listener = {
+  primary_offer_offer,
+};
+
+static void
+primary_selection_data_offer (void                                *data,
+                              struct gtk_primary_selection_device *device,
+                              struct gtk_primary_selection_offer  *offer)
+{
+  GdkWaylandPrimary *cb = data;
+
+  GDK_NOTE (SELECTION, g_printerr ("%p: new primary offer %p\n",
+                                   cb, offer));
+
+  gdk_wayland_primary_discard_pending (cb);
+
+  cb->pending = offer;
+  gtk_primary_selection_offer_add_listener (offer,
+                                            &primary_offer_listener,
+                                            cb);
+
+  cb->pending_builder = gdk_content_formats_builder_new ();
+}
+
+static void
+primary_selection_selection (void                                *data,
+                             struct gtk_primary_selection_device *device,
+                             struct gtk_primary_selection_offer  *offer)
+{
+  GdkWaylandPrimary *cb = data;
+  GdkContentFormats *formats;
+
+  if (offer == NULL)
+    {
+      gdk_wayland_primary_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0));
+      return;
+    }
+
+  if (cb->pending != offer)
+    {
+      GDK_NOTE (SELECTION, g_printerr ("%p: ignoring unknown data offer %p\n",
+                                       cb, offer));
+      return;
+    }
+
+  formats = gdk_content_formats_builder_free (cb->pending_builder);
+  cb->pending_builder = NULL;
+  cb->pending = NULL;
+
+  gdk_wayland_primary_claim_remote (cb, offer, formats);
+}
+
+static const struct gtk_primary_selection_device_listener primary_selection_device_listener = {
+  primary_selection_data_offer,
+  primary_selection_selection,
+};
+
+static void
+gdk_wayland_primary_write_done (GObject      *clipboard,
+                                GAsyncResult *result,
+                                gpointer      user_data)
+{
+  GError *error = NULL;
+
+  if (!gdk_clipboard_write_finish (GDK_CLIPBOARD (clipboard), result, &error))
+    {
+      GDK_NOTE (SELECTION, g_printerr ("%p: failed to write stream: %s\n", clipboard, error->message));
+      g_error_free (error);
+    }
+}
+
+static void
+gdk_wayland_primary_data_source_send (void                                *data,
+                                      struct gtk_primary_selection_source *source,
+                                      const char                          *mime_type,
+                                      int32_t                              fd)
+{
+  GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (data);
+  GOutputStream *stream;
+
+  GDK_NOTE (SELECTION, g_printerr ("%p: data source send request for %s on fd %d\n",
+                                   source, mime_type, fd));
+
+  mime_type = gdk_intern_mime_type (mime_type);
+  stream = g_unix_output_stream_new (fd, TRUE);
+
+  gdk_clipboard_write_async (GDK_CLIPBOARD (cb),
+                             mime_type,
+                             stream,
+                             G_PRIORITY_DEFAULT,
+                             NULL,
+                             gdk_wayland_primary_write_done,
+                             cb);
+  g_object_unref (stream);
+}
+
+static void
+gdk_wayland_primary_data_source_cancelled (void                                *data,
+                                           struct gtk_primary_selection_source *source)
+{
+  GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (data);
+
+  GDK_NOTE (CLIPBOARD, g_printerr ("%p: data source cancelled\n", data));
+
+  if (cb->source == source)
+    {
+      gdk_wayland_primary_discard_source (cb);
+      gdk_wayland_primary_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0));
+    }
+}
+
+static const struct gtk_primary_selection_source_listener primary_source_listener = {
+  gdk_wayland_primary_data_source_send,
+  gdk_wayland_primary_data_source_cancelled,
+};
+
+static gboolean
+gdk_wayland_primary_claim (GdkClipboard       *clipboard,
+                           GdkContentFormats  *formats,
+                           gboolean            local,
+                           GdkContentProvider *content)
+{
+  GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard);
+
+  if (local)
+    {
+      GdkWaylandDisplay *wdisplay = GDK_WAYLAND_DISPLAY (gdk_clipboard_get_display (clipboard));
+      const char * const *mime_types;
+      gsize i, n_mime_types;
+
+      gdk_wayland_primary_discard_offer (cb);
+      gdk_wayland_primary_discard_source (cb);
+
+      cb->source = gtk_primary_selection_device_manager_create_source (wdisplay->primary_selection_manager);
+      gtk_primary_selection_source_add_listener (cb->source, &primary_source_listener, cb);
+
+      mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
+      for (i = 0; i < n_mime_types; i++)
+        {
+          gtk_primary_selection_source_offer (cb->source, mime_types[i]);
+        }
+
+      gtk_primary_selection_device_set_selection (cb->primary_data_device,
+                                                  cb->source,
+                                                  _gdk_wayland_display_get_serial (wdisplay));
+    }
+
+  return GDK_CLIPBOARD_CLASS (gdk_wayland_primary_parent_class)->claim (clipboard, formats, local, content);
+}
+
+static void
+gdk_wayland_primary_read_async (GdkClipboard        *clipboard,
+                                GdkContentFormats   *formats,
+                                int                  io_priority,
+                                GCancellable        *cancellable,
+                                GAsyncReadyCallback  callback,
+                                gpointer             user_data)
+{
+  GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard);
+  GInputStream *stream;
+  const char *mime_type;
+  int pipe_fd[2];
+  GError *error = NULL;
+  GTask *task;
+
+  task = g_task_new (clipboard, cancellable, callback, user_data);
+  g_task_set_priority (task, io_priority);
+  g_task_set_source_tag (task, gdk_wayland_primary_read_async);
+
+  GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats);
+                       g_printerr ("%p: read for %s\n", cb, s);
+                       g_free (s); );
+  mime_type = gdk_content_formats_match_mime_type (formats, cb->offer_formats);
+  if (mime_type == NULL)
+    {
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               _("No compatible transfer format found"));
+      return;
+    }
+  /* offer formats should be empty if we have no offer */
+  g_assert (cb->offer);
+
+  g_task_set_task_data (task, (gpointer) mime_type, NULL);
+
+  if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error))
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  gtk_primary_selection_offer_receive (cb->offer, mime_type, pipe_fd[1]);
+  stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
+  close (pipe_fd[1]);
+  g_task_return_pointer (task, stream, g_object_unref);
+}
+
+static GInputStream *
+gdk_wayland_primary_read_finish (GdkClipboard  *clipboard,
+                                 const char   **out_mime_type,
+                                 GAsyncResult  *result,
+                                 GError       **error)
+{
+  GInputStream *stream;
+  GTask *task;
+
+  g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (clipboard)), NULL);
+  task = G_TASK (result);
+  g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_primary_read_async, NULL);
+
+  stream = g_task_propagate_pointer (task, error);
+
+  if (stream)
+    {
+      if (out_mime_type)
+        *out_mime_type = g_task_get_task_data (task);
+      g_object_ref (stream);
+    }
+  else
+    {
+      if (out_mime_type)
+        *out_mime_type = NULL;
+    }
+
+  return stream;
+}
+
+static void
+gdk_wayland_primary_class_init (GdkWaylandPrimaryClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class);
+
+  object_class->finalize = gdk_wayland_primary_finalize;
+
+  clipboard_class->claim = gdk_wayland_primary_claim;
+  clipboard_class->read_async = gdk_wayland_primary_read_async;
+  clipboard_class->read_finish = gdk_wayland_primary_read_finish;
+}
+
+static void
+gdk_wayland_primary_init (GdkWaylandPrimary *cb)
+{
+}
+
+GdkClipboard *
+gdk_wayland_primary_new (GdkWaylandSeat *seat)
+{
+  GdkWaylandDisplay *wdisplay;
+  GdkWaylandPrimary *cb;
+
+  wdisplay = GDK_WAYLAND_DISPLAY (gdk_seat_get_display (GDK_SEAT (seat)));
+
+  cb = g_object_new (GDK_TYPE_WAYLAND_PRIMARY,
+                     "display", wdisplay,
+                     NULL);
+
+  cb->primary_data_device =
+        gtk_primary_selection_device_manager_get_device (wdisplay->primary_selection_manager,
+                                                         gdk_wayland_seat_get_wl_seat (GDK_SEAT (seat)));
+  gtk_primary_selection_device_add_listener (cb->primary_data_device,
+                                             &primary_selection_device_listener, cb);
+
+  return GDK_CLIPBOARD (cb);
+}
diff --git a/gdk/wayland/gdkprimary-wayland.h b/gdk/wayland/gdkprimary-wayland.h
new file mode 100644
index 0000000..106ef5e
--- /dev/null
+++ b/gdk/wayland/gdkprimary-wayland.h
@@ -0,0 +1,41 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_PRIMARY_WAYLAND_H__
+#define __GDK_PRIMARY_WAYLAND_H__
+
+#include "gdk/gdkclipboard.h"
+
+#include "gdkseat-wayland.h"
+#include <wayland-client.h>
+#include "gtk-primary-selection-client-protocol.h"
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_WAYLAND_PRIMARY    (gdk_wayland_primary_get_type ())
+#define GDK_WAYLAND_PRIMARY(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WAYLAND_PRIMARY, 
GdkWaylandPrimary))
+#define GDK_IS_WAYLAND_PRIMARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WAYLAND_PRIMARY))
+
+typedef struct _GdkWaylandPrimary GdkWaylandPrimary;
+
+GType                   gdk_wayland_primary_get_type            (void) G_GNUC_CONST;
+
+GdkClipboard *          gdk_wayland_primary_new                 (GdkWaylandSeat         *seat);
+
+G_END_DECLS
+
+#endif /* __GDK_PRIMARY_WAYLAND_H__ */
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 2f99104..ef7f52a 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -184,9 +184,6 @@ struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_devic
 void gdk_wayland_device_set_selection (GdkDevice             *gdk_device,
                                        struct wl_data_source *source);
 
-void gdk_wayland_seat_set_primary (GdkSeat                             *seat,
-                                   struct gtk_primary_selection_source *source);
-
 GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
 
 void gdk_wayland_device_unset_touch_grab (GdkDevice        *device,
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index 1a20148..cb888f0 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -82,7 +82,6 @@ struct _SelectionData
 };
 
 enum {
-  ATOM_PRIMARY,
   ATOM_DND,
   N_ATOMS
 };
@@ -100,9 +99,6 @@ struct _GdkWaylandSelection
   GArray *source_targets;
   GdkAtom requested_target;
 
-  struct gtk_primary_selection_source *primary_source;
-  GdkWindow *primary_owner;
-
   struct wl_data_source *dnd_source; /* Owned by the GdkDragContext */
   GdkWindow *dnd_owner;
 };
@@ -307,7 +303,6 @@ gdk_wayland_selection_new (void)
   gint i;
 
   /* init atoms */
-  atoms[ATOM_PRIMARY] = gdk_atom_intern_static_string ("PRIMARY");
   atoms[ATOM_DND] = gdk_atom_intern_static_string ("GdkWaylandSelection");
 
   selection = g_new0 (GdkWaylandSelection, 1);
@@ -348,8 +343,6 @@ gdk_wayland_selection_free (GdkWaylandSelection *selection)
   if (selection->stored_selection.fd > 0)
     close (selection->stored_selection.fd);
 
-  if (selection->primary_source)
-    gtk_primary_selection_source_destroy (selection->primary_source);
   if (selection->dnd_source)
     wl_data_source_destroy (selection->dnd_source);
 
@@ -448,41 +441,11 @@ static const struct wl_data_offer_listener data_offer_listener = {
   data_offer_action
 };
 
-static void
-primary_offer_offer (void                               *data,
-                     struct gtk_primary_selection_offer *gtk_offer,
-                     const char                         *type)
-{
-  GdkWaylandSelection *selection = data;
-  GdkContentFormatsBuilder *builder;
-  DataOfferData *info;
-
-  info = g_hash_table_lookup (selection->offers, gtk_offer);
-
-  if (!info || gdk_content_formats_contain_mime_type (info->targets, type))
-    return;
-
-  GDK_NOTE (EVENTS,
-            g_message ("primary offer offer, offer %p, type = %s", gtk_offer, type));
-
-  builder = gdk_content_formats_builder_new ();
-  gdk_content_formats_builder_add_formats (builder, info->targets);
-  gdk_content_formats_builder_add_mime_type (builder, type);
-  gdk_content_formats_unref (info->targets);
-  info->targets = gdk_content_formats_builder_free (builder);
-}
-
-static const struct gtk_primary_selection_offer_listener primary_offer_listener = {
-  primary_offer_offer,
-};
-
 static SelectionData *
 selection_lookup_offer_by_atom (GdkWaylandSelection *selection,
                                 GdkAtom              selection_atom)
 {
-  if (selection_atom == atoms[ATOM_PRIMARY])
-    return &selection->selections[ATOM_PRIMARY];
-  else if (selection_atom == atoms[ATOM_DND])
+  if (selection_atom == atoms[ATOM_DND])
     return &selection->selections[ATOM_DND];
   else
     return NULL;
@@ -508,26 +471,6 @@ gdk_wayland_selection_ensure_offer (GdkDisplay           *display,
     }
 }
 
-void
-gdk_wayland_selection_ensure_primary_offer (GdkDisplay                         *display,
-                                            struct gtk_primary_selection_offer *gtk_offer)
-{
-  GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
-  DataOfferData *info;
-
-  info = g_hash_table_lookup (selection->offers, gtk_offer);
-
-  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);
-    }
-}
-
 GdkContentFormats *
 gdk_wayland_selection_steal_offer (GdkDisplay *display,
                                    gpointer    wl_offer)
@@ -1006,55 +949,6 @@ static const struct wl_data_source_listener data_source_listener = {
   data_source_action,
 };
 
-static void
-primary_source_send (void                                *data,
-                     struct gtk_primary_selection_source *source,
-                     const char                          *mime_type,
-                     int32_t                              fd)
-{
-  GdkWaylandSelection *wayland_selection = data;
-
-  GDK_NOTE (EVENTS,
-            g_message ("primary source send, source = %p, mime_type = %s, fd = %d",
-                       source, mime_type, fd));
-
-  if (!mime_type || !wayland_selection->primary_owner)
-    {
-      close (fd);
-      return;
-    }
-
-  if (!gdk_wayland_selection_request_target (wayland_selection,
-                                             wayland_selection->primary_owner,
-                                             atoms[ATOM_PRIMARY],
-                                             gdk_atom_intern (mime_type, FALSE),
-                                             fd))
-    gdk_wayland_selection_check_write (wayland_selection);
-}
-
-static void
-primary_source_cancelled (void                                *data,
-                          struct gtk_primary_selection_source *source)
-{
-  GdkDisplay *display;
-  GdkAtom atom;
-
-  GDK_NOTE (EVENTS,
-            g_message ("primary source cancelled, source = %p", source));
-
-  display = gdk_display_get_default ();
-
-  atom = atoms[ATOM_PRIMARY];
-  emit_selection_clear (display, atom);
-  gdk_selection_owner_set (NULL, atom, GDK_CURRENT_TIME, TRUE);
-  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,
-};
-
 struct wl_data_source *
 gdk_wayland_selection_get_data_source (GdkWindow *owner,
                                        GdkAtom    selection)
@@ -1070,18 +964,6 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
           (!owner || owner == wayland_selection->dnd_owner))
         return wayland_selection->dnd_source;
     }
-  else if (selection == atoms[ATOM_PRIMARY])
-    {
-      if (wayland_selection->primary_source &&
-          (!owner || owner == wayland_selection->primary_owner))
-        return (gpointer) wayland_selection->primary_source;
-
-      if (wayland_selection->primary_source)
-        {
-          gtk_primary_selection_source_destroy (wayland_selection->primary_source);
-          wayland_selection->primary_source = NULL;
-        }
-    }
   else
     return NULL;
 
@@ -1090,28 +972,13 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
 
   display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (owner));
 
-  if (selection == atoms[ATOM_PRIMARY])
-    {
-      if (display_wayland->primary_selection_manager)
-        {
-          source = gtk_primary_selection_device_manager_create_source 
(display_wayland->primary_selection_manager);
-          gtk_primary_selection_source_add_listener (source,
-                                                     &primary_source_listener,
-                                                     wayland_selection);
-        }
-    }
-  else
-    {
-      source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
-      wl_data_source_add_listener (source,
-                                   &data_source_listener,
-                                   wayland_selection);
-    }
+  source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
+  wl_data_source_add_listener (source,
+                               &data_source_listener,
+                               wayland_selection);
 
   if (selection == atoms[ATOM_DND])
     wayland_selection->dnd_source = source;
-  else if (selection == atoms[ATOM_PRIMARY])
-    wayland_selection->primary_source = source;
 
   return source;
 }
@@ -1122,19 +989,7 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display,
 {
   GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
 
-  if (selection == atoms[ATOM_PRIMARY])
-    {
-      GdkSeat *seat = gdk_display_get_default_seat (display);
-
-      gdk_wayland_seat_set_primary (seat, NULL);
-
-      if (wayland_selection->primary_source)
-        {
-          gtk_primary_selection_source_destroy (wayland_selection->primary_source);
-          wayland_selection->primary_source = NULL;
-        }
-    }
-  else if (selection == atoms[ATOM_DND])
+  if (selection == atoms[ATOM_DND])
     {
       wayland_selection->dnd_source = NULL;
     }
@@ -1146,9 +1001,7 @@ _gdk_wayland_display_get_selection_owner (GdkDisplay *display,
 {
   GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
 
-  if (selection == atoms[ATOM_PRIMARY])
-    return wayland_selection->primary_owner;
-  else if (selection == atoms[ATOM_DND])
+  if (selection == atoms[ATOM_DND])
     return wayland_selection->dnd_owner;
 
   return NULL;
@@ -1163,12 +1016,7 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display,
 {
   GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
 
-  if (selection == atoms[ATOM_PRIMARY])
-    {
-      wayland_selection->primary_owner = owner;
-      return TRUE;
-    }
-  else if (selection == atoms[ATOM_DND])
+  if (selection == atoms[ATOM_DND])
     {
       wayland_selection->dnd_owner = owner;
       return TRUE;
@@ -1311,10 +1159,9 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
           return;
         }
 
-      if (selection != atoms[ATOM_PRIMARY])
-        wl_data_offer_accept (offer,
-                              _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
-                              mimetype);
+    wl_data_offer_accept (offer,
+                          _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
+                          mimetype);
     }
 
   buffer_data = g_hash_table_lookup (selection_data->buffers, target);
@@ -1336,10 +1183,7 @@ _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]);
-          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]);
@@ -1501,14 +1345,6 @@ gdk_wayland_display_add_selection_targets (GdkDisplay *display,
       wl_data_source_offer (data_source, mimetype);
       g_free (mimetype);
     }
-
-  if (selection == atoms[ATOM_PRIMARY])
-    {
-      GdkSeat *seat;
-
-      seat = gdk_display_get_default_seat (display);
-      gdk_wayland_seat_set_primary (seat, data_source);
-    }
 }
 
 void
diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build
index c395631..fec3d2c 100644
--- a/gdk/wayland/meson.build
+++ b/gdk/wayland/meson.build
@@ -9,6 +9,7 @@ gdk_wayland_sources = files([
   'gdkglcontext-wayland.c',
   'gdkkeys-wayland.c',
   'gdkmonitor-wayland.c',
+  'gdkprimary-wayland.c',
   'gdkselection-wayland.c',
   'gdkvulkancontext-wayland.c',
   'gdkwindow-wayland.c',


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