[mutter] remote-desktop/session: Implement SelectionRead()
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] remote-desktop/session: Implement SelectionRead()
- Date: Fri, 5 Feb 2021 17:04:38 +0000 (UTC)
commit d7c8535ac6ade82d99830489c3a0ba2c64dade49
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Wed Nov 4 15:03:16 2020 +0100
remote-desktop/session: Implement SelectionRead()
This makes it possible to retrieve the clipboard content from the
current selection clipboard source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1552>
src/backends/meta-remote-desktop-session.c | 132 ++++++++++++++++++++++++++++-
1 file changed, 128 insertions(+), 4 deletions(-)
---
diff --git a/src/backends/meta-remote-desktop-session.c b/src/backends/meta-remote-desktop-session.c
index 8a86bf5416..fcdf8d9fa5 100644
--- a/src/backends/meta-remote-desktop-session.c
+++ b/src/backends/meta-remote-desktop-session.c
@@ -24,9 +24,14 @@
#include "backends/meta-remote-desktop-session.h"
+#include <fcntl.h>
+#include <gio/gunixfdlist.h>
+#include <gio/gunixoutputstream.h>
+#include <glib-unix.h>
#include <linux/input.h>
-#include <xkbcommon/xkbcommon.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <xkbcommon/xkbcommon.h>
#include "backends/meta-dbus-session-watcher.h"
#include "backends/meta-screen-cast-session.h"
@@ -34,6 +39,7 @@
#include "backends/x11/meta-backend-x11.h"
#include "cogl/cogl.h"
#include "core/display-private.h"
+#include "core/meta-selection-private.h"
#include "meta/meta-backend.h"
#include "meta-dbus-remote-desktop.h"
@@ -49,6 +55,13 @@ typedef enum _MetaRemoteDesktopNotifyAxisFlags
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS = 1 << 3,
} MetaRemoteDesktopNotifyAxisFlags;
+typedef struct _SelectionReadData
+{
+ MetaRemoteDesktopSession *session;
+ GOutputStream *stream;
+ GCancellable *cancellable;
+} SelectionReadData;
+
struct _MetaRemoteDesktopSession
{
MetaDBusRemoteDesktopSessionSkeleton parent;
@@ -71,6 +84,7 @@ struct _MetaRemoteDesktopSession
gboolean is_clipboard_enabled;
gulong owner_changed_handler_id;
+ SelectionReadData *read_data;
unsigned int transfer_serial;
};
@@ -918,6 +932,17 @@ handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
return TRUE;
}
+static void
+cancel_selection_read (MetaRemoteDesktopSession *session)
+{
+ if (!session->read_data)
+ return;
+
+ g_cancellable_cancel (session->read_data->cancellable);
+ session->read_data->session = NULL;
+ session->read_data = NULL;
+}
+
static gboolean
handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
GDBusMethodInvocation *invocation)
@@ -939,6 +964,7 @@ handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
}
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
+ cancel_selection_read (session);
meta_dbus_remote_desktop_session_complete_disable_clipboard (skeleton,
invocation);
@@ -1037,13 +1063,52 @@ handle_selection_write_done (MetaDBusRemoteDesktopSession *skeleton,
return TRUE;
}
+static void
+transfer_cb (MetaSelection *selection,
+ GAsyncResult *res,
+ SelectionReadData *read_data)
+{
+ g_autoptr (GError) error = NULL;
+
+ if (!meta_selection_transfer_finish (selection, res, &error))
+ {
+ g_warning ("Could not fetch selection data "
+ "for remote desktop session: %s",
+ error->message);
+ }
+
+ if (read_data->session)
+ {
+ meta_topic (META_DEBUG_REMOTE_DESKTOP, "Finished selection transfer for %s",
+ read_data->session->peer_name);
+ }
+
+ g_output_stream_close (read_data->stream, NULL, NULL);
+ g_clear_object (&read_data->stream);
+ g_clear_object (&read_data->cancellable);
+
+ if (read_data->session)
+ read_data->session->read_data = NULL;
+
+ g_free (read_data);
+}
+
static gboolean
handle_selection_read (MetaDBusRemoteDesktopSession *skeleton,
GDBusMethodInvocation *invocation,
- GUnixFDList *fd_list,
+ GUnixFDList *fd_list_in,
const char *mime_type)
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
+ MetaDisplay *display = meta_get_display ();
+ MetaSelection *selection = meta_display_get_selection (display);
+ MetaSelectionSource *source;
+ g_autoptr (GError) error = NULL;
+ int pipe_fds[2];
+ g_autoptr (GUnixFDList) fd_list = NULL;
+ int fd_idx;
+ GVariant *fd_variant;
+ SelectionReadData *read_data;
meta_topic (META_DEBUG_REMOTE_DESKTOP,
"Read selection for %s",
@@ -1057,10 +1122,68 @@ handle_selection_read (MetaDBusRemoteDesktopSession *skeleton,
return TRUE;
}
+ source = meta_selection_get_current_owner (selection,
+ META_SELECTION_CLIPBOARD);
+ if (!source)
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+ G_DBUS_ERROR_FILE_NOT_FOUND,
+ "No selection owner available");
+ return TRUE;
+ }
+
+ if (session->read_data)
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+ G_DBUS_ERROR_LIMITS_EXCEEDED,
+ "Tried to read in parallel");
+ 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[0], NULL);
+ close (pipe_fds[0]);
+ fd_variant = g_variant_new_handle (fd_idx);
+
+ session->read_data = read_data = g_new0 (SelectionReadData, 1);
+ read_data->session = session;
+ read_data->stream = g_unix_output_stream_new (pipe_fds[1], TRUE);
+ read_data->cancellable = g_cancellable_new ();
+ meta_selection_transfer_async (selection,
+ META_SELECTION_CLIPBOARD,
+ mime_type,
+ -1,
+ read_data->stream,
+ read_data->cancellable,
+ (GAsyncReadyCallback) transfer_cb,
+ read_data);
+
meta_dbus_remote_desktop_session_complete_selection_read (skeleton,
invocation,
- NULL,
- NULL);
+ fd_list,
+ fd_variant);
return TRUE;
}
@@ -1110,6 +1233,7 @@ meta_remote_desktop_session_finalize (GObject *object)
g_assert (!meta_remote_desktop_session_is_running (session));
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
+ cancel_selection_read (session);
g_clear_object (&session->handle);
g_free (session->peer_name);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]