[gtk+/wip/otte/clipboard: 116/117] textview: Redo clipboard handling



commit dff4f646801aa728704d3708a39a6d1292be04ad
Author: Benjamin Otte <otte redhat com>
Date:   Tue Nov 28 02:09:21 2017 +0100

    textview: Redo clipboard handling
    
    Instead of using GtkClipboard and handling everything ourselves, we now
    put GtkTextBuffer into the GdkClipboard and register (de)serializers for
    text/plain.

 demos/widget-factory/widget-factory.c |   12 +-
 examples/bp/bloatpad.c                |   10 +-
 examples/plugman.c                    |   10 +-
 gtk/gtktextbuffer.c                   |  731 ++++++++++++++-------------------
 gtk/gtktextbuffer.h                   |   15 +-
 gtk/gtktextview.c                     |  145 ++-----
 testsuite/gtk/textbuffer.c            |    4 +-
 7 files changed, 372 insertions(+), 555 deletions(-)
---
diff --git a/demos/widget-factory/widget-factory.c b/demos/widget-factory/widget-factory.c
index 6759eb2..d2f5ddc 100644
--- a/demos/widget-factory/widget-factory.c
+++ b/demos/widget-factory/widget-factory.c
@@ -1232,10 +1232,10 @@ static void
 handle_cutcopypaste (GtkWidget *button, GtkWidget *textview)
 {
   GtkTextBuffer *buffer;
-  GtkClipboard *clipboard;
+  GdkClipboard *clipboard;
   const gchar *id;
 
-  clipboard = gtk_widget_get_old_clipboard (textview, GDK_SELECTION_CLIPBOARD);
+  clipboard = gtk_widget_get_clipboard (textview);
   buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
   id = gtk_buildable_get_name (GTK_BUILDABLE (button));
 
@@ -1250,13 +1250,13 @@ handle_cutcopypaste (GtkWidget *button, GtkWidget *textview)
 }
 
 static void
-clipboard_owner_change (GtkClipboard *clipboard, GdkEvent *event, GtkWidget *button)
+clipboard_formats_notify (GdkClipboard *clipboard, GdkEvent *event, GtkWidget *button)
 {
   const gchar *id;
   gboolean has_text;
 
   id = gtk_buildable_get_name (GTK_BUILDABLE (button));
-  has_text = gtk_clipboard_wait_is_text_available (clipboard);
+  has_text = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_TEXT_BUFFER);
 
   if (strcmp (id, "pastebutton") == 0)
     gtk_widget_set_sensitive (button, has_text);
@@ -1843,8 +1843,8 @@ activate (GApplication *app)
                     G_CALLBACK (textbuffer_notify_selection), widget);
   widget = (GtkWidget *)gtk_builder_get_object (builder, "pastebutton");
   g_signal_connect (widget, "clicked", G_CALLBACK (handle_cutcopypaste), widget2);
-  g_signal_connect_object (gtk_widget_get_old_clipboard (widget2, GDK_SELECTION_CLIPBOARD), "owner-change",
-                           G_CALLBACK (clipboard_owner_change), widget, 0);
+  g_signal_connect_object (gtk_widget_get_clipboard (widget2), "notify::formats",
+                           G_CALLBACK (clipboard_formats_notify), widget, 0);
 
   widget = (GtkWidget *)gtk_builder_get_object (builder, "osd_frame");
   widget2 = (GtkWidget *)gtk_builder_get_object (builder, "totem_like_osd");
diff --git a/examples/bp/bloatpad.c b/examples/bp/bloatpad.c
index 5a52f92..78ca433 100644
--- a/examples/bp/bloatpad.c
+++ b/examples/bp/bloatpad.c
@@ -93,12 +93,6 @@ change_justify_state (GSimpleAction *action,
   g_simple_action_set_state (action, state);
 }
 
-static GtkClipboard *
-get_clipboard (GtkWidget *widget)
-{
-  return gtk_widget_get_old_clipboard (widget, gdk_atom_intern_static_string ("CLIPBOARD"));
-}
-
 static void
 window_copy (GSimpleAction *action,
              GVariant      *parameter,
@@ -108,7 +102,7 @@ window_copy (GSimpleAction *action,
   GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
 
   gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text),
-                                  get_clipboard ((GtkWidget*) text));
+                                  gtk_widget_get_clipboard (GTK_WIDGET (text)));
 }
 
 static void
@@ -120,7 +114,7 @@ window_paste (GSimpleAction *action,
   GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
   
   gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
-                                   get_clipboard ((GtkWidget*) text),
+                                   gtk_widget_get_clipboard (GTK_WIDGET (text)),
                                    NULL,
                                    TRUE);
 
diff --git a/examples/plugman.c b/examples/plugman.c
index 8605587..67d7960 100644
--- a/examples/plugman.c
+++ b/examples/plugman.c
@@ -38,12 +38,6 @@ change_fullscreen_state (GSimpleAction *action,
   g_simple_action_set_state (action, state);
 }
 
-static GtkClipboard *
-get_clipboard (GtkWidget *widget)
-{
-  return gtk_widget_get_old_clipboard (widget, gdk_atom_intern_static_string ("CLIPBOARD"));
-}
-
 static void
 window_copy (GSimpleAction *action,
              GVariant      *parameter,
@@ -53,7 +47,7 @@ window_copy (GSimpleAction *action,
   GtkTextView *text = g_object_get_data ((GObject*)window, "plugman-text");
 
   gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text),
-                                  get_clipboard ((GtkWidget*) text));
+                                  gtk_widget_get_clipboard (GTK_WIDGET (text)));
 }
 
 static void
