]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkclipboard.c
Declare gtk_tree_row_reference_get_type(). It is already used by a macro
[~andy/gtk] / gtk / gtkclipboard.c
index 3c7ff99e3392b7248c4d3e5d90e440457ad0b53c..8415918d4525a3cc0c845ffc44e664fef7f17fc0 100644 (file)
@@ -24,7 +24,6 @@
 #include "gtkclipboard.h"
 #include "gtkinvisible.h"
 #include "gtkmain.h"
-#include "gtksignal.h"
 
 #ifdef GDK_WINDOWING_X11
 #include "x11/gdkx.h"
 #include "win32/gdkwin32.h"
 #endif
 
+typedef struct _GtkClipboardClass GtkClipboardClass;
+
 typedef struct _RequestContentsInfo RequestContentsInfo;
 typedef struct _RequestTextInfo RequestTextInfo;
 
 struct _GtkClipboard 
 {
+  GObject parent_instance;
+
   GdkAtom selection;
 
   GtkClipboardGetFunc get_func;
@@ -49,6 +52,12 @@ struct _GtkClipboard
   guint32 timestamp;
 
   gboolean have_selection;
+  GdkDisplay *display;
+};
+
+struct _GtkClipboardClass
+{
+  GObjectClass parent_class;
 };
 
 struct _RequestContentsInfo
@@ -63,14 +72,14 @@ struct _RequestTextInfo
   gpointer user_data;
 };
 
+static void gtk_clipboard_class_init (GtkClipboardClass *class);
+static void gtk_clipboard_finalize   (GObject           *object);
+
 static void clipboard_unset    (GtkClipboard     *clipboard);
 static void selection_received (GtkWidget        *widget,
                                GtkSelectionData *selection_data,
                                guint             time);
 
-static GSList *clipboards;
-static GtkWidget *clipboard_widget;
-
 enum {
   TARGET_STRING,
   TARGET_TEXT,
@@ -83,32 +92,121 @@ static GQuark request_contents_key_id = 0;
 
 static const gchar *clipboards_owned_key = "gtk-clipboards-owned";
 static GQuark clipboards_owned_key_id = 0;
+
+static GObjectClass *parent_class;
+
+GType
+gtk_clipboard_get_type (void)
+{
+  static GType clipboard_type = 0;
+  
+  if (!clipboard_type)
+    {
+      static const GTypeInfo clipboard_info =
+      {
+       sizeof (GtkClipboardClass),
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+       (GClassInitFunc) gtk_clipboard_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       sizeof (GtkClipboard),
+       0,              /* n_preallocs */
+       (GInstanceInitFunc) NULL,
+      };
+      
+      clipboard_type = g_type_register_static (G_TYPE_OBJECT, "GtkClipboard",
+                                              &clipboard_info, 0);
+    }
+  
+  return clipboard_type;
+}
+
+static void
+gtk_clipboard_class_init (GtkClipboardClass *class)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+  parent_class = g_type_class_peek_parent (class);
+  
+  gobject_class->finalize = gtk_clipboard_finalize;
+}
+
+static void
+gtk_clipboard_finalize   (GObject *object)
+{
+  clipboard_unset (GTK_CLIPBOARD (object));
+}
+
+static void
+clipboard_display_closed (GdkDisplay   *display,
+                         gboolean      is_error,
+                         GtkClipboard *clipboard)
+{
+  GSList *clipboards;
+
+  clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
+  g_object_run_dispose (G_OBJECT (clipboard));
+  g_object_unref (clipboard);
+  clipboards = g_slist_remove (clipboards, clipboard);
   
+  g_object_set_data (G_OBJECT (display), "gtk-clipboard-list", clipboards);
+}
 
 /**
- * gtk_clipboard_get:
+ * gtk_clipboard_get_for_display:
+ * @display: the display for which the clipboard is to be retrieved or created
  * @selection: a #GdkAtom which identifies the clipboard
- *             to use. A value of GDK_NONE here is the
- *             same as gdk_atom_intern ("CLIPBOARD", FALSE),
- *             and provides the default clipboard. Another
- *             common value is GDK_SELECTION_PRIMARY, which
- *             identifies the primary X selection. 
+ *             to use.
  * 
  * Returns the clipboard object for the given selection.
+ * Cut/copy/paste menu items and keyboard shortcuts should use
+ * the default clipboard, returned by passing %GDK_SELECTION_CLIPBOARD for @selection.
+ * (%GDK_NONE is supported as a synonym for GDK_SELECTION_CLIPBOARD
+ * for backwards compatibility reasons.)
+ * The currently-selected object or text should be provided on the clipboard
+ * identified by #GDK_SELECTION_PRIMARY. Cut/copy/paste menu items
+ * conceptually copy the contents of the #GDK_SELECTION_PRIMARY clipboard
+ * to the default clipboard, i.e. they copy the selection to what the
+ * user sees as the clipboard.
+ *
+ * (Passing #GDK_NONE is the same as using <literal>gdk_atom_intern
+ * ("CLIPBOARD", FALSE)</literal>. See
+ * <ulink url="http://www.freedesktop.org/standards/clipboards.txt">
+ * http://www.freedesktop.org/standards/clipboards.txt</ulink>
+ * for a detailed discussion of the "CLIPBOARD" vs. "PRIMARY" selections
+ * under the X window system. On Win32 the #GDK_SELECTION_PRIMARY
+ * clipboard is essentially ignored.)
+ *
+ * It's possible to have arbitrary named clipboards; if you do invent
+ * new clipboards, you should prefix the selection name with an
+ * underscore (because the ICCCM requires that nonstandard atoms are
+ * underscore-prefixed), and namespace it as well. For example,
+ * if your application called "Foo" has a special-purpose
+ * clipboard, you might call it "_FOO_SPECIAL_CLIPBOARD".
  * 
  * Return value: the appropriate clipboard object. If no
  *             clipboard already exists, a new one will
  *             be created. Once a clipboard object has
- *             been created, it is persistant for all time.
+ *             been created, it is persistent for all time and
+ *             cannot be freed.
+ *
+ * Since: 2.2
  **/
 GtkClipboard *
