[mutter] remote-desktop/session: Forward MetaSelection::owner-changed



commit 6398d5a10910b116e42d4050ea97b18aff3d4333
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Nov 4 10:27:40 2020 +0100

    remote-desktop/session: Forward MetaSelection::owner-changed
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1552>

 src/backends/meta-remote-desktop-session.c | 124 ++++++++++++++++++++++++++++-
 1 file changed, 121 insertions(+), 3 deletions(-)
---
diff --git a/src/backends/meta-remote-desktop-session.c b/src/backends/meta-remote-desktop-session.c
index e7cedb40dd..8a86bf5416 100644
--- a/src/backends/meta-remote-desktop-session.c
+++ b/src/backends/meta-remote-desktop-session.c
@@ -33,6 +33,7 @@
 #include "backends/meta-remote-access-controller-private.h"
 #include "backends/x11/meta-backend-x11.h"
 #include "cogl/cogl.h"
+#include "core/display-private.h"
 #include "meta/meta-backend.h"
 
 #include "meta-dbus-remote-desktop.h"
@@ -52,6 +53,7 @@ struct _MetaRemoteDesktopSession
 {
   MetaDBusRemoteDesktopSessionSkeleton parent;
 
+  GDBusConnection *connection;
   char *peer_name;
 
   char *session_id;
@@ -68,6 +70,8 @@ struct _MetaRemoteDesktopSession
   MetaRemoteDesktopSessionHandle *handle;
 
   gboolean is_clipboard_enabled;
+  gulong owner_changed_handler_id;
+  unsigned int transfer_serial;
 };
 
 static void
@@ -231,16 +235,15 @@ meta_remote_desktop_session_new (MetaRemoteDesktop  *remote_desktop,
 {
   GDBusInterfaceSkeleton *interface_skeleton;
   MetaRemoteDesktopSession *session;
-  GDBusConnection *connection;
 
   session = g_object_new (META_TYPE_REMOTE_DESKTOP_SESSION, NULL);
 
   session->peer_name = g_strdup (peer_name);
 
   interface_skeleton = G_DBUS_INTERFACE_SKELETON (session);
-  connection = meta_remote_desktop_get_connection (remote_desktop);
+  session->connection = meta_remote_desktop_get_connection (remote_desktop);
   if (!g_dbus_interface_skeleton_export (interface_skeleton,
-                                         connection,
+                                         session->connection,
                                          session->object_path,
                                          error))
     {
@@ -793,12 +796,103 @@ handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
   return TRUE;
 }
 
+static const char *
+mime_types_to_string (char **formats,
+                      char  *buf,
+                      int    buf_len)
+{
+  g_autofree char *mime_types_string = NULL;
+  int len;
+
+  if (!formats)
+    return "N\\A";
+
+  mime_types_string = g_strjoinv (",", formats);
+  len = strlen (mime_types_string);
+  strncpy (buf, mime_types_string, buf_len - 1);
+  if (len >= buf_len - 1)
+    buf[buf_len - 2] = '*';
+  buf[buf_len - 1] = '\0';
+
+  return buf;
+}
+
+static GVariant *
+generate_owner_changed_variant (char **mime_types_array)
+{
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+  if (mime_types_array)
+    {
+      g_variant_builder_add (&builder, "{sv}", "mime-types",
+                             g_variant_new ("(^as)", mime_types_array));
+    }
+
+  return g_variant_builder_end (&builder);
+}
+
+static void
+on_selection_owner_changed (MetaSelection            *selection,
+                            MetaSelectionType         selection_type,
+                            MetaSelectionSource      *owner,
+                            MetaRemoteDesktopSession *session)
+{
+  char log_buf[255];
+  g_autofree char **mime_types_array = NULL;
+  GList *l;
+  int i;
+  GVariant *options_variant;
+  const char *object_path;
+
+  if (selection_type != META_SELECTION_CLIPBOARD)
+    return;
+
+  if (owner)
+    {
+      GList *mime_types;
+      mime_types = meta_selection_source_get_mimetypes (owner);
+
+      mime_types_array = g_new0 (char *, g_list_length (mime_types) + 1);
+      for (l = meta_selection_source_get_mimetypes (owner), i = 0;
+           l;
+           l = l->next, i++)
+        mime_types_array[i] = l->data;
+    }
+
+  meta_topic (META_DEBUG_REMOTE_DESKTOP,
+              "Clipboard owner changed, owner: %p (%s), mime types: [%s], "
+              "notifying %s",
+              owner,
+              owner ? g_type_name_from_instance ((GTypeInstance *) owner)
+                    : "NULL",
+              mime_types_to_string (mime_types_array, log_buf,
+                                    G_N_ELEMENTS (log_buf)),
+              session->peer_name);
+
+  options_variant = generate_owner_changed_variant (mime_types_array);
+
+  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",
+                                 "SelectionOwnerChanged",
+                                 g_variant_new ("(@a{sv})", options_variant),
+                                 NULL);
+
+  session->transfer_serial++;
+}
+
 static gboolean
 handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
                          GDBusMethodInvocation        *invocation,
                          GVariant                     *arg_options)
 {
   MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
+  MetaDisplay *display = meta_get_display ();
+  MetaSelection *selection = meta_display_get_selection (display);
 
   meta_topic (META_DEBUG_REMOTE_DESKTOP,
               "Enable clipboard for %s",
@@ -813,6 +907,10 @@ handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
     }
 
   session->is_clipboard_enabled = TRUE;
+  session->owner_changed_handler_id =
+    g_signal_connect (selection, "owner-changed",
+                      G_CALLBACK (on_selection_owner_changed),
+                      session);
 
   meta_dbus_remote_desktop_session_complete_enable_clipboard (skeleton,
                                                               invocation);
@@ -825,6 +923,8 @@ handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
                           GDBusMethodInvocation        *invocation)
 {
   MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
+  MetaDisplay *display = meta_get_display ();
+  MetaSelection *selection = meta_display_get_selection (display);
 
   meta_topic (META_DEBUG_REMOTE_DESKTOP,
               "Disable clipboard for %s",
@@ -838,6 +938,8 @@ handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
       return TRUE;
     }
 
+  g_clear_signal_handler (&session->owner_changed_handler_id, selection);
+
   meta_dbus_remote_desktop_session_complete_disable_clipboard (skeleton,
                                                                invocation);
 
@@ -889,6 +991,18 @@ handle_selection_write (MetaDBusRemoteDesktopSession *skeleton,
       return TRUE;
     }
 
+  if (session->transfer_serial != serial)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_FAILED,
+                                             "Provided transfer serial %u "
+                                             "doesn't match current current "
+                                             "transfer serial %u",
+                                             serial,
+                                             session->transfer_serial);
+      return TRUE;
+    }
+
   meta_dbus_remote_desktop_session_complete_selection_write (skeleton,
                                                              invocation,
                                                              NULL,
@@ -990,9 +1104,13 @@ static void
 meta_remote_desktop_session_finalize (GObject *object)
 {
   MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (object);
+  MetaDisplay *display = meta_get_display ();
+  MetaSelection *selection = meta_display_get_selection (display);
 
   g_assert (!meta_remote_desktop_session_is_running (session));
 
+  g_clear_signal_handler (&session->owner_changed_handler_id, selection);
+
   g_clear_object (&session->handle);
   g_free (session->peer_name);
   g_free (session->session_id);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]