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-adapter"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <gio/gio.h>
9 : : #include <libvalent-core.h>
10 : :
11 : : #include "valent-clipboard-adapter.h"
12 : :
13 : :
14 : : /**
15 : : * ValentClipboardAdapter:
16 : : *
17 : : * An abstract base class for clipboard selections.
18 : : *
19 : : * `ValentClipboardAdapter` is a base class for plugins that provide an interface
20 : : * to the desktop clipboard. This usually means reading and writing content,
21 : : * including notification of content changes.
22 : : *
23 : : * ## `.plugin` File
24 : : *
25 : : * Implementations may define the following extra fields in the `.plugin` file:
26 : : *
27 : : * - `X-ClipboardAdapterPriority`
28 : : *
29 : : * An integer indicating the adapter priority. The implementation with the
30 : : * lowest value will be used as the primary adapter.
31 : : *
32 : : * Since: 1.0
33 : : */
34 : :
35 : : typedef struct
36 : : {
37 : : int64_t timestamp;
38 : : } ValentClipboardAdapterPrivate;
39 : :
40 [ + + + - ]: 584 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ValentClipboardAdapter, valent_clipboard_adapter, VALENT_TYPE_EXTENSION)
41 : :
42 : : /**
43 : : * ValentClipboardAdapterClass:
44 : : * @changed: class closure for `ValentClipboardAdapter`::changed signal
45 : : * @get_mimetypes: the virtual function pointer for valent_clipboard_adapter_get_mimetypes()
46 : : * @get_timestamp: the virtual function pointer for valent_clipboard_adapter_get_timestamp()
47 : : * @read_bytes: the virtual function pointer for valent_clipboard_adapter_read_bytes()
48 : : * @read_bytes_finish: the virtual function pointer for valent_clipboard_adapter_read_bytes_finish()
49 : : * @write_bytes: the virtual function pointer for valent_clipboard_adapter_write_bytes()
50 : : * @write_bytes_finish: the virtual function pointer for valent_clipboard_adapter_write_bytes_finish()
51 : : *
52 : : * The virtual function table for `ValentClipboardAdapter`.
53 : : */
54 : :
55 : : enum {
56 : : CHANGED,
57 : : N_SIGNALS
58 : : };
59 : :
60 : : static guint signals[N_SIGNALS] = { 0, };
61 : :
62 : :
63 : : /* LCOV_EXCL_START */
64 : : static GStrv
65 : : valent_clipboard_adapter_real_get_mimetypes (ValentClipboardAdapter *adapter)
66 : : {
67 : : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
68 : :
69 : : g_warning ("%s does not implement get_mimetypes",
70 : : G_OBJECT_TYPE_NAME (adapter));
71 : :
72 : : return NULL;
73 : : }
74 : :
75 : : static int64_t
76 : : valent_clipboard_adapter_real_get_timestamp (ValentClipboardAdapter *adapter)
77 : : {
78 : : ValentClipboardAdapterPrivate *priv = valent_clipboard_adapter_get_instance_private (adapter);
79 : :
80 : : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
81 : :
82 : : return priv->timestamp;
83 : : }
84 : :
85 : : static void
86 : : valent_clipboard_adapter_real_read_bytes (ValentClipboardAdapter *adapter,
87 : : const char *mimetype,
88 : : GCancellable *cancellable,
89 : : GAsyncReadyCallback callback,
90 : : gpointer user_data)
91 : : {
92 : : g_task_report_new_error (adapter, callback, user_data,
93 : : valent_clipboard_adapter_real_read_bytes,
94 : : G_IO_ERROR,
95 : : G_IO_ERROR_NOT_SUPPORTED,
96 : : "%s does not implement read_bytes",
97 : : G_OBJECT_TYPE_NAME (adapter));
98 : : }
99 : :
100 : : GBytes *
101 : : valent_clipboard_adapter_real_read_bytes_finish (ValentClipboardAdapter *adapter,
102 : : GAsyncResult *result,
103 : : GError **error)
104 : : {
105 : : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
106 : : g_assert (g_task_is_valid (result, adapter));
107 : : g_assert (error == NULL || *error == NULL);
108 : :
109 : : return g_task_propagate_pointer (G_TASK (result), error);
110 : : }
111 : :
112 : : static void
113 : : valent_clipboard_adapter_real_write_bytes (ValentClipboardAdapter *adapter,
114 : : const char *mimetype,
115 : : GBytes *bytes,
116 : : GCancellable *cancellable,
117 : : GAsyncReadyCallback callback,
118 : : gpointer user_data)
119 : : {
120 : : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
121 : : g_assert (bytes == NULL || (mimetype != NULL && *mimetype != '\0'));
122 : : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
123 : :
124 : : g_task_report_new_error (adapter, callback, user_data,
125 : : valent_clipboard_adapter_real_write_bytes,
126 : : G_IO_ERROR,
127 : : G_IO_ERROR_NOT_SUPPORTED,
128 : : "%s does not implement write_bytes",
129 : : G_OBJECT_TYPE_NAME (adapter));
130 : : }
131 : :
132 : : static gboolean
133 : : valent_clipboard_adapter_real_write_bytes_finish (ValentClipboardAdapter *adapter,
134 : : GAsyncResult *result,
135 : : GError **error)
136 : : {
137 : : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
138 : : g_assert (g_task_is_valid (result, adapter));
139 : : g_assert (error == NULL || *error == NULL);
140 : :
141 : : return g_task_propagate_boolean (G_TASK (result), error);
142 : : }
143 : :
144 : : static void
145 : : valent_clipboard_adapter_real_changed (ValentClipboardAdapter *adapter)
146 : : {
147 : : ValentClipboardAdapterPrivate *priv = valent_clipboard_adapter_get_instance_private (adapter);
148 : :
149 : : g_assert (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
150 : :
151 : : priv->timestamp = valent_timestamp_ms ();
152 : : }
153 : : /* LCOV_EXCL_STOP */
154 : :
155 : : /*
156 : : * GObject
157 : : */
158 : : static void
159 : 66 : valent_clipboard_adapter_class_init (ValentClipboardAdapterClass *klass)
160 : : {
161 : 66 : klass->changed = valent_clipboard_adapter_real_changed;
162 : 66 : klass->get_mimetypes = valent_clipboard_adapter_real_get_mimetypes;
163 : 66 : klass->get_timestamp = valent_clipboard_adapter_real_get_timestamp;
164 : 66 : klass->read_bytes = valent_clipboard_adapter_real_read_bytes;
165 : 66 : klass->read_bytes_finish = valent_clipboard_adapter_real_read_bytes_finish;
166 : 66 : klass->write_bytes = valent_clipboard_adapter_real_write_bytes;
167 : 66 : klass->write_bytes_finish = valent_clipboard_adapter_real_write_bytes_finish;
168 : :
169 : : /**
170 : : * ValentClipboardAdapter::changed:
171 : : * @adapter: a `ValentClipboardAdapter`
172 : : *
173 : : * Emitted when the content of @adapter changes.
174 : : *
175 : : * The default handler for this signal updates the value returned by the
176 : : * default implementation of [vfunc@Valent.ClipboardAdapter.get_timestamp].
177 : : *
178 : : * Since: 1.0
179 : : */
180 : 132 : signals [CHANGED] =
181 : 66 : g_signal_new ("changed",
182 : : G_TYPE_FROM_CLASS (klass),
183 : : G_SIGNAL_RUN_FIRST,
184 : : G_STRUCT_OFFSET (ValentClipboardAdapterClass, changed),
185 : : NULL, NULL, NULL,
186 : : G_TYPE_NONE, 0);
187 : 66 : }
188 : :
189 : : static void
190 : 4 : valent_clipboard_adapter_init (ValentClipboardAdapter *adapter)
191 : : {
192 : 4 : }
193 : :
194 : : /**
195 : : * valent_clipboard_adapter_changed: (virtual changed)
196 : : * @adapter: a `ValentClipboardAdapter`
197 : : *
198 : : * Emits [signal@Valent.ClipboardAdapter::changed] signal on @adapter.
199 : : *
200 : : * The default handler for this signal updates the value returned by the default
201 : : * implementation of [vfunc@Valent.ClipboardAdapter.get_timestamp].
202 : : *
203 : : * This method should only be called by implementations of
204 : : * [class@Valent.ClipboardAdapter].
205 : : *
206 : : * Since: 1.0
207 : : */
208 : : void
209 : 14 : valent_clipboard_adapter_changed (ValentClipboardAdapter *adapter)
210 : : {
211 [ + - ]: 14 : g_return_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
212 : :
213 : 14 : g_signal_emit (G_OBJECT (adapter), signals [CHANGED], 0);
214 : : }
215 : :
216 : : /**
217 : : * valent_clipboard_adapter_get_timestamp: (virtual get_timestamp)
218 : : * @adapter: a `ValentClipboardAdapter`
219 : : *
220 : : * Get the timestamp of the current clipboard content.
221 : : *
222 : : * The default implementation of this method returns the last time
223 : : * [signal@Valent.ClipboardAdapter::changed] was emitted
224 : : *
225 : : * Returns: a UNIX epoch timestamp (ms)
226 : : *
227 : : * Since: 1.0
228 : : */
229 : : int64_t
230 : 16 : valent_clipboard_adapter_get_timestamp (ValentClipboardAdapter *adapter)
231 : : {
232 : 16 : int64_t ret;
233 : :
234 : 16 : VALENT_ENTRY;
235 : :
236 [ + - ]: 16 : g_return_val_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter), 0);
237 : :
238 : 16 : ret = VALENT_CLIPBOARD_ADAPTER_GET_CLASS (adapter)->get_timestamp (adapter);
239 : :
240 : 16 : VALENT_RETURN (ret);
241 : : }
242 : :
243 : : /**
244 : : * valent_clipboard_adapter_get_mimetypes: (virtual get_mimetypes)
245 : : * @adapter: a `ValentClipboardAdapter`
246 : : *
247 : : * Get the mime-types of the current clipboard content.
248 : : *
249 : : * Returns: (transfer full) (nullable) (array zero-terminated=1): a list of
250 : : * mime-types
251 : : *
252 : : * Since: 1.0
253 : : */
254 : : GStrv
255 : 21 : valent_clipboard_adapter_get_mimetypes (ValentClipboardAdapter *adapter)
256 : : {
257 : 21 : GStrv ret = NULL;
258 : :
259 : 21 : VALENT_ENTRY;
260 : :
261 [ + - ]: 21 : g_return_val_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter), NULL);
262 : :
263 : 21 : ret = VALENT_CLIPBOARD_ADAPTER_GET_CLASS (adapter)->get_mimetypes (adapter);
264 : :
265 : 21 : VALENT_RETURN (g_steal_pointer (&ret));
266 : : }
267 : :
268 : : /**
269 : : * valent_clipboard_adapter_read_bytes: (virtual read_bytes)
270 : : * @adapter: a `ValentClipboardAdapter`
271 : : * @mimetype: a mime-type
272 : : * @cancellable: (nullable): a `GCancellable`
273 : : * @callback: (scope async): a `GAsyncReadyCallback`
274 : : * @user_data: (closure): user supplied data
275 : : *
276 : : * Get the content of @adapter.
277 : : *
278 : : * Call [method@Valent.ClipboardAdapter.read_bytes_finish] to get the result.
279 : : *
280 : : * Since: 1.0
281 : : */
282 : : void
283 : 18 : valent_clipboard_adapter_read_bytes (ValentClipboardAdapter *adapter,
284 : : const char *mimetype,
285 : : GCancellable *cancellable,
286 : : GAsyncReadyCallback callback,
287 : : gpointer user_data)
288 : : {
289 : 18 : VALENT_ENTRY;
290 : :
291 [ + - ]: 18 : g_return_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
292 [ + - - + ]: 18 : g_return_if_fail (mimetype != NULL && *mimetype != '\0');
293 [ + + + - : 18 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
294 : :
295 : 18 : VALENT_CLIPBOARD_ADAPTER_GET_CLASS (adapter)->read_bytes (adapter,
296 : : mimetype,
297 : : cancellable,
298 : : callback,
299 : : user_data);
300 : 18 : VALENT_EXIT;
301 : : }
302 : :
303 : : /**
304 : : * valent_clipboard_adapter_read_bytes_finish: (virtual read_bytes_finish)
305 : : * @adapter: a `ValentClipboardAdapter`
306 : : * @result: a `GAsyncResult`
307 : : * @error: (nullable): a `GError`
308 : : *
309 : : * Finish an operation started by [method@Valent.ClipboardAdapter.read_bytes].
310 : : *
311 : : * Returns: (transfer full) (nullable): a `GBytes`, or %NULL with @error set
312 : : *
313 : : * Since: 1.0
314 : : */
315 : : GBytes *
316 : 18 : valent_clipboard_adapter_read_bytes_finish (ValentClipboardAdapter *adapter,
317 : : GAsyncResult *result,
318 : : GError **error)
319 : : {
320 : 18 : GBytes *ret;
321 : :
322 : 18 : VALENT_ENTRY;
323 : :
324 [ + - ]: 18 : g_return_val_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter), NULL);
325 [ - + ]: 18 : g_return_val_if_fail (g_task_is_valid (result, adapter), NULL);
326 [ + - - + ]: 18 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
327 : :
328 : 18 : ret = VALENT_CLIPBOARD_ADAPTER_GET_CLASS (adapter)->read_bytes_finish (adapter,
329 : : result,
330 : : error);
331 : :
332 : 18 : VALENT_RETURN (g_steal_pointer (&ret));
333 : : }
334 : :
335 : : /**
336 : : * valent_clipboard_adapter_write_bytes: (virtual write_bytes)
337 : : * @adapter: a `ValentClipboardAdapter`
338 : : * @mimetype: (nullable): a mime-type, or %NULL if @bytes is %NULL
339 : : * @bytes: (nullable): a `GBytes`, or %NULL if @mimetype is %NULL
340 : : * @cancellable: (nullable): a `GCancellable`
341 : : * @callback: (scope async): a `GAsyncReadyCallback`
342 : : * @user_data: (closure): user supplied data
343 : : *
344 : : * Set the content of the clipboard.
345 : : *
346 : : * Call [method@Valent.ClipboardAdapter.write_bytes_finish] to get the result.
347 : : *
348 : : * Since: 1.0
349 : : */
350 : : void
351 : 11 : valent_clipboard_adapter_write_bytes (ValentClipboardAdapter *adapter,
352 : : const char *mimetype,
353 : : GBytes *bytes,
354 : : GCancellable *cancellable,
355 : : GAsyncReadyCallback callback,
356 : : gpointer user_data)
357 : : {
358 : 11 : VALENT_ENTRY;
359 : :
360 [ + - ]: 11 : g_return_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter));
361 [ + - + - : 11 : g_return_if_fail (bytes == NULL || (mimetype != NULL && *mimetype != '\0'));
- + ]
362 [ + + + - : 11 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- + - - ]
363 : :
364 : 11 : VALENT_CLIPBOARD_ADAPTER_GET_CLASS (adapter)->write_bytes (adapter,
365 : : mimetype,
366 : : bytes,
367 : : cancellable,
368 : : callback,
369 : : user_data);
370 : :
371 : 11 : VALENT_EXIT;
372 : : }
373 : :
374 : : /**
375 : : * valent_clipboard_adapter_write_bytes_finish: (virtual write_bytes_finish)
376 : : * @adapter: a `ValentClipboardAdapter`
377 : : * @result: a `GAsyncResult`
378 : : * @error: (nullable): a `GError`
379 : : *
380 : : * Finish an operation started by [method@Valent.ClipboardAdapter.write_bytes].
381 : : *
382 : : * Returns: %TRUE if successful, or %FALSE with @error set
383 : : *
384 : : * Since: 1.0
385 : : */
386 : : gboolean
387 : 11 : valent_clipboard_adapter_write_bytes_finish (ValentClipboardAdapter *adapter,
388 : : GAsyncResult *result,
389 : : GError **error)
390 : : {
391 : 11 : gboolean ret;
392 : :
393 : 11 : VALENT_ENTRY;
394 : :
395 [ + - ]: 11 : g_return_val_if_fail (VALENT_IS_CLIPBOARD_ADAPTER (adapter), FALSE);
396 [ - + ]: 11 : g_return_val_if_fail (g_task_is_valid (result, adapter), FALSE);
397 [ + - - + ]: 11 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
398 : :
399 : 11 : ret = VALENT_CLIPBOARD_ADAPTER_GET_CLASS (adapter)->write_bytes_finish (adapter,
400 : : result,
401 : : error);
402 : :
403 : 11 : VALENT_RETURN (ret);
404 : : }
405 : :
|