Compare commits
5 Commits
wip/matthi
...
wip/otte/c
Author | SHA1 | Date | |
---|---|---|---|
|
cdf990617f | ||
|
57431a4afd | ||
|
93862561c9 | ||
|
5da179e4e4 | ||
|
2489e0047a |
@@ -121,6 +121,9 @@ gdk_content_formats_new_take (GType * gtypes,
|
||||
GdkContentFormats *result = g_slice_new0 (GdkContentFormats);
|
||||
result->ref_count = 1;
|
||||
|
||||
g_assert (n_mime_types > 0 || mime_types == NULL);
|
||||
g_assert (n_gtypes > 0 || gtypes == NULL);
|
||||
|
||||
result->gtypes = gtypes;
|
||||
result->n_gtypes = n_gtypes;
|
||||
result->mime_types = mime_types;
|
||||
@@ -650,19 +653,33 @@ gdk_content_formats_builder_to_formats (GdkContentFormatsBuilder *builder)
|
||||
|
||||
g_return_val_if_fail (builder != NULL, NULL);
|
||||
|
||||
gtypes = g_new (GType, builder->n_gtypes + 1);
|
||||
i = builder->n_gtypes;
|
||||
gtypes[i--] = G_TYPE_INVALID;
|
||||
/* add backwards because most important type is last in the list */
|
||||
for (l = builder->gtypes; l; l = l->next)
|
||||
gtypes[i--] = GPOINTER_TO_SIZE (l->data);
|
||||
if (builder->n_gtypes == 0)
|
||||
{
|
||||
gtypes = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtypes = g_new (GType, builder->n_gtypes + 1);
|
||||
i = builder->n_gtypes;
|
||||
gtypes[i--] = G_TYPE_INVALID;
|
||||
/* add backwards because most important type is last in the list */
|
||||
for (l = builder->gtypes; l; l = l->next)
|
||||
gtypes[i--] = GPOINTER_TO_SIZE (l->data);
|
||||
}
|
||||
|
||||
mime_types = g_new (const char *, builder->n_mime_types + 1);
|
||||
i = builder->n_mime_types;
|
||||
mime_types[i--] = NULL;
|
||||
/* add backwards because most important type is last in the list */
|
||||
for (l = builder->mime_types; l; l = l->next)
|
||||
mime_types[i--] = l->data;
|
||||
if (builder->n_mime_types == 0)
|
||||
{
|
||||
mime_types = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mime_types = g_new (const char *, builder->n_mime_types + 1);
|
||||
i = builder->n_mime_types;
|
||||
mime_types[i--] = NULL;
|
||||
/* add backwards because most important type is last in the list */
|
||||
for (l = builder->mime_types; l; l = l->next)
|
||||
mime_types[i--] = l->data;
|
||||
}
|
||||
|
||||
result = gdk_content_formats_new_take (gtypes, builder->n_gtypes,
|
||||
mime_types, builder->n_mime_types);
|
||||
|
@@ -317,17 +317,23 @@ gdk_content_serializer_get_task_data (GdkContentSerializer *serializer)
|
||||
return serializer->task_data;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_content_serializer_emit_callback (gpointer data)
|
||||
static void
|
||||
gdk_content_serializer_close_finish (GObject *stream,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GdkContentSerializer *serializer = data;
|
||||
|
||||
g_output_stream_close_finish (G_OUTPUT_STREAM (stream),
|
||||
res,
|
||||
serializer->error ? NULL : &serializer->error);
|
||||
|
||||
if (serializer->callback)
|
||||
{
|
||||
serializer->callback (NULL, G_ASYNC_RESULT (serializer), serializer->callback_data);
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
g_object_unref (serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,6 +341,8 @@ gdk_content_serializer_emit_callback (gpointer data)
|
||||
* @serializer: a #GdkContentSerializer
|
||||
*
|
||||
* Indicate that the serialization has been successfully completed.
|
||||
*
|
||||
* The serializer will close the output stream and report success to the callback.
|
||||
*/
|
||||
void
|
||||
gdk_content_serializer_return_success (GdkContentSerializer *serializer)
|
||||
@@ -343,11 +351,11 @@ gdk_content_serializer_return_success (GdkContentSerializer *serializer)
|
||||
g_return_if_fail (!serializer->returned);
|
||||
|
||||
serializer->returned = TRUE;
|
||||
g_idle_add_full (serializer->priority,
|
||||
gdk_content_serializer_emit_callback,
|
||||
serializer,
|
||||
g_object_unref);
|
||||
/* NB: the idle will destroy our reference */
|
||||
g_output_stream_close_async (serializer->stream,
|
||||
serializer->priority,
|
||||
serializer->cancellable,
|
||||
gdk_content_serializer_close_finish,
|
||||
serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,8 +531,9 @@ serialize_not_found (GdkContentSerializer *serializer)
|
||||
* @user_data: (closure): data to pass to the callback function
|
||||
*
|
||||
* Serialize content and write it to the given output stream, asynchronously.
|
||||
* When the operation is finished, @callback will be called. You can then
|
||||
* call gdk_content_serialize_finish() to get the result of the operation.
|
||||
* When the operation is finished, the @stream will be closed and @callback
|
||||
* will be called. You can then call gdk_content_serialize_finish() to get
|
||||
* the result of the operation.
|
||||
*/
|
||||
void
|
||||
gdk_content_serialize_async (GOutputStream *stream,
|
||||
|
@@ -439,8 +439,33 @@ gdk_x11_selection_output_stream_flush (GOutputStream *output_stream,
|
||||
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_flush, stream);
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
if (gdk_x11_selection_output_stream_needs_flush_unlocked (stream))
|
||||
g_cond_wait (&priv->cond, &priv->mutex);
|
||||
while (gdk_x11_selection_output_stream_needs_flush_unlocked (stream))
|
||||
{
|
||||
/* We cannot do sync flushes as we need to run the main loop to do the flushing. */
|
||||
if (g_main_context_is_owner (NULL))
|
||||
{
|
||||
#define ERROR_MESSAGE \
|
||||
"Synchronous flushing of X11 data streams from the main loop is not possible.\n" \
|
||||
"Use g_output_stream_flush_async() or g_output_stream_close_async() to avoid data loss."
|
||||
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, ERROR_MESSAGE);
|
||||
|
||||
/* We also warn here instead of just erroring out because this happens when people forget
|
||||
* to explicitly close a data stream and just unref() it as dispose() runs a sync close()
|
||||
* which does a sync flush().
|
||||
*/
|
||||
g_warning (ERROR_MESSAGE);
|
||||
|
||||
return FALSE;
|
||||
#undef ERROR_MESSAGE
|
||||
}
|
||||
else
|
||||
{
|
||||
g_cond_wait (&priv->cond, &priv->mutex);
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
|
||||
return TRUE;
|
||||
@@ -531,7 +556,7 @@ gdk_x11_selection_output_stream_close_async (GOutputStream *stream,
|
||||
g_task_set_source_tag (task, gdk_x11_selection_output_stream_close_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
gdk_x11_selection_output_stream_invoke_close (stream);
|
||||
gdk_x11_selection_output_stream_invoke_close (g_object_ref (stream));
|
||||
g_task_return_boolean (task, TRUE);
|
||||
|
||||
g_object_unref (task);
|
||||
|
@@ -2,10 +2,46 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include "wayland/gdkwayland.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
text_received (GObject *source,
|
||||
value_received (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||||
const GValue *value;
|
||||
GValue *expected = data;
|
||||
GError *error = NULL;
|
||||
|
||||
value = gdk_clipboard_read_value_finish (clipboard, res, &error);
|
||||
|
||||
g_assert_nonnull (value);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_cmpuint (G_VALUE_TYPE (value), ==, G_VALUE_TYPE (expected));
|
||||
|
||||
if (G_VALUE_TYPE (value) == G_TYPE_STRING)
|
||||
{
|
||||
g_assert_cmpstr (g_value_get_string (value), ==, g_value_get_string (expected));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add a comparison for the missing type here */
|
||||
g_assert_cmpuint (G_VALUE_TYPE (value), ==, G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
g_value_unset (expected);
|
||||
|
||||
g_main_context_wakeup (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
text_received (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||||
gboolean *done = data;
|
||||
@@ -70,14 +106,98 @@ test_clipboard_basic (void)
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_clipboard_sync_changed_cb (GdkClipboard *clipboard,
|
||||
gboolean *done)
|
||||
{
|
||||
GdkContentFormats *formats = gdk_clipboard_get_formats (clipboard);
|
||||
|
||||
/* X11 needs to query formats first and reports empty until then */
|
||||
if (gdk_content_formats_get_gtypes (formats, NULL) == NULL &&
|
||||
gdk_content_formats_get_mime_types (formats, NULL) == NULL)
|
||||
return;
|
||||
|
||||
*done = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
remote_clipboard_sync (GdkClipboard *clipboard)
|
||||
{
|
||||
guint signal;
|
||||
gboolean done;
|
||||
|
||||
done = FALSE;
|
||||
signal = g_signal_connect (clipboard, "changed", G_CALLBACK (remote_clipboard_sync_changed_cb), &done);
|
||||
|
||||
while (!done)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
g_signal_handler_disconnect (clipboard, signal);
|
||||
}
|
||||
|
||||
static void
|
||||
test_remote_basic (gconstpointer data)
|
||||
{
|
||||
GdkDisplay *display, *remote_display;
|
||||
GdkClipboard *clipboard, *remote_clipboard;
|
||||
GdkContentFormats *formats;
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
clipboard = gdk_display_get_clipboard (display);
|
||||
remote_display = GDK_DISPLAY (data);
|
||||
remote_clipboard = gdk_display_get_clipboard (remote_display);
|
||||
|
||||
g_assert_true (gdk_clipboard_get_display (clipboard) == display);
|
||||
g_assert_true (gdk_clipboard_get_display (remote_clipboard) == remote_display);
|
||||
|
||||
gdk_clipboard_set_text (clipboard, "testing, 1, 2");
|
||||
remote_clipboard_sync (remote_clipboard);
|
||||
|
||||
g_assert_true (gdk_clipboard_is_local (clipboard));
|
||||
g_assert_false (gdk_clipboard_is_local (remote_clipboard));
|
||||
g_assert_null (gdk_clipboard_get_content (remote_clipboard));
|
||||
|
||||
formats = gdk_clipboard_get_formats (remote_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"));
|
||||
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
g_value_set_string (&value, "testing, 1, 2");
|
||||
gdk_clipboard_read_value_async (remote_clipboard, G_TYPE_STRING, G_PRIORITY_DEFAULT, NULL, value_received, &value);
|
||||
while (G_IS_VALUE (&value))
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
g_assert_null (gdk_clipboard_get_content (remote_clipboard));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GdkDisplay *remote_display;
|
||||
int result;
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
gtk_init ();
|
||||
|
||||
g_test_add_func ("/clipboard/basic", test_clipboard_basic);
|
||||
|
||||
return g_test_run ();
|
||||
remote_display = gdk_display_open (NULL);
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (!GDK_IS_WAYLAND_DISPLAY (remote_display))
|
||||
#else
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
g_test_add_data_func ("/clipboard/remote/basic", remote_display, test_remote_basic);
|
||||
}
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
g_object_unref (remote_display);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user