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].
(cherry picked from commit f2b74db5dc
)
This commit is contained in:
parent
c74d79bb55
commit
f08fc12741
@ -45,6 +45,7 @@ struct _GtkClipboard
|
|||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
NSPasteboard *pasteboard;
|
NSPasteboard *pasteboard;
|
||||||
|
NSInteger change_count;
|
||||||
|
|
||||||
GdkAtom selection;
|
GdkAtom selection;
|
||||||
|
|
||||||
@ -76,13 +77,18 @@ struct _GtkClipboardClass
|
|||||||
GdkEventOwnerChange *event);
|
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 {
|
@interface GtkClipboardOwner : NSObject {
|
||||||
GtkClipboard *clipboard;
|
GtkClipboard *clipboard;
|
||||||
|
|
||||||
GtkClipboardGetFunc get_func;
|
|
||||||
GtkClipboardClearFunc clear_func;
|
|
||||||
gpointer user_data;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@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
|
- (void)pasteboardChangedOwner:(NSPasteboard *)sender
|
||||||
{
|
{
|
||||||
if (clear_func)
|
clipboard_unset (clipboard);
|
||||||
clear_func (clipboard, user_data);
|
|
||||||
|
|
||||||
[self release];
|
[self release];
|
||||||
}
|
}
|
||||||
@ -139,15 +150,6 @@ struct _GtkClipboardClass
|
|||||||
|
|
||||||
@end
|
@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 const gchar clipboards_owned_key[] = "gtk-clipboards-owned";
|
||||||
static GQuark clipboards_owned_key_id = 0;
|
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->user_data = user_data;
|
||||||
clipboard->have_owner = have_owner;
|
clipboard->have_owner = have_owner;
|
||||||
if (have_owner)
|
if (have_owner)
|
||||||
@ -371,12 +382,6 @@ gtk_clipboard_set_contents (GtkClipboard *clipboard,
|
|||||||
gtk_target_list_unref (clipboard->target_list);
|
gtk_target_list_unref (clipboard->target_list);
|
||||||
clipboard->target_list = gtk_target_list_new (targets, n_targets);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,6 +425,12 @@ gtk_clipboard_get_owner (GtkClipboard *clipboard)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (clipboard != NULL, NULL);
|
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)
|
if (clipboard->have_owner)
|
||||||
return clipboard->user_data;
|
return clipboard->user_data;
|
||||||
else
|
else
|
||||||
@ -473,6 +484,8 @@ clipboard_unset (GtkClipboard *clipboard)
|
|||||||
void
|
void
|
||||||
gtk_clipboard_clear (GtkClipboard *clipboard)
|
gtk_clipboard_clear (GtkClipboard *clipboard)
|
||||||
{
|
{
|
||||||
|
clipboard_unset (clipboard);
|
||||||
|
|
||||||
[clipboard->pasteboard declareTypes:nil owner:nil];
|
[clipboard->pasteboard declareTypes:nil owner:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,6 +669,12 @@ gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
|
|||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||||
GtkSelectionData *selection_data = NULL;
|
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"))
|
if (target == gdk_atom_intern_static_string ("TARGETS"))
|
||||||
{
|
{
|
||||||
NSArray *types = [clipboard->pasteboard types];
|
NSArray *types = [clipboard->pasteboard types];
|
||||||
|
Loading…
Reference in New Issue
Block a user