@@ -65,7 +59,7 @@ window_paste (GSimpleAction *action,
   GtkTextView *text = g_object_get_data ((GObject*)window, "plugman-text");
   
   gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
-                                   get_clipboard ((GtkWidget*) text),
+                                   gtk_widget_get_clipboard (GTK_WIDGET (text)),
                                    NULL,
                                    TRUE);
 
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index c55b895..6268be3 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -55,14 +55,11 @@ typedef struct _GtkTextLogAttrCache GtkTextLogAttrCache;
 
 struct _GtkTextBufferPrivate
 {
-  GdkContentFormats  *copy_target_list;
-  GdkContentFormats  *paste_target_list;
-
   GtkTextTagTable *tag_table;
   GtkTextBTree *btree;
 
-  GSList *clipboard_contents_buffers;
   GSList *selection_clipboards;
+  GdkContentProvider *selection_content;
 
   GtkTextLogAttrCache *log_attr_cache;
 
@@ -149,10 +146,6 @@ static void          free_log_attr_cache (GtkTextLogAttrCache *cache);
 static void remove_all_selection_clipboards       (GtkTextBuffer *buffer);
 static void update_selection_clipboards           (GtkTextBuffer *buffer);
 
-static GtkTextBuffer *create_clipboard_contents_buffer (GtkTextBuffer *buffer);
-
-static void gtk_text_buffer_free_target_lists     (GtkTextBuffer *buffer);
-
 static void gtk_text_buffer_set_property (GObject         *object,
                                          guint            prop_id,
                                          const GValue    *value,
@@ -161,14 +154,239 @@ static void gtk_text_buffer_get_property (GObject         *object,
                                          guint            prop_id,
                                          GValue          *value,
                                          GParamSpec      *pspec);
-static void gtk_text_buffer_notify       (GObject         *object,
-                                          GParamSpec      *pspec);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *text_buffer_props[LAST_PROP];
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkTextBuffer, gtk_text_buffer, G_TYPE_OBJECT)
 
+#define GTK_TYPE_TEXT_BUFFER_CONTENT            (gtk_text_buffer_content_get_type ())
+#define GTK_TEXT_BUFFER_CONTENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GTK_TYPE_TEXT_BUFFER_CONTENT, GtkTextBufferContent))
+#define GTK_IS_TEXT_BUFFER_CONTENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GTK_TYPE_TEXT_BUFFER_CONTENT))
+#define GTK_TEXT_BUFFER_CONTENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
GTK_TYPE_TEXT_BUFFER_CONTENT, GtkTextBufferContentClass))
+#define GTK_IS_TEXT_BUFFER_CONTENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GTK_TYPE_TEXT_BUFFER_CONTENT))
+#define GTK_TEXT_BUFFER_CONTENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_TEXT_BUFFER_CONTENT, GtkTextBufferContentClass))
+
+typedef struct _GtkTextBufferContent GtkTextBufferContent;
+typedef struct _GtkTextBufferContentClass GtkTextBufferContentClass;
+
+struct _GtkTextBufferContent
+{
+  GdkContentProvider parent;
+
+  GtkTextBuffer *text_buffer;
+};
+
+struct _GtkTextBufferContentClass
+{
+  GdkContentProviderClass parent_class;
+};
+
+GType gtk_text_buffer_content_get_type (void) G_GNUC_CONST;
+
+G_DEFINE_TYPE (GtkTextBufferContent, gtk_text_buffer_content, GDK_TYPE_CONTENT_PROVIDER)
+
+static GdkContentFormats *
+gtk_text_buffer_content_ref_formats (GdkContentProvider *provider)
+{
+  GtkTextBufferContent *content = GTK_TEXT_BUFFER_CONTENT (provider);
+
+  if (content->text_buffer)
+    return gdk_content_formats_new_for_gtype (GTK_TYPE_TEXT_BUFFER);
+  else
+    return gdk_content_formats_new (NULL, 0);
+}
+
+static gboolean
+gtk_text_buffer_content_get_value (GdkContentProvider  *provider,
+                                   GValue              *value,
+                                   GError             **error)
+{
+  GtkTextBufferContent *content = GTK_TEXT_BUFFER_CONTENT (provider);
+
+  if (G_VALUE_HOLDS (value, GTK_TYPE_TEXT_BUFFER) &&
+      content->text_buffer != NULL)
+    {
+      g_value_set_object (value, content->text_buffer);
+      return TRUE;
+    }
+
+  return GDK_CONTENT_PROVIDER_CLASS (gtk_text_buffer_content_parent_class)->get_value (provider, value, 
error);
+}
+
+static void
+gtk_text_buffer_content_detach (GdkContentProvider *provider,
+                                GdkClipboard       *clipboard)
+{
+  GtkTextBufferContent *content = GTK_TEXT_BUFFER_CONTENT (provider);
+  GtkTextIter insert;
+  GtkTextIter selection_bound;
+
+  if (content->text_buffer == NULL)
+    return;
+
+  /* Move selection_bound to the insertion point */
+  gtk_text_buffer_get_iter_at_mark (content->text_buffer, &insert,
+                                    gtk_text_buffer_get_insert (content->text_buffer));
+  gtk_text_buffer_get_iter_at_mark (content->text_buffer, &selection_bound,
+                                    gtk_text_buffer_get_selection_bound (content->text_buffer));
+
+  if (!gtk_text_iter_equal (&insert, &selection_bound))
+    gtk_text_buffer_move_mark (content->text_buffer,
+                               gtk_text_buffer_get_selection_bound (content->text_buffer),
+                               &insert);
+}
+
+static void
+gtk_text_buffer_content_class_init (GtkTextBufferContentClass *class)
+{
+  GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
+
+  provider_class->ref_formats = gtk_text_buffer_content_ref_formats;
+  provider_class->get_value = gtk_text_buffer_content_get_value;
+  provider_class->detach_clipboard = gtk_text_buffer_content_detach;
+}
+
+static void
+gtk_text_buffer_content_init (GtkTextBufferContent *content)
+{
+}
+
+static GdkContentProvider *
+gtk_text_buffer_content_new (GtkTextBuffer *buffer)
+{
+  GtkTextBufferContent *content;
+
+  content = g_object_new (GTK_TYPE_TEXT_BUFFER_CONTENT, NULL);
+  content->text_buffer = g_object_ref (buffer);
+  
+  return GDK_CONTENT_PROVIDER (content);
+}
+
+static void
+gtk_text_buffer_deserialize_text_plain_finish (GObject      *source,
+                                               GAsyncResult *result,
+                                               gpointer      deserializer)
+{
+  GOutputStream *stream = G_OUTPUT_STREAM (source);
+  GtkTextBuffer *buffer;
+  GtkTextIter start, end;
+  GError *error = NULL;
+  gssize written;
+
+  written = g_output_stream_splice_finish (stream, result, &error);
+  if (written < 0)
+    {
+      gdk_content_deserializer_return_error (deserializer, error);
+      return;
+    }
+
+  buffer = g_value_get_object (gdk_content_deserializer_get_value (deserializer));
+  gtk_text_buffer_get_end_iter (buffer, &end);
+  gtk_text_buffer_insert (buffer, 
+                          &end,
+                          g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (
+                               g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (stream)))),
+                          -1);
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+  gtk_text_buffer_select_range (buffer, &start, &end);
+
+  gdk_content_deserializer_return_success (deserializer);
+}
+
+static void
+gtk_text_buffer_deserialize_text_plain (GdkContentDeserializer *deserializer)
+{
+  GOutputStream *output, *filter;
+  GCharsetConverter *converter;
+  GtkTextBuffer *buffer;
+  GError *error = NULL;
+
+  buffer = gtk_text_buffer_new (NULL);
+  g_value_set_object (gdk_content_deserializer_get_value (deserializer),
+                      buffer);
+
+  /* validates the stream */
+  converter = g_charset_converter_new ("utf-8", "utf-8", &error);
+  if (converter == NULL)
+    {
+      gdk_content_deserializer_return_error (deserializer, error);
+      return;
+    }
+  g_charset_converter_set_use_fallback (converter, TRUE);
+
+  output = g_memory_output_stream_new_resizable ();
+  filter = g_converter_output_stream_new (output, G_CONVERTER (converter));
+  g_object_unref (output);
+  g_object_unref (converter);
+
+  g_output_stream_splice_async (filter,
+                                gdk_content_deserializer_get_input_stream (deserializer),
+                                G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                gdk_content_deserializer_get_priority (deserializer),
+                                gdk_content_deserializer_get_cancellable (deserializer),
+                                gtk_text_buffer_deserialize_text_plain_finish,
+                                deserializer);
+  g_object_unref (filter);
+}
+
+static void
+gtk_text_buffer_serialize_text_plain_finish (GObject      *source,
+                                             GAsyncResult *result,
+                                             gpointer      serializer)
+{
+  GOutputStream *stream = G_OUTPUT_STREAM (source);
+  GError *error = NULL;
+
+  if (!g_output_stream_write_all_finish (stream, result, NULL, &error))
+    gdk_content_serializer_return_error (serializer, error);
+  else
+    gdk_content_serializer_return_success (serializer);
+}
+
+static void
+gtk_text_buffer_serialize_text_plain (GdkContentSerializer *serializer)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter start, end;
+  char *str;
+
+  buffer = g_value_get_object (gdk_content_serializer_get_value (serializer));
+
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+    {
+      str = gtk_text_iter_get_visible_text (&start, &end);
+    }
+  else
+    {
+      str = g_strdup ("");
+    }
+  gdk_content_serializer_set_task_data (serializer, str, g_free);
+
+  g_output_stream_write_all_async (gdk_content_serializer_get_output_stream (serializer),
+                                   str,
+                                   strlen (str) + 1,
+                                   gdk_content_serializer_get_priority (serializer),
+                                   gdk_content_serializer_get_cancellable (serializer),
+                                   gtk_text_buffer_serialize_text_plain_finish,
+                                   serializer);
+}
+
+static void
+gtk_text_buffer_register_serializers (void)
+{
+  gdk_content_register_deserializer ("text/plain;charset=utf-8",
+                                     GTK_TYPE_TEXT_BUFFER,
+                                     gtk_text_buffer_deserialize_text_plain,
+                                     NULL,
+                                     NULL);
+  gdk_content_register_serializer (GTK_TYPE_TEXT_BUFFER,
+                                   "text/plain;charset=utf-8",
+                                   gtk_text_buffer_serialize_text_plain,
+                                   NULL,
+                                   NULL);
+}
+
 static void
 gtk_text_buffer_class_init (GtkTextBufferClass *klass)
 {
@@ -177,7 +395,6 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
   object_class->finalize = gtk_text_buffer_finalize;
   object_class->set_property = gtk_text_buffer_set_property;
   object_class->get_property = gtk_text_buffer_get_property;
-  object_class->notify       = gtk_text_buffer_notify;
  
   klass->insert_text = gtk_text_buffer_real_insert_text;
   klass->insert_pixbuf = gtk_text_buffer_real_insert_pixbuf;
@@ -617,7 +834,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
    /**
    * GtkTextBuffer::paste-done:
    * @textbuffer: the object which received the signal
-   * @clipboard: the #GtkClipboard pasted from
+   * @clipboard: the #GdkClipboard pasted from
    * 
    * The paste-done signal is emitted after paste operation has been completed.
    * This is useful to properly scroll the view to the end of the pasted text.
@@ -634,14 +851,15 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
                   NULL,
                   G_TYPE_NONE,
                   1,
-                  GTK_TYPE_CLIPBOARD);
+                  GDK_TYPE_CLIPBOARD);
+
+  gtk_text_buffer_register_serializers ();
 }
 
 static void
 gtk_text_buffer_init (GtkTextBuffer *buffer)
 {
   buffer->priv = gtk_text_buffer_get_instance_private (buffer);
-  buffer->priv->clipboard_contents_buffers = NULL;
   buffer->priv->tag_table = NULL;
 }
 
@@ -741,31 +959,12 @@ gtk_text_buffer_get_property (GObject         *object,
       g_value_set_int (value, gtk_text_iter_get_offset (&iter));
       break;
 
-    case PROP_COPY_TARGET_LIST:
-      g_value_set_boxed (value, gtk_text_buffer_get_copy_target_list (text_buffer));
-      break;
-
-    case PROP_PASTE_TARGET_LIST:
-      g_value_set_boxed (value, gtk_text_buffer_get_paste_target_list (text_buffer));
-      break;
-
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
 }
 
-static void
-gtk_text_buffer_notify (GObject    *object,
-                        GParamSpec *pspec)
-{
-  if (!strcmp (pspec->name, "copy-target-list") ||
-      !strcmp (pspec->name, "paste-target-list"))
-    {
-      gtk_text_buffer_free_target_lists (GTK_TEXT_BUFFER (object));
-    }
-}
-
 /**
  * gtk_text_buffer_new:
  * @table: (allow-none): a tag table, or %NULL to create a new one
@@ -813,8 +1012,6 @@ gtk_text_buffer_finalize (GObject *object)
 
   priv->log_attr_cache = NULL;
 
-  gtk_text_buffer_free_target_lists (buffer);
-
   G_OBJECT_CLASS (gtk_text_buffer_parent_class)->finalize (object);
 }
 
@@ -3172,74 +3369,20 @@ gtk_text_buffer_get_char_count (GtkTextBuffer *buffer)
   return _gtk_text_btree_char_count (get_btree (buffer));
 }
 
-/* Called when we lose the primary selection.
- */
-static void
-clipboard_clear_selection_cb (GtkClipboard *clipboard,
-                              gpointer      data)
-{
-  /* Move selection_bound to the insertion point */
-  GtkTextIter insert;
-  GtkTextIter selection_bound;
-  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
-
-  gtk_text_buffer_get_iter_at_mark (buffer, &insert,
-                                    gtk_text_buffer_get_insert (buffer));
-  gtk_text_buffer_get_iter_at_mark (buffer, &selection_bound,
-                                    gtk_text_buffer_get_selection_bound (buffer));
-
-  if (!gtk_text_iter_equal (&insert, &selection_bound))
-    gtk_text_buffer_move_mark (buffer,
-                               gtk_text_buffer_get_selection_bound (buffer),
-                               &insert);
-}
-
-/* Called when we have the primary selection and someone else wants our
- * data in order to paste it.
- */
-static void
-clipboard_get_selection_cb (GtkClipboard     *clipboard,
-                            GtkSelectionData *selection_data,
-                            gpointer          data)
-{
-  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
-  GtkTextIter start, end;
-
-  if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
-    {
-      if (gtk_selection_data_get_target (selection_data) == gdk_atom_intern_static_string 
("GTK_TEXT_BUFFER_CONTENTS"))
-        {
-          /* Provide the address of the buffer; this will only be
-           * used within-process
-           */
-          gtk_selection_data_set (selection_data,
-                                  gtk_selection_data_get_target (selection_data),
-                                  8, /* bytes */
-                                  (void*)&buffer,
-                                  sizeof (buffer));
-        }
-      else if (gtk_selection_data_targets_include_text (selection_data))
-        {
-          gchar *str;
-
-          str = gtk_text_iter_get_visible_text (&start, &end);
-          gtk_selection_data_set_text (selection_data, str, -1);
-          g_free (str);
-        }
-    }
-}
-
 static GtkTextBuffer *
-create_clipboard_contents_buffer (GtkTextBuffer *buffer)
+create_clipboard_contents_buffer (GtkTextBuffer *buffer,
+                                  GtkTextIter   *start_iter,
+                                  GtkTextIter   *end_iter)
 {
+  GtkTextIter start, end;
   GtkTextBuffer *contents;
 
   contents = gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
 
-  g_object_set_data (G_OBJECT (contents), I_("gtk-text-buffer-clipboard-source"),
-                     buffer);
-  g_object_set_data (G_OBJECT (contents), I_("gtk-text-buffer-clipboard"),
-                     GINT_TO_POINTER (1));
+  gtk_text_buffer_get_iter_at_offset (contents, &start, 0);
+  gtk_text_buffer_insert_range (contents, &start, start_iter, end_iter);
+  gtk_text_buffer_get_bounds (contents, &start, &end);
+  gtk_text_buffer_select_range (contents, &start, &end);
 
   /*  Ref the source buffer as long as the clipboard contents buffer
    *  exists, because it's needed for serializing the contents buffer.
@@ -3251,49 +3394,6 @@ create_clipboard_contents_buffer (GtkTextBuffer *buffer)
   return contents;
 }
 
-/* Provide cut/copied data */
-static void
-clipboard_get_contents_cb (GtkClipboard     *clipboard,
-                           GtkSelectionData *selection_data,
-                           gpointer          data)
-{
-  GtkTextBuffer *contents = GTK_TEXT_BUFFER (data);
-
-  g_assert (contents); /* This should never be called unless we own the clipboard */
-
-  if (gtk_selection_data_get_target (selection_data) == gdk_atom_intern_static_string 
("GTK_TEXT_BUFFER_CONTENTS"))
-    {
-      /* Provide the address of the clipboard buffer; this will only
-       * be used within-process. OK to supply a NULL value for contents.
-       */
-      gtk_selection_data_set (selection_data,
-                              gtk_selection_data_get_target (selection_data),
-                              8, /* bytes */
-                              (void*)&contents,
-                              sizeof (contents));
-    }
-  else
-    {
-      gchar *str;
-      GtkTextIter start, end;
-
-      gtk_text_buffer_get_bounds (contents, &start, &end);
-
-      str = gtk_text_iter_get_visible_text (&start, &end);
-      gtk_selection_data_set_text (selection_data, str, -1);
-      g_free (str);
-    }
-}
-
-static void
-clipboard_clear_contents_cb (GtkClipboard *clipboard,
-                             gpointer      data)
-{
-  GtkTextBuffer *contents = GTK_TEXT_BUFFER (data);
-
-  g_object_unref (contents);
-}
-
 static void
 get_paste_point (GtkTextBuffer *buffer,
                  GtkTextIter   *iter,
@@ -3350,7 +3450,7 @@ pre_paste_prep (ClipboardRequest *request_data,
 
 static void
 emit_paste_done (GtkTextBuffer *buffer,
-                 GtkClipboard  *clipboard)
+                 GdkClipboard  *clipboard)
 {
   g_signal_emit (buffer, signals[PASTE_DONE], 0, clipboard);
 }
@@ -3362,90 +3462,6 @@ free_clipboard_request (ClipboardRequest *request_data)
   g_slice_free (ClipboardRequest, request_data);
 }
 
-/* Called when we request a paste and receive the text data
- */
-static void
-clipboard_text_received (GtkClipboard *clipboard,
-                         const gchar  *str,
-                         gpointer      data)
-{
-  ClipboardRequest *request_data = data;
-  GtkTextBuffer *buffer = request_data->buffer;
-
-  if (str)
-    {
-      GtkTextIter insert_point;
-      
-      if (request_data->interactive) 
-       gtk_text_buffer_begin_user_action (buffer);
-
-      pre_paste_prep (request_data, &insert_point);
-      
-      if (request_data->interactive) 
-       gtk_text_buffer_insert_interactive (buffer, &insert_point,
-                                           str, -1, request_data->default_editable);
-      else
-        gtk_text_buffer_insert (buffer, &insert_point,
-                                str, -1);
-
-      if (request_data->interactive) 
-       gtk_text_buffer_end_user_action (buffer);
-
-      emit_paste_done (buffer, clipboard);
-    }
-  else
-    {
-      /* It may happen that we set a point override but we are not inserting
-         any text, so we must remove it afterwards */
-      GtkTextMark *paste_point_override;
-
-      paste_point_override = gtk_text_buffer_get_mark (buffer,
-                                                       "gtk_paste_point_override");
-
-      if (paste_point_override != NULL)
-        gtk_text_buffer_delete_mark (buffer, paste_point_override);
-    }
-
-  free_clipboard_request (request_data);
-}
-
-static GtkTextBuffer*
-selection_data_get_buffer (GtkSelectionData *selection_data,
-                           ClipboardRequest *request_data)
-{
-  GdkWindow *owner;
-  GtkTextBuffer *src_buffer = NULL;
-
-  /* If we can get the owner, the selection is in-process */
-  owner = gdk_selection_owner_get_for_display (gtk_selection_data_get_display (selection_data),
-                                              gtk_selection_data_get_selection (selection_data));
-
-  if (owner == NULL)
-    return NULL;
-  
-  if (gdk_window_get_window_type (owner) == GDK_WINDOW_FOREIGN)
-    return NULL;
-
-  if (gtk_selection_data_get_data_type (selection_data) != gdk_atom_intern_static_string 
("GTK_TEXT_BUFFER_CONTENTS"))
-    return NULL;
-
-  if (gtk_selection_data_get_length (selection_data) != sizeof (src_buffer))
-    return NULL;
-
-  memcpy (&src_buffer, gtk_selection_data_get_data (selection_data), sizeof (src_buffer));
-
-  if (src_buffer == NULL)
-    return NULL;
-  
-  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (src_buffer), NULL);
-
-  if (gtk_text_buffer_get_tag_table (src_buffer) !=
-      gtk_text_buffer_get_tag_table (request_data->buffer))
-    return NULL;
-  
-  return src_buffer;
-}
-
 #if 0
 /* These are pretty handy functions; maybe something like them
  * should be in the public API. Also, there are other places in this
@@ -3474,7 +3490,7 @@ restore_iter (const GtkTextIter *iter,
 #endif
 
 static void
-paste_from_buffer (GtkClipboard      *clipboard,
+paste_from_buffer (GdkClipboard      *clipboard,
                    ClipboardRequest  *request_data,
                    GtkTextBuffer     *src_buffer,
                    const GtkTextIter *start,
@@ -3524,45 +3540,30 @@ done:
 }
 
 static void
-clipboard_clipboard_buffer_received (GtkClipboard     *clipboard,
-                                     GtkSelectionData *selection_data,
-                                     gpointer          data)
+gtk_text_buffer_paste_clipboard_finish (GObject      *source,
+                                        GAsyncResult *result,
+                                        gpointer      data)
 {
+  GdkClipboard *clipboard = GDK_CLIPBOARD (source);
   ClipboardRequest *request_data = data;
   GtkTextBuffer *src_buffer;
+  GtkTextIter start, end;
+  const GValue *value;
 
-  src_buffer = selection_data_get_buffer (selection_data, request_data); 
-
-  if (src_buffer)
-    {
-      GtkTextIter start, end;
+  value = gdk_clipboard_read_value_finish (clipboard, result, NULL);
+  if (value == NULL)
+    return;
 
-      if (g_object_get_data (G_OBJECT (src_buffer), "gtk-text-buffer-clipboard"))
-       {
-         gtk_text_buffer_get_bounds (src_buffer, &start, &end);
+  src_buffer = g_value_get_object (value);
 
-         paste_from_buffer (clipboard, request_data, src_buffer,
-                            &start, &end);
-       }
-      else
-       {
-         if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
-           paste_from_buffer (clipboard, request_data, src_buffer,
-                              &start, &end);
-       }
-    }
-  else
-    {
-      /* Request the text selection instead */
-      gtk_clipboard_request_text (clipboard,
-                                  clipboard_text_received,
-                                  data);
-    }
+  if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
+    paste_from_buffer (clipboard, request_data, src_buffer,
+                       &start, &end);
 }
 
 typedef struct
 {
-  GtkClipboard *clipboard;
+  GdkClipboard *clipboard;
   guint ref_count;
 } SelectionClipboard;
 
