GObject *owner;
GdkDisplay *display;
+ GdkAtom selection;
+
SetContentClosure *last_closure;
};
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-GtkClipboard *
-gtk_clipboard_get_for_display (GdkDisplay *display,
- GdkAtom selection)
+static void
+clipboard_display_closed (GdkDisplay *display,
+ gboolean is_error,
+ GtkClipboard *clipboard)
{
- GtkClipboard *clipboard;
+ GSList *clipboards;
+
+ clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
+ g_object_run_dispose (G_OBJECT (clipboard));
+ clipboards = g_slist_remove (clipboards, clipboard);
+ g_object_set_data (G_OBJECT (display), I_("gtk-clipboard-list"), clipboards);
+ g_object_unref (clipboard);
+}
+
+static GtkClipboard *
+clipboard_peek (GdkDisplay *display,
+ GdkAtom selection,
+ gboolean only_if_exists)
+{
+ GtkClipboard *clipboard = NULL;
+ GSList *clipboards;
+ GSList *tmp_list;
if (selection == GDK_NONE)
selection = GDK_SELECTION_CLIPBOARD;
- if (selection != GDK_SELECTION_CLIPBOARD)
- {
- g_warning (G_STRLOC ": Only able to create clipboard for CLIPBOARD");
- }
+ clipboards = g_object_get_data (G_OBJECT (display), "gtk-clipboard-list");
- selection = GDK_SELECTION_CLIPBOARD;
-
- clipboard = g_object_get_data (G_OBJECT (display), "gtk-clipboard");
+ tmp_list = clipboards;
+ while (tmp_list)
+ {
+ clipboard = tmp_list->data;
+ if (clipboard->selection == selection)
+ break;
- if (clipboard)
- return clipboard;
+ tmp_list = tmp_list->next;
+ }
- clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
- clipboard->display = display;
+ if (!tmp_list && !only_if_exists)
+ {
+ 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), I_("gtk-clipboard-list"), clipboards);
+ g_signal_connect (display, "closed",
+ G_CALLBACK (clipboard_display_closed), clipboard);
+ gdk_display_request_selection_notification (display, selection);
+ }
+
+ return clipboard;
+}
- g_object_set_data (G_OBJECT (display), "gtk-clipboard", clipboard);
+GtkClipboard *
+gtk_clipboard_get_for_display (GdkDisplay *display,
+ GdkAtom selection)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+ g_return_val_if_fail (!gdk_display_is_closed (display), NULL);
- /* TODO: Need to connect to display closed to free this */
- return clipboard;
+ return clipboard_peek (display, selection, FALSE);
}
GtkClipboard *
GtkClipboardGetFunc get_func;
GtkClipboardClearFunc clear_func;
guint info;
+ gboolean have_owner;
gpointer userdata;
GtkTargetPair *targets;
gint n_targets;
return (gchar *)selection_data.data;
}
+static void
+clipboard_owner_destroyed (gpointer data,
+ GObject *owner)
+{
+ GtkClipboard *clipboard = (GtkClipboard *) data;
+ SetContentClosure *last_closure = clipboard->last_closure;
+
+ last_closure->userdata = NULL;
+ last_closure->get_func = NULL;
+ last_closure->clear_func = NULL;
+ last_closure->have_owner = FALSE;
+
+ gtk_clipboard_clear (clipboard);
+}
+
static gboolean
gtk_clipboard_set_contents (GtkClipboard *clipboard,
const GtkTargetEntry *targets,
GdkDevice *device;
gint i;
gchar **mimetypes;
- SetContentClosure *closure;
-
- gtk_clipboard_clear (clipboard);
+ SetContentClosure *closure, *last_closure;
+
+ last_closure = clipboard->last_closure;
+ if (!last_closure ||
+ (!last_closure->have_owner && have_owner) ||
+ (last_closure->userdata != user_data)) {
+ gtk_clipboard_clear (clipboard);
+
+ closure = g_new0 (SetContentClosure, 1);
+ closure->clipboard = clipboard;
+ closure->userdata = user_data;
+ closure->have_owner = have_owner;
+
+ if (have_owner)
+ g_object_weak_ref (G_OBJECT (user_data), clipboard_owner_destroyed, clipboard);
+ } else {
+ closure = last_closure;
+ g_free (closure->targets);
+ }
- device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
- device = gdk_device_manager_get_client_pointer (device_manager);
-
- closure = g_new0 (SetContentClosure, 1);
- closure->clipboard = clipboard;
closure->get_func = get_func;
closure->clear_func = clear_func;
- closure->userdata = user_data;
closure->targets = g_new0 (GtkTargetPair, n_targets);
closure->n_targets = n_targets;
+ device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
+ device = gdk_device_manager_get_client_pointer (device_manager);
+
mimetypes = g_new (gchar *, n_targets);
for (i = 0; i < n_targets; i++)
clipboard->last_closure->userdata);
}
- /* TODO: Free last closure */
+ if (clipboard->last_closure->have_owner)
+ g_object_weak_unref (G_OBJECT (clipboard->last_closure->userdata),
+ clipboard_owner_destroyed, clipboard);
+ g_free (clipboard->last_closure->targets);
+ g_free (clipboard->last_closure);
+
clipboard->last_closure = NULL;
}
if (g_main_loop_is_running (closure->loop))
{
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
g_main_loop_run (closure->loop);
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
g_main_loop_unref (closure->loop);