1 /* GDK - The GIMP Drawing Kit
2 *
3 * Copyright (C) 2017,2020 Benjamin Otte <otte@gnome.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20
21 #include "gdkcontentproviderprivate.h"
22
23 #include <gobject/gvaluecollector.h>
24
25 #include "gdkcontentformats.h"
26 #include "gdkcontentserializer.h"
27 #include "gdkintl.h"
28 #include "gdkcontentproviderimpl.h"
29
30 #include "gdk-private.h"
31
32 #define GDK_TYPE_CONTENT_PROVIDER_VALUE (gdk_content_provider_value_get_type ())
33 #define GDK_CONTENT_PROVIDER_VALUE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_VALUE, GdkContentProviderValue))
34 #define GDK_IS_CONTENT_PROVIDER_VALUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CONTENT_PROVIDER_VALUE))
35 #define GDK_CONTENT_PROVIDER_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CONTENT_PROVIDER_VALUE, GdkContentProviderValueClass))
36 #define GDK_IS_CONTENT_PROVIDER_VALUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CONTENT_PROVIDER_VALUE))
37 #define GDK_CONTENT_PROVIDER_VALUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CONTENT_PROVIDER_VALUE, GdkContentProviderValueClass))
38
39 typedef struct _GdkContentProviderValue GdkContentProviderValue;
40 typedef struct _GdkContentProviderValueClass GdkContentProviderValueClass;
41
42 struct _GdkContentProviderValue
43 {
44 GdkContentProvider parent;
45
46 GValue value;
47 };
48
49 struct _GdkContentProviderValueClass
50 {
51 GdkContentProviderClass parent_class;
52 };
53
54 GType gdk_content_provider_value_get_type (void) G_GNUC_CONST;
55
G_DEFINE_TYPE(GdkContentProviderValue,gdk_content_provider_value,GDK_TYPE_CONTENT_PROVIDER)56 G_DEFINE_TYPE (GdkContentProviderValue, gdk_content_provider_value, GDK_TYPE_CONTENT_PROVIDER)
57
58 static void
59 gdk_content_provider_value_finalize (GObject *object)
60 {
61 GdkContentProviderValue *content = GDK_CONTENT_PROVIDER_VALUE (object);
62
63 g_value_unset (&content->value);
64
65 G_OBJECT_CLASS (gdk_content_provider_value_parent_class)->finalize (object);
66 }
67
68 static GdkContentFormats *
gdk_content_provider_value_ref_formats(GdkContentProvider * provider)69 gdk_content_provider_value_ref_formats (GdkContentProvider *provider)
70 {
71 GdkContentProviderValue *content = GDK_CONTENT_PROVIDER_VALUE (provider);
72
73 return gdk_content_formats_new_for_gtype (G_VALUE_TYPE (&content->value));
74 }
75
76 static gboolean
gdk_content_provider_value_get_value(GdkContentProvider * provider,GValue * value,GError ** error)77 gdk_content_provider_value_get_value (GdkContentProvider *provider,
78 GValue *value,
79 GError **error)
80 {
81 GdkContentProviderValue *content = GDK_CONTENT_PROVIDER_VALUE (provider);
82
83 if (G_VALUE_HOLDS (&content->value, G_VALUE_TYPE (value)))
84 {
85 g_value_copy (&content->value, value);
86 return TRUE;
87 }
88
89 return GDK_CONTENT_PROVIDER_CLASS (gdk_content_provider_value_parent_class)->get_value (provider, value, error);
90 }
91
92 static void
gdk_content_provider_value_class_init(GdkContentProviderValueClass * class)93 gdk_content_provider_value_class_init (GdkContentProviderValueClass *class)
94 {
95 GObjectClass *object_class = G_OBJECT_CLASS (class);
96 GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
97
98 object_class->finalize = gdk_content_provider_value_finalize;
99
100 provider_class->ref_formats = gdk_content_provider_value_ref_formats;
101 provider_class->get_value = gdk_content_provider_value_get_value;
102 }
103
104 static void
gdk_content_provider_value_init(GdkContentProviderValue * content)105 gdk_content_provider_value_init (GdkContentProviderValue *content)
106 {
107 }
108
109 /**
110 * gdk_content_provider_new_for_value:
111 * @value: a `GValue`
112 *
113 * Create a content provider that provides the given @value.
114 *
115 * Returns: a new `GdkContentProvider`
116 */
117 GdkContentProvider *
gdk_content_provider_new_for_value(const GValue * value)118 gdk_content_provider_new_for_value (const GValue *value)
119 {
120 GdkContentProviderValue *content;
121
122 g_return_val_if_fail (G_IS_VALUE (value), NULL);
123
124 content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_VALUE, NULL);
125 g_value_init (&content->value, G_VALUE_TYPE (value));
126 g_value_copy (value, &content->value);
127
128 return GDK_CONTENT_PROVIDER (content);
129 }
130
131 /**
132 * gdk_content_provider_new_typed:
133 * @type: Type of value to follow
134 * @...: value
135 *
136 * Create a content provider that provides the value of the given
137 * @type.
138 *
139 * The value is provided using G_VALUE_COLLECT(), so the same rules
140 * apply as when calling g_object_new() or g_object_set().
141 *
142 * Returns: a new `GdkContentProvider`
143 */
144 GdkContentProvider *
gdk_content_provider_new_typed(GType type,...)145 gdk_content_provider_new_typed (GType type,
146 ...)
147 {
148 GdkContentProviderValue *content;
149 va_list args;
150 char *error;
151
152 content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_VALUE, NULL);
153
154 va_start (args, type);
155 G_VALUE_COLLECT_INIT (&content->value, type, args, 0, &error);
156 if (error)
157 {
158 g_warning ("%s: %s", G_STRLOC, error);
159 g_free (error);
160 /* we purposely leak the value here, it might not be
161 * in a sane state if an error condition occurred
162 */
163 }
164 va_end (args);
165
166 return GDK_CONTENT_PROVIDER (content);
167 }
168
169 #define GDK_TYPE_CONTENT_PROVIDER_UNION (gdk_content_provider_union_get_type ())
170 #define GDK_CONTENT_PROVIDER_UNION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_UNION, GdkContentProviderUnion))
171 #define GDK_IS_CONTENT_PROVIDER_UNION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CONTENT_PROVIDER_UNION))
172 #define GDK_CONTENT_PROVIDER_UNION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CONTENT_PROVIDER_UNION, GdkContentProviderUnionClass))
173 #define GDK_IS_CONTENT_PROVIDER_UNION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CONTENT_PROVIDER_UNION))
174 #define GDK_CONTENT_PROVIDER_UNION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CONTENT_PROVIDER_UNION, GdkContentProviderUnionClass))
175
176 typedef struct _GdkContentProviderUnion GdkContentProviderUnion;
177 typedef struct _GdkContentProviderUnionClass GdkContentProviderUnionClass;
178
179 struct _GdkContentProviderUnion
180 {
181 GdkContentProvider parent;
182
183 GdkContentProvider **providers;
184 gsize n_providers;
185 };
186
187 struct _GdkContentProviderUnionClass
188 {
189 GdkContentProviderClass parent_class;
190 };
191
192 GType gdk_content_provider_union_get_type (void) G_GNUC_CONST;
193
G_DEFINE_TYPE(GdkContentProviderUnion,gdk_content_provider_union,GDK_TYPE_CONTENT_PROVIDER)194 G_DEFINE_TYPE (GdkContentProviderUnion, gdk_content_provider_union, GDK_TYPE_CONTENT_PROVIDER)
195
196 static void
197 gdk_content_provider_union_attach_clipboard (GdkContentProvider *provider,
198 GdkClipboard *clipboard)
199 {
200 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (provider);
201 gsize i;
202
203 for (i = 0; i < self->n_providers; i++)
204 gdk_content_provider_attach_clipboard (self->providers[i], clipboard);
205 }
206
207 static void
gdk_content_provider_union_detach_clipboard(GdkContentProvider * provider,GdkClipboard * clipboard)208 gdk_content_provider_union_detach_clipboard (GdkContentProvider *provider,
209 GdkClipboard *clipboard)
210 {
211 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (provider);
212 gsize i;
213
214 for (i = 0; i < self->n_providers; i++)
215 gdk_content_provider_detach_clipboard (self->providers[i], clipboard);
216 }
217
218 static GdkContentFormats *
gdk_content_provider_union_ref_formats(GdkContentProvider * provider)219 gdk_content_provider_union_ref_formats (GdkContentProvider *provider)
220 {
221 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (provider);
222 GdkContentFormatsBuilder *builder;
223 gsize i;
224
225 builder = gdk_content_formats_builder_new ();
226
227 for (i = 0; i < self->n_providers; i++)
228 {
229 GdkContentFormats *formats = gdk_content_provider_ref_formats (self->providers[i]);
230 gdk_content_formats_builder_add_formats (builder, formats);
231 gdk_content_formats_unref (formats);
232 }
233
234 return gdk_content_formats_builder_free_to_formats (builder);
235 }
236
237 static GdkContentFormats *
gdk_content_provider_union_ref_storable_formats(GdkContentProvider * provider)238 gdk_content_provider_union_ref_storable_formats (GdkContentProvider *provider)
239 {
240 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (provider);
241 GdkContentFormatsBuilder *builder;
242 gsize i;
243
244 builder = gdk_content_formats_builder_new ();
245
246 for (i = 0; i < self->n_providers; i++)
247 {
248 GdkContentFormats *formats = gdk_content_provider_ref_storable_formats (self->providers[i]);
249 gdk_content_formats_builder_add_formats (builder, formats);
250 gdk_content_formats_unref (formats);
251 }
252
253 return gdk_content_formats_builder_free_to_formats (builder);
254 }
255
256 static void
gdk_content_provider_union_write_mime_type_done(GObject * source_object,GAsyncResult * res,gpointer data)257 gdk_content_provider_union_write_mime_type_done (GObject *source_object,
258 GAsyncResult *res,
259 gpointer data)
260 {
261 GTask *task = data;
262 GError *error = NULL;
263
264 if (!gdk_content_provider_write_mime_type_finish (GDK_CONTENT_PROVIDER (source_object), res, &error))
265 {
266 g_task_return_error (task, error);
267 }
268 else
269 {
270 g_task_return_boolean (task, TRUE);
271 }
272
273 g_object_unref (task);
274 }
275
276 static void
gdk_content_provider_union_write_mime_type_async(GdkContentProvider * provider,const char * mime_type,GOutputStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)277 gdk_content_provider_union_write_mime_type_async (GdkContentProvider *provider,
278 const char *mime_type,
279 GOutputStream *stream,
280 int io_priority,
281 GCancellable *cancellable,
282 GAsyncReadyCallback callback,
283 gpointer user_data)
284 {
285 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (provider);
286 GTask *task;
287 gsize i;
288
289 task = g_task_new (self, cancellable, callback, user_data);
290 g_task_set_priority (task, io_priority);
291 g_task_set_source_tag (task, gdk_content_provider_union_write_mime_type_async);
292
293 for (i = 0; i < self->n_providers; i++)
294 {
295 GdkContentFormats *formats = gdk_content_provider_ref_formats (self->providers[i]);
296
297 if (gdk_content_formats_contain_mime_type (formats, mime_type))
298 {
299 gdk_content_provider_write_mime_type_async (self->providers[i],
300 mime_type,
301 stream,
302 io_priority,
303 cancellable,
304 gdk_content_provider_union_write_mime_type_done,
305 task);
306 gdk_content_formats_unref (formats);
307 return;
308 }
309 gdk_content_formats_unref (formats);
310 }
311
312 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
313 _("Cannot provide contents as “%s”"), mime_type);
314 g_object_unref (task);
315 }
316
317 static gboolean
gdk_content_provider_union_write_mime_type_finish(GdkContentProvider * provider,GAsyncResult * result,GError ** error)318 gdk_content_provider_union_write_mime_type_finish (GdkContentProvider *provider,
319 GAsyncResult *result,
320 GError **error)
321 {
322 g_return_val_if_fail (g_task_is_valid (result, provider), FALSE);
323 g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_content_provider_union_write_mime_type_async, FALSE);
324
325 return g_task_propagate_boolean (G_TASK (result), error);
326 }
327
328 static gboolean
gdk_content_provider_union_get_value(GdkContentProvider * provider,GValue * value,GError ** error)329 gdk_content_provider_union_get_value (GdkContentProvider *provider,
330 GValue *value,
331 GError **error)
332 {
333 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (provider);
334 gsize i;
335
336 for (i = 0; i < self->n_providers; i++)
337 {
338 GError *provider_error = NULL;
339
340 if (gdk_content_provider_get_value (self->providers[i], value, &provider_error))
341 return TRUE;
342
343 if (!g_error_matches (provider_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
344 {
345 g_propagate_error (error, provider_error);
346 return FALSE;
347 }
348
349 g_clear_error (&provider_error);
350 }
351
352 return GDK_CONTENT_PROVIDER_CLASS (gdk_content_provider_union_parent_class)->get_value (provider, value, error);
353 }
354
355 static void
gdk_content_provider_union_finalize(GObject * object)356 gdk_content_provider_union_finalize (GObject *object)
357 {
358 GdkContentProviderUnion *self = GDK_CONTENT_PROVIDER_UNION (object);
359 gsize i;
360
361 for (i = 0; i < self->n_providers; i++)
362 {
363 g_signal_handlers_disconnect_by_func (self->providers[i], gdk_content_provider_content_changed, self);
364 g_object_unref (self->providers[i]);
365 }
366
367 g_free (self->providers);
368
369 G_OBJECT_CLASS (gdk_content_provider_union_parent_class)->finalize (object);
370 }
371
372 static void
gdk_content_provider_union_class_init(GdkContentProviderUnionClass * class)373 gdk_content_provider_union_class_init (GdkContentProviderUnionClass *class)
374 {
375 GObjectClass *object_class = G_OBJECT_CLASS (class);
376 GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
377
378 object_class->finalize = gdk_content_provider_union_finalize;
379
380 provider_class->attach_clipboard = gdk_content_provider_union_attach_clipboard;
381 provider_class->detach_clipboard = gdk_content_provider_union_detach_clipboard;
382 provider_class->ref_formats = gdk_content_provider_union_ref_formats;
383 provider_class->ref_storable_formats = gdk_content_provider_union_ref_storable_formats;
384 provider_class->write_mime_type_async = gdk_content_provider_union_write_mime_type_async;
385 provider_class->write_mime_type_finish = gdk_content_provider_union_write_mime_type_finish;
386 provider_class->get_value = gdk_content_provider_union_get_value;
387 }
388
389 static void
gdk_content_provider_union_init(GdkContentProviderUnion * self)390 gdk_content_provider_union_init (GdkContentProviderUnion *self)
391 {
392 }
393
394 /**
395 * gdk_content_provider_new_union:
396 * @providers: (nullable) (array length=n_providers) (transfer full):
397 * The `GdkContentProvider`s to present the union of
398 * @n_providers: the number of providers
399 *
400 * Creates a content provider that represents all the given @providers.
401 *
402 * Whenever data needs to be written, the union provider will try the given
403 * @providers in the given order and the first one supporting a format will
404 * be chosen to provide it.
405 *
406 * This allows an easy way to support providing data in different formats.
407 * For example, an image may be provided by its file and by the image
408 * contents with a call such as
409 * ```c
410 * gdk_content_provider_new_union ((GdkContentProvider *[2]) {
411 * gdk_content_provider_new_typed (G_TYPE_FILE, file),
412 * gdk_content_provider_new_typed (G_TYPE_TEXTURE, texture)
413 * }, 2);
414 * ```
415 *
416 * Returns: a new `GdkContentProvider`
417 */
418 GdkContentProvider *
gdk_content_provider_new_union(GdkContentProvider ** providers,gsize n_providers)419 gdk_content_provider_new_union (GdkContentProvider **providers,
420 gsize n_providers)
421 {
422 GdkContentProviderUnion *result;
423 gsize i;
424
425 g_return_val_if_fail (providers != NULL || n_providers == 0, NULL);
426
427 result = g_object_new (GDK_TYPE_CONTENT_PROVIDER_UNION, NULL);
428
429 result->n_providers = n_providers;
430 result->providers = g_memdup2 (providers, sizeof (GdkContentProvider *) * n_providers);
431
432 for (i = 0; i < n_providers; i++)
433 {
434 g_signal_connect_swapped (result->providers[i],
435 "content-changed",
436 G_CALLBACK (gdk_content_provider_content_changed),
437 result);
438 }
439
440 return GDK_CONTENT_PROVIDER (result);
441 }
442
443 #define GDK_TYPE_CONTENT_PROVIDER_BYTES (gdk_content_provider_bytes_get_type ())
444 #define GDK_CONTENT_PROVIDER_BYTES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_BYTES, GdkContentProviderBytes))
445 #define GDK_IS_CONTENT_PROVIDER_BYTES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CONTENT_PROVIDER_BYTES))
446 #define GDK_CONTENT_PROVIDER_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CONTENT_PROVIDER_BYTES, GdkContentProviderBytesClass))
447 #define GDK_IS_CONTENT_PROVIDER_BYTES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CONTENT_PROVIDER_BYTES))
448 #define GDK_CONTENT_PROVIDER_BYTES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CONTENT_PROVIDER_BYTES, GdkContentProviderBytesClass))
449
450 typedef struct _GdkContentProviderBytes GdkContentProviderBytes;
451 typedef struct _GdkContentProviderBytesClass GdkContentProviderBytesClass;
452
453 struct _GdkContentProviderBytes
454 {
455 GdkContentProvider parent;
456
457 /* interned */const char *mime_type;
458 GBytes *bytes;
459 };
460
461 struct _GdkContentProviderBytesClass
462 {
463 GdkContentProviderClass parent_class;
464 };
465
466 GType gdk_content_provider_bytes_get_type (void) G_GNUC_CONST;
467
G_DEFINE_TYPE(GdkContentProviderBytes,gdk_content_provider_bytes,GDK_TYPE_CONTENT_PROVIDER)468 G_DEFINE_TYPE (GdkContentProviderBytes, gdk_content_provider_bytes, GDK_TYPE_CONTENT_PROVIDER)
469
470 static void
471 gdk_content_provider_bytes_finalize (GObject *object)
472 {
473 GdkContentProviderBytes *content = GDK_CONTENT_PROVIDER_BYTES (object);
474
475 g_bytes_unref (content->bytes);
476
477 G_OBJECT_CLASS (gdk_content_provider_bytes_parent_class)->finalize (object);
478 }
479
480 static GdkContentFormats *
gdk_content_provider_bytes_ref_formats(GdkContentProvider * provider)481 gdk_content_provider_bytes_ref_formats (GdkContentProvider *provider)
482 {
483 GdkContentProviderBytes *content = GDK_CONTENT_PROVIDER_BYTES (provider);
484 GdkContentFormatsBuilder *builder;
485
486 builder = gdk_content_formats_builder_new ();
487 gdk_content_formats_builder_add_mime_type (builder, content->mime_type);
488 return gdk_content_formats_builder_free_to_formats (builder);
489 }
490
491 static void
gdk_content_provider_bytes_write_mime_type_done(GObject * stream,GAsyncResult * result,gpointer task)492 gdk_content_provider_bytes_write_mime_type_done (GObject *stream,
493 GAsyncResult *result,
494 gpointer task)
495 {
496 GError *error = NULL;
497
498 if (!g_output_stream_write_all_finish (G_OUTPUT_STREAM (stream),
499 result,
500 NULL,
501 &error))
502 {
503 g_task_return_error (task, error);
504 }
505 else
506 {
507 g_task_return_boolean (task, TRUE);
508 }
509
510 g_object_unref (task);
511 }
512
513 static void
gdk_content_provider_bytes_write_mime_type_async(GdkContentProvider * provider,const char * mime_type,GOutputStream * stream,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)514 gdk_content_provider_bytes_write_mime_type_async (GdkContentProvider *provider,
515 const char *mime_type,
516 GOutputStream *stream,
517 int io_priority,
518 GCancellable *cancellable,
519 GAsyncReadyCallback callback,
520 gpointer user_data)
521 {
522 GdkContentProviderBytes *content = GDK_CONTENT_PROVIDER_BYTES (provider);
523 GTask *task;
524
525 task = g_task_new (content, cancellable, callback, user_data);
526 g_task_set_priority (task, io_priority);
527 g_task_set_source_tag (task, gdk_content_provider_bytes_write_mime_type_async);
528
529 if (mime_type != content->mime_type)
530 {
531 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
532 _("Cannot provide contents as “%s”"), mime_type);
533 g_object_unref (task);
534 return;
535 }
536
537 g_output_stream_write_all_async (stream,
538 g_bytes_get_data (content->bytes, NULL),
539 g_bytes_get_size (content->bytes),
540 io_priority,
541 cancellable,
542 gdk_content_provider_bytes_write_mime_type_done,
543 task);
544 }
545
546 static gboolean
gdk_content_provider_bytes_write_mime_type_finish(GdkContentProvider * provider,GAsyncResult * result,GError ** error)547 gdk_content_provider_bytes_write_mime_type_finish (GdkContentProvider *provider,
548 GAsyncResult *result,
549 GError **error)
550 {
551 g_return_val_if_fail (g_task_is_valid (result, provider), FALSE);
552 g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gdk_content_provider_bytes_write_mime_type_async, FALSE);
553
554 return g_task_propagate_boolean (G_TASK (result), error);
555 }
556
557 static void
gdk_content_provider_bytes_class_init(GdkContentProviderBytesClass * class)558 gdk_content_provider_bytes_class_init (GdkContentProviderBytesClass *class)
559 {
560 GObjectClass *object_class = G_OBJECT_CLASS (class);
561 GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class);
562
563 object_class->finalize = gdk_content_provider_bytes_finalize;
564
565 provider_class->ref_formats = gdk_content_provider_bytes_ref_formats;
566 provider_class->write_mime_type_async = gdk_content_provider_bytes_write_mime_type_async;
567 provider_class->write_mime_type_finish = gdk_content_provider_bytes_write_mime_type_finish;
568 }
569
570 static void
gdk_content_provider_bytes_init(GdkContentProviderBytes * content)571 gdk_content_provider_bytes_init (GdkContentProviderBytes *content)
572 {
573 }
574
575 /**
576 * gdk_content_provider_new_for_bytes:
577 * @mime_type: the mime type
578 * @bytes: (transfer none): a `GBytes` with the data for @mime_type
579 *
580 * Create a content provider that provides the given @bytes as data for
581 * the given @mime_type.
582 *
583 * Returns: a new `GdkContentProvider`
584 */
585 GdkContentProvider *
gdk_content_provider_new_for_bytes(const char * mime_type,GBytes * bytes)586 gdk_content_provider_new_for_bytes (const char *mime_type,
587 GBytes *bytes)
588 {
589 GdkContentProviderBytes *content;
590
591 g_return_val_if_fail (mime_type != NULL, NULL);
592 g_return_val_if_fail (bytes != NULL, NULL);
593
594 content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_BYTES, NULL);
595 content->mime_type = g_intern_string (mime_type);
596 content->bytes = g_bytes_ref (bytes);
597
598 return GDK_CONTENT_PROVIDER (content);
599 }
600
601