@@ -3570,43 +3571,45 @@ static void
 update_selection_clipboards (GtkTextBuffer *buffer)
 {
   GtkTextBufferPrivate *priv;
-  gboolean has_selection;
   GtkTextIter start;
   GtkTextIter end;
-  GSList *tmp_list;
+  GSList *l;
 
   priv = buffer->priv;
 
-  gtk_text_buffer_get_copy_target_list (buffer);
-  has_selection = gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
-  tmp_list = buffer->priv->selection_clipboards;
-
-  while (tmp_list)
+  if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
     {
-      SelectionClipboard *selection_clipboard = tmp_list->data;
-      GtkClipboard *clipboard = selection_clipboard->clipboard;
-
-      if (has_selection)
+      if (priv->selection_content)
+        gdk_content_provider_content_changed (priv->selection_content);
+      else
+        priv->selection_content = gtk_text_buffer_content_new (buffer);
+      
+      for (l = priv->selection_clipboards; l; l = l->next)
         {
-          /* Even if we already have the selection, we need to update our
-           * timestamp.
-           */
-          gtk_clipboard_set_with_owner (clipboard,
-                                        priv->copy_target_list,
-                                        clipboard_get_selection_cb,
-                                        clipboard_clear_selection_cb,
-                                        G_OBJECT (buffer));
+          SelectionClipboard *selection_clipboard = l->data;
+          gdk_clipboard_set_content (selection_clipboard->clipboard, priv->selection_content);
+        }
+    }
+  else
+    {
+      if (priv->selection_content)
+        {
+          GTK_TEXT_BUFFER_CONTENT (priv->selection_content)->text_buffer = NULL;
+          for (l = priv->selection_clipboards; l; l = l->next)
+            {
+              SelectionClipboard *selection_clipboard = l->data;
+              GdkClipboard *clipboard = selection_clipboard->clipboard;
+              if (gdk_clipboard_get_content (clipboard) == priv->selection_content)
+                gdk_clipboard_set_content (clipboard, NULL);
+            }
+          g_clear_object (&priv->selection_content);
         }
-      else if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
-        gtk_clipboard_clear (clipboard);
-
-      tmp_list = tmp_list->next;
     }
 }
 
 static SelectionClipboard *
 find_selection_clipboard (GtkTextBuffer *buffer,
-                         GtkClipboard  *clipboard)
+                         GdkClipboard  *clipboard)
 {
   GSList *tmp_list = buffer->priv->selection_clipboards;
   while (tmp_list)
@@ -3624,15 +3627,16 @@ find_selection_clipboard (GtkTextBuffer *buffer,
 /**
  * gtk_text_buffer_add_selection_clipboard:
  * @buffer: a #GtkTextBuffer
- * @clipboard: a #GtkClipboard
+ * @clipboard: a #GdkClipboard
  * 
  * Adds @clipboard to the list of clipboards in which the selection 
  * contents of @buffer are available. In most cases, @clipboard will be 
- * the #GtkClipboard of type %GDK_SELECTION_PRIMARY for a view of @buffer.
+ * the #GdkClipboard returned by gdk_widget_get_primary_clipboard()
+ * for a view of @buffer.
  **/
 void
 gtk_text_buffer_add_selection_clipboard (GtkTextBuffer *buffer,
-                                        GtkClipboard  *clipboard)
+                                        GdkClipboard  *clipboard)
 {
   SelectionClipboard *selection_clipboard;
 
@@ -3659,16 +3663,17 @@ gtk_text_buffer_add_selection_clipboard (GtkTextBuffer *buffer,
 /**
  * gtk_text_buffer_remove_selection_clipboard:
  * @buffer: a #GtkTextBuffer
- * @clipboard: a #GtkClipboard added to @buffer by 
+ * @clipboard: a #GdkClipboard added to @buffer by 
  *             gtk_text_buffer_add_selection_clipboard()
  * 
- * Removes a #GtkClipboard added with 
+ * Removes a #GdkClipboard added with 
  * gtk_text_buffer_add_selection_clipboard().
  **/
 void 
 gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer *buffer,
-                                           GtkClipboard  *clipboard)
+                                           GdkClipboard  *clipboard)
 {
+  GtkTextBufferPrivate *priv;
   SelectionClipboard *selection_clipboard;
 
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
@@ -3677,11 +3682,13 @@ gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer *buffer,
   selection_clipboard = find_selection_clipboard (buffer, clipboard);
   g_return_if_fail (selection_clipboard != NULL);
 
+  priv = buffer->priv;
   selection_clipboard->ref_count--;
   if (selection_clipboard->ref_count == 0)
     {
-      if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer))
-       gtk_clipboard_clear (selection_clipboard->clipboard);
+      if (priv->selection_content &&
+          gdk_clipboard_get_content (clipboard) == priv->selection_content)
+       gdk_clipboard_set_content (clipboard, NULL);
 
       buffer->priv->selection_clipboards = g_slist_remove (buffer->priv->selection_clipboards,
                                                            selection_clipboard);
@@ -3709,7 +3716,7 @@ remove_all_selection_clipboards (GtkTextBuffer *buffer)
 /**
  * gtk_text_buffer_paste_clipboard:
  * @buffer: a #GtkTextBuffer
- * @clipboard: the #GtkClipboard to paste from
+ * @clipboard: the #GdkClipboard to paste from
  * @override_location: (allow-none): location to insert pasted text, or %NULL
  * @default_editable: whether the buffer is editable by default
  *
@@ -3723,7 +3730,7 @@ remove_all_selection_clipboards (GtkTextBuffer *buffer)
  **/
 void
 gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
-                                GtkClipboard  *clipboard,
+                                GdkClipboard  *clipboard,
                                 GtkTextIter   *override_location,
                                  gboolean       default_editable)
 {
@@ -3754,9 +3761,12 @@ gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
        gtk_text_iter_equal (&paste_point, &end)))
     data->replace_selection = TRUE;
 
