mir: copy clipboard data to content-hub

https://bugzilla.gnome.org/show_bug.cgi?id=775732
This commit is contained in:
William Hua
2016-10-12 16:56:01 -04:00
parent dcda372c15
commit 516c0a2aab
3 changed files with 212 additions and 3 deletions

View File

@@ -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);

View File

@@ -544,7 +544,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;
}
@@ -685,6 +706,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)
{

View File

@@ -1507,6 +1507,140 @@ gdk_mir_window_impl_get_property (GdkWindow *window,
return TRUE;
}
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,
@@ -1518,6 +1652,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 */
@@ -1525,9 +1660,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)
{
@@ -1554,6 +1695,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