1#include <stdlib.h>
2
3#include <gtk/gtk.h>
4
5static void
6text_received (GObject *source,
7 GAsyncResult *res,
8 gpointer data)
9{
10 GdkClipboard *clipboard = GDK_CLIPBOARD (source);
11 gboolean *done = data;
12 GError *error = NULL;
13 char *text;
14
15 text = gdk_clipboard_read_text_finish (clipboard, result: res, error: &error);
16
17 g_assert_no_error (error);
18 g_assert_cmpstr (text, ==, "testing, 1, 2");
19
20 g_free (mem: text);
21
22 *done = TRUE;
23
24 g_main_context_wakeup (NULL);
25}
26
27static void
28test_clipboard_basic (void)
29{
30 GdkDisplay *display;
31 GdkClipboard *clipboard;
32 GdkContentFormats *formats;
33 GdkContentProvider *content;
34 gboolean done;
35 gboolean ret;
36 GValue value = G_VALUE_INIT;
37 GError *error = NULL;
38
39 display = gdk_display_get_default ();
40 clipboard = gdk_display_get_clipboard (display);
41
42 g_assert_true (gdk_clipboard_get_display (clipboard) == display);
43
44 gdk_clipboard_set_text (clipboard, text: "testing, 1, 2");
45
46 g_assert_true (gdk_clipboard_is_local (clipboard));
47
48 formats = gdk_clipboard_get_formats (clipboard);
49
50 g_assert_true (gdk_content_formats_contain_gtype (formats, G_TYPE_STRING));
51 g_assert_true (gdk_content_formats_contain_mime_type (formats, "text/plain"));
52
53 done = FALSE;
54
55 gdk_clipboard_read_text_async (clipboard, NULL, callback: text_received, user_data: &done);
56
57 while (!done)
58 g_main_context_iteration (NULL, TRUE);
59
60 content = gdk_clipboard_get_content (clipboard);
61 g_assert_nonnull (content);
62
63 g_value_init (value: &value, G_TYPE_STRING);
64 ret = gdk_content_provider_get_value (provider: content, value: &value, error: &error);
65 g_assert_true (ret);
66 g_assert_no_error (error);
67 g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_STRING);
68 g_assert_cmpstr (g_value_get_string (&value), ==, "testing, 1, 2");
69
70 g_value_unset (value: &value);
71}
72
73static void
74read_upto_done (GObject *source,
75 GAsyncResult *result,
76 gpointer data)
77{
78 GDataInputStream *out = G_DATA_INPUT_STREAM (source);
79 gboolean *done = data;
80 char *str;
81 GError *error = NULL;
82
83 str = g_data_input_stream_read_upto_finish (stream: out, result, NULL, error: &error);
84 g_assert_no_error (error);
85 g_free (mem: str);
86
87 *done = TRUE;
88 g_main_context_wakeup (NULL);
89}
90
91static void
92assert_texture_equal (GdkTexture *t1,
93 GdkTexture *t2)
94{
95 int width;
96 int height;
97 int stride;
98 guchar *d1;
99 guchar *d2;
100
101 width = gdk_texture_get_width (texture: t1);
102 height = gdk_texture_get_height (texture: t1);
103 stride = 4 * width;
104
105 g_assert_cmpint (width, ==, gdk_texture_get_width (t2));
106 g_assert_cmpint (height, ==, gdk_texture_get_height (t2));
107
108 d1 = g_malloc (n_bytes: stride * height);
109 d2 = g_malloc (n_bytes: stride * height);
110
111 gdk_texture_download (texture: t1, data: d1, stride);
112 gdk_texture_download (texture: t2, data: d2, stride);
113
114 g_assert_cmpmem (d1, stride * height, d2, stride * height);
115
116 g_free (mem: d1);
117 g_free (mem: d2);
118}
119
120static void
121test_clipboard_roundtrip (const char *type,
122 const char *value,
123 const char *result)
124{
125 GSubprocess *source, *target;
126 char *clipboard_client;
127 GError *error = NULL;
128 GDataInputStream *out;
129 gboolean done = FALSE;
130 char *stdout_buf = NULL;
131 char *stderr_buf = NULL;
132
133 if (gdk_display_get_default_seat (display: gdk_display_get_default ()) == NULL)
134 {
135 g_test_skip (msg: "we have no seat, so focus won't work");
136 return;
137 }
138
139 clipboard_client = g_test_build_filename (file_type: G_TEST_BUILT, first_path: "/clipboard-client", NULL);
140
141 source = g_subprocess_new (flags: G_SUBPROCESS_FLAGS_STDOUT_PIPE,
142 error: &error,
143 argv0: clipboard_client,
144 "set", type, value, NULL);
145 g_assert_no_error (error);
146
147 /* Wait until the first child has claimed the clipboard */
148 out = g_data_input_stream_new (base_stream: g_subprocess_get_stdout_pipe (subprocess: source));
149 g_data_input_stream_read_upto_async (stream: out, stop_chars: "\n", stop_chars_len: 1, io_priority: 0, NULL, callback: read_upto_done, user_data: &done);
150
151 while (!done)
152 g_main_context_iteration (NULL, TRUE);
153
154 g_object_unref (object: out);
155
156 target = g_subprocess_new (flags: G_SUBPROCESS_FLAGS_STDOUT_PIPE,
157 error: &error,
158 argv0: clipboard_client,
159 "get", type, NULL);
160
161 g_free (mem: clipboard_client);
162
163 if (!target)
164 {
165 g_test_fail ();
166 g_error_free (error);
167
168 g_subprocess_force_exit (subprocess: source);
169 g_object_unref (object: source);
170
171 return;
172 }
173
174 g_subprocess_communicate_utf8 (subprocess: target, NULL, NULL, stdout_buf: &stdout_buf, stderr_buf: &stderr_buf, error: &error);
175
176 g_subprocess_force_exit (subprocess: source);
177 g_object_unref (object: source);
178
179 g_assert_no_error (error);
180
181 if (result)
182 g_assert_cmpstr (stdout_buf, ==, result);
183 else if (g_str_has_prefix (str: stdout_buf, prefix: "ERROR"))
184 {
185 g_test_fail ();
186 }
187 else if (g_str_has_suffix (str: value, suffix: ".png"))
188 {
189 GFile *f1, *f2;
190 GdkTexture *t1, *t2;
191
192 f1 = g_file_new_for_path (path: value);
193 f2 = g_file_new_for_path (path: stdout_buf);
194
195 t1 = gdk_texture_new_from_file (file: f1, error: &error);
196 g_assert_no_error (error);
197 t2 = gdk_texture_new_from_file (file: f2, error: &error);
198 g_assert_no_error (error);
199
200 assert_texture_equal (t1, t2);
201
202 g_object_unref (object: t1);
203 g_object_unref (object: t2);
204 g_object_unref (object: f1);
205 g_object_unref (object: f2);
206 }
207 else
208 {
209 char *m1, *m2;
210 gsize l1, l2;
211
212 g_file_get_contents (filename: value, contents: &m1, length: &l1, error: &error);
213 g_assert_no_error (error);
214 g_file_get_contents (filename: stdout_buf, contents: &m2, length: &l2, error: &error);
215 g_assert_no_error (error);
216
217 g_assert_cmpmem (m1, l1, m2, l2);
218
219 g_free (mem: m1);
220 g_free (mem: m2);
221 }
222
223 g_assert_null (stderr_buf);
224 g_free (mem: stdout_buf);
225 g_object_unref (object: target);
226}
227
228static void
229test_clipboard_string (void)
230{
231 test_clipboard_roundtrip (type: "string", value: "abcdef1230", result: "abcdef1230");
232}
233
234static void
235test_clipboard_text (void)
236{
237 char *filename;
238
239 filename = g_test_build_filename (file_type: G_TEST_DIST, first_path: "clipboard-data", "test.txt", NULL);
240
241 test_clipboard_roundtrip (type: "text", value: filename, NULL);
242}
243
244static void
245test_clipboard_image (void)
246{
247 char *filename;
248
249 filename = g_test_build_filename (file_type: G_TEST_DIST, first_path: "clipboard-data", "image.png", NULL);
250
251 test_clipboard_roundtrip (type: "image", value: filename, NULL);
252}
253
254static void
255test_clipboard_color (void)
256{
257 test_clipboard_roundtrip (type: "color", value: "red", result: "rgb(255,0,0)");
258}
259
260static void
261test_clipboard_file (void)
262{
263 test_clipboard_roundtrip (type: "file", value: "/etc/passwd", result: "/etc/passwd");
264}
265
266static void
267test_clipboard_files (void)
268{
269 test_clipboard_roundtrip (type: "files", value: "/etc/passwd:/boot/ostree", result: "/etc/passwd:/boot/ostree");
270}
271
272int
273main (int argc, char *argv[])
274{
275 (g_test_init) (argc: &argc, argv: &argv, NULL);
276
277 gtk_init ();
278
279 g_test_add_func (testpath: "/clipboard/basic", test_func: test_clipboard_basic);
280 g_test_add_func (testpath: "/clipboard/string", test_func: test_clipboard_string);
281 g_test_add_func (testpath: "/clipboard/text", test_func: test_clipboard_text);
282 g_test_add_func (testpath: "/clipboard/image", test_func: test_clipboard_image);
283 g_test_add_func (testpath: "/clipboard/color", test_func: test_clipboard_color);
284 g_test_add_func (testpath: "/clipboard/file", test_func: test_clipboard_file);
285 g_test_add_func (testpath: "/clipboard/files", test_func: test_clipboard_files);
286
287 return g_test_run ();
288}
289

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