-  gtk_clipboard_request_contents (clipboard,
-                                 gdk_atom_intern_static_string ("GTK_TEXT_BUFFER_CONTENTS"),
-                                 clipboard_clipboard_buffer_received, data);
+  gdk_clipboard_read_value_async (clipboard,
+                                  GTK_TYPE_TEXT_BUFFER,
+                                  G_PRIORITY_DEFAULT,
+                                  NULL,
+                                  gtk_text_buffer_paste_clipboard_finish,
+                                  data);
 }
 
 /**
@@ -3887,44 +3897,12 @@ gtk_text_buffer_backspace (GtkTextBuffer *buffer,
 }
 
 static void
-gtk_text_buffer_free_target_lists (GtkTextBuffer *buffer)
-{
-  GtkTextBufferPrivate *priv = buffer->priv;
-
-  g_clear_pointer (&priv->copy_target_list, gdk_content_formats_unref);
-  g_clear_pointer (&priv->paste_target_list, gdk_content_formats_unref);
-}
-
-static GdkContentFormats *
-gtk_text_buffer_get_target_list (GtkTextBuffer   *buffer,
-                                 gboolean         deserializable,
-                                 gboolean         include_local)
-{
-  GdkContentFormats *target_list;
-
-
-  if (include_local)
-    target_list = gdk_content_formats_new ((const char *[2]) {
-                                             "GTK_TEXT_BUFFER_CONTENTS",
-                                             NULL
-                                           }, 1);
-  else
-    target_list = gdk_content_formats_new (NULL, 0);
-
-  target_list = gtk_content_formats_add_text_targets (target_list);
-
-  return target_list;
-}
-
-static void
 cut_or_copy (GtkTextBuffer *buffer,
-            GtkClipboard  *clipboard,
+            GdkClipboard  *clipboard,
              gboolean       delete_region_after,
              gboolean       interactive,
              gboolean       default_editable)
 {
-  GtkTextBufferPrivate *priv;
-
   /* We prefer to cut the selected region between selection_bound and
    * insertion point. If that region is empty, then we cut the region
    * between the "anchor" and the insertion point (this is for
@@ -3935,10 +3913,6 @@ cut_or_copy (GtkTextBuffer *buffer,
   GtkTextIter start;
   GtkTextIter end;
 
-  priv = buffer->priv;
-
-  gtk_text_buffer_get_copy_target_list (buffer);
-
   if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
     {
       /* Let's try the anchor thing */
