]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkclipboard-wayland.c
gtkfilechooserbutton: In tests, allow the possibility of doing unselect_all
[~andy/gtk] / gtk / gtkclipboard-wayland.c
index 649acbd202bef78a1262a624fec3a822df8dfadc..3ed3b4e6e4b8f4660dd368611dd4c55245bdbbc9 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.
  *
  */
 
@@ -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);