* 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Global clipboard abstraction.
*/
#include "x11/gdkx.h"
#endif
+#ifdef GDK_WINDOWING_BROADWAY
+#include "broadway/gdkbroadway.h"
+#endif
+
#ifdef GDK_WINDOWING_WIN32
#include "win32/gdkwin32.h"
#endif
+
+/**
+ * SECTION:gtkclipboard
+ * @Short_description: Storing data on clipboards
+ * @Title: Clipboards
+ * @See_also: #GtkSelection
+ *
+ * The #GtkClipboard object represents a clipboard of data shared
+ * between different processes or between different widgets in
+ * the same process. Each clipboard is identified by a name encoded as a
+ * #GdkAtom. (Conversion to and from strings can be done with
+ * gdk_atom_intern() and gdk_atom_name().) The default clipboard
+ * corresponds to the "CLIPBOARD" atom; another commonly used clipboard
+ * is the "PRIMARY" clipboard, which, in X, traditionally contains
+ * the currently selected text.
+ *
+ * To support having a number of different formats on the clipboard
+ * at the same time, the clipboard mechanism allows providing
+ * callbacks instead of the actual data. When you set the contents
+ * of the clipboard, you can either supply the data directly (via
+ * functions like gtk_clipboard_set_text()), or you can supply a
+ * callback to be called at a later time when the data is needed (via
+ * gtk_clipboard_set_with_data() or gtk_clipboard_set_with_owner().)
+ * Providing a callback also avoids having to make copies of the data
+ * when it is not needed.
+ *
+ * gtk_clipboard_set_with_data() and gtk_clipboard_set_with_owner()
+ * are quite similar; the choice between the two depends mostly on
+ * which is more convenient in a particular situation.
+ * The former is most useful when you want to have a blob of data
+ * with callbacks to convert it into the various data types that you
+ * advertise. When the @clear_func you provided is called, you
+ * simply free the data blob. The latter is more useful when the
+ * contents of clipboard reflect the internal state of a #GObject
+ * (As an example, for the PRIMARY clipboard, when an entry widget
+ * provides the clipboard's contents the contents are simply the
+ * text within the selected region.) If the contents change, the
+ * entry widget can call gtk_clipboard_set_with_owner() to update
+ * the timestamp for clipboard ownership, without having to worry
+ * about @clear_func being called.
+ *
+ * Requesting the data from the clipboard is essentially
+ * asynchronous. If the contents of the clipboard are provided within
+ * the same process, then a direct function call will be made to
+ * retrieve the data, but if they are provided by another process,
+ * then the data needs to be retrieved from the other process, which
+ * may take some time. To avoid blocking the user interface, the call
+ * to request the selection, gtk_clipboard_request_contents() takes a
+ * callback that will be called when the contents are received (or
+ * when the request fails.) If you don't want to deal with providing
+ * a separate callback, you can also use gtk_clipboard_wait_for_contents().
+ * What this does is run the GLib main loop recursively waiting for
+ * the contents. This can simplify the code flow, but you still have
+ * to be aware that other callbacks in your program can be called
+ * while this recursive mainloop is running.
+ *
+ * Along with the functions to get the clipboard contents as an
+ * arbitrary data chunk, there are also functions to retrieve
+ * it as text, gtk_clipboard_request_text() and
+ * gtk_clipboard_wait_for_text(). These functions take care of
+ * determining which formats are advertised by the clipboard
+ * provider, asking for the clipboard in the best available format
+ * and converting the results into the UTF-8 encoding. (The standard
+ * form for representing strings in GTK+.)
+ */
+
+
enum {
OWNER_CHANGE,
LAST_SIGNAL
/**
* GtkClipboard::owner-change:
* @clipboard: the #GtkClipboard on which the signal is emitted
- * @event: the @GdkEventOwnerChange event
+ * @event: (type Gdk.EventOwnerChange): the @GdkEventOwnerChange event
*
* The ::owner-change signal is emitted when GTK+ receives an
- * event that indicates that the ownership of the selection
+ * event that indicates that the ownership of the selection
* associated with @clipboard has changed.
*
* Since: 2.6
- */
+ */
clipboard_signals[OWNER_CHANGE] =
g_signal_new (I_("owner-change"),
G_TYPE_FROM_CLASS (gobject_class),
if (clipboard->notify_signal_id != 0)
g_signal_handler_disconnect (clipboard_widget, clipboard->notify_signal_id);
-
+
g_free (clipboard->storable_targets);
g_free (clipboard->cached_targets);
/**
* 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.
- *
+ * @selection: a #GdkAtom which identifies the clipboard 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.
* 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: (transfer none): 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 and, since
- * it is owned by GTK+, must not be freed or
- * unrefd.
+ * clipboard already exists, a new one will be created. Once a clipboard
+ * object has been created, it is persistent and, since it is owned by
+ * GTK+, must not be freed or unrefd.
*
* Since: 2.2
**/
{
g_return_val_if_fail (display != NULL, NULL); /* See bgo#463773; this is needed because Flash Player sucks */
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
- g_return_val_if_fail (!display->closed, NULL);
+ g_return_val_if_fail (!gdk_display_is_closed (display), NULL);
return clipboard_peek (display, selection, FALSE);
}
guint info,
guint time)
{
- GtkClipboard *clipboard = gtk_widget_get_clipboard (widget, selection_data->selection);
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_widget_get_clipboard (widget,
+ gtk_selection_data_get_selection (selection_data));
if (clipboard && clipboard->get_func)
clipboard->get_func (clipboard, selection_data, info, clipboard->user_data);
{
GtkWidget *clipboard_widget = get_clipboard_widget (clipboard->display);
guint32 timestamp = gtk_get_current_event_time ();
+ GdkWindow *window;
if (timestamp == GDK_CURRENT_TIME)
{
+ window = gtk_widget_get_window (clipboard_widget);
#ifdef GDK_WINDOWING_X11
- timestamp = gdk_x11_get_server_time (gtk_widget_get_window (clipboard_widget));
-#elif defined GDK_WINDOWING_WIN32
- timestamp = GetMessageTime ();
+ if (GDK_IS_X11_WINDOW (window))
+ {
+ timestamp = gdk_x11_get_server_time (gtk_widget_get_window (clipboard_widget));
+ }
+ else
+#endif
+#if defined GDK_WINDOWING_WIN32
+ if (GDK_IS_WIN32_WINDOW (window))
+ {
+ timestamp = GetMessageTime ();
+ }
+ else
+#endif
+#if defined GDK_WINDOWING_BROADWAY
+ if (GDK_IS_BROADWAY_WINDOW (window))
+ {
+ timestamp = gdk_broadway_get_last_seen_time (window);
+ }
+ else
#endif
+ {
+ /* No implementation */
+ }
}
else
{
}
/**
- * gtk_clipboard_set_with_data:
+ * gtk_clipboard_set_with_data: (skip)
* @clipboard: a #GtkClipboard
- * @targets: array containing information about the available forms for the
- * clipboard data
+ * @targets: (array length=n_targets): array containing information
+ * about the available forms for the clipboard data
* @n_targets: number of elements in @targets
* @get_func: (scope async): function to call to get the actual clipboard data
* @clear_func: (scope async): when the clipboard contents are set again,
}
/**
- * gtk_clipboard_set_with_owner:
+ * gtk_clipboard_set_with_owner: (skip)
* @clipboard: a #GtkClipboard
- * @targets: array containing information about the available forms for
- * the clipboard data
+ * @targets: (array length=n_targets): array containing information
+ * about the available forms for the clipboard data
* @n_targets: number of elements in @targets
* @get_func: (scope async): function to call to get the actual clipboard data
* @clear_func: (scope async): when the clipboard contents are set again,
{
RequestContentsInfo *request_info = get_request_contents_info (widget);
set_request_contents_info (widget, NULL);
-
- request_info->callback (gtk_widget_get_clipboard (widget, selection_data->selection),
+
+ request_info->callback (gtk_widget_get_clipboard (widget, gtk_selection_data_get_selection (selection_data)),
selection_data,
request_info->user_data);
* 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_static_string ("UTF8_STRING"))
+ GdkAtom target = gtk_selection_data_get_target (selection_data);
+
+ if (target == gdk_atom_intern_static_string ("UTF8_STRING"))
{
gtk_clipboard_request_contents (clipboard,
gdk_atom_intern_static_string ("COMPOUND_TEXT"),
request_text_received_func, info);
return;
}
- else if (selection_data->target == gdk_atom_intern_static_string ("COMPOUND_TEXT"))
+ else if (target == gdk_atom_intern_static_string ("COMPOUND_TEXT"))
{
gtk_clipboard_request_contents (clipboard,
GDK_TARGET_STRING,
guint8 *result = NULL;
gsize length = 0;
- result = selection_data->data;
- length = selection_data->length;
+ result = (guint8 *) gtk_selection_data_get_data (selection_data);
+ length = gtk_selection_data_get_length (selection_data);
info->current_atom++;
return;
}
- info->callback (clipboard, selection_data->target, result, length,
+ info->callback (clipboard, gtk_selection_data_get_target (selection_data),
+ result, length,
info->user_data);
g_free (info->atoms);
g_free (info);
* if we asked for image/gif and didn't get it, try image/bmp;
* If we asked for anything else and didn't get it, give up.
*/
- if (selection_data->target == gdk_atom_intern_static_string ("image/png"))
+ GdkAtom target = gtk_selection_data_get_target (selection_data);
+
+ if (target == gdk_atom_intern_static_string ("image/png"))
{
gtk_clipboard_request_contents (clipboard,
gdk_atom_intern_static_string ("image/jpeg"),
request_image_received_func, info);
return;
}
- else if (selection_data->target == gdk_atom_intern_static_string ("image/jpeg"))
+ else if (target == gdk_atom_intern_static_string ("image/jpeg"))
{
gtk_clipboard_request_contents (clipboard,
gdk_atom_intern_static_string ("image/gif"),
request_image_received_func, info);
return;
}
- else if (selection_data->target == gdk_atom_intern_static_string ("image/gif"))
+ else if (target == gdk_atom_intern_static_string ("image/gif"))
{
gtk_clipboard_request_contents (clipboard,
gdk_atom_intern_static_string ("image/bmp"),
{
WaitResults *results = data;
- if (selection_data->length >= 0)
+ if (gtk_selection_data_get_length (selection_data) >= 0)
results->data = gtk_selection_data_copy (selection_data);
g_main_loop_quit (results->loop);
if (g_main_loop_is_running (results.loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (results.loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (results.loop);
if (g_main_loop_is_running (results.loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (results.loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (results.loop);
* gtk_clipboard_wait_for_rich_text:
* @clipboard: a #GtkClipboard
* @buffer: a #GtkTextBuffer
- * @format: return location for the format of the returned data
+ * @format: (out): return location for the format of the returned data
* @length: return location for the length of the returned data
*
* Requests the contents of the clipboard as rich text. 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 binary block of data 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
- * clipboard was empty or if the contents of the
- * clipboard could not be converted into text form.)
+ * Return value: (array length=length) (transfer full): a
+ * newly-allocated binary block of data 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 clipboard was empty or
+ * if the contents of the clipboard could not be
+ * converted into text form.)
*
* Since: 2.10
**/
if (g_main_loop_is_running (results.loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (results.loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (results.loop);
if (g_main_loop_is_running (results.loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (results.loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (results.loop);
if (g_main_loop_is_running (results.loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (results.loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (results.loop);
}
/**
- * gtk_clipboard_wait_for_targets
+ * gtk_clipboard_wait_for_targets:
* @clipboard: a #GtkClipboard
- * @targets: location to store an array of targets. The result
- * stored here must be freed with g_free().
+ * @targets: (out) (array length=n_targets) (transfer container): location
+ * to store an array of targets. The result stored here must
+ * be freed with g_free().
* @n_targets: location to store number of items in @targets.
*
* Returns a list of targets that are present on the clipboard, or %NULL
- * if there aren't any targets available. The returned list must be
+ * if there aren't any targets available. The returned list must be
* freed with g_free().
- * This function waits for the data to be received using the main
+ * 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: %TRUE if any targets are present on the clipboard,
{
g_main_loop_quit (clipboard->store_loop);
- return FALSE;
+ return G_SOURCE_REMOVE;
}
/**
* gtk_clipboard_set_can_store:
* @clipboard: a #GtkClipboard
- * @targets: (allow-none): array containing information about which forms
- * should be stored or %NULL to indicate that all forms should
- * be stored.
+ * @targets: (allow-none) (array length=n_targets): array containing
+ * information about which forms should be stored or %NULL
+ * to indicate that all forms should be stored.
* @n_targets: number of elements in @targets
*
* Hints that the clipboard data should be stored somewhere when the
if (g_main_loop_is_running (clipboard->store_loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (clipboard->store_loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (clipboard->store_loop);