@@ -3955,31 +3929,20 @@ cut_or_copy (GtkTextBuffer *buffer,
 
   if (!gtk_text_iter_equal (&start, &end))
     {
-      GtkTextIter ins;
       GtkTextBuffer *contents;
+      GdkContentProvider *provider;
+      GValue value = G_VALUE_INIT;
 
-      contents = create_clipboard_contents_buffer (buffer);
+      contents = create_clipboard_contents_buffer (buffer, &start, &end);
 
-      gtk_text_buffer_get_iter_at_offset (contents, &ins, 0);
-      
-      gtk_text_buffer_insert_range (contents, &ins, &start, &end);
-                                    
-      if (!gtk_clipboard_set_with_data (clipboard,
-                                        priv->copy_target_list,
-                                       clipboard_get_contents_cb,
-                                       clipboard_clear_contents_cb,
-                                       contents))
-        {
-         g_object_unref (contents);
-        }
-      else
-        {
-          GdkContentFormats *list;
-          
-          list = gtk_text_buffer_get_target_list (buffer, FALSE, FALSE);
-          gtk_clipboard_set_can_store (clipboard, list);
-          gdk_content_formats_unref (list);
-        }
+      g_value_init (&value, GTK_TYPE_TEXT_BUFFER);
+      g_value_take_object (&value, contents);
+
+      provider = gdk_content_provider_new_for_value (&value);
+      g_value_unset (&value);
+
+      gdk_clipboard_set_content (clipboard, provider);
+      g_object_unref (provider);
 
       if (delete_region_after)
         {
@@ -3995,7 +3958,7 @@ cut_or_copy (GtkTextBuffer *buffer,
 /**
  * gtk_text_buffer_cut_clipboard:
  * @buffer: a #GtkTextBuffer
- * @clipboard: the #GtkClipboard object to cut to
+ * @clipboard: the #GdkClipboard object to cut to
  * @default_editable: default editability of the buffer
  *
  * Copies the currently-selected text to a clipboard, then deletes
@@ -4003,7 +3966,7 @@ cut_or_copy (GtkTextBuffer *buffer,
  **/
 void
 gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
-                              GtkClipboard  *clipboard,
+                              GdkClipboard  *clipboard,
                                gboolean       default_editable)
 {
   gtk_text_buffer_begin_user_action (buffer);
@@ -4014,13 +3977,13 @@ gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
 /**
  * gtk_text_buffer_copy_clipboard:
  * @buffer: a #GtkTextBuffer 
- * @clipboard: the #GtkClipboard object to copy to
+ * @clipboard: the #GdkClipboard object to copy to
  *
  * Copies the currently-selected text to a clipboard.
  **/
 void
 gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer,
-                               GtkClipboard  *clipboard)
+                               GdkClipboard  *clipboard)
 {
   cut_or_copy (buffer, clipboard, FALSE, TRUE, TRUE);
 }
@@ -4108,64 +4071,6 @@ gtk_text_buffer_end_user_action (GtkTextBuffer *buffer)
     }
 }
 
