[gtk+/wip/attente/mir-content-hub: 4/5] mir: copy clipboard data to content-hub



commit b68aaee902ebfa0c2a4486ded51b9a01200e9dfc
Author: William Hua <william hua canonical com>
Date:   Wed Oct 12 16:56:01 2016 -0400

    mir: copy clipboard data to content-hub
    
    https://bugzilla.gnome.org/show_bug.cgi?id=775732

 gdk/mir/gdkmir-private.h   |    5 ++
 gdk/mir/gdkmirdisplay.c    |   60 +++++++++++++++++-
 gdk/mir/gdkmirwindowimpl.c |  150 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 212 insertions(+), 3 deletions(-)
---
diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
index 7e3893c..a677dec 100644
--- a/gdk/mir/gdkmir-private.h
+++ b/gdk/mir/gdkmir-private.h
@@ -111,6 +111,11 @@ void _gdk_mir_display_focus_window (GdkDisplay *display, GdkWindow *window);
 
 void _gdk_mir_display_unfocus_window (GdkDisplay *display, GdkWindow *window);
 
+void _gdk_mir_display_create_paste (GdkDisplay          *display,
+                                    const gchar * const *paste_formats,
+                                    gconstpointer        paste_data,
+                                    gsize                paste_size);
+
 gboolean _gdk_mir_display_init_egl_display (GdkDisplay *display);
 
 EGLDisplay _gdk_mir_display_get_egl_display (GdkDisplay *display);
diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
index 718ab60..3dd3798 100644
--- a/gdk/mir/gdkmirdisplay.c
+++ b/gdk/mir/gdkmirdisplay.c
@@ -504,7 +504,28 @@ gdk_mir_display_set_selection_owner (GdkDisplay *display,
                                      guint32     time,
                                      gboolean    send_event)
 {
-  //g_printerr ("gdk_mir_display_set_selection_owner\n");
+  GdkEvent *event;
+
+  if (selection == GDK_SELECTION_CLIPBOARD)
+    {
+      if (owner)
+        {
+          event = gdk_event_new (GDK_SELECTION_REQUEST);
+          event->selection.window = g_object_ref (owner);
+          event->selection.send_event = FALSE;
+          event->selection.selection = selection;
+          event->selection.target = gdk_atom_intern_static_string ("TARGETS");
+          event->selection.property = gdk_atom_intern_static_string ("AVAILABLE_TARGETS");
+          event->selection.time = GDK_CURRENT_TIME;
+          event->selection.requestor = g_object_ref (owner);
+
+          gdk_event_put (event);
+          gdk_event_free (event);
+
+          return TRUE;
+        }
+    }
+
   return FALSE;
 }
 
@@ -645,6 +666,43 @@ _gdk_mir_display_unfocus_window (GdkDisplay *display,
     g_clear_object (&mir_display->focused_window);
 }
 
