[gtk+] Bug 626499 - GtkClipboard unnotified on change of OS X pasteboard owner



commit f08fc1274141a0e631687de12246409881ec2454
Author: Michael Natterer <mitch gimp org>
Date:   Tue Dec 4 14:31:13 2012 +0100

    Bug 626499 - GtkClipboard unnotified on change of OS X pasteboard owner
    
    pasteboardChangedOwner is not called as reliably as we'd want to get it,
    so keep track of [pasteboard changeCount] and drop clipboard ownership
    when a change happened. Also better unset the clipboard content redundantly
    in a few places rather than missing one, and reorder the code in
    gtk_clipboard_set_contents() so that the new aggressive unsetting
    won't unset the clipboard under our feet when we call
    [pasteboard declareTypes].
    (cherry picked from commit f2b74db5dcbd28a1e27431f413c66d2a5d50b2bd)

 gtk/gtkclipboard-quartz.c |   63 +++++++++++++++++++++++++++++---------------
 1 files changed, 41 insertions(+), 22 deletions(-)
---
diff --git a/gtk/gtkclipboard-quartz.c b/gtk/gtkclipboard-quartz.c
index 35ab27b..9a01b7c 100644
--- a/gtk/gtkclipboard-quartz.c
+++ b/gtk/gtkclipboard-quartz.c
@@ -45,6 +45,7 @@ struct _GtkClipboard
   GObject parent_instance;
 
   NSPasteboard *pasteboard;
+  NSInteger change_count;
 
   GdkAtom selection;
 
@@ -76,13 +77,18 @@ struct _GtkClipboardClass
 			GdkEventOwnerChange *event);
 };
 
+static void gtk_clipboard_class_init   (GtkClipboardClass   *class);
+static void gtk_clipboard_finalize     (GObject             *object);
+static void gtk_clipboard_owner_change (GtkClipboard        *clipboard,
+					GdkEventOwnerChange *event);
+
+static void          clipboard_unset      (GtkClipboard     *clipboard);
+static GtkClipboard *clipboard_peek       (GdkDisplay       *display,
+					   GdkAtom           selection,
+					   gboolean          only_if_exists);
+
 @interface GtkClipboardOwner : NSObject {
   GtkClipboard *clipboard;
-
-  GtkClipboardGetFunc get_func;
-  GtkClipboardClearFunc clear_func;
-  gpointer user_data;
-  
 }
 
 @end
@@ -117,10 +123,15 @@ struct _GtkClipboardClass
     }
 }
 
+/*  pasteboardChangedOwner is not called immediately, and it's not called
+ *  reliably. It is somehow documented in the apple api docs, but the docs
+ *  suck and don't really give clear instructions. Therefore we track
+ *  changeCount in several places below and clear the clipboard if it
+ *  changed.
+ */
 - (void)pasteboardChangedOwner:(NSPasteboard *)sender
 {
-  if (clear_func)
-    clear_func (clipboard, user_data);
+  clipboard_unset (clipboard);
 
   [self release];
 }
@@ -139,15 +150,6 @@ struct _GtkClipboardClass
 
 @end
 
-static void gtk_clipboard_class_init   (GtkClipboardClass   *class);
-static void gtk_clipboard_finalize     (GObject             *object);
-static void gtk_clipboard_owner_change (GtkClipboard        *clipboard,
-					GdkEventOwnerChange *event);
-
-static void          clipboard_unset      (GtkClipboard     *clipboard);
-static GtkClipboard *clipboard_peek       (GdkDisplay       *display,
-					   GdkAtom           selection,
-					   gboolean          only_if_exists);
 
 static const gchar clipboards_owned_key[] = "gtk-clipboards-owned";
 static GQuark clipboards_owned_key_id = 0;
@@ -360,6 +362,15 @@ gtk_clipboard_set_contents (GtkClipboard         *clipboard,
         }
     }
 
+  /*  call declareTypes before setting the clipboard members because
+   *  declareTypes might clear the clipboard
+   */
+  types = _gtk_quartz_target_entries_to_pasteboard_types (targets, n_targets);
+  clipboard->change_count = [clipboard->pasteboard declareTypes: [types allObjects]
+                                                          owner: owner];
+  [types release];
+  [pool release];
+
   clipboard->user_data = user_data;
   clipboard->have_owner = have_owner;
   if (have_owner)
@@ -371,12 +382,6 @@ gtk_clipboard_set_contents (GtkClipboard         *clipboard,
     gtk_target_list_unref (clipboard->target_list);
   clipboard->target_list = gtk_target_list_new (targets, n_targets);
 
-  types = _gtk_quartz_target_entries_to_pasteboard_types (targets, n_targets);
-
-  [clipboard->pasteboard declareTypes:[types allObjects] owner:owner];
-  [types release];
-  [pool release];
-
   return TRUE;
 }
 
@@ -420,6 +425,12 @@ gtk_clipboard_get_owner (GtkClipboard *clipboard)
 {
   g_return_val_if_fail (clipboard != NULL, NULL);
 
+  if (clipboard->change_count < [clipboard->pasteboard changeCount])
+    {
+      clipboard_unset (clipboard);
+      clipboard->change_count = [clipboard->pasteboard changeCount];
+    }
+
   if (clipboard->have_owner)
     return clipboard->user_data;
   else
@@ -473,6 +484,8 @@ clipboard_unset (GtkClipboard *clipboard)
 void
 gtk_clipboard_clear (GtkClipboard *clipboard)
 {
+  clipboard_unset (clipboard);
+
   [clipboard->pasteboard declareTypes:nil owner:nil];
 }
 
@@ -656,6 +669,12 @@ gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   GtkSelectionData *selection_data = NULL;
 
+  if (clipboard->change_count < [clipboard->pasteboard changeCount])
+    {
+      clipboard_unset (clipboard);
+      clipboard->change_count = [clipboard->pasteboard changeCount];
+    }
+
   if (target == gdk_atom_intern_static_string ("TARGETS")) 
     {
       NSArray *types = [clipboard->pasteboard types];



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]