-/**
- * gtk_text_buffer_get_copy_target_list:
- * @buffer: a #GtkTextBuffer
- *
- * This function returns the list of targets this text buffer can
- * provide for copying and as DND source. The targets in the list are
- * added with @info values from the #GtkTextBufferTargetInfo enum,
- * using gdk_content_formats_add_text_targets().
- *
- * Returns: (transfer none): the #GdkContentFormats
- *
- * Since: 2.10
- **/
-GdkContentFormats *
-gtk_text_buffer_get_copy_target_list (GtkTextBuffer *buffer)
-{
-  GtkTextBufferPrivate *priv;
-
-  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
-
-  priv = buffer->priv;
-
-  if (! priv->copy_target_list)
-    priv->copy_target_list =
-      gtk_text_buffer_get_target_list (buffer, FALSE, TRUE);
-
-  return priv->copy_target_list;
-}
-
-/**
- * gtk_text_buffer_get_paste_target_list:
- * @buffer: a #GtkTextBuffer
- *
- * This function returns the list of targets this text buffer supports
- * for pasting and as DND destination. The targets in the list are
- * added with @info values from the #GtkTextBufferTargetInfo enum,
- * using gtk_content_formats_add_text_targets().
- *
- * Returns: (transfer none): the #GdkContentFormats
- *
- * Since: 2.10
- **/
-GdkContentFormats *
-gtk_text_buffer_get_paste_target_list (GtkTextBuffer *buffer)
-{
-  GtkTextBufferPrivate *priv;
-
-  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
-
-  priv = buffer->priv;
-
-  if (! priv->paste_target_list)
-    priv->paste_target_list =
-      gtk_text_buffer_get_target_list (buffer, TRUE, TRUE);
-
-  return priv->paste_target_list;
-}
-
 /*
  * Logical attribute cache
  */
diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h
index eab07b5..e00cd5d 100644
--- a/gtk/gtktextbuffer.h
+++ b/gtk/gtktextbuffer.h
@@ -430,21 +430,21 @@ gboolean        gtk_text_buffer_get_has_selection       (GtkTextBuffer *buffer);
 
 GDK_AVAILABLE_IN_ALL
 void gtk_text_buffer_add_selection_clipboard    (GtkTextBuffer     *buffer,
-                                                GtkClipboard      *clipboard);
+                                                GdkClipboard      *clipboard);
 GDK_AVAILABLE_IN_ALL
 void gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer     *buffer,
-                                                GtkClipboard      *clipboard);
+                                                GdkClipboard      *clipboard);
 
 GDK_AVAILABLE_IN_ALL
 void            gtk_text_buffer_cut_clipboard           (GtkTextBuffer *buffer,
-                                                        GtkClipboard  *clipboard,
+                                                        GdkClipboard  *clipboard,
                                                          gboolean       default_editable);
 GDK_AVAILABLE_IN_ALL
 void            gtk_text_buffer_copy_clipboard          (GtkTextBuffer *buffer,
-                                                        GtkClipboard  *clipboard);
+                                                        GdkClipboard  *clipboard);
 GDK_AVAILABLE_IN_ALL
 void            gtk_text_buffer_paste_clipboard         (GtkTextBuffer *buffer,
-                                                        GtkClipboard  *clipboard,
+                                                        GdkClipboard  *clipboard,
                                                         GtkTextIter   *override_location,
                                                          gboolean       default_editable);
 
@@ -463,11 +463,6 @@ void            gtk_text_buffer_begin_user_action       (GtkTextBuffer *buffer);
 GDK_AVAILABLE_IN_ALL
 void            gtk_text_buffer_end_user_action         (GtkTextBuffer *buffer);
 
-GDK_AVAILABLE_IN_ALL
-GdkContentFormats * gtk_text_buffer_get_copy_target_list    (GtkTextBuffer *buffer);
-GDK_AVAILABLE_IN_ALL
-GdkContentFormats * gtk_text_buffer_get_paste_target_list   (GtkTextBuffer *buffer);
-
 
 G_END_DECLS
 
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index f8c5376..359c145 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -536,11 +536,8 @@ static void gtk_text_view_mark_set_handler       (GtkTextBuffer     *buffer,
                                                   const GtkTextIter *location,
                                                   GtkTextMark       *mark,
                                                   gpointer           data);
-static void gtk_text_view_target_list_notify     (GtkTextBuffer     *buffer,
-                                                  const GParamSpec  *pspec,
-                                                  gpointer           data);
 static void gtk_text_view_paste_done_handler     (GtkTextBuffer     *buffer,
-                                                  GtkClipboard      *clipboard,
+                                                  GdkClipboard      *clipboard,
                                                   gpointer           data);
 static void gtk_text_view_buffer_changed_handler (GtkTextBuffer     *buffer,
                                                   gpointer           data);
