[gtk/wip/chergert/quartz4u: 127/142] macos: make basic clipboard work
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/quartz4u: 127/142] macos: make basic clipboard work
- Date: Tue, 23 Jun 2020 18:40:28 +0000 (UTC)
commit c60df91144b9ebe9377f467fd3f00ab5ac184adf
Author: Christian Hergert <chergert redhat com>
Date: Mon Jun 15 17:16:45 2020 -0700
macos: make basic clipboard work
gdk/macos/gdkmacosclipboard-private.h | 8 +--
gdk/macos/gdkmacosclipboard.c | 109 ++++++++++++++++++++--------------
2 files changed, 68 insertions(+), 49 deletions(-)
---
diff --git a/gdk/macos/gdkmacosclipboard-private.h b/gdk/macos/gdkmacosclipboard-private.h
index 8098fc8a5b..ab37d707a5 100644
--- a/gdk/macos/gdkmacosclipboard-private.h
+++ b/gdk/macos/gdkmacosclipboard-private.h
@@ -39,12 +39,12 @@ const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardTy
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
{
- GdkContentProvider *contentProvider;
- char **mimeTypes;
- GCancellable *cancellable;
+ GCancellable *cancellable;
+ GdkClipboard *clipboard;
+ char **mimeTypes;
}
--(id)initDataProvider:(GdkContentProvider *)contentProvider withMimeTypes:(const char * const *)mime_types;
+-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
-(NSArray<NSPasteboardType> *)types;
@end
diff --git a/gdk/macos/gdkmacosclipboard.c b/gdk/macos/gdkmacosclipboard.c
index f75331c243..7297045b76 100644
--- a/gdk/macos/gdkmacosclipboard.c
+++ b/gdk/macos/gdkmacosclipboard.c
@@ -36,6 +36,8 @@ typedef struct
GMemoryOutputStream *stream;
NSPasteboardItem *item;
NSPasteboardType type;
+ GMainContext *main_context;
+ guint done : 1;
} WriteRequest;
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
@@ -43,6 +45,7 @@ G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
static void
write_request_free (WriteRequest *wr)
{
+ g_clear_pointer (&wr->main_context, g_main_context_unref);
g_clear_object (&wr->stream);
[wr->item release];
g_slice_free (WriteRequest, wr);
@@ -80,11 +83,6 @@ _gdk_macos_clipboard_to_ns_type (const char *mime_type,
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
{
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- if (alternate)
- *alternate = NSStringPboardType;
- G_GNUC_END_IGNORE_DEPRECATIONS;
-
return NSPasteboardTypeString;
}
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
@@ -214,7 +212,7 @@ _gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
{
const char *str = [nsstr UTF8String];
stream = g_memory_input_stream_new_from_data (g_strdup (str),
- strlen (str),
+ strlen (str) + 1,
g_free);
}
}
@@ -317,37 +315,37 @@ _gdk_macos_clipboard_read_finish (GdkClipboard *clipboard,
}
static void
-_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self)
+_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
+ GdkContentProvider *content)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosClipboardDataProvider *dataProvider;
- GdkContentProvider *content;
+ GdkContentFormats *serializable;
NSPasteboardItem *item;
const char * const *mime_types;
- GdkContentFormats *formats;
gsize n_mime_types;
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
+ g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
- if (!(content = gdk_clipboard_get_content (GDK_CLIPBOARD (self))))
- goto cleanup;
-
- formats = gdk_content_provider_ref_storable_formats (content);
- formats = gdk_content_formats_union_serialize_mime_types (formats);
+ serializable = gdk_content_provider_ref_storable_formats (content);
+ serializable = gdk_content_formats_union_serialize_mime_types (serializable);
+ mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
- mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types);
- dataProvider = [[GdkMacosClipboardDataProvider alloc] initDataProvider:content
- withMimeTypes:mime_types];
+ dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
+ mimetypes:mime_types];
item = [[NSPasteboardItem alloc] init];
- [item setDataProvider:dataProvider forTypes:[item types]];
+ [item setDataProvider:dataProvider forTypes:[dataProvider types]];
[self->pasteboard clearContents];
- [self->pasteboard writeObjects:[NSArray arrayWithObject:item]];
+ if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
+ g_warning ("Failed to write object to pasteboard");
- g_clear_pointer (&formats, gdk_content_formats_unref);
+ self->last_change_count = [self->pasteboard changeCount];
+
+ g_clear_pointer (&serializable, gdk_content_formats_unref);
-cleanup:
GDK_END_MACOS_ALLOC_POOL;
}
@@ -367,7 +365,7 @@ _gdk_macos_clipboard_claim (GdkClipboard *clipboard,
ret = GDK_CLIPBOARD_CLASS (_gdk_macos_clipboard_parent_class)->claim (clipboard, formats, local, provider);
if (local)
- _gdk_macos_clipboard_send_to_pasteboard (self);
+ _gdk_macos_clipboard_send_to_pasteboard (self, provider);
return ret;
}
@@ -443,12 +441,12 @@ _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
@implementation GdkMacosClipboardDataProvider
--(id)initDataProvider:(GdkContentProvider *)content_provider withMimeTypes:(const char * const *)mime_types
+-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
{
[super init];
self->mimeTypes = g_strdupv ((char **)mime_types);
- self->contentProvider = g_object_ref (content_provider);
+ self->clipboard = g_object_ref (gdkClipboard);
return self;
}
@@ -458,19 +456,24 @@ _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
g_cancellable_cancel (self->cancellable);
g_clear_pointer (&self->mimeTypes, g_strfreev);
- g_clear_object (&self->contentProvider);
+ g_clear_object (&self->clipboard);
g_clear_object (&self->cancellable);
[super dealloc];
}
+-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
+{
+ g_clear_object (&self->clipboard);
+}
+
-(NSArray<NSPasteboardType> *)types
{
- NSMutableArray *ret = [NSMutableArray alloc];
- const char *mime_type;
+ NSMutableArray *ret = [[NSMutableArray alloc] init];
for (guint i = 0; self->mimeTypes[i]; i++)
{
+ const char *mime_type = self->mimeTypes[i];
NSPasteboardType type;
NSPasteboardType alternate = nil;
@@ -492,36 +495,40 @@ on_data_ready_cb (GObject *object,
{
GDK_BEGIN_MACOS_ALLOC_POOL;
- GdkContentProvider *content = (GdkContentProvider *)object;
+ GdkClipboard *clipboard = (GdkClipboard *)object;
WriteRequest *wr = user_data;
GError *error = NULL;
- NSData *data;
+ NSData *data = nil;
- g_assert (GDK_IS_CONTENT_PROVIDER (content));
+ g_assert (GDK_IS_CLIPBOARD (clipboard));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (wr != NULL);
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
- if (gdk_content_provider_write_mime_type_finish (content, result, &error))
+ if (gdk_clipboard_write_finish (clipboard, result, &error))
{
- gsize size = g_memory_output_stream_get_size (wr->stream);
- gpointer bytes = g_memory_output_stream_steal_data (wr->stream);
+ gsize size;
+ gpointer bytes;
+
+ g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
+ size = g_memory_output_stream_get_size (wr->stream);
+ bytes = g_memory_output_stream_steal_data (wr->stream);
data = [[NSData alloc] initWithBytesNoCopy:bytes
length:size
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
}
else
{
- data = [NSData data];
- g_warning ("Failed to serialize clipboard contents: %s", error->message);
+ g_warning ("Failed to serialize clipboard contents: %s",
+ error->message);
g_clear_error (&error);
}
[wr->item setData:data forType:wr->type];
- write_request_free (wr);
+ wr->done = TRUE;
GDK_END_MACOS_ALLOC_POOL;
}
@@ -530,11 +537,11 @@ on_data_ready_cb (GObject *object,
item:(NSPasteboardItem *)item
provideDataForType:(NSPasteboardType)type
{
- GdkContentProvider *content = self->contentProvider;
const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
+ GMainContext *main_context = g_main_context_default ();
WriteRequest *wr;
- if (content == NULL || mime_type == NULL)
+ if (self->clipboard == NULL || mime_type == NULL)
{
[item setData:[NSData data] forType:type];
return;
@@ -544,14 +551,26 @@ on_data_ready_cb (GObject *object,
wr->item = [item retain];
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
wr->type = type;
+ wr->main_context = g_main_context_ref (main_context);
+ wr->done = FALSE;
+
+ gdk_clipboard_write_async (self->clipboard,
+ mime_type,
+ G_OUTPUT_STREAM (wr->stream),
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ on_data_ready_cb,
+ wr);
+
+ /* We're forced to provide data synchronously via this API
+ * so we must block on the main loop. Using another main loop
+ * than the default tends to get us locked up here, so that is
+ * what we'll do for now.
+ */
+ while (!wr->done)
+ g_main_context_iteration (wr->main_context, TRUE);
- gdk_content_provider_write_mime_type_async (content,
- mime_type,
- G_OUTPUT_STREAM (wr->stream),
- G_PRIORITY_DEFAULT,
- self->cancellable,
- on_data_ready_cb,
- wr);
+ write_request_free (wr);
}
@end
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]