mirror of
https://github.com/brl/mutter.git
synced 2025-02-19 14:44:10 +00:00
remote-desktop/session: Add support for SelectionTransfer/Write
When a transfer request is done to the MetaSelectionSourceRemote source, it's translated to a SelectionTransfer signal, which the remote desktop server is supposed to respond to with SelectionWrite. A timeout (set to 15 seconds) is added to handle too long timeouts, which cancels the transfer request. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1552>
This commit is contained in:
parent
d7c8535ac6
commit
5104a9b2ce
@ -312,6 +312,12 @@ s2us (int64_t s)
|
|||||||
return ms2us (s * 1000);
|
return ms2us (s * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int64_t
|
||||||
|
s2ms (int64_t s)
|
||||||
|
{
|
||||||
|
return (int64_t) ms (s * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_PRIVATE_H__ */
|
#endif /* __CLUTTER_PRIVATE_H__ */
|
||||||
|
@ -40,12 +40,15 @@
|
|||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
#include "core/display-private.h"
|
#include "core/display-private.h"
|
||||||
#include "core/meta-selection-private.h"
|
#include "core/meta-selection-private.h"
|
||||||
|
#include "core/meta-selection-source-remote.h"
|
||||||
#include "meta/meta-backend.h"
|
#include "meta/meta-backend.h"
|
||||||
|
|
||||||
#include "meta-dbus-remote-desktop.h"
|
#include "meta-dbus-remote-desktop.h"
|
||||||
|
|
||||||
#define META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/org/gnome/Mutter/RemoteDesktop/Session"
|
#define META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/org/gnome/Mutter/RemoteDesktop/Session"
|
||||||
|
|
||||||
|
#define TRANSFER_REQUEST_CLEANUP_TIMEOUT_MS (s2ms (15))
|
||||||
|
|
||||||
typedef enum _MetaRemoteDesktopNotifyAxisFlags
|
typedef enum _MetaRemoteDesktopNotifyAxisFlags
|
||||||
{
|
{
|
||||||
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_NONE = 0,
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_NONE = 0,
|
||||||
@ -86,6 +89,9 @@ struct _MetaRemoteDesktopSession
|
|||||||
gulong owner_changed_handler_id;
|
gulong owner_changed_handler_id;
|
||||||
SelectionReadData *read_data;
|
SelectionReadData *read_data;
|
||||||
unsigned int transfer_serial;
|
unsigned int transfer_serial;
|
||||||
|
MetaSelectionSourceRemote *current_source;
|
||||||
|
GHashTable *transfer_requests;
|
||||||
|
guint transfer_request_timeout_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -810,6 +816,31 @@ handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaSelectionSourceRemote *
|
||||||
|
create_remote_desktop_source (MetaRemoteDesktopSession *session,
|
||||||
|
GVariant *mime_types_variant,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GVariantIter iter;
|
||||||
|
char *mime_type;
|
||||||
|
GList *mime_types = NULL;
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, mime_types_variant);
|
||||||
|
if (g_variant_iter_n_children (&iter) == 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||||
|
"No mime types in mime types list");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (g_variant_iter_next (&iter, "s", &mime_type))
|
||||||
|
mime_types = g_list_prepend (mime_types, mime_type);
|
||||||
|
|
||||||
|
mime_types = g_list_reverse (mime_types);
|
||||||
|
|
||||||
|
return meta_selection_source_remote_new (session, mime_types);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
mime_types_to_string (char **formats,
|
mime_types_to_string (char **formats,
|
||||||
char *buf,
|
char *buf,
|
||||||
@ -831,8 +862,16 @@ mime_types_to_string (char **formats,
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_own_source (MetaRemoteDesktopSession *session,
|
||||||
|
MetaSelectionSource *source)
|
||||||
|
{
|
||||||
|
return source && source == META_SELECTION_SOURCE (session->current_source);
|
||||||
|
}
|
||||||
|
|
||||||
static GVariant *
|
static GVariant *
|
||||||
generate_owner_changed_variant (char **mime_types_array)
|
generate_owner_changed_variant (char **mime_types_array,
|
||||||
|
gboolean is_own_source)
|
||||||
{
|
{
|
||||||
GVariantBuilder builder;
|
GVariantBuilder builder;
|
||||||
|
|
||||||
@ -841,6 +880,8 @@ generate_owner_changed_variant (char **mime_types_array)
|
|||||||
{
|
{
|
||||||
g_variant_builder_add (&builder, "{sv}", "mime-types",
|
g_variant_builder_add (&builder, "{sv}", "mime-types",
|
||||||
g_variant_new ("(^as)", mime_types_array));
|
g_variant_new ("(^as)", mime_types_array));
|
||||||
|
g_variant_builder_add (&builder, "{sv}", "session-is-owner",
|
||||||
|
g_variant_new_boolean (is_own_source));
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_variant_builder_end (&builder);
|
return g_variant_builder_end (&builder);
|
||||||
@ -875,16 +916,19 @@ on_selection_owner_changed (MetaSelection *selection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
"Clipboard owner changed, owner: %p (%s), mime types: [%s], "
|
"Clipboard owner changed, owner: %p (%s, is own? %s), mime types: [%s], "
|
||||||
"notifying %s",
|
"notifying %s",
|
||||||
owner,
|
owner,
|
||||||
owner ? g_type_name_from_instance ((GTypeInstance *) owner)
|
owner ? g_type_name_from_instance ((GTypeInstance *) owner)
|
||||||
: "NULL",
|
: "NULL",
|
||||||
|
is_own_source (session, owner) ? "yes" : "no",
|
||||||
mime_types_to_string (mime_types_array, log_buf,
|
mime_types_to_string (mime_types_array, log_buf,
|
||||||
G_N_ELEMENTS (log_buf)),
|
G_N_ELEMENTS (log_buf)),
|
||||||
session->peer_name);
|
session->peer_name);
|
||||||
|
|
||||||
options_variant = generate_owner_changed_variant (mime_types_array);
|
options_variant =
|
||||||
|
generate_owner_changed_variant (mime_types_array,
|
||||||
|
is_own_source (session, owner));
|
||||||
|
|
||||||
object_path = g_dbus_interface_skeleton_get_object_path (
|
object_path = g_dbus_interface_skeleton_get_object_path (
|
||||||
G_DBUS_INTERFACE_SKELETON (session));
|
G_DBUS_INTERFACE_SKELETON (session));
|
||||||
@ -895,8 +939,6 @@ on_selection_owner_changed (MetaSelection *selection,
|
|||||||
"SelectionOwnerChanged",
|
"SelectionOwnerChanged",
|
||||||
g_variant_new ("(@a{sv})", options_variant),
|
g_variant_new ("(@a{sv})", options_variant),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
session->transfer_serial++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -905,6 +947,8 @@ handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
GVariant *arg_options)
|
GVariant *arg_options)
|
||||||
{
|
{
|
||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
|
GVariant *mime_types_variant;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
MetaDisplay *display = meta_get_display ();
|
MetaDisplay *display = meta_get_display ();
|
||||||
MetaSelection *selection = meta_display_get_selection (display);
|
MetaSelection *selection = meta_display_get_selection (display);
|
||||||
|
|
||||||
@ -920,6 +964,35 @@ handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mime_types_variant = g_variant_lookup_value (arg_options,
|
||||||
|
"mime-types",
|
||||||
|
G_VARIANT_TYPE_STRING_ARRAY);
|
||||||
|
if (mime_types_variant)
|
||||||
|
{
|
||||||
|
g_autoptr (MetaSelectionSourceRemote) source_remote = NULL;
|
||||||
|
|
||||||
|
source_remote = create_remote_desktop_source (session,
|
||||||
|
mime_types_variant,
|
||||||
|
&error);
|
||||||
|
if (!source_remote)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Invalid mime type list: %s",
|
||||||
|
error->message);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
|
"Setting remote desktop clipboard source: %p from %s",
|
||||||
|
source_remote, session->peer_name);
|
||||||
|
|
||||||
|
g_set_object (&session->current_source, source_remote);
|
||||||
|
meta_selection_set_owner (selection,
|
||||||
|
META_SELECTION_CLIPBOARD,
|
||||||
|
META_SELECTION_SOURCE (source_remote));
|
||||||
|
}
|
||||||
|
|
||||||
session->is_clipboard_enabled = TRUE;
|
session->is_clipboard_enabled = TRUE;
|
||||||
session->owner_changed_handler_id =
|
session->owner_changed_handler_id =
|
||||||
g_signal_connect (selection, "owner-changed",
|
g_signal_connect (selection, "owner-changed",
|
||||||
@ -932,6 +1005,64 @@ handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cancel_transfer_request (gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GTask *task = G_TASK (value);
|
||||||
|
MetaRemoteDesktopSession *session = user_data;
|
||||||
|
|
||||||
|
meta_selection_source_remote_cancel_transfer (session->current_source,
|
||||||
|
task);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_desktop_session_cancel_transfer_requests (MetaRemoteDesktopSession *session)
|
||||||
|
{
|
||||||
|
g_return_if_fail (session->current_source);
|
||||||
|
|
||||||
|
g_hash_table_foreach_remove (session->transfer_requests,
|
||||||
|
cancel_transfer_request,
|
||||||
|
session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
transfer_request_cleanup_timout (gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaRemoteDesktopSession *session = user_data;
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
|
"Cancel unanswered SelectionTransfer requests for %s, "
|
||||||
|
"waited for %.02f seconds already",
|
||||||
|
session->peer_name,
|
||||||
|
TRANSFER_REQUEST_CLEANUP_TIMEOUT_MS / 1000.0);
|
||||||
|
|
||||||
|
meta_remote_desktop_session_cancel_transfer_requests (session);
|
||||||
|
|
||||||
|
session->transfer_request_timeout_id = 0;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_current_selection_source (MetaRemoteDesktopSession *session)
|
||||||
|
{
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
MetaSelection *selection = meta_display_get_selection (display);
|
||||||
|
|
||||||
|
if (!session->current_source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_selection_unset_owner (selection,
|
||||||
|
META_SELECTION_CLIPBOARD,
|
||||||
|
META_SELECTION_SOURCE (session->current_source));
|
||||||
|
meta_remote_desktop_session_cancel_transfer_requests (session);
|
||||||
|
g_clear_handle_id (&session->transfer_request_timeout_id, g_source_remove);
|
||||||
|
g_clear_object (&session->current_source);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cancel_selection_read (MetaRemoteDesktopSession *session)
|
cancel_selection_read (MetaRemoteDesktopSession *session)
|
||||||
{
|
{
|
||||||
@ -964,6 +1095,7 @@ handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
|
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
|
||||||
|
reset_current_selection_source (session);
|
||||||
cancel_selection_read (session);
|
cancel_selection_read (session);
|
||||||
|
|
||||||
meta_dbus_remote_desktop_session_complete_disable_clipboard (skeleton,
|
meta_dbus_remote_desktop_session_complete_disable_clipboard (skeleton,
|
||||||
@ -978,10 +1110,8 @@ handle_set_selection (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
GVariant *arg_options)
|
GVariant *arg_options)
|
||||||
{
|
{
|
||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
|
g_autoptr (GVariant) mime_types_variant = NULL;
|
||||||
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
g_autoptr (GError) error = NULL;
|
||||||
"Set selection for %s",
|
|
||||||
g_dbus_method_invocation_get_sender (invocation));
|
|
||||||
|
|
||||||
if (!session->is_clipboard_enabled)
|
if (!session->is_clipboard_enabled)
|
||||||
{
|
{
|
||||||
@ -991,19 +1121,114 @@ handle_set_selection (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (session->current_source)
|
||||||
|
{
|
||||||
|
meta_remote_desktop_session_cancel_transfer_requests (session);
|
||||||
|
g_clear_handle_id (&session->transfer_request_timeout_id,
|
||||||
|
g_source_remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
mime_types_variant = g_variant_lookup_value (arg_options,
|
||||||
|
"mime-types",
|
||||||
|
G_VARIANT_TYPE_STRING_ARRAY);
|
||||||
|
if (mime_types_variant)
|
||||||
|
{
|
||||||
|
g_autoptr (MetaSelectionSourceRemote) source_remote = NULL;
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
|
||||||
|
source_remote = create_remote_desktop_source (session,
|
||||||
|
mime_types_variant,
|
||||||
|
&error);
|
||||||
|
if (!source_remote)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Invalid format list: %s",
|
||||||
|
error->message);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
|
"Set selection for %s to %p",
|
||||||
|
g_dbus_method_invocation_get_sender (invocation),
|
||||||
|
source_remote);
|
||||||
|
|
||||||
|
g_set_object (&session->current_source, source_remote);
|
||||||
|
meta_selection_set_owner (meta_display_get_selection (display),
|
||||||
|
META_SELECTION_CLIPBOARD,
|
||||||
|
META_SELECTION_SOURCE (source_remote));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
|
"Unset selection for %s",
|
||||||
|
g_dbus_method_invocation_get_sender (invocation));
|
||||||
|
|
||||||
|
reset_current_selection_source (session);
|
||||||
|
}
|
||||||
|
|
||||||
meta_dbus_remote_desktop_session_complete_set_selection (skeleton,
|
meta_dbus_remote_desktop_session_complete_set_selection (skeleton,
|
||||||
invocation);
|
invocation);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_transfer_cleanup_timeout (MetaRemoteDesktopSession *session)
|
||||||
|
{
|
||||||
|
g_clear_handle_id (&session->transfer_request_timeout_id, g_source_remove);
|
||||||
|
session->transfer_request_timeout_id =
|
||||||
|
g_timeout_add (TRANSFER_REQUEST_CLEANUP_TIMEOUT_MS,
|
||||||
|
transfer_request_cleanup_timout,
|
||||||
|
session);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_remote_desktop_session_request_transfer (MetaRemoteDesktopSession *session,
|
||||||
|
const char *mime_type,
|
||||||
|
GTask *task)
|
||||||
|
{
|
||||||
|
const char *object_path;
|
||||||
|
|
||||||
|
session->transfer_serial++;
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
|
"Emit SelectionTransfer ('%s', %u) for %s",
|
||||||
|
mime_type,
|
||||||
|
session->transfer_serial,
|
||||||
|
session->peer_name);
|
||||||
|
|
||||||
|
g_hash_table_insert (session->transfer_requests,
|
||||||
|
GUINT_TO_POINTER (session->transfer_serial),
|
||||||
|
task);
|
||||||
|
reset_transfer_cleanup_timeout (session);
|
||||||
|
|
||||||
|
object_path = g_dbus_interface_skeleton_get_object_path (
|
||||||
|
G_DBUS_INTERFACE_SKELETON (session));
|
||||||
|
g_dbus_connection_emit_signal (session->connection,
|
||||||
|
NULL,
|
||||||
|
object_path,
|
||||||
|
"org.gnome.Mutter.RemoteDesktop.Session",
|
||||||
|
"SelectionTransfer",
|
||||||
|
g_variant_new ("(su)",
|
||||||
|
mime_type,
|
||||||
|
session->transfer_serial),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_selection_write (MetaDBusRemoteDesktopSession *skeleton,
|
handle_selection_write (MetaDBusRemoteDesktopSession *skeleton,
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
GUnixFDList *fd_list,
|
GUnixFDList *fd_list_in,
|
||||||
unsigned int serial)
|
unsigned int serial)
|
||||||
{
|
{
|
||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
int pipe_fds[2];
|
||||||
|
g_autoptr (GUnixFDList) fd_list = NULL;
|
||||||
|
int fd_idx;
|
||||||
|
GVariant *fd_variant;
|
||||||
|
GTask *task;
|
||||||
|
|
||||||
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
||||||
"Write selection for %s",
|
"Write selection for %s",
|
||||||
@ -1017,22 +1242,62 @@ handle_selection_write (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->transfer_serial != serial)
|
if (!session->current_source)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_FAILED,
|
G_DBUS_ERROR_FAILED,
|
||||||
"Provided transfer serial %u "
|
"No current selection owned");
|
||||||
"doesn't match current current "
|
|
||||||
"transfer serial %u",
|
|
||||||
serial,
|
|
||||||
session->transfer_serial);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_hash_table_steal_extended (session->transfer_requests,
|
||||||
|
GUINT_TO_POINTER (serial),
|
||||||
|
NULL,
|
||||||
|
(gpointer *) &task))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Transfer serial %u doesn't match "
|
||||||
|
"any transfer request",
|
||||||
|
serial);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Failed open pipe: %s",
|
||||||
|
error->message);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_unix_set_fd_nonblocking (pipe_fds[0], TRUE, &error))
|
||||||
|
{
|
||||||
|
close (pipe_fds[0]);
|
||||||
|
close (pipe_fds[1]);
|
||||||
|
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Failed to make pipe non-blocking: %s",
|
||||||
|
error->message);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_list = g_unix_fd_list_new ();
|
||||||
|
|
||||||
|
fd_idx = g_unix_fd_list_append (fd_list, pipe_fds[1], NULL);
|
||||||
|
close (pipe_fds[1]);
|
||||||
|
fd_variant = g_variant_new_handle (fd_idx);
|
||||||
|
|
||||||
|
meta_selection_source_remote_complete_transfer (session->current_source,
|
||||||
|
pipe_fds[0],
|
||||||
|
task);
|
||||||
|
|
||||||
meta_dbus_remote_desktop_session_complete_selection_write (skeleton,
|
meta_dbus_remote_desktop_session_complete_selection_write (skeleton,
|
||||||
invocation,
|
invocation,
|
||||||
NULL,
|
fd_list,
|
||||||
NULL);
|
fd_variant);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -1132,6 +1397,14 @@ handle_selection_read (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_own_source (session, source))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Tried to read own selection");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->read_data)
|
if (session->read_data)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
@ -1233,7 +1506,9 @@ meta_remote_desktop_session_finalize (GObject *object)
|
|||||||
g_assert (!meta_remote_desktop_session_is_running (session));
|
g_assert (!meta_remote_desktop_session_is_running (session));
|
||||||
|
|
||||||
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
|
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
|
||||||
|
reset_current_selection_source (session);
|
||||||
cancel_selection_read (session);
|
cancel_selection_read (session);
|
||||||
|
g_hash_table_unref (session->transfer_requests);
|
||||||
|
|
||||||
g_clear_object (&session->handle);
|
g_clear_object (&session->handle);
|
||||||
g_free (session->peer_name);
|
g_free (session->peer_name);
|
||||||
@ -1260,6 +1535,8 @@ meta_remote_desktop_session_init (MetaRemoteDesktopSession *session)
|
|||||||
session->object_path =
|
session->object_path =
|
||||||
g_strdup_printf (META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/u%u",
|
g_strdup_printf (META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/u%u",
|
||||||
++global_session_number);
|
++global_session_number);
|
||||||
|
|
||||||
|
session->transfer_requests = g_hash_table_new (NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -47,6 +47,10 @@ gboolean meta_remote_desktop_session_register_screen_cast (MetaRemoteDesktopSess
|
|||||||
MetaScreenCastSession *screen_cast_session,
|
MetaScreenCastSession *screen_cast_session,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
void meta_remote_desktop_session_request_transfer (MetaRemoteDesktopSession *session,
|
||||||
|
const char *mime_type,
|
||||||
|
GTask *task);
|
||||||
|
|
||||||
void meta_remote_desktop_session_close (MetaRemoteDesktopSession *session);
|
void meta_remote_desktop_session_close (MetaRemoteDesktopSession *session);
|
||||||
|
|
||||||
MetaRemoteDesktopSession * meta_remote_desktop_session_new (MetaRemoteDesktop *remote_desktop,
|
MetaRemoteDesktopSession * meta_remote_desktop_session_new (MetaRemoteDesktop *remote_desktop,
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "core/meta-selection-source-remote.h"
|
#include "core/meta-selection-source-remote.h"
|
||||||
|
|
||||||
|
#include <gio/gunixinputstream.h>
|
||||||
|
|
||||||
#include "backends/meta-remote-desktop-session.h"
|
#include "backends/meta-remote-desktop-session.h"
|
||||||
|
|
||||||
struct _MetaSelectionSourceRemote
|
struct _MetaSelectionSourceRemote
|
||||||
@ -56,16 +58,16 @@ meta_selection_source_remote_read_async (MetaSelectionSource *source,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
MetaSelectionSourceRemote *source_remote =
|
||||||
|
META_SELECTION_SOURCE_REMOTE (source);
|
||||||
GTask *task;
|
GTask *task;
|
||||||
GInputStream *stream;
|
|
||||||
|
|
||||||
task = g_task_new (source, cancellable, callback, user_data);
|
task = g_task_new (source, cancellable, callback, user_data);
|
||||||
g_task_set_source_tag (task, meta_selection_source_remote_read_async);
|
g_task_set_source_tag (task, meta_selection_source_remote_read_async);
|
||||||
|
|
||||||
stream = g_memory_input_stream_new_from_data ("place holder text", -1, NULL);
|
meta_remote_desktop_session_request_transfer (source_remote->session,
|
||||||
g_task_return_pointer (task, stream, g_object_unref);
|
mimetype,
|
||||||
|
task);
|
||||||
g_object_unref (task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GInputStream *
|
static GInputStream *
|
||||||
@ -80,6 +82,27 @@ meta_selection_source_remote_read_finish (MetaSelectionSource *source,
|
|||||||
return g_task_propagate_pointer (G_TASK (result), error);
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_selection_source_remote_complete_transfer (MetaSelectionSourceRemote *source_remote,
|
||||||
|
int fd,
|
||||||
|
GTask *task)
|
||||||
|
{
|
||||||
|
GInputStream *stream;
|
||||||
|
|
||||||
|
stream = g_unix_input_stream_new (fd, TRUE);
|
||||||
|
g_task_return_pointer (task, stream, g_object_unref);
|
||||||
|
g_object_unref (task);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_selection_source_remote_cancel_transfer (MetaSelectionSourceRemote *source_remote,
|
||||||
|
GTask *task)
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
||||||
|
"Remote selection transfer was cancelled");
|
||||||
|
g_object_unref (task);
|
||||||
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
meta_selection_source_remote_get_mimetypes (MetaSelectionSource *source)
|
meta_selection_source_remote_get_mimetypes (MetaSelectionSource *source)
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,13 @@ G_DECLARE_FINAL_TYPE (MetaSelectionSourceRemote,
|
|||||||
META, SELECTION_SOURCE_REMOTE,
|
META, SELECTION_SOURCE_REMOTE,
|
||||||
MetaSelectionSource)
|
MetaSelectionSource)
|
||||||
|
|
||||||
|
void meta_selection_source_remote_complete_transfer (MetaSelectionSourceRemote *source_remote,
|
||||||
|
int fd,
|
||||||
|
GTask *task);
|
||||||
|
|
||||||
|
void meta_selection_source_remote_cancel_transfer (MetaSelectionSourceRemote *source_remote,
|
||||||
|
GTask *task);
|
||||||
|
|
||||||
MetaSelectionSourceRemote * meta_selection_source_remote_new (MetaRemoteDesktopSession *session,
|
MetaSelectionSourceRemote * meta_selection_source_remote_new (MetaRemoteDesktopSession *session,
|
||||||
GList *mime_types);
|
GList *mime_types);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user