@@ -1690,7 +1687,7 @@ gtk_text_view_init (GtkTextView *text_view)
   gtk_drag_dest_set (widget, 0, NULL,
                      GDK_ACTION_COPY | GDK_ACTION_MOVE);
 
-  target_list = gdk_content_formats_new (NULL, 0);
+  target_list = gdk_content_formats_new_for_gtype (GTK_TYPE_TEXT_BUFFER);
   gtk_drag_dest_set_target_list (widget, target_list);
   gdk_content_formats_unref (target_list);
 
@@ -1883,9 +1880,6 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
                                            gtk_text_view_mark_set_handler,
                                            text_view);
       g_signal_handlers_disconnect_by_func (priv->buffer,
-                                            gtk_text_view_target_list_notify,
-                                            text_view);
-      g_signal_handlers_disconnect_by_func (priv->buffer,
                                             gtk_text_view_paste_done_handler,
                                             text_view);
       g_signal_handlers_disconnect_by_func (priv->buffer,
@@ -1894,8 +1888,7 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
 
       if (gtk_widget_get_realized (GTK_WIDGET (text_view)))
        {
-         GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                             GDK_SELECTION_PRIMARY);
+         GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (text_view));
          gtk_text_buffer_remove_selection_clipboard (priv->buffer, clipboard);
         }
 
@@ -1934,9 +1927,6 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
       g_signal_connect (priv->buffer, "mark-set",
                        G_CALLBACK (gtk_text_view_mark_set_handler),
                         text_view);
-      g_signal_connect (priv->buffer, "notify::paste-target-list",
-                       G_CALLBACK (gtk_text_view_target_list_notify),
-                        text_view);
       g_signal_connect (priv->buffer, "paste-done",
                        G_CALLBACK (gtk_text_view_paste_done_handler),
                         text_view);
@@ -1944,12 +1934,9 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
                        G_CALLBACK (gtk_text_view_buffer_changed_handler),
                         text_view);
 
-      gtk_text_view_target_list_notify (priv->buffer, NULL, text_view);
-
       if (gtk_widget_get_realized (GTK_WIDGET (text_view)))
        {
-         GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                             GDK_SELECTION_PRIMARY);
+         GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (text_view));
          gtk_text_buffer_add_selection_clipboard (priv->buffer, clipboard);
        }
 
@@ -4582,8 +4569,7 @@ gtk_text_view_realize (GtkWidget *widget)
 
   if (priv->buffer)
     {
-      GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                         GDK_SELECTION_PRIMARY);
+      GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (text_view));
       gtk_text_buffer_add_selection_clipboard (priv->buffer, clipboard);
     }
 
@@ -4602,8 +4588,7 @@ gtk_text_view_unrealize (GtkWidget *widget)
 
   if (priv->buffer)
     {
-      GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                         GDK_SELECTION_PRIMARY);
+      GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (text_view));
       gtk_text_buffer_remove_selection_clipboard (priv->buffer, clipboard);
     }
 
@@ -5289,8 +5274,7 @@ gtk_text_view_multipress_gesture_pressed (GtkGestureMultiPress *gesture,
       get_iter_from_gesture (text_view, priv->multipress_gesture,
                              &iter, NULL, NULL);
       gtk_text_buffer_paste_clipboard (get_buffer (text_view),
-                                       gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                                 GDK_SELECTION_PRIMARY),
+                                       gtk_widget_get_primary_clipboard (GTK_WIDGET (text_view)),
                                        &iter,
                                        priv->editable);
     }
@@ -6770,8 +6754,7 @@ gtk_text_view_backspace (GtkTextView *text_view)
 static void
 gtk_text_view_cut_clipboard (GtkTextView *text_view)
 {
-  GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                     GDK_SELECTION_CLIPBOARD);
+  GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view));
   
   gtk_text_buffer_cut_clipboard (get_buffer (text_view),
                                 clipboard,
@@ -6785,8 +6768,7 @@ gtk_text_view_cut_clipboard (GtkTextView *text_view)
 static void
 gtk_text_view_copy_clipboard (GtkTextView *text_view)
 {
-  GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                     GDK_SELECTION_CLIPBOARD);
+  GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view));
   
   gtk_text_buffer_copy_clipboard (get_buffer (text_view),
                                  clipboard);
