mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
core/selection: Cancel selection transfer requests after a timeout
When a selection owner advertises a mime type, but does not provide the content upon a request for the mime type content, the requesting side might wait indefinitely on the content. To avoid this situation, add a timeout source, which will cancel the selection transfer request after a certain timeout (15 seconds) passed. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1874>
This commit is contained in:
parent
20db6af4e6
commit
537e2dfafe
@ -39,6 +39,10 @@ struct TransferRequest
|
|||||||
GInputStream *istream;
|
GInputStream *istream;
|
||||||
GOutputStream *ostream;
|
GOutputStream *ostream;
|
||||||
gssize len;
|
gssize len;
|
||||||
|
GSource *timeout_source;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GCancellable *external_cancellable;
|
||||||
|
gulong cancellable_signal_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -174,10 +178,39 @@ meta_selection_get_mimetypes (MetaSelection *selection,
|
|||||||
return meta_selection_source_get_mimetypes (selection->owners[selection_type]);
|
return meta_selection_source_get_mimetypes (selection->owners[selection_type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cancel_transfer_request (gpointer user_data)
|
||||||
|
{
|
||||||
|
TransferRequest *request = user_data;
|
||||||
|
|
||||||
|
g_cancellable_cancel (request->cancellable);
|
||||||
|
if (request->cancellable_signal_handler)
|
||||||
|
{
|
||||||
|
g_assert (request->external_cancellable);
|
||||||
|
g_cancellable_disconnect (request->external_cancellable,
|
||||||
|
request->cancellable_signal_handler);
|
||||||
|
request->cancellable_signal_handler = 0;
|
||||||
|
g_object_unref (request->external_cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_external_cancellable_cancelled (GCancellable *external_cancellable,
|
||||||
|
TransferRequest *request)
|
||||||
|
{
|
||||||
|
g_cancellable_cancel (request->cancellable);
|
||||||
|
|
||||||
|
g_source_destroy (request->timeout_source);
|
||||||
|
g_clear_pointer (&request->timeout_source, g_source_unref);
|
||||||
|
}
|
||||||
|
|
||||||
static TransferRequest *
|
static TransferRequest *
|
||||||
transfer_request_new (GOutputStream *ostream,
|
transfer_request_new (GOutputStream *ostream,
|
||||||
MetaSelectionType selection_type,
|
MetaSelectionType selection_type,
|
||||||
gssize len)
|
ssize_t len,
|
||||||
|
GCancellable *external_cancellable)
|
||||||
{
|
{
|
||||||
TransferRequest *request;
|
TransferRequest *request;
|
||||||
|
|
||||||
@ -185,12 +218,44 @@ transfer_request_new (GOutputStream *ostream,
|
|||||||
request->ostream = g_object_ref (ostream);
|
request->ostream = g_object_ref (ostream);
|
||||||
request->selection_type = selection_type;
|
request->selection_type = selection_type;
|
||||||
request->len = len;
|
request->len = len;
|
||||||
|
request->cancellable = g_cancellable_new ();
|
||||||
|
request->timeout_source = g_timeout_source_new_seconds (15);
|
||||||
|
|
||||||
|
g_source_set_callback (request->timeout_source, cancel_transfer_request,
|
||||||
|
request, NULL);
|
||||||
|
g_source_attach (request->timeout_source, NULL);
|
||||||
|
|
||||||
|
if (external_cancellable)
|
||||||
|
{
|
||||||
|
request->external_cancellable = g_object_ref (external_cancellable);
|
||||||
|
request->cancellable_signal_handler =
|
||||||
|
g_cancellable_connect (external_cancellable,
|
||||||
|
G_CALLBACK (on_external_cancellable_cancelled),
|
||||||
|
request, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
transfer_request_free (TransferRequest *request)
|
transfer_request_free (TransferRequest *request)
|
||||||
{
|
{
|
||||||
|
if (request->cancellable_signal_handler)
|
||||||
|
{
|
||||||
|
g_assert (request->external_cancellable);
|
||||||
|
g_cancellable_disconnect (request->external_cancellable,
|
||||||
|
request->cancellable_signal_handler);
|
||||||
|
request->cancellable_signal_handler = 0;
|
||||||
|
g_object_unref (request->external_cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->timeout_source)
|
||||||
|
{
|
||||||
|
g_source_destroy (request->timeout_source);
|
||||||
|
g_clear_pointer (&request->timeout_source, g_source_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&request->cancellable);
|
||||||
g_clear_object (&request->istream);
|
g_clear_object (&request->istream);
|
||||||
g_clear_object (&request->ostream);
|
g_clear_object (&request->ostream);
|
||||||
g_free (request);
|
g_free (request);
|
||||||
@ -362,6 +427,7 @@ meta_selection_transfer_async (MetaSelection *selection,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
TransferRequest *transfer_request;
|
||||||
GTask *task;
|
GTask *task;
|
||||||
|
|
||||||
g_return_if_fail (META_IS_SELECTION (selection));
|
g_return_if_fail (META_IS_SELECTION (selection));
|
||||||
@ -372,12 +438,14 @@ meta_selection_transfer_async (MetaSelection *selection,
|
|||||||
task = g_task_new (selection, cancellable, callback, user_data);
|
task = g_task_new (selection, cancellable, callback, user_data);
|
||||||
g_task_set_source_tag (task, meta_selection_transfer_async);
|
g_task_set_source_tag (task, meta_selection_transfer_async);
|
||||||
|
|
||||||
g_task_set_task_data (task,
|
transfer_request = transfer_request_new (output, selection_type, size,
|
||||||
transfer_request_new (output, selection_type, size),
|
cancellable);
|
||||||
|
|
||||||
|
g_task_set_task_data (task, transfer_request,
|
||||||
(GDestroyNotify) transfer_request_free);
|
(GDestroyNotify) transfer_request_free);
|
||||||
meta_selection_source_read_async (selection->owners[selection_type],
|
meta_selection_source_read_async (selection->owners[selection_type],
|
||||||
mimetype,
|
mimetype,
|
||||||
cancellable,
|
transfer_request->cancellable,
|
||||||
(GAsyncReadyCallback) source_read_cb,
|
(GAsyncReadyCallback) source_read_cb,
|
||||||
task);
|
task);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user