+void
+_gdk_mir_display_create_paste (GdkDisplay          *display,
+                               const gchar * const *paste_formats,
+                               gconstpointer        paste_data,
+                               gsize                paste_size)
+{
+  GdkMirDisplay *mir_display = GDK_MIR_DISPLAY (display);
+  MirSurface *surface;
+  MirPersistentId *persistent_id;
+
+  if (!mir_display->focused_window)
+    return;
+
+  surface = gdk_mir_window_get_mir_surface (mir_display->focused_window);
+
+  if (!surface)
+    return;
+
+  persistent_id = mir_surface_request_persistent_id_sync (surface);
+
+  if (!persistent_id)
+    return;
+
+  if (mir_persistent_id_is_valid (persistent_id))
+    content_hub_service_call_create_paste_sync (
+      mir_display->content_service,
+      g_application_get_application_id (g_application_get_default ()),
+      mir_persistent_id_as_string (persistent_id),
+      g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, paste_data, paste_size, sizeof (guchar)),
+      paste_formats,
+      NULL,
+      NULL,
+      NULL);
+
+  mir_persistent_id_release (persistent_id);
+}
+
 gboolean
 _gdk_mir_display_init_egl_display (GdkDisplay *display)
 {
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
index 48e66ca..8a15816 100644
--- a/gdk/mir/gdkmirwindowimpl.c
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -1594,6 +1594,140 @@ gdk_mir_window_impl_get_property (GdkWindow  *window,
 }
 
 static void
+request_targets (GdkWindow     *window,
+                 const GdkAtom *available_targets,
+                 gint           n_available_targets)
+{
+  GArray *requested_targets;
+  GdkAtom target_pair[2];
+  gchar *target_location;
+  GdkEvent *event;
+  gint i;
+
+  requested_targets = g_array_sized_new (TRUE, FALSE, sizeof (GdkAtom), 2 * n_available_targets);
+
+  for (i = 0; i < n_available_targets; i++)
+    {
+      target_pair[0] = available_targets[i];
+
+      if (target_pair[0] == gdk_atom_intern_static_string ("TIMESTAMP") ||
+          target_pair[0] == gdk_atom_intern_static_string ("TARGETS") ||
+          target_pair[0] == gdk_atom_intern_static_string ("MULTIPLE") ||
+          target_pair[0] == gdk_atom_intern_static_string ("SAVE_TARGETS"))
+        continue;
+
+      target_location = g_strdup_printf ("REQUESTED_TARGET_U%u", requested_targets->len / 2);
+      target_pair[1] = gdk_atom_intern (target_location, FALSE);
+      g_free (target_location);
+
+      g_array_append_vals (requested_targets, target_pair, 2);
+    }
+
+  gdk_property_delete (window, gdk_atom_intern_static_string ("AVAILABLE_TARGETS"));
+  gdk_property_delete (window, gdk_atom_intern_static_string ("REQUESTED_TARGETS"));
+
+  gdk_property_change (window,
+                       gdk_atom_intern_static_string ("REQUESTED_TARGETS"),
+                       GDK_SELECTION_TYPE_ATOM,
+                       8 * sizeof (GdkAtom),
+                       GDK_PROP_MODE_REPLACE,
+                       (const guchar *) requested_targets->data,
+                       requested_targets->len);
+
+  g_array_unref (requested_targets);
+
+  event = gdk_event_new (GDK_SELECTION_REQUEST);
+  event->selection.window = g_object_ref (window);
+  event->selection.send_event = FALSE;
+  event->selection.selection = GDK_SELECTION_CLIPBOARD;
+  event->selection.target = gdk_atom_intern_static_string ("MULTIPLE");
+  event->selection.property = gdk_atom_intern_static_string ("REQUESTED_TARGETS");
+  event->selection.time = GDK_CURRENT_TIME;
+  event->selection.requestor = g_object_ref (window);
+
+  gdk_event_put (event);
+  gdk_event_free (event);
+}
+
+static void
+create_paste (GdkWindow     *window,
+              const GdkAtom *requested_targets,
+              gint           n_requested_targets)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  GPtrArray *paste_formats;
+  GArray *paste_header;
+  GByteArray *paste_data;
+  gint sizes[4];
+  GdkMirProperty *mir_property;
+  const gchar *paste_format;
+  gint i;
+
+  paste_formats = g_ptr_array_new_full (n_requested_targets, g_free);
+  paste_header = g_array_sized_new (FALSE, FALSE, sizeof (gint), 1 + 4 * n_requested_targets);
+  paste_data = g_byte_array_new ();
+
+  g_array_append_val (paste_header, sizes[0]);
+
+  for (i = 0; i < n_requested_targets; i++)
+    {
+      if (requested_targets[i] == GDK_NONE)
+        continue;
+
+      mir_property = g_hash_table_lookup (impl->properties, requested_targets[i]);
+
+      if (!mir_property)
+        continue;
+
+      paste_format = _gdk_atom_name_const (mir_property->type);
+
+      /* skip non-MIME targets */
+      if (!strchr (paste_format, '/'))
+        {
+          g_hash_table_remove (impl->properties, requested_targets[i]);
+          continue;
+        }
+
+      sizes[0] = paste_data->len;
+      sizes[1] = strlen (paste_format);
+      sizes[2] = sizes[0] + sizes[1];
+      sizes[3] = mir_property->array->len * g_array_get_element_size (mir_property->array);
+
+      g_ptr_array_add (paste_formats, g_strdup (paste_format));
+      g_array_append_vals (paste_header, sizes, 4);
+      g_byte_array_append (paste_data, (const guint8 *) paste_format, sizes[1]);
+      g_byte_array_append (paste_data, (const guint8 *) mir_property->array->data, sizes[3]);
+
+      g_hash_table_remove (impl->properties, requested_targets[i]);
+    }
+
+  gdk_property_delete (window, gdk_atom_intern_static_string ("REQUESTED_TARGETS"));
+
+  g_array_index (paste_header, gint, 0) = paste_formats->len;
+
+  for (i = 0; i < paste_formats->len; i++)
+    {
+      g_array_index (paste_header, gint, 1 + 4 * i) += paste_header->len * sizeof (gint);
+      g_array_index (paste_header, gint, 3 + 4 * i) += paste_header->len * sizeof (gint);
+    }
+
+  g_byte_array_prepend (paste_data,
+                        (const guint8 *) paste_header->data,
+                        paste_header->len * g_array_get_element_size (paste_header));
+
+  g_ptr_array_add (paste_formats, NULL);
+
+  _gdk_mir_display_create_paste (gdk_window_get_display (window),
+                                 (const gchar * const *) paste_formats->pdata,
+                                 paste_data->data,
+                                 paste_data->len);
+
+  g_byte_array_unref (paste_data);
+  g_array_unref (paste_header);
+  g_ptr_array_unref (paste_formats);
+}
+
+static void
 gdk_mir_window_impl_change_property (GdkWindow    *window,
                                      GdkAtom       property,
                                      GdkAtom       type,
@@ -1604,6 +1738,7 @@ gdk_mir_window_impl_change_property (GdkWindow    *window,
 {
   GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
   GdkMirProperty *mir_property;
+  gboolean existed;
   GdkEvent *event;
 
   /* ICCCM 2.7: ATOMs and ATOM_PAIRs have format 32, but GdkAtoms can be 64-bit */
@@ -1611,9 +1746,15 @@ gdk_mir_window_impl_change_property (GdkWindow    *window,
     format = 8 * sizeof (GdkAtom);
 
   if (mode != GDK_PROP_MODE_REPLACE)
-    mir_property = g_hash_table_lookup (impl->properties, property);
+    {
+      mir_property = g_hash_table_lookup (impl->properties, property);
+      existed = mir_property != NULL;
+    }
   else
-    mir_property = NULL;
+    {
+      mir_property = NULL;
+      existed = g_hash_table_contains (impl->properties, property);
+    }
 
   if (!mir_property)
     {
@@ -1640,6 +1781,11 @@ gdk_mir_window_impl_change_property (GdkWindow    *window,
 
   gdk_event_put (event);
   gdk_event_free (event);
+
+  if (property == gdk_atom_intern_static_string ("AVAILABLE_TARGETS"))
+    request_targets (window, (const GdkAtom *) data, n_elements);
+  else if (property == gdk_atom_intern_static_string ("REQUESTED_TARGETS") && existed)
+    create_paste (window, (const GdkAtom *) data, n_elements);
 }
 
 static void


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