@@ -6797,8 +6779,7 @@ gtk_text_view_copy_clipboard (GtkTextView *text_view)
 static void
 gtk_text_view_paste_clipboard (GtkTextView *text_view)
 {
-  GtkClipboard *clipboard = gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                     GDK_SELECTION_CLIPBOARD);
+  GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view));
   
   gtk_text_buffer_paste_clipboard (get_buffer (text_view),
                                   clipboard,
@@ -6808,7 +6789,7 @@ gtk_text_view_paste_clipboard (GtkTextView *text_view)
 
 static void
 gtk_text_view_paste_done_handler (GtkTextBuffer *buffer,
-                                  GtkClipboard  *clipboard,
+                                  GdkClipboard  *clipboard,
                                   gpointer       data)
 {
   GtkTextView *text_view = data;
@@ -7836,13 +7817,13 @@ gtk_text_view_start_selection_dnd (GtkTextView       *text_view,
                                    gint               x,
                                    gint               y)
 {
-  GdkContentFormats *target_list;
+  GdkContentFormats *formats;
 
-  target_list = gtk_text_buffer_get_copy_target_list (get_buffer (text_view));
+  formats = gdk_content_formats_new_for_gtype (GTK_TYPE_TEXT_BUFFER);
 
   g_signal_connect (text_view, "drag-begin",
                     G_CALLBACK (drag_begin_cb), NULL);
-  gtk_drag_begin_with_coordinates (GTK_WIDGET (text_view), target_list,
+  gtk_drag_begin_with_coordinates (GTK_WIDGET (text_view), formats,
                                    GDK_ACTION_COPY | GDK_ACTION_MOVE,
                                    1, (GdkEvent*) event, x, y);
 }
@@ -8610,14 +8591,6 @@ gtk_text_view_mark_set_handler (GtkTextBuffer     *buffer,
 }
 
 static void
-gtk_text_view_target_list_notify (GtkTextBuffer    *buffer,
-                                  const GParamSpec *pspec,
-                                  gpointer          data)
-{
-  gtk_drag_dest_set_target_list (data, gtk_text_buffer_get_paste_target_list (buffer));
-}
-
-static void
 gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
                                       GtkTextIter *cursor,
                                       gint        *x,
@@ -8747,12 +8720,6 @@ popup_menu_detach (GtkWidget *attach_widget,
   GTK_TEXT_VIEW (attach_widget)->priv->popup_menu = NULL;
 }
 
-typedef struct
-{
-  GtkTextView *text_view;
-  GdkEvent *trigger_event;
-} PopupInfo;
-
 static gboolean
 range_contains_editable_text (const GtkTextIter *start,
                               const GtkTextIter *end,
@@ -8772,34 +8739,28 @@ range_contains_editable_text (const GtkTextIter *start,
 }
 
 static void
-popup_targets_received (GtkClipboard     *clipboard,
-                       GtkSelectionData *data,
-                       gpointer          user_data)
+gtk_text_view_do_popup (GtkTextView    *text_view,
+                        const GdkEvent *event)
 {
-  PopupInfo *info = user_data;
-  GtkTextView *text_view;
-  GtkTextViewPrivate *priv;
+  GtkTextViewPrivate *priv = text_view->priv;
+  GdkEvent *trigger_event;
 
-  text_view = info->text_view;
-  priv = text_view->priv;
+  if (event)
+    trigger_event = gdk_event_copy (event);
+  else
+    trigger_event = gtk_get_current_event ();
 
   if (gtk_widget_get_realized (GTK_WIDGET (text_view)))
     {
-      /* We implicitely rely here on the fact that if we are pasting ourself, we'll
-       * have text targets as well as the private GTK_TEXT_BUFFER_CONTENTS target.
-       */
-      gboolean clipboard_contains_text;
       GtkWidget *menuitem;
       gboolean have_selection;
-      gboolean can_insert;
+      gboolean can_insert, can_paste;
       GtkTextIter iter;
       GtkTextIter sel_start, sel_end;
       GdkRectangle iter_location;
       GdkRectangle visible_rect;
       gboolean is_visible;
 
-      clipboard_contains_text = gtk_selection_data_targets_include_text (data);
-
       if (priv->popup_menu)
        gtk_widget_destroy (priv->popup_menu);
 
@@ -8819,6 +8780,8 @@ popup_targets_received (GtkClipboard     *clipboard,
                                        gtk_text_buffer_get_insert (get_buffer (text_view)));
 
       can_insert = gtk_text_iter_can_insert (&iter, priv->editable);
+      can_paste = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (gtk_widget_get_clipboard 
(GTK_WIDGET (text_view))),
+                                                     GTK_TYPE_TEXT_BUFFER);
 
       append_action_signal (text_view, priv->popup_menu, _("Cu_t"), "cut-clipboard",
                            have_selection &&
@@ -8827,7 +8790,7 @@ popup_targets_received (GtkClipboard     *clipboard,
       append_action_signal (text_view, priv->popup_menu, _("_Copy"), "copy-clipboard",
                            have_selection);
       append_action_signal (text_view, priv->popup_menu, _("_Paste"), "paste-clipboard",
-                           can_insert && clipboard_contains_text);
+                           can_insert && can_paste);
 
       menuitem = gtk_menu_item_new_with_mnemonic (_("_Delete"));
       gtk_widget_set_sensitive (menuitem,
@@ -8864,8 +8827,8 @@ popup_targets_received (GtkClipboard     *clipboard,
       g_signal_emit (text_view, signals[POPULATE_POPUP],
                     0, priv->popup_menu);
 
-      if (info->trigger_event && gdk_event_triggers_context_menu (info->trigger_event))
-        gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), info->trigger_event);
+      if (trigger_event && gdk_event_triggers_context_menu (trigger_event))
+        gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), trigger_event);
       else
         {
           gtk_text_view_get_iter_location (text_view, &iter, &iter_location);
@@ -8890,42 +8853,20 @@ popup_targets_received (GtkClipboard     *clipboard,
                                       &iter_location,
                                       GDK_GRAVITY_SOUTH_EAST,
                                       GDK_GRAVITY_NORTH_WEST,
-                                      info->trigger_event);
+                                      trigger_event);
             }
           else
             gtk_menu_popup_at_widget (GTK_MENU (priv->popup_menu),
                                       GTK_WIDGET (text_view),
                                       GDK_GRAVITY_CENTER,
                                       GDK_GRAVITY_CENTER,
-                                      info->trigger_event);
+                                      trigger_event);
 
           gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->popup_menu), FALSE);
         }
     }
 
-  g_clear_pointer (&info->trigger_event, gdk_event_free);
-  g_object_unref (text_view);
-  g_slice_free (PopupInfo, info);
-}
-
-static void
-gtk_text_view_do_popup (GtkTextView    *text_view,
-                        const GdkEvent *event)
-{
-  PopupInfo *info = g_slice_new (PopupInfo);
-
-  /* In order to know what entries we should make sensitive, we
-   * ask for the current targets of the clipboard, and when
-   * we get them, then we actually pop up the menu.
-   */
-  info->text_view = g_object_ref (text_view);
-  info->trigger_event = event ? gdk_event_copy (event) : gtk_get_current_event ();
-
-  gtk_clipboard_request_contents (gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                           GDK_SELECTION_CLIPBOARD),
-                                 gdk_atom_intern_static_string ("TARGETS"),
-                                 popup_targets_received,
-                                 info);
+  g_clear_pointer (&trigger_event, gdk_event_free);
 }
 
 static gboolean
@@ -9022,14 +8963,13 @@ append_bubble_action (GtkTextView  *text_view,
   gtk_container_add (GTK_CONTAINER (toolbar), item);
 }
 
-static void
-bubble_targets_received (GtkClipboard     *clipboard,
-                         GtkSelectionData *data,
-                         gpointer          user_data)
+static gboolean
+gtk_text_view_selection_bubble_popup_show (gpointer user_data)
 {
   GtkTextView *text_view = user_data;
   GtkTextViewPrivate *priv = text_view->priv;
   cairo_rectangle_int_t rect;
+  GdkClipboard *clipboard;
   gboolean has_selection;
   gboolean has_clipboard;
   gboolean can_insert;
@@ -9050,7 +8990,7 @@ bubble_targets_received (GtkClipboard     *clipboard,
   if (!priv->editable && !has_selection)
     {
       priv->selection_bubble_timeout_id = 0;
-      return;
+      return G_SOURCE_REMOVE;
     }
 
   if (priv->selection_bubble)
@@ -9075,7 +9015,8 @@ bubble_targets_received (GtkClipboard     *clipboard,
   gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter,
                                     gtk_text_buffer_get_insert (get_buffer (text_view)));
   can_insert = gtk_text_iter_can_insert (&iter, priv->editable);
-  has_clipboard = gtk_selection_data_targets_include_text (data);
+  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view));
+  has_clipboard = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), 
GTK_TYPE_TEXT_BUFFER);
 
   if (range_contains_editable_text (&sel_start, &sel_end, priv->editable) && has_selection)
     append_bubble_action (text_view, toolbar, _("Select all"), "edit-select-all-symbolic", "select-all", 
!all_selected);
@@ -9105,18 +9046,6 @@ bubble_targets_received (GtkClipboard     *clipboard,
 
   gtk_popover_set_pointing_to (GTK_POPOVER (priv->selection_bubble), &rect);
   gtk_widget_show (priv->selection_bubble);
-}
-
-static gboolean
-gtk_text_view_selection_bubble_popup_show (gpointer user_data)
-{
-  GtkTextView *text_view = user_data;
-  gtk_clipboard_request_contents (gtk_widget_get_old_clipboard (GTK_WIDGET (text_view),
-                                                           GDK_SELECTION_CLIPBOARD),
-                                 gdk_atom_intern_static_string ("TARGETS"),
-                                 bubble_targets_received,
-                                 text_view);
-  text_view->priv->selection_bubble_timeout_id = 0;
 
   return G_SOURCE_REMOVE;
 }
diff --git a/testsuite/gtk/textbuffer.c b/testsuite/gtk/textbuffer.c
index f7b2651..51ca017 100644
--- a/testsuite/gtk/textbuffer.c
+++ b/testsuite/gtk/textbuffer.c
@@ -1362,13 +1362,13 @@ check_buffer_contents (GtkTextBuffer *buffer,
 static void
 test_clipboard (void)
 {
-  GtkClipboard *clipboard;
+  GdkClipboard *clipboard;
   GtkTextBuffer *buffer;
   GtkTextIter start;
   GtkTextIter end;
   GtkTextTag *tag;
 
-  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+  clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
 
   buffer = gtk_text_buffer_new (NULL);
   gtk_text_buffer_set_text (buffer, "abcdef", -1);


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