-gtk_clipboard_get (GdkAtom selection)
+gtk_clipboard_get_for_display (GdkDisplay *display, GdkAtom selection)
 {
   GtkClipboard *clipboard = NULL;
+  GSList *clipboards;
   GSList *tmp_list;
 
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  g_return_val_if_fail (!display->closed, NULL);
+
   if (selection == GDK_NONE)
-    selection = gdk_atom_intern ("CLIPBOARD", FALSE);
+    selection = GDK_SELECTION_CLIPBOARD;
+
+  clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
 
   tmp_list = clipboards;
   while (tmp_list)
@@ -122,21 +220,45 @@ gtk_clipboard_get (GdkAtom selection)
 
   if (!tmp_list)
     {
-      clipboard = g_new0 (GtkClipboard, 1);
+      clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
       clipboard->selection = selection;
+      clipboard->display = display;
       clipboards = g_slist_prepend (clipboards, clipboard);
+      g_object_set_data (G_OBJECT (display), "gtk-clipboard-list", clipboards);
+      g_signal_connect (display, "closed",
+                       G_CALLBACK (clipboard_display_closed), clipboard);
     }
   
   return clipboard;
 }
 
+/**
+ * gtk_clipboard_get():
+ * @selection: a #GdkAtom which identifies the clipboard
+ *             to use.
+ * 
+ * Returns the clipboard object for the given selection.
+ * See gtk_clipboard_get_for_display() for complete details.
+ * 
+ * Return value: the appropriate clipboard object. If no
+ *             clipboard already exists, a new one will
+ *             be created. Once a clipboard object has
+ *             been created, it is persistent for all time and
+ *             cannot be freed.
+ **/
+GtkClipboard *
+gtk_clipboard_get (GdkAtom selection)
+{
+  return gtk_clipboard_get_for_display (gdk_display_get_default (), selection);
+}
+
 static void 
 selection_get_cb (GtkWidget          *widget,
                  GtkSelectionData   *selection_data,
-                 guint               time,
-                 guint               info)
+                 guint               info,
+                 guint               time)
 {
-  GtkClipboard *clipboard = gtk_clipboard_get (selection_data->selection);
+  GtkClipboard *clipboard = gtk_widget_get_clipboard (widget, selection_data->selection);
 
   if (clipboard && clipboard->get_func)
     clipboard->get_func (clipboard, selection_data, info, clipboard->user_data);
@@ -146,7 +268,7 @@ static gboolean
 selection_clear_event_cb (GtkWidget        *widget,
                          GdkEventSelection *event)
 {
-  GtkClipboard *clipboard = gtk_clipboard_get (event->selection);
+  GtkClipboard *clipboard = gtk_widget_get_clipboard (widget, event->selection);
 
   if (clipboard)
     {
@@ -157,34 +279,40 @@ selection_clear_event_cb (GtkWidget           *widget,
   return FALSE;
 }
 
-GtkWidget *
-make_clipboard_widget (gboolean provider)
+static GtkWidget *
+make_clipboard_widget (GdkDisplay *display, 
+                      gboolean    provider)
 {
-  GtkWidget *widget = gtk_invisible_new ();
+  GtkWidget *widget = gtk_invisible_new_for_screen (gdk_display_get_default_screen (display));
 
-  gtk_signal_connect (GTK_OBJECT (widget), "selection_received",
-                     GTK_SIGNAL_FUNC (selection_received), NULL);
+  g_signal_connect (widget, "selection_received",
+                   G_CALLBACK (selection_received), NULL);
 
   if (provider)
     {
       /* We need this for gdk_x11_get_server_time() */
       gtk_widget_add_events (widget, GDK_PROPERTY_CHANGE_MASK);
       
-      gtk_signal_connect (GTK_OBJECT (widget), "selection_get",
-                         GTK_SIGNAL_FUNC (selection_get_cb), NULL);
-      gtk_signal_connect (GTK_OBJECT (widget), "selection_clear_event",
-                         GTK_SIGNAL_FUNC (selection_clear_event_cb), NULL);
+      g_signal_connect (widget, "selection_get",
+                       G_CALLBACK (selection_get_cb), NULL);
+      g_signal_connect (widget, "selection_clear_event",
+                       G_CALLBACK (selection_clear_event_cb), NULL);
     }
 
   return widget;
 }
 
-
-void
-ensure_clipboard_widget ()
+static GtkWidget *
+get_clipboard_widget (GdkDisplay *display)
 {
-  if (!clipboard_widget)
-    clipboard_widget = make_clipboard_widget (TRUE);
+  GtkWidget *clip_widget = g_object_get_data (G_OBJECT (display), "gtk-clipboard-widget");
+  if (!clip_widget)
+    {
+      clip_widget = make_clipboard_widget (display, TRUE);
+      g_object_set_data (G_OBJECT (display), "gtk-clipboard-widget", clip_widget);
+    }
+
+  return clip_widget;
 }
 
 /* This function makes a very good guess at what the correct
@@ -205,10 +333,9 @@ ensure_clipboard_widget ()
 static guint32
 clipboard_get_timestamp (GtkClipboard *clipboard)
 {
+  GtkWidget *clipboard_widget = get_clipboard_widget (clipboard->display);
   guint32 timestamp = gtk_get_current_event_time ();
 
-  ensure_clipboard_widget ();
-  
   if (timestamp == GDK_CURRENT_TIME)
     {
 #ifdef GDK_WINDOWING_X11
@@ -302,10 +429,12 @@ gtk_clipboard_set_contents (GtkClipboard         *clipboard,
                            gpointer              user_data,
                            gboolean              have_owner)
 {
-  ensure_clipboard_widget ();
+  GtkWidget *clipboard_widget = get_clipboard_widget (clipboard->display);
 
-  if (gtk_selection_owner_set (clipboard_widget, clipboard->selection,
-                              clipboard_get_timestamp (clipboard)))
+  if (gtk_selection_owner_set_for_display (clipboard->display,
+                                          clipboard_widget,
+                                          clipboard->selection,
+                                          clipboard_get_timestamp (clipboard)))
     {
       clipboard->have_selection = TRUE;
 
@@ -359,10 +488,10 @@ gtk_clipboard_set_contents (GtkClipboard         *clipboard,
  * @n_targets:  number of elements in @targets
  * @get_func:   function to call to get the actual clipboard data
  * @clear_func: when the clipboard contents are set again, this function will
- *              be called, and get_func will not be subsequently called.
+ *              be called, and @get_func will not be subsequently called.
  * @user_data:  user data to pass to @get_func and @clear_func.
  * 
- * Virtually set the contents of the specified clipboard by providing
+ * Virtually sets the contents of the specified clipboard by providing
  * a list of supported formats for the clipboard data and a function
  * to call to get the actual data when it is requested.
  * 
@@ -395,17 +524,17 @@ gtk_clipboard_set_with_data (GtkClipboard          *clipboard,
  * @n_targets:  number of elements in @targets
  * @get_func:   function to call to get the actual clipboard data
  * @clear_func: when the clipboard contents are set again, this function will
- *              be called, and get_func will not be subsequently called.
+ *              be called, and @get_func will not be subsequently called.
  * @owner:      an object that "owns" the data. This object will be passed
  *              to the callbacks when called. 
  * 
- * Virtually set the contents of the specified clipboard by providing
+ * Virtually sets the contents of the specified clipboard by providing
  * a list of supported formats for the clipboard data and a function
  * to call to get the actual data when it is requested.
  *
- * The difference between this function and gtk_clipboard_set_with_data
+ * The difference between this function and gtk_clipboard_set_with_data()
  * is that instead of an generic @user_data pointer, a #GObject is passed
- * in. Because of this, 
+ * in. 
  * 
  * Return value: %TRUE if setting the clipboard data succeeded. If setting
  *               the clipboard data failed the provided callback functions
@@ -433,9 +562,10 @@ gtk_clipboard_set_with_owner (GtkClipboard          *clipboard,
  * gtk_clipboard_get_owner:
  * @clipboard: a #GtkClipboard
  * 
- * If the clipboard contents callbacks were set with gtk_clipboard_set_owner(),
- * and the gtk_clipboard_set_with_data() or gtk_clipboard_clear() has not
- * subsequently called, returns the @owner set by gtk_clipboard_set_owner().
+ * If the clipboard contents callbacks were set with 
+ * gtk_clipboard_set_with_owner(), and the gtk_clipboard_set_with_data() or 
+ * gtk_clipboard_clear() has not subsequently called, returns the owner set 
+ * by gtk_clipboard_set_with_owner().
  * 
  * Return value: the owner of the clipboard, if any; otherwise %NULL.
  **/
@@ -477,8 +607,9 @@ clipboard_unset (GtkClipboard *clipboard)
  * gtk_clipboard_clear:
  * @clipboard:  a #GtkClipboard
  * 
- * Clear the contents of the clipboard. Generally this should only
- * be called between the time you call gtk_clipboard_set_contents(),
+ * Clears the contents of the clipboard. Generally this should only
+ * be called between the time you call gtk_clipboard_set_with_owner()
+ * or gtk_clipboard_set_with_data(),
  * and when the @clear_func you supplied is called. Otherwise, the
  * clipboard may be owned by someone else.
  **/
@@ -488,20 +619,22 @@ gtk_clipboard_clear (GtkClipboard *clipboard)
   g_return_if_fail (clipboard != NULL);
 
   if (clipboard->have_selection)
-    gtk_selection_owner_set (NULL, clipboard->selection,
-                            clipboard_get_timestamp (clipboard));
+    gtk_selection_owner_set_for_display (clipboard->display, 
+                                        NULL,
+                                        clipboard->selection,
+                                        clipboard_get_timestamp (clipboard));
 }
 
-void 
+static void 
 text_get_func (GtkClipboard     *clipboard,
               GtkSelectionData *selection_data,
               guint             info,
               gpointer          data)
 {
-  gtk_selection_data_set_text (selection_data, data);
+  gtk_selection_data_set_text (selection_data, data, -1);
 }
 
-void 
+static void 
 text_clear_func (GtkClipboard *clipboard,
                 gpointer      data)
 {
@@ -513,9 +646,9 @@ text_clear_func (GtkClipboard *clipboard,
  * @clipboard: a #GtkClipboard object
  * @text:      a UTF-8 string.
  * @len:       length of @text, in bytes, or -1, in which case
- *             the length will be determined with strlen().
+ *             the length will be determined with <function>strlen()</function>.
  * 
- * Set the contents of the clipboard to the given UTF-8 string. GTK+ will
+ * Sets the contents of the clipboard to the given UTF-8 string. GTK+ will
  * make a copy of the text and take responsibility for responding
  * for requests for the text, and for converting the text into
  * the requested format.
@@ -551,9 +684,7 @@ set_request_contents_info (GtkWidget           *widget,
   if (!request_contents_key_id)
     request_contents_key_id = g_quark_from_static_string (request_contents_key);
 
-  gtk_object_set_data_by_id (GTK_OBJECT (widget),
-                            request_contents_key_id,
-                            info);
+  g_object_set_qdata (G_OBJECT (widget), request_contents_key_id, info);
 }
 
 static RequestContentsInfo *
@@ -562,8 +693,7 @@ get_request_contents_info (GtkWidget *widget)
   if (!request_contents_key_id)
     return NULL;
   else
-    return gtk_object_get_data_by_id (GTK_OBJECT (widget),
-                                     request_contents_key_id);
+    return g_object_get_qdata (G_OBJECT (widget), request_contents_key_id);
 }
 
 static void 
@@ -574,13 +704,13 @@ selection_received (GtkWidget            *widget,
   RequestContentsInfo *request_info = get_request_contents_info (widget);
   set_request_contents_info (widget, NULL);
   
-  request_info->callback (gtk_clipboard_get (selection_data->selection), 
+  request_info->callback (gtk_widget_get_clipboard (widget, selection_data->selection), 
                          selection_data,
                          request_info->user_data);
 
   g_free (request_info);
 
-  if (widget != clipboard_widget)
+  if (widget != get_clipboard_widget (gtk_widget_get_display (widget)))
     gtk_widget_destroy (widget);
 }
 
@@ -590,7 +720,7 @@ selection_received (GtkWidget            *widget,
  * @target:    an atom representing the form into which the clipboard
  *             owner should convert the selection.
  * @callback:  A function to call when the results are received
- *             (or the retrieval fails.) If the retrieval fails
+ *             (or the retrieval fails). If the retrieval fails
  *             the length field of @selection_data will be
  *             negative.
  * @user_data: user data to pass to @callback
@@ -607,15 +737,16 @@ gtk_clipboard_request_contents (GtkClipboard            *clipboard,
 {
   RequestContentsInfo *info;
   GtkWidget *widget;
+  GtkWidget *clipboard_widget;
 
   g_return_if_fail (clipboard != NULL);
   g_return_if_fail (target != GDK_NONE);
   g_return_if_fail (callback != NULL);
   
-  ensure_clipboard_widget ();
+  clipboard_widget = get_clipboard_widget (clipboard->display);
 
   if (get_request_contents_info (clipboard_widget))
-    widget = make_clipboard_widget (FALSE);
+    widget = make_clipboard_widget (clipboard->display, FALSE);
   else
     widget = clipboard_widget;
 
@@ -641,18 +772,18 @@ request_text_received_func (GtkClipboard     *clipboard,
 
   if (!result)
     {
-      /* If we asked for UTF8 and didn't get it, try text; if we asked
-       * for text and didn't get it, try string.  If we asked for
-       * anything else and didn't get it, give up.
+      /* If we asked for UTF8 and didn't get it, try compound_text;
+       * if we asked for compound_text and didn't get it, try string;
+       * If we asked for anything else and didn't get it, give up.
        */
       if (selection_data->target == gdk_atom_intern ("UTF8_STRING", FALSE))
        {
          gtk_clipboard_request_contents (clipboard,
-                                         gdk_atom_intern ("TEXT", FALSE), 
+                                         gdk_atom_intern ("COMPOUND_TEXT", FALSE), 
                                          request_text_received_func, info);
          return;
        }
-      else if (selection_data->target == gdk_atom_intern ("TEXT", FALSE))
+      else if (selection_data->target == gdk_atom_intern ("COMPOUND_TEXT", FALSE))
        {
          gtk_clipboard_request_contents (clipboard,
                                          GDK_TARGET_STRING, 
@@ -719,7 +850,7 @@ clipboard_received_func (GtkClipboard     *clipboard,
   if (selection_data->length >= 0)
     results->data = gtk_selection_data_copy (selection_data);
   
-  g_main_quit (results->loop);
+  g_main_loop_quit (results->loop);
 }
 
 /**
@@ -732,10 +863,10 @@ clipboard_received_func (GtkClipboard     *clipboard,
  * This function waits for the data to be received using the main 
  * loop, so events, timeouts, etc, may be dispatched during the wait.
  * 
- * Return value: a newly allocated #GtkSelectionData object or %NULL
+ * Return value: a newly-allocated #GtkSelectionData object or %NULL
  *               if retrieving the given target failed. If non-%NULL,
- *               this value freed with gtk_selection_data_free() when
- *               you are finished with it.
+ *               this value must be freed with gtk_selection_data_free() 
+ *               when you are finished with it.
  **/
 GtkSelectionData *
 gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
@@ -747,16 +878,20 @@ gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
   g_return_val_if_fail (target != GDK_NONE, NULL);
   
   results.data = NULL;
-  results.loop = g_main_new (TRUE);
+  results.loop = g_main_loop_new (NULL, TRUE);
 
   gtk_clipboard_request_contents (clipboard, target, 
                                  clipboard_received_func,
                                  &results);
 
-  if (g_main_is_running (results.loop))
-    g_main_run (results.loop);
+  if (g_main_loop_is_running (results.loop))
+    {
+      GDK_THREADS_LEAVE ();
+      g_main_loop_run (results.loop);
+      GDK_THREADS_ENTER ();
+    }
 
-  g_main_destroy (results.loop);
+  g_main_loop_unref (results.loop);
 
   return results.data;
 }
@@ -769,7 +904,7 @@ clipboard_text_received_func (GtkClipboard *clipboard,
   WaitResults *results = data;
 
   results->data = g_strdup (text);
-  g_main_quit (results->loop);
+  g_main_loop_quit (results->loop);
 }
 
 
@@ -782,7 +917,7 @@ clipboard_text_received_func (GtkClipboard *clipboard,
  * the data to be received using the main loop, so events,
  * timeouts, etc, may be dispatched during the wait.
  * 
- * Return value: a newly allocated UTF-8 string which must
+ * Return value: a newly-allocated UTF-8 string which must
  *               be freed with g_free(), or %NULL if retrieving
  *               the selection data failed. (This could happen
  *               for various reasons, in particular if the
@@ -798,17 +933,70 @@ gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
   g_return_val_if_fail (clipboard != NULL, NULL);
   
   results.data = NULL;
-  results.loop = g_main_new (TRUE);
+  results.loop = g_main_loop_new (NULL, TRUE);
 
   gtk_clipboard_request_text (clipboard,
                              clipboard_text_received_func,
                              &results);
 
-  if (g_main_is_running (results.loop))
-    g_main_run (results.loop);
+  if (g_main_loop_is_running (results.loop))
+    {
+      GDK_THREADS_LEAVE ();
+      g_main_loop_run (results.loop);
+      GDK_THREADS_ENTER ();
+    }
 
-  g_main_destroy (results.loop);
+  g_main_loop_unref (results.loop);
 
   return results.data;
 }
+/**
+ * gtk_clipboard_get_display:
+ * @clipboard: a #GtkClipboard
+ *
+ * Gets the #GdkDisplay associated with @clipboard
+ *
+ * Return value: the #GdkDisplay associated with @clipboard
+ *
+ * Since: 2.2
+ **/
+GdkDisplay *
+gtk_clipboard_get_display (GtkClipboard *clipboard)
+{
+  g_return_val_if_fail (clipboard != NULL, NULL);
+
+  return clipboard->display;
+}
+
+/**
+ * gtk_clipboard_wait_is_text_available:
+ * @clipboard: a #GtkClipboard
+ * 
+ * Test to see if there is text available to be pasted
+ * This is done by requesting the TARGETS atom and checking
+ * if it contains any of the names: STRING, TEXT, COMPOUND_TEXT,
+ * UTF8_STRING. This function waits for the data to be received
+ * using the main loop, so events, timeouts, etc, may be dispatched
+ * during the wait.
+ *
+ * This function is a little faster than calling
+ * gtk_clipboard_wait_for_text() since it doesn't need to retrieve
+ * the actual text.
+ * 
+ * Return value: %TRUE is there is text available, %FALSE otherwise.
+ **/
+gboolean
+gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
+{
+  GtkSelectionData *data;
+  gboolean result = FALSE;
 
+  data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern ("TARGETS", FALSE));
+  if (data)
+    {
+      result = gtk_selection_data_targets_include_text (data);
+      gtk_selection_data_free (data);
+    }
+
+  return result;
+}