1 | #include <stdlib.h> |
2 | |
3 | #include <gtk/gtk.h> |
4 | |
5 | static void |
6 | text_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 | |
27 | static void |
28 | test_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 | |
73 | static void |
74 | read_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 | |
91 | static void |
92 | assert_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 | |
120 | static void |
121 | test_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 | |
228 | static void |
229 | test_clipboard_string (void) |
230 | { |
231 | test_clipboard_roundtrip (type: "string" , value: "abcdef1230" , result: "abcdef1230" ); |
232 | } |
233 | |
234 | static void |
235 | test_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 | |
244 | static void |
245 | test_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 | |
254 | static void |
255 | test_clipboard_color (void) |
256 | { |
257 | test_clipboard_roundtrip (type: "color" , value: "red" , result: "rgb(255,0,0)" ); |
258 | } |
259 | |
260 | static void |
261 | test_clipboard_file (void) |
262 | { |
263 | test_clipboard_roundtrip (type: "file" , value: "/etc/passwd" , result: "/etc/passwd" ); |
264 | } |
265 | |
266 | static void |
267 | test_clipboard_files (void) |
268 | { |
269 | test_clipboard_roundtrip (type: "files" , value: "/etc/passwd:/boot/ostree" , result: "/etc/passwd:/boot/ostree" ); |
270 | } |
271 | |
272 | int |
273 | main (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 | |