Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-clipboard"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <gio/gio.h>
9 : : #include <libpeas.h>
10 : : #include <libvalent-core.h>
11 : :
12 : : #include "valent-clipboard-adapter.h"
13 : :
14 : : #include "valent-clipboard.h"
15 : :
16 : : /**
17 : : * ValentClipboard:
18 : : *
19 : : * A class for reading and writing the desktop clipboard.
20 : : *
21 : : * `ValentClipboard` is an abstraction of clipboard selections, intended for use
22 : : * by [class@Valent.DevicePlugin] implementations.
23 : : *
24 : : * Plugins can implement [class@Valent.ClipboardAdapter] to provide an interface
25 : : * to access a clipboard selection.
26 : : *
27 : : * Since: 1.0
28 : : */
29 : :
30 : : struct _ValentClipboard
31 : : {
32 : : ValentComponent parent_instance;
33 : :
34 : : ValentClipboardAdapter *default_adapter;
35 : : };
36 : :
37 [ + + + - ]: 242 : G_DEFINE_FINAL_TYPE (ValentClipboard, valent_clipboard, VALENT_TYPE_COMPONENT)
38 : :
39 : : enum {
40 : : CHANGED,
41 : : N_SIGNALS
42 : : };
43 : :
44 : : static guint signals[N_SIGNALS] = { 0, };
45 : :
46 : : static ValentClipboard *default_clipboard = NULL;
47 : :
48 : : static const char * const text_mimetypes[] = {
49 : : "text/plain;charset=utf-8",
50 : : "text/plain",
51 : : "UTF8_STRING",
52 : : "STRING",
53 : : "TEXT",
54 : : "COMPOUND_TEXT",
55 : : };
56 : :
57 : :
58 : : static void
59 : 2 : valent_clipboard_adapter_read_bytes_cb (ValentClipboardAdapter *adapter,
60 : : GAsyncResult *result,
61 : : gpointer user_data)
62 : : {
63 : 2 : g_autoptr (GTask) task = G_TASK (user_data);
64 [ - - + - ]: 2 : g_autoptr (GBytes) bytes = NULL;
65 [ - - + - ]: 2 : g_autoptr (GError) error = NULL;
66 : :
67 [ + - ]: 2 : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
68 [ - + ]: 2 : g_assert (g_task_is_valid (result, adapter));
69 : :
70 : 2 : bytes = valent_clipboard_adapter_read_bytes_finish (adapter, result, &error);
71 : :
72 [ - + ]: 2 : if (bytes == NULL)
73 [ # # ]: 0 : return g_task_return_error (task, g_steal_pointer (&error));
74 : :
75 [ - + ]: 2 : g_task_return_pointer (task,
76 : : g_steal_pointer (&bytes),
77 : : (GDestroyNotify)g_bytes_unref);
78 : : }
79 : :
80 : : static void
81 : 10 : valent_clipboard_adapter_write_bytes_cb (ValentClipboardAdapter *adapter,
82 : : GAsyncResult *result,
83 : : gpointer user_data)
84 : : {
85 : 10 : g_autoptr (GTask) task = G_TASK (user_data);
86 [ - - + - ]: 10 : g_autoptr (GError) error = NULL;
87 : :
88 [ + - ]: 10 : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
89 [ - + ]: 10 : g_assert (g_task_is_valid (result, adapter));
90 : :
91 [ - + ]: 10 : if (!valent_clipboard_adapter_write_bytes_finish (adapter, result, &error))
92 [ # # ]: 0 : return g_task_return_error (task, g_steal_pointer (&error));
93 : :
94 [ - + ]: 10 : g_task_return_boolean (task, TRUE);
95 : : }
96 : :
97 : : static void
98 : 15 : valent_clipboard_adapter_read_text_cb (ValentClipboardAdapter *adapter,
99 : : GAsyncResult *result,
100 : : gpointer user_data)
101 : : {
102 : 15 : g_autoptr (GTask) task = G_TASK (user_data);
103 [ - - + - ]: 15 : g_autoptr (GError) error = NULL;
104 [ - - - + ]: 15 : g_autoptr (GBytes) bytes = NULL;
105 : 15 : const char *data = NULL;
106 : 15 : size_t size;
107 : :
108 [ + - ]: 15 : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
109 [ - + ]: 15 : g_assert (g_task_is_valid (result, adapter));
110 : :
111 : 15 : bytes = valent_clipboard_adapter_read_bytes_finish (adapter, result, &error);
112 : :
113 [ - + ]: 15 : if (bytes == NULL)
114 [ # # ]: 0 : return g_task_return_error (task, g_steal_pointer (&error));
115 : :
116 : 15 : data = g_bytes_get_data (bytes, &size);
117 : :
118 [ + - + - ]: 15 : if (size > 0 && data[size - 1] == '\0')
119 [ - + ]: 30 : g_task_return_pointer (task, g_strdup (data), g_free);
120 : : else
121 : 0 : g_task_return_pointer (task, g_strndup (data, size), g_free);
122 : : }
123 : :
124 : : static void
125 : 14 : on_clipboard_adapter_changed (ValentClipboardAdapter *clipboard,
126 : : ValentClipboard *self)
127 : : {
128 : 14 : VALENT_ENTRY;
129 : :
130 [ + - ]: 14 : if (self->default_adapter == clipboard)
131 : 14 : g_signal_emit (G_OBJECT (self), signals [CHANGED], 0);
132 : :
133 : 14 : VALENT_EXIT;
134 : : }
135 : :
136 : : /*
137 : : * ValentComponent
138 : : */
139 : : static void
140 : 10 : valent_clipboard_bind_preferred (ValentComponent *component,
141 : : ValentExtension *extension)
142 : : {
143 : 10 : ValentClipboard *self = VALENT_CLIPBOARD (component);
144 : 10 : ValentClipboardAdapter *adapter = VALENT_CLIPBOARD_ADAPTER (extension);
145 : :
146 : 10 : VALENT_ENTRY;
147 : :
148 [ + - ]: 10 : g_assert (VALENT_IS_CLIPBOARD (self));
149 [ + + - + ]: 10 : g_assert (adapter == NULL || VALENT_IS_CLIPBOARD_ADAPTER (adapter));
150 : :
151 [ + + ]: 10 : if (self->default_adapter != NULL)
152 : : {
153 : 5 : g_signal_handlers_disconnect_by_func (self->default_adapter,
154 : : self,
155 : : on_clipboard_adapter_changed);
156 : 5 : self->default_adapter = NULL;
157 : : }
158 : :
159 [ + + ]: 10 : if (adapter != NULL)
160 : : {
161 : 7 : self->default_adapter = adapter;
162 : 7 : g_signal_connect_object (self->default_adapter,
163 : : "changed",
164 : : G_CALLBACK (on_clipboard_adapter_changed),
165 : : self,
166 : : G_CONNECT_DEFAULT);
167 : : }
168 : :
169 : 10 : VALENT_EXIT;
170 : : }
171 : :
172 : : /*
173 : : * GObject
174 : : */
175 : : static void
176 : 5 : valent_clipboard_class_init (ValentClipboardClass *klass)
177 : : {
178 : 5 : ValentComponentClass *component_class = VALENT_COMPONENT_CLASS (klass);
179 : :
180 : 5 : component_class->bind_preferred = valent_clipboard_bind_preferred;
181 : :
182 : : /**
183 : : * ValentClipboard::changed:
184 : : * @clipboard: a `ValentClipboard`
185 : : *
186 : : * Emitted when the content of the primary [class@Valent.ClipboardAdapter]
187 : : * changes.
188 : : *
189 : : * Since: 1.0
190 : : */
191 : 10 : signals [CHANGED] =
192 : 5 : g_signal_new ("changed",
193 : : G_TYPE_FROM_CLASS (klass),
194 : : G_SIGNAL_RUN_FIRST,
195 : : 0,
196 : : NULL, NULL, NULL,
197 : : G_TYPE_NONE, 0);
198 : 5 : }
199 : :
200 : : static void
201 : 5 : valent_clipboard_init (ValentClipboard *self)
202 : : {
203 : 5 : }
204 : :
205 : : /**
206 : : * valent_clipboard_get_default:
207 : : *
208 : : * Get the default [class@Valent.Clipboard].
209 : : *
210 : : * Returns: (transfer none) (not nullable): a `ValentClipboard`
211 : : *
212 : : * Since: 1.0
213 : : */
214 : : ValentClipboard *
215 : 19 : valent_clipboard_get_default (void)
216 : : {
217 [ + + ]: 19 : if (default_clipboard == NULL)
218 : : {
219 : 5 : default_clipboard = g_object_new (VALENT_TYPE_CLIPBOARD,
220 : : "plugin-domain", "clipboard",
221 : : "plugin-type", VALENT_TYPE_CLIPBOARD_ADAPTER,
222 : : NULL);
223 : :
224 : 5 : g_object_add_weak_pointer (G_OBJECT (default_clipboard),
225 : : (gpointer)&default_clipboard);
226 : : }
227 : :
228 : 19 : return default_clipboard;
229 : : }
230 : :
231 : : /**
232 : : * valent_clipboard_get_mimetypes:
233 : : * @clipboard: a `ValentClipboard`
234 : : *
235 : : * Get the mime-types of the primary clipboard content.
236 : : *
237 : : * Returns: (transfer full) (nullable) (array zero-terminated=1): a list of
238 : : * mime-types
239 : : *
240 : : * Since: 1.0
241 : : */
242 : : GStrv
243 : 4 : valent_clipboard_get_mimetypes (ValentClipboard *clipboard)
244 : : {
245 : 4 : GStrv ret = NULL;
246 : :
247 : 4 : VALENT_ENTRY;
248 : :
249 [ + - ]: 4 : g_return_val_if_fail (VALENT_IS_CLIPBOARD (clipboard), NULL);
250 : :
251 [ - + ]: 4 : if G_LIKELY (clipboard->default_adapter != NULL)
252 : 4 : ret = valent_clipboard_adapter_get_mimetypes (clipboard->default_adapter);
253 : :
254 : 4 : VALENT_RETURN (g_steal_pointer (&ret));
255 : : }
256 : :
257 : : /**
258 : : * valent_clipboard_get_timestamp:
259 : : * @clipboard: a `ValentClipboard`
260 : : *
261 : : * Get the timestamp of the current clipboard content, in milliseconds since the
262 : : * UNIX epoch.
263 : : *
264 : : * Returns: a UNIX epoch timestamp (ms)
265 : : *
266 : : * Since: 1.0
267 : : */
268 : : int64_t
269 : 15 : valent_clipboard_get_timestamp (ValentClipboard *clipboard)
270 : : {
271 : 15 : int64_t ret = 0;
272 : :
273 : 15 : VALENT_ENTRY;
274 : :
275 [ + - ]: 15 : g_return_val_if_fail (VALENT_IS_CLIPBOARD (clipboard), 0);
276 : :
277 [ - + ]: 15 : if G_LIKELY (clipboard->default_adapter != NULL)
278 : 15 : ret = valent_clipboard_adapter_get_timestamp (clipboard->default_adapter);
279 : :
280 : 15 : VALENT_RETURN (ret);
281 : : }
282 : :
283 : : /**
284 : : * valent_clipboard_read_bytes:
285 : : * @clipboard: a `ValentClipboard`
286 : : * @mimetype: a mime-type
287 : : * @cancellable: (nullable): a `GCancellable`
288 : : * @callback: (scope async): a `GAsyncReadyCallback`
289 : : * @user_data: user supplied data
290 : : *
291 : : * Get the content of the primary clipboard adapter.
292 : : *
293 : : * Call [method@Valent.Clipboard.read_bytes_finish] to get the result.
294 : : *
295 : : * Since: 1.0
296 : : */
297 : : void
298 : 2 : valent_clipboard_read_bytes (ValentClipboard *clipboard,
299 : : const char *mimetype,
300 : : GCancellable *cancellable,
301 : : GAsyncReadyCallback callback,
302 : : gpointer user_data)
303 : : {
304 : 4 : g_autoptr (GTask) task = NULL;
305 : :
306 : 2 : VALENT_ENTRY;
307 : :
308 [ + - ]: 2 : g_return_if_fail (VALENT_IS_CLIPBOARD (clipboard));
309 [ + - - + ]: 2 : g_return_if_fail (mimetype != NULL && *mimetype != '\0');
310 [ - + - - : 2 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
311 : :
312 [ + - ]: 2 : if G_UNLIKELY (clipboard->default_adapter == NULL)
313 : : {
314 : 0 : g_task_report_new_error (clipboard, callback, user_data,
315 : : valent_clipboard_read_bytes,
316 : : G_IO_ERROR,
317 : : G_IO_ERROR_NOT_SUPPORTED,
318 : : "No clipboard adapter available");
319 : 0 : return;
320 : : }
321 : :
322 : 2 : task = g_task_new (clipboard, cancellable, callback, user_data);
323 [ + - ]: 2 : g_task_set_source_tag (task, valent_clipboard_read_bytes);
324 : 2 : valent_clipboard_adapter_read_bytes (clipboard->default_adapter,
325 : : mimetype,
326 : : cancellable,
327 : : (GAsyncReadyCallback)valent_clipboard_adapter_read_bytes_cb,
328 : : g_steal_pointer (&task));
329 : :
330 : 2 : VALENT_EXIT;
331 : : }
332 : :
333 : : /**
334 : : * valent_clipboard_read_bytes_finish:
335 : : * @clipboard: a `ValentClipboard`
336 : : * @result: a `GAsyncResult`
337 : : * @error: (nullable): a `GError`
338 : : *
339 : : * Finish an operation started by [method@Valent.Clipboard.read_bytes].
340 : : *
341 : : * Returns: (transfer full) (nullable): the content
342 : : *
343 : : * Since: 1.0
344 : : */
345 : : GBytes *
346 : 2 : valent_clipboard_read_bytes_finish (ValentClipboard *clipboard,
347 : : GAsyncResult *result,
348 : : GError **error)
349 : : {
350 : 2 : GBytes *ret;
351 : :
352 : 2 : VALENT_ENTRY;
353 : :
354 [ + - ]: 2 : g_return_val_if_fail (VALENT_IS_CLIPBOARD (clipboard), NULL);
355 [ - + ]: 2 : g_return_val_if_fail (g_task_is_valid (result, clipboard), NULL);
356 [ + - - + ]: 2 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
357 : :
358 : 2 : ret = g_task_propagate_pointer (G_TASK (result), error);
359 : :
360 : 2 : VALENT_RETURN (g_steal_pointer (&ret));
361 : : }
362 : :
363 : : /**
364 : : * valent_clipboard_write_bytes:
365 : : * @clipboard: a `ValentClipboard`
366 : : * @mimetype: (nullable): a mime-type, or %NULL if @bytes is %NULL
367 : : * @bytes: (nullable): a `GBytes`, or %NULL if @mimetype is %NULL
368 : : * @cancellable: (nullable): a `GCancellable`
369 : : * @callback: (scope async): a `GAsyncReadyCallback`
370 : : * @user_data: user supplied data
371 : : *
372 : : * Set the content of the primary clipboard adapter.
373 : : *
374 : : * Call [method@Valent.Clipboard.write_bytes_finish] to get the result.
375 : : *
376 : : * Since: 1.0
377 : : */
378 : : void
379 : 2 : valent_clipboard_write_bytes (ValentClipboard *clipboard,
380 : : const char *mimetype,
381 : : GBytes *bytes,
382 : : GCancellable *cancellable,
383 : : GAsyncReadyCallback callback,
384 : : gpointer user_data)
385 : : {
386 : 4 : g_autoptr (GTask) task = NULL;
387 : :
388 : 2 : VALENT_ENTRY;
389 : :
390 [ + - ]: 2 : g_return_if_fail (VALENT_IS_CLIPBOARD (clipboard));
391 [ + - + - : 2 : g_return_if_fail (bytes == NULL || (mimetype != NULL && *mimetype != '\0'));
- + ]
392 [ - + - - : 2 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - ]
393 : :
394 [ + - ]: 2 : if G_UNLIKELY (clipboard->default_adapter == NULL)
395 : : {
396 : 0 : g_task_report_new_error (clipboard, callback, user_data,
397 : : valent_clipboard_write_bytes,
398 : : G_IO_ERROR,
399 : : G_IO_ERROR_NOT_SUPPORTED,
400 : : "No clipboard adapter available");
401 : 0 : return;
402 : : }
403 : :
404 : 2 : task = g_task_new (clipboard, cancellable, callback, user_data);
405 [ + - ]: 2 : g_task_set_source_tag (task, valent_clipboard_write_bytes);
406 : 2 : valent_clipboard_adapter_write_bytes (clipboard->default_adapter,
407 : : mimetype,
408 : : bytes,
409 : : cancellable,
410 : : (GAsyncReadyCallback)valent_clipboard_adapter_write_bytes_cb,
411 : : g_steal_pointer (&task));
412 : :
413 : 2 : VALENT_EXIT;
414 : : }
415 : :
416 : : /**
417 : : * valent_clipboard_write_bytes_finish:
418 : : * @clipboard: a `ValentClipboard`
419 : : * @result: a `GAsyncResult`
420 : : * @error: (nullable): a `GError`
421 : : *
422 : : * Finish an operation started by [method@Valent.Clipboard.write_bytes].
423 : : *
424 : : * Returns: %TRUE if successful, or %FALSE with @error set
425 : : *
426 : : * Since: 1.0
427 : : */
428 : : gboolean
429 : 2 : valent_clipboard_write_bytes_finish (ValentClipboard *clipboard,
430 : : GAsyncResult *result,
431 : : GError **error)
432 : : {
433 : 2 : gboolean ret;
434 : :
435 : 2 : VALENT_ENTRY;
436 : :
437 [ + - ]: 2 : g_return_val_if_fail (VALENT_IS_CLIPBOARD (clipboard), FALSE);
438 [ - + ]: 2 : g_return_val_if_fail (g_task_is_valid (result, clipboard), FALSE);
439 [ + - - + ]: 2 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
440 : :
441 : 2 : ret = g_task_propagate_boolean (G_TASK (result), error);
442 : :
443 : 2 : VALENT_RETURN (ret);
444 : : }
445 : :
446 : : /**
447 : : * valent_clipboard_read_text:
448 : : * @clipboard: a `ValentClipboard`
449 : : * @cancellable: (nullable): a `GCancellable`
450 : : * @callback: (scope async): a `GAsyncReadyCallback`
451 : : * @user_data: user supplied data
452 : : *
453 : : * Get the text content of the primary clipboard adapter.
454 : : *
455 : : * Call [method@Valent.Clipboard.read_text_finish] to get the result.
456 : : *
457 : : * Since: 1.0
458 : : */
459 : : void
460 : 15 : valent_clipboard_read_text (ValentClipboard *clipboard,
461 : : GCancellable *cancellable,
462 : : GAsyncReadyCallback callback,
463 : : gpointer user_data)
464 : : {
465 : 30 : g_autoptr (GTask) task = NULL;
466 : 30 : g_auto (GStrv) mimetypes = NULL;
467 : 15 : const char *mimetype = NULL;
468 : :
469 : 15 : VALENT_ENTRY;
470 : :
471 [ + - ]: 15 : g_return_if_fail (VALENT_IS_CLIPBOARD (clipboard));
472 [ + + + - : 15 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
473 : :
474 [ + - ]: 15 : if G_UNLIKELY (clipboard->default_adapter == NULL)
475 : : {
476 : 0 : g_task_report_new_error (clipboard, callback, user_data,
477 : : valent_clipboard_read_text,
478 : : G_IO_ERROR,
479 : : G_IO_ERROR_NOT_SUPPORTED,
480 : : "No clipboard adapter available");
481 : 0 : return;
482 : : }
483 : :
484 : 15 : mimetypes = valent_clipboard_adapter_get_mimetypes (clipboard->default_adapter);
485 : :
486 [ + - ]: 15 : if (mimetypes != NULL)
487 : : {
488 [ + - ]: 15 : for (size_t i = 0; i < G_N_ELEMENTS (text_mimetypes); i++)
489 : : {
490 : 15 : const char *text_mimetype = text_mimetypes[i];
491 : :
492 [ - + ]: 15 : if (g_strv_contains ((const char * const *)mimetypes, text_mimetype))
493 : : {
494 : : mimetype = text_mimetypes[i];
495 : : break;
496 : : }
497 : : }
498 : : }
499 : :
500 [ - + ]: 15 : if (mimetype == NULL)
501 : 0 : return g_task_report_new_error (clipboard, callback, user_data,
502 : : valent_clipboard_read_text,
503 : : G_IO_ERROR,
504 : : G_IO_ERROR_NOT_SUPPORTED,
505 : : "text not available");
506 : :
507 : 15 : task = g_task_new (clipboard, cancellable, callback, user_data);
508 [ + - ]: 15 : g_task_set_source_tag (task, valent_clipboard_read_text);
509 : 15 : valent_clipboard_adapter_read_bytes (clipboard->default_adapter,
510 : : mimetype,
511 : : cancellable,
512 : : (GAsyncReadyCallback)valent_clipboard_adapter_read_text_cb,
513 : : g_steal_pointer (&task));
514 : :
515 [ + - ]: 30 : VALENT_EXIT;
516 : : }
517 : :
518 : : /**
519 : : * valent_clipboard_read_text_finish:
520 : : * @clipboard: a `ValentClipboard`
521 : : * @result: a `GAsyncResult`
522 : : * @error: (nullable): a `GError`
523 : : *
524 : : * Finish an operation started by [method@Valent.Clipboard.read_text].
525 : : *
526 : : * Returns: (transfer full) (nullable): the text content
527 : : *
528 : : * Since: 1.0
529 : : */
530 : : char *
531 : 15 : valent_clipboard_read_text_finish (ValentClipboard *clipboard,
532 : : GAsyncResult *result,
533 : : GError **error)
534 : : {
535 : 15 : char *ret;
536 : :
537 : 15 : VALENT_ENTRY;
538 : :
539 [ + - ]: 15 : g_return_val_if_fail (VALENT_IS_CLIPBOARD (clipboard), NULL);
540 [ - + ]: 15 : g_return_val_if_fail (g_task_is_valid (result, clipboard), NULL);
541 [ + - - + ]: 15 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
542 : :
543 : 15 : ret = g_task_propagate_pointer (G_TASK (result), error);
544 : :
545 : 15 : VALENT_RETURN (g_steal_pointer (&ret));
546 : : }
547 : :
548 : : /**
549 : : * valent_clipboard_write_text:
550 : : * @clipboard: a `ValentClipboard`
551 : : * @text: text content
552 : : * @cancellable: (nullable): a `GCancellable`
553 : : * @callback: (scope async): a `GAsyncReadyCallback`
554 : : * @user_data: user supplied data
555 : : *
556 : : * Set the text content of the primary clipboard adapter.
557 : : *
558 : : * Call [method@Valent.Clipboard.write_text_finish] to get the result.
559 : : *
560 : : * Since: 1.0
561 : : */
562 : : void
563 : 8 : valent_clipboard_write_text (ValentClipboard *clipboard,
564 : : const char *text,
565 : : GCancellable *cancellable,
566 : : GAsyncReadyCallback callback,
567 : : gpointer user_data)
568 : : {
569 : 16 : g_autoptr (GTask) task = NULL;
570 : 16 : g_autoptr (GBytes) bytes = NULL;
571 : :
572 : 8 : VALENT_ENTRY;
573 : :
574 [ + - ]: 8 : g_return_if_fail (VALENT_IS_CLIPBOARD (clipboard));
575 [ + + + - : 8 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
576 [ - + ]: 8 : g_return_if_fail (text != NULL);
577 : :
578 [ + - ]: 8 : if G_UNLIKELY (clipboard->default_adapter == NULL)
579 : : {
580 : 0 : g_task_report_new_error (clipboard, callback, user_data,
581 : : valent_clipboard_write_text,
582 : : G_IO_ERROR,
583 : : G_IO_ERROR_NOT_SUPPORTED,
584 : : "No clipboard adapter available");
585 : 0 : return;
586 : : }
587 : :
588 : 8 : task = g_task_new (clipboard, cancellable, callback, user_data);
589 [ + - ]: 8 : g_task_set_source_tag (task, valent_clipboard_write_text);
590 : :
591 : 8 : bytes = g_bytes_new (text, strlen (text) + 1);
592 : 8 : valent_clipboard_adapter_write_bytes (clipboard->default_adapter,
593 : : "text/plain;charset=utf-8",
594 : : bytes,
595 : : cancellable,
596 : : (GAsyncReadyCallback)valent_clipboard_adapter_write_bytes_cb,
597 : : g_steal_pointer (&task));
598 : :
599 [ + - ]: 8 : VALENT_EXIT;
600 : : }
601 : :
602 : : /**
603 : : * valent_clipboard_write_text_finish:
604 : : * @clipboard: a `ValentClipboard`
605 : : * @result: a `GAsyncResult`
606 : : * @error: (nullable): a `GError`
607 : : *
608 : : * Finish an operation started by [method@Valent.Clipboard.write_text].
609 : : *
610 : : * Returns: %TRUE if successful, or %FALSE with @error set
611 : : *
612 : : * Since: 1.0
613 : : */
614 : : gboolean
615 : 6 : valent_clipboard_write_text_finish (ValentClipboard *clipboard,
616 : : GAsyncResult *result,
617 : : GError **error)
618 : : {
619 : 6 : gboolean ret;
620 : :
621 : 6 : VALENT_ENTRY;
622 : :
623 [ + - ]: 6 : g_return_val_if_fail (VALENT_IS_CLIPBOARD (clipboard), FALSE);
624 [ - + ]: 6 : g_return_val_if_fail (g_task_is_valid (result, clipboard), FALSE);
625 [ + - - + ]: 6 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
626 : :
627 : 6 : ret = g_task_propagate_boolean (G_TASK (result), error);
628 : :
629 : 6 : VALENT_RETURN (ret);
630 : : }
631 : :
|