forked from AuroraMiddleware/gtk
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].
This commit is contained in:
parent
6056f1855b
commit
f2b74db5dc
@ -46,6 +46,7 @@ struct _GtkClipboard
|
||||
GObject parent_instance;
|
||||
|
||||
NSPasteboard *pasteboard;
|
||||
NSInteger change_count;
|
||||
|
||||
GdkAtom selection;
|
||||
|
||||
@ -77,13 +78,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
|
||||
@ -118,10 +124,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];
|
||||
}
|
||||
@ -140,15 +151,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;
|
||||
@ -361,6 +363,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)
|
||||
@ -372,12 +383,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;
|
||||
}
|
||||
|
||||
@ -421,6 +426,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
|
||||
@ -474,6 +485,8 @@ clipboard_unset (GtkClipboard *clipboard)
|
||||
void
|
||||
gtk_clipboard_clear (GtkClipboard *clipboard)
|
||||
{
|
||||
clipboard_unset (clipboard);
|
||||
|
||||
[clipboard->pasteboard declareTypes:nil owner:nil];
|
||||
}
|
||||
|
||||
@ -658,6 +671,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];
|
||||
|
Loading…
Reference in New Issue
Block a user