339 lines
8.0 KiB
C
339 lines
8.0 KiB
C
|
#include <stdlib.h>
|
||
|
|
||
|
#include <gtk/gtk.h>
|
||
|
|
||
|
static void
|
||
|
text_received (GObject *source,
|
||
|
GAsyncResult *res,
|
||
|
gpointer data)
|
||
|
{
|
||
|
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||
|
gboolean *done = data;
|
||
|
GError *error = NULL;
|
||
|
char *text;
|
||
|
|
||
|
text = gdk_clipboard_read_text_finish (clipboard, res, &error);
|
||
|
|
||
|
g_assert_no_error (error);
|
||
|
g_assert_cmpstr (text, ==, "testing, 1, 2");
|
||
|
|
||
|
g_free (text);
|
||
|
|
||
|
*done = TRUE;
|
||
|
|
||
|
g_main_context_wakeup (NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_basic (void)
|
||
|
{
|
||
|
GdkDisplay *display;
|
||
|
GdkClipboard *clipboard;
|
||
|
GdkContentFormats *formats;
|
||
|
GdkContentProvider *content;
|
||
|
gboolean done;
|
||
|
gboolean ret;
|
||
|
GValue value = G_VALUE_INIT;
|
||
|
GError *error = NULL;
|
||
|
|
||
|
display = gdk_display_get_default ();
|
||
|
clipboard = gdk_display_get_clipboard (display);
|
||
|
|
||
|
g_assert_true (gdk_clipboard_get_display (clipboard) == display);
|
||
|
|
||
|
gdk_clipboard_set_text (clipboard, "testing, 1, 2");
|
||
|
|
||
|
g_assert_true (gdk_clipboard_is_local (clipboard));
|
||
|
|
||
|
formats = gdk_clipboard_get_formats (clipboard);
|
||
|
|
||
|
g_assert_true (gdk_content_formats_contain_gtype (formats, G_TYPE_STRING));
|
||
|
g_assert_true (gdk_content_formats_contain_mime_type (formats, "text/plain"));
|
||
|
|
||
|
done = FALSE;
|
||
|
|
||
|
gdk_clipboard_read_text_async (clipboard, NULL, text_received, &done);
|
||
|
|
||
|
while (!done)
|
||
|
g_main_context_iteration (NULL, TRUE);
|
||
|
|
||
|
content = gdk_clipboard_get_content (clipboard);
|
||
|
g_assert_nonnull (content);
|
||
|
|
||
|
g_value_init (&value, G_TYPE_STRING);
|
||
|
ret = gdk_content_provider_get_value (content, &value, &error);
|
||
|
g_assert_true (ret);
|
||
|
g_assert_no_error (error);
|
||
|
g_assert_true (G_VALUE_TYPE (&value) == G_TYPE_STRING);
|
||
|
g_assert_cmpstr (g_value_get_string (&value), ==, "testing, 1, 2");
|
||
|
|
||
|
g_value_unset (&value);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
read_upto_done (GObject *source,
|
||
|
GAsyncResult *result,
|
||
|
gpointer data)
|
||
|
{
|
||
|
GDataInputStream *out = G_DATA_INPUT_STREAM (source);
|
||
|
gboolean *done = data;
|
||
|
char *str;
|
||
|
GError *error = NULL;
|
||
|
|
||
|
str = g_data_input_stream_read_upto_finish (out, result, NULL, &error);
|
||
|
g_assert_no_error (error);
|
||
|
|
||
|
if (g_test_verbose ())
|
||
|
g_test_message ("src formats: %s", str);
|
||
|
|
||
|
g_free (str);
|
||
|
|
||
|
*done = TRUE;
|
||
|
g_main_context_wakeup (NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
compare_textures (GdkTexture *t1,
|
||
|
GdkTexture *t2)
|
||
|
{
|
||
|
int width;
|
||
|
int height;
|
||
|
int stride;
|
||
|
guchar *d1;
|
||
|
guchar *d2;
|
||
|
|
||
|
width = gdk_texture_get_width (t1);
|
||
|
height = gdk_texture_get_height (t1);
|
||
|
stride = 4 * width;
|
||
|
|
||
|
g_assert_cmpint (width, ==, gdk_texture_get_width (t2));
|
||
|
g_assert_cmpint (height, ==, gdk_texture_get_height (t2));
|
||
|
|
||
|
d1 = g_malloc (stride * height);
|
||
|
d2 = g_malloc (stride * height);
|
||
|
|
||
|
gdk_texture_download (t1, d1, stride);
|
||
|
gdk_texture_download (t2, d2, stride);
|
||
|
|
||
|
g_assert_cmpmem (d1, stride * height, d2, stride * height);
|
||
|
|
||
|
g_free (d1);
|
||
|
g_free (d2);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
compare_files (const char *file1,
|
||
|
const char *file2)
|
||
|
{
|
||
|
char *m1, *m2;
|
||
|
gsize l1, l2;
|
||
|
GError *error = NULL;
|
||
|
|
||
|
g_file_get_contents (file1, &m1, &l1, &error);
|
||
|
g_assert_no_error (error);
|
||
|
g_file_get_contents (file2, &m2, &l2, &error);
|
||
|
g_assert_no_error (error);
|
||
|
|
||
|
if (l1 != l2)
|
||
|
g_test_fail_printf ("file length mismatch: %s %s\n", file1, file2);
|
||
|
else if (memcmp (m1, m2, l1) != 0)
|
||
|
g_test_fail_printf ("file mismatch: %s %s\n", file1, file2);
|
||
|
|
||
|
g_free (m1);
|
||
|
g_free (m2);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_roundtrip (const char *type,
|
||
|
const char *value,
|
||
|
const char *result)
|
||
|
{
|
||
|
GSubprocess *source, *target;
|
||
|
char *clipboard_client;
|
||
|
GError *error = NULL;
|
||
|
GDataInputStream *out;
|
||
|
gboolean done = FALSE;
|
||
|
char *stdout_buf = NULL;
|
||
|
char *stderr_buf = NULL;
|
||
|
|
||
|
if (gdk_display_get_default_seat (gdk_display_get_default ()) == NULL)
|
||
|
{
|
||
|
g_test_skip ("we have no seat, so focus won't work");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
clipboard_client = g_test_build_filename (G_TEST_BUILT, "/clipboard-client", NULL);
|
||
|
|
||
|
source = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE,
|
||
|
&error,
|
||
|
clipboard_client,
|
||
|
"set", type, value, NULL);
|
||
|
g_assert_no_error (error);
|
||
|
|
||
|
/* Wait until the first child has claimed the clipboard */
|
||
|
out = g_data_input_stream_new (g_subprocess_get_stdout_pipe (source));
|
||
|
g_data_input_stream_read_upto_async (out, "\n", 1, 0, NULL, read_upto_done, &done);
|
||
|
|
||
|
while (!done)
|
||
|
g_main_context_iteration (NULL, TRUE);
|
||
|
|
||
|
g_object_unref (out);
|
||
|
|
||
|
target = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE,
|
||
|
&error,
|
||
|
clipboard_client,
|
||
|
"get", type, NULL);
|
||
|
|
||
|
g_free (clipboard_client);
|
||
|
|
||
|
if (!target)
|
||
|
{
|
||
|
g_test_fail ();
|
||
|
g_error_free (error);
|
||
|
|
||
|
g_subprocess_force_exit (source);
|
||
|
g_object_unref (source);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
g_subprocess_communicate_utf8 (target, NULL, NULL, &stdout_buf, &stderr_buf, &error);
|
||
|
|
||
|
g_subprocess_force_exit (source);
|
||
|
g_object_unref (source);
|
||
|
|
||
|
g_assert_no_error (error);
|
||
|
|
||
|
if (result)
|
||
|
g_assert_cmpstr (stdout_buf, ==, result);
|
||
|
else if (g_str_has_prefix (stdout_buf, "ERROR"))
|
||
|
{
|
||
|
g_test_fail_printf ("dest error: %s", stdout_buf);
|
||
|
}
|
||
|
else if (g_str_equal (type, "image"))
|
||
|
{
|
||
|
GFile *f1, *f2;
|
||
|
GdkTexture *t1, *t2;
|
||
|
|
||
|
f1 = g_file_new_for_path (value);
|
||
|
f2 = g_file_new_for_path (stdout_buf);
|
||
|
|
||
|
t1 = gdk_texture_new_from_file (f1, &error);
|
||
|
g_assert_no_error (error);
|
||
|
t2 = gdk_texture_new_from_file (f2, &error);
|
||
|
g_assert_no_error (error);
|
||
|
|
||
|
compare_textures (t1, t2);
|
||
|
|
||
|
g_object_unref (t1);
|
||
|
g_object_unref (t2);
|
||
|
g_object_unref (f1);
|
||
|
g_object_unref (f2);
|
||
|
}
|
||
|
else if (g_str_equal (type, "file"))
|
||
|
{
|
||
|
compare_files (value, stdout_buf);
|
||
|
}
|
||
|
else if (g_str_equal (type, "files"))
|
||
|
{
|
||
|
char **in_files, **out_files;
|
||
|
|
||
|
in_files = g_strsplit (value, ":", -1);
|
||
|
out_files = g_strsplit (stdout_buf, ":", -1);
|
||
|
|
||
|
g_assert_cmpint (g_strv_length (in_files), ==, g_strv_length (out_files));
|
||
|
for (int i = 0; in_files[i]; i++)
|
||
|
compare_files (in_files[i], out_files[i]);
|
||
|
|
||
|
g_strfreev (in_files);
|
||
|
g_strfreev (out_files);
|
||
|
}
|
||
|
|
||
|
g_assert_null (stderr_buf);
|
||
|
g_free (stdout_buf);
|
||
|
g_object_unref (target);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_string (void)
|
||
|
{
|
||
|
test_clipboard_roundtrip ("string", "abcdef1230", "abcdef1230");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_text (void)
|
||
|
{
|
||
|
char *filename;
|
||
|
|
||
|
filename = g_test_build_filename (G_TEST_DIST, "clipboard-data", "test.txt", NULL);
|
||
|
|
||
|
test_clipboard_roundtrip ("text", filename, NULL);
|
||
|
|
||
|
g_free (filename);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_image (void)
|
||
|
{
|
||
|
char *filename;
|
||
|
|
||
|
filename = g_test_build_filename (G_TEST_DIST, "clipboard-data", "image.png", NULL);
|
||
|
|
||
|
test_clipboard_roundtrip ("image", filename, NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_color (void)
|
||
|
{
|
||
|
test_clipboard_roundtrip ("color", "red", "rgb(255,0,0)");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_file (void)
|
||
|
{
|
||
|
char *filename;
|
||
|
|
||
|
filename = g_test_build_filename (G_TEST_DIST, "clipboard-data", "test.txt", NULL);
|
||
|
|
||
|
test_clipboard_roundtrip ("file", filename, NULL);
|
||
|
|
||
|
g_free (filename);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
test_clipboard_files (void)
|
||
|
{
|
||
|
char **filenames;
|
||
|
char *string;
|
||
|
|
||
|
filenames = g_new (char *, 3);
|
||
|
filenames[0] = g_test_build_filename (G_TEST_DIST, "clipboard-data", "image.png", NULL);
|
||
|
filenames[1] = g_test_build_filename (G_TEST_DIST, "clipboard-data", "test.txt", NULL);
|
||
|
filenames[2] = NULL;
|
||
|
|
||
|
string = g_strjoinv (":", filenames);
|
||
|
|
||
|
test_clipboard_roundtrip ("files", string, NULL);
|
||
|
|
||
|
g_free (string);
|
||
|
g_strfreev (filenames);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main (int argc, char *argv[])
|
||
|
{
|
||
|
(g_test_init) (&argc, &argv, NULL);
|
||
|
|
||
|
gtk_init ();
|
||
|
|
||
|
g_test_add_func ("/clipboard/basic", test_clipboard_basic);
|
||
|
g_test_add_func ("/clipboard/string", test_clipboard_string);
|
||
|
g_test_add_func ("/clipboard/text", test_clipboard_text);
|
||
|
g_test_add_func ("/clipboard/image", test_clipboard_image);
|
||
|
g_test_add_func ("/clipboard/color", test_clipboard_color);
|
||
|
g_test_add_func ("/clipboard/file", test_clipboard_file);
|
||
|
g_test_add_func ("/clipboard/files", test_clipboard_files);
|
||
|
|
||
|
return g_test_run ();
|
||
|
}
|