1#include <gtk/gtk.h>
2
3#ifdef GDK_WINDOWING_WAYLAND
4#include "wayland/gdkwayland.h"
5#endif
6
7#ifdef G_OS_WIN32
8#include <io.h>
9#include <process.h>
10#endif
11
12G_GNUC_NORETURN static void
13got_string_cb (GObject *source,
14 GAsyncResult *result,
15 gpointer data)
16{
17 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
18 GError *error = NULL;
19 char *text;
20
21 text = gdk_clipboard_read_text_finish (clipboard, result, error: &error);
22 if (text)
23 {
24 g_print (format: "%s", text);
25 g_free (mem: text);
26 }
27 else
28 {
29 g_print (format: "ERROR: %s", error->message);
30 g_clear_error (err: &error);
31 }
32
33 exit (status: 0);
34}
35
36G_GNUC_NORETURN static void
37got_text_cb (GObject *source,
38 GAsyncResult *result,
39 gpointer data)
40{
41 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
42 GError *error = NULL;
43 char *text;
44
45 text = gdk_clipboard_read_text_finish (clipboard, result, error: &error);
46 if (text)
47 {
48 int fd;
49 char *name;
50
51 fd = g_file_open_tmp (tmpl: "XXXXXX.out", name_used: &name, error: &error);
52 if (error)
53 g_error ("Failed to create tmp file: %s", error->message);
54 close (fd: fd);
55 g_file_set_contents (filename: name, contents: text, length: -1, error: &error);
56 g_print (format: "%s", name);
57 g_free (mem: text);
58 g_free (mem: name);
59 }
60 else
61 {
62 g_print (format: "ERROR: %s", error->message);
63 g_clear_error (err: &error);
64 }
65
66 exit (status: 0);
67}
68
69G_GNUC_NORETURN static void
70got_texture_cb (GObject *source,
71 GAsyncResult *result,
72 gpointer data)
73{
74 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
75 GError *error = NULL;
76 GdkTexture *texture;
77
78 texture = gdk_clipboard_read_texture_finish (clipboard, result, error: &error);
79 if (texture)
80 {
81 int fd;
82 char *name;
83
84 fd = g_file_open_tmp (tmpl: "XXXXXX.out", name_used: &name, error: &error);
85 if (error)
86 g_error ("Failed to create tmp file: %s", error->message);
87 close (fd: fd);
88 gdk_texture_save_to_png (texture, filename: name);
89 g_print (format: "%s", name);
90 g_object_unref (object: texture);
91 g_free (mem: name);
92 }
93 else
94 {
95 g_print (format: "ERROR: %s", error->message);
96 g_clear_error (err: &error);
97 }
98
99 exit (status: 0);
100}
101
102G_GNUC_NORETURN static void
103got_file (GObject *source,
104 GAsyncResult *result,
105 gpointer data)
106{
107 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
108 GError *error = NULL;
109 const GValue *value;
110
111 value = gdk_clipboard_read_value_finish (clipboard, result, error: &error);
112 if (value)
113 {
114 GFile *file = g_value_get_object (value);
115 char *path = g_file_get_path (file);
116 g_print (format: "%s", path);
117 g_free (mem: path);
118 }
119 else
120 {
121 g_print (format: "ERROR: %s", error->message);
122 g_clear_error (err: &error);
123 }
124
125 exit (status: 0);
126}
127
128G_GNUC_NORETURN static void
129got_files (GObject *source,
130 GAsyncResult *result,
131 gpointer data)
132{
133 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
134 GError *error = NULL;
135 const GValue *value;
136
137 value = gdk_clipboard_read_value_finish (clipboard, result, error: &error);
138 if (value)
139 {
140 GSList *files = g_value_get_boxed (value);
141 for (GSList *l = files; l; l = l->next)
142 {
143 GFile *file = l->data;
144 char *path = g_file_get_path (file);
145 if (l != files)
146 g_print (format: ":");
147 g_print (format: "%s", path);
148 g_free (mem: path);
149 }
150 }
151 else
152 {
153 g_print (format: "ERROR: %s", error->message);
154 g_clear_error (err: &error);
155 }
156
157 exit (status: 0);
158}
159
160G_GNUC_NORETURN static void
161got_color (GObject *source,
162 GAsyncResult *result,
163 gpointer data)
164{
165 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
166 GError *error = NULL;
167 const GValue *value;
168
169 value = gdk_clipboard_read_value_finish (clipboard, result, error: &error);
170 if (value)
171 {
172 GdkRGBA *color = g_value_get_boxed (value);
173 char *s = gdk_rgba_to_string (rgba: color);
174 g_print (format: "%s", s);
175 g_free (mem: s);
176 }
177 else
178 {
179 g_print (format: "ERROR: %s", error->message);
180 g_clear_error (err: &error);
181 }
182
183 exit (status: 0);
184}
185
186static const char *action;
187static const char *type;
188static const char *value;
189static gulong handler;
190
191static void
192do_it (GObject *object,
193 GParamSpec *pspec)
194{
195 GdkClipboard *clipboard;
196
197 if (object)
198 g_signal_handler_disconnect (instance: object, handler_id: handler);
199
200 clipboard = gdk_display_get_clipboard (display: gdk_display_get_default ());
201
202 if (strcmp (s1: action, s2: "info") == 0)
203 {
204 GdkContentFormats *formats;
205 char *s;
206
207 formats = gdk_clipboard_get_formats (clipboard);
208 s = gdk_content_formats_to_string (formats);
209 g_print (format: "%s\n", s);
210 g_free (mem: s);
211 }
212 else if (strcmp (s1: action, s2: "set") == 0)
213 {
214 GdkContentFormats *formats;
215 char *s;
216
217 if (strcmp (s1: type, s2: "string") == 0)
218 {
219 gdk_clipboard_set_text (clipboard, text: value);
220 }
221 else if (strcmp (s1: type, s2: "text") == 0)
222 {
223 char *contents;
224 gsize len;
225
226 if (!g_file_get_contents (filename: value, contents: &contents, length: &len, NULL))
227 g_error ("Failed to read %s\n", value);
228
229 gdk_clipboard_set_text (clipboard, text: contents);
230 g_free (mem: contents);
231 }
232 else if (strcmp (s1: type, s2: "image") == 0)
233 {
234 GFile *file;
235 GdkTexture *texture;
236
237 file = g_file_new_for_commandline_arg (arg: value);
238 texture = gdk_texture_new_from_file (file, NULL);
239 if (!texture)
240 g_error ("Failed to read %s\n", value);
241
242 gdk_clipboard_set_texture (clipboard, texture);
243 g_object_unref (object: texture);
244 g_object_unref (object: file);
245 }
246 else if (strcmp (s1: type, s2: "file") == 0)
247 {
248 GFile *file;
249
250 file = g_file_new_for_commandline_arg (arg: value);
251 gdk_clipboard_set (clipboard, G_TYPE_FILE, file);
252 g_object_unref (object: file);
253 }
254 else if (strcmp (s1: type, s2: "files") == 0)
255 {
256 char **strv;
257 GSList *files;
258
259 strv = g_strsplit (string: value, delimiter: ":", max_tokens: 0);
260
261 files = NULL;
262 for (int i = 0; strv[i]; i++)
263 files = g_slist_append (list: files, data: g_file_new_for_commandline_arg (arg: strv[i]));
264
265 gdk_clipboard_set (clipboard, GDK_TYPE_FILE_LIST, files);
266
267 g_slist_free_full (list: files, free_func: g_object_unref);
268 g_strfreev (str_array: strv);
269 }
270 else if (strcmp (s1: type, s2: "color") == 0)
271 {
272 GdkRGBA color;
273
274 gdk_rgba_parse (rgba: &color, spec: value);
275 gdk_clipboard_set (clipboard, GDK_TYPE_RGBA, &color);
276 }
277 else
278 g_error ("can't set %s", type);
279
280 formats = gdk_clipboard_get_formats (clipboard);
281 s = gdk_content_formats_to_string (formats);
282 g_print (format: "%s\n", s);
283 g_free (mem: s);
284 }
285 else if (strcmp (s1: action, s2: "get") == 0)
286 {
287 if (strcmp (s1: type, s2: "string") == 0)
288 {
289 gdk_clipboard_read_text_async (clipboard, NULL, callback: got_string_cb, NULL);
290 }
291 else if (strcmp (s1: type, s2: "text") == 0)
292 {
293 gdk_clipboard_read_text_async (clipboard, NULL, callback: got_text_cb, NULL);
294 }
295 else if (strcmp (s1: type, s2: "image") == 0)
296 {
297 gdk_clipboard_read_texture_async (clipboard, NULL, callback: got_texture_cb, NULL);
298 }
299 else if (strcmp (s1: type, s2: "file") == 0)
300 {
301 gdk_clipboard_read_value_async (clipboard, G_TYPE_FILE, io_priority: 0, NULL, callback: got_file, NULL);
302 }
303 else if (strcmp (s1: type, s2: "files") == 0)
304 {
305 gdk_clipboard_read_value_async (clipboard, GDK_TYPE_FILE_LIST, io_priority: 0, NULL, callback: got_files, NULL);
306 }
307 else if (strcmp (s1: type, s2: "color") == 0)
308 {
309 gdk_clipboard_read_value_async (clipboard, GDK_TYPE_RGBA, io_priority: 0, NULL, callback: got_color, NULL);
310 }
311 else
312 g_error ("can't get %s", type);
313 }
314 else
315 g_error ("can only set, get or info");
316}
317
318int
319main (int argc, char *argv[])
320{
321 gboolean done = FALSE;
322
323 if (argc < 2)
324 g_error ("too few arguments");
325
326 action = argv[1];
327
328 if (strcmp (s1: action, s2: "info") == 0)
329 {
330 }
331 else if (strcmp (s1: action, s2: "set") == 0)
332 {
333 if (argc < 4)
334 g_error ("too few arguments for set");
335
336 type = argv[2];
337 value = argv[3];
338 }
339 else if (strcmp (s1: action, s2: "get") == 0)
340 {
341 if (argc < 3)
342 g_error ("too few arguments for get");
343
344 type = argv[2];
345 }
346 else
347 g_error ("can only set or get");
348
349 gtk_init ();
350
351 /* Don't wait for a window manager to give us focus when
352 * we may be running on bare wm-less X.
353 */
354#ifdef GDK_WINDOWING_WAYLAND
355 if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
356 {
357 GtkWidget *window;
358
359 window = gtk_window_new ();
360 gtk_window_present (GTK_WINDOW (window));
361 handler = g_signal_connect (window, "notify::is-active", G_CALLBACK (do_it), NULL);
362 }
363 else
364#endif
365 do_it (NULL, NULL);
366
367 while (!done)
368 g_main_context_iteration (NULL, TRUE);
369
370 return 0;
371}
372

source code of gtk/testsuite/gdk/clipboard-client.c