X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkclipboard-wayland.c;h=3ed3b4e6e4b8f4660dd368611dd4c55245bdbbc9;hb=cade42d5094ceaa7799aa8e2135959573646a4b6;hp=649acbd202bef78a1262a624fec3a822df8dfadc;hpb=2d837769a0c0f11b15c45ff4ff18b820299320d8;p=~andy%2Fgtk diff --git a/gtk/gtkclipboard-wayland.c b/gtk/gtkclipboard-wayland.c index 649acbd20..3ed3b4e6e 100644 --- a/gtk/gtkclipboard-wayland.c +++ b/gtk/gtkclipboard-wayland.c @@ -15,9 +15,7 @@ * 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 . * */ @@ -50,6 +48,8 @@ struct _GtkClipboard GObject *owner; GdkDisplay *display; + GdkAtom selection; + SetContentClosure *last_closure; }; @@ -124,34 +124,68 @@ gtk_clipboard_finalize (GObject *object) 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 * @@ -166,6 +200,7 @@ struct _SetContentClosure { GtkClipboardGetFunc get_func; GtkClipboardClearFunc clear_func; guint info; + gboolean have_owner; gpointer userdata; GtkTargetPair *targets; gint n_targets; @@ -205,6 +240,21 @@ _offer_cb (GdkDevice *device, 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, @@ -218,21 +268,34 @@ gtk_clipboard_set_contents (GtkClipboard *clipboard, 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++) @@ -320,7 +383,12 @@ gtk_clipboard_clear (GtkClipboard *clipboard) 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; } @@ -606,9 +674,9 @@ gtk_clipboard_wait_for_contents (GtkClipboard *clipboard, 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);