diff --git a/src/Makefile.am b/src/Makefile.am index 9316e954d..be444f4de 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -242,6 +242,7 @@ libmutter_la_SOURCES += \ wayland/meta-xwayland.c \ wayland/meta-xwayland.h \ wayland/meta-xwayland-selection.c \ + wayland/meta-xwayland-selection-private.h \ wayland/meta-xwayland-private.h \ wayland/meta-wayland-buffer.c \ wayland/meta-wayland-buffer.h \ @@ -249,6 +250,7 @@ libmutter_la_SOURCES += \ wayland/meta-wayland-region.h \ wayland/meta-wayland-data-device.c \ wayland/meta-wayland-data-device.h \ + wayland/meta-wayland-data-device-private.h \ wayland/meta-wayland-keyboard.c \ wayland/meta-wayland-keyboard.h \ wayland/meta-wayland-pointer.c \ diff --git a/src/wayland/meta-wayland-data-device-private.h b/src/wayland/meta-wayland-data-device-private.h new file mode 100644 index 000000000..9f5377af7 --- /dev/null +++ b/src/wayland/meta-wayland-data-device-private.h @@ -0,0 +1,34 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2015 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jonas Ådahl + */ + +#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H +#define META_WAYLAND_DATA_DEVICE_PRIVATE_H + +#define META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND (meta_wayland_data_source_wayland_get_type ()) +G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland, + meta_wayland_data_source_wayland, + META, WAYLAND_DATA_SOURCE_WAYLAND, + MetaWaylandDataSource); + +#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index 5e5d0be32..099f6c503 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -31,6 +31,7 @@ #include #include "meta-wayland-data-device.h" +#include "meta-wayland-data-device-private.h" #include "meta-wayland-seat.h" #include "meta-wayland-pointer.h" #include "meta-wayland-private.h" @@ -43,12 +44,87 @@ struct _MetaWaylandDataOffer struct wl_listener source_destroy_listener; }; +typedef struct _MetaWaylandDataSourcePrivate +{ + struct wl_array mime_types; + gboolean has_target; +} MetaWaylandDataSourcePrivate; + +typedef struct _MetaWaylandDataSourceWayland +{ + MetaWaylandDataSource parent; + + struct wl_resource *resource; +} MetaWaylandDataSourceWayland; + +GType meta_wayland_data_source_wayland_get_type (void) G_GNUC_CONST; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source, + G_TYPE_OBJECT); +G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland, + META_TYPE_WAYLAND_DATA_SOURCE); + +static MetaWaylandDataSource * +meta_wayland_data_source_wayland_new (struct wl_resource *resource); + +static void +drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was); + static void unbind_resource (struct wl_resource *resource) { wl_list_remove (wl_resource_get_link (resource)); } +static void +meta_wayland_data_source_target (MetaWaylandDataSource *source, + const char *mime_type) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type); +} + +void +meta_wayland_data_source_send (MetaWaylandDataSource *source, + const char *mime_type, + int fd) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd); +} + +gboolean +meta_wayland_data_source_has_target (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return priv->has_target; +} + +void +meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, + gboolean has_target) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + priv->has_target = has_target; +} + +struct wl_array * +meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + return &priv->mime_types; +} + +static void +meta_wayland_data_source_cancel (MetaWaylandDataSource *source) +{ + META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source); +} + static void data_offer_accept (struct wl_client *client, struct wl_resource *resource, @@ -63,8 +139,9 @@ data_offer_accept (struct wl_client *client, if (offer->source) { - offer->source->funcs.target (offer->source, mime_type); - offer->source->has_target = mime_type != NULL; + meta_wayland_data_source_target (offer->source, mime_type); + meta_wayland_data_source_set_has_target (offer->source, + mime_type != NULL); } } @@ -97,41 +174,35 @@ destroy_data_offer (struct wl_resource *resource) { MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - if (offer->source && offer->source->resource) - wl_list_remove (&offer->source_destroy_listener.link); + if (offer->source) + g_object_remove_weak_pointer (G_OBJECT (offer->source), + (gpointer *)&offer->source); g_slice_free (MetaWaylandDataOffer, offer); } -static void -destroy_offer_data_source (struct wl_listener *listener, void *data) -{ - MetaWaylandDataOffer *offer; - - offer = wl_container_of (listener, offer, source_destroy_listener); - offer->source = NULL; -} - static struct wl_resource * meta_wayland_data_source_send_offer (MetaWaylandDataSource *source, struct wl_resource *target) { + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer); char **p; offer->source = source; - offer->resource = wl_resource_create (wl_resource_get_client (target), &wl_data_offer_interface, wl_resource_get_version (target), 0); - wl_resource_set_implementation (offer->resource, &data_offer_interface, offer, destroy_data_offer); - - if (source->resource) - { - offer->source_destroy_listener.notify = destroy_offer_data_source; - wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener); - } + g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source); + offer->resource = wl_resource_create (wl_resource_get_client (target), + &wl_data_offer_interface, + wl_resource_get_version (target), 0); + wl_resource_set_implementation (offer->resource, + &data_offer_interface, + offer, + destroy_data_offer); wl_data_device_send_data_offer (target, offer->resource); - wl_array_for_each (p, &source->mime_types) + wl_array_for_each (p, &priv->mime_types) wl_data_offer_send_offer (offer->resource, *p); return offer->resource; @@ -172,7 +243,6 @@ struct _MetaWaylandDragGrab { struct wl_listener drag_icon_listener; MetaWaylandDataSource *drag_data_source; - struct wl_listener drag_data_source_listener; ClutterActor *feedback_actor; @@ -275,9 +345,10 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) wl_list_remove (&drag_grab->drag_icon_listener.link); } - if (drag_grab->drag_data_source && - drag_grab->drag_data_source->resource) - wl_list_remove (&drag_grab->drag_data_source_listener.link); + if (drag_grab->drag_data_source) + g_object_weak_unref (G_OBJECT (drag_grab->drag_data_source), + drag_grab_data_source_destroyed, + drag_grab); if (drag_grab->feedback_actor) { @@ -304,7 +375,7 @@ drag_grab_button (MetaWaylandPointerGrab *grab, { gboolean success = FALSE; - if (drag_grab->drag_data_source->has_target) + if (meta_wayland_data_source_has_target (drag_grab->drag_data_source)) { meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus); success = TRUE; @@ -339,13 +410,11 @@ destroy_data_device_origin (struct wl_listener *listener, void *data) } static void -destroy_data_device_source (struct wl_listener *listener, void *data) +drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was) { - MetaWaylandDragGrab *drag_grab = - wl_container_of (listener, drag_grab, drag_data_source_listener); + MetaWaylandDragGrab *drag_grab = data; drag_grab->drag_data_source = NULL; - drag_grab->seat->data_device.dnd_data_source = NULL; data_device_end_drag_grab (drag_grab); meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL); } @@ -393,19 +462,13 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data drag_grab->drag_start_x = stage_pos.x; drag_grab->drag_start_y = stage_pos.y; - if (source) - { - if (source->resource) - { - drag_grab->drag_data_source_listener.notify = destroy_data_device_source; - wl_resource_add_destroy_listener (source->resource, - &drag_grab->drag_data_source_listener); - } + g_object_weak_ref (G_OBJECT (source), + drag_grab_data_source_destroyed, + drag_grab); - drag_grab->drag_data_source = source; - meta_wayland_data_device_set_dnd_source (data_device, - drag_grab->drag_data_source); - } + drag_grab->drag_data_source = source; + meta_wayland_data_device_set_dnd_source (data_device, + drag_grab->drag_data_source); if (icon_surface) { @@ -487,9 +550,9 @@ data_device_start_drag (struct wl_client *client, } static void -destroy_selection_data_source (struct wl_listener *listener, void *data) +selection_data_source_destroyed (gpointer data, GObject *object_was_here) { - MetaWaylandDataDevice *data_device = wl_container_of (listener, data_device, selection_data_source_listener); + MetaWaylandDataDevice *data_device = data; MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); struct wl_resource *data_device_resource; struct wl_client *focus_client = NULL; @@ -510,7 +573,10 @@ meta_wayland_source_send (MetaWaylandDataSource *source, const gchar *mime_type, gint fd) { - wl_data_source_send_send (source->resource, mime_type, fd); + MetaWaylandDataSourceWayland *source_wayland = + META_WAYLAND_DATA_SOURCE_WAYLAND (source); + + wl_data_source_send_send (source_wayland->resource, mime_type, fd); close (fd); } @@ -518,20 +584,77 @@ static void meta_wayland_source_target (MetaWaylandDataSource *source, const gchar *mime_type) { - wl_data_source_send_target (source->resource, mime_type); + MetaWaylandDataSourceWayland *source_wayland = + META_WAYLAND_DATA_SOURCE_WAYLAND (source); + + wl_data_source_send_target (source_wayland->resource, mime_type); } static void meta_wayland_source_cancel (MetaWaylandDataSource *source) { - wl_data_source_send_cancelled (source->resource); + MetaWaylandDataSourceWayland *source_wayland = + META_WAYLAND_DATA_SOURCE_WAYLAND (source); + + wl_data_source_send_cancelled (source_wayland->resource); } -static const MetaWaylandDataSourceFuncs meta_wayland_source_funcs = { - meta_wayland_source_send, - meta_wayland_source_target, - meta_wayland_source_cancel -}; +static void +meta_wayland_source_finalize (GObject *object) +{ + G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object); +} + +static void +meta_wayland_data_source_wayland_init (MetaWaylandDataSourceWayland *source_wayland) +{ +} + +static void +meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaWaylandDataSourceClass *data_source_class = + META_WAYLAND_DATA_SOURCE_CLASS (klass); + + object_class->finalize = meta_wayland_source_finalize; + + data_source_class->send = meta_wayland_source_send; + data_source_class->target = meta_wayland_source_target; + data_source_class->cancel = meta_wayland_source_cancel; +} + +static void +meta_wayland_data_source_finalize (GObject *object) +{ + MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object); + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + char **pos; + + wl_array_for_each (pos, &priv->mime_types) + g_free (*pos); + wl_array_release (&priv->mime_types); + + G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object); +} + +static void +meta_wayland_data_source_init (MetaWaylandDataSource *source) +{ + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); + + wl_array_init (&priv->mime_types); +} + +static void +meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_wayland_data_source_finalize; +} static void meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device, @@ -619,9 +742,13 @@ meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device, return; if (data_device->dnd_data_source) - meta_wayland_data_source_free (data_device->dnd_data_source); + g_object_remove_weak_pointer (G_OBJECT (source), + (gpointer *)&data_device->dnd_data_source); data_device->dnd_data_source = source; + g_object_add_weak_pointer (G_OBJECT (source), + (gpointer *)&data_device->dnd_data_source); + wl_signal_emit (&data_device->dnd_ownership_signal, source); } @@ -640,15 +767,10 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, if (data_device->selection_data_source) { - data_device->selection_data_source->funcs.cancel (data_device->selection_data_source); - - if (data_device->selection_data_source->resource) - { - wl_list_remove (&data_device->selection_data_source_listener.link); - data_device->selection_data_source->resource = NULL; - } - - meta_wayland_data_source_free (data_device->selection_data_source); + meta_wayland_data_source_cancel (data_device->selection_data_source); + g_object_weak_unref (G_OBJECT (data_device->selection_data_source), + selection_data_source_destroyed, + data_device); data_device->selection_data_source = NULL; } @@ -675,11 +797,9 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, if (source) { - if (source->resource) - { - data_device->selection_data_source_listener.notify = destroy_selection_data_source; - wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener); - } + g_object_weak_ref (G_OBJECT (source), + selection_data_source_destroyed, + data_device); } wl_signal_emit (&data_device->selection_ownership_signal, source); @@ -718,24 +838,21 @@ static const struct wl_data_device_interface data_device_interface = { static void destroy_data_source (struct wl_resource *resource) { - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); + MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource); source->resource = NULL; + g_object_unref (source); } static void create_data_source (struct wl_client *client, struct wl_resource *resource, guint32 id) { - MetaWaylandDataSource *source; struct wl_resource *source_resource; source_resource = wl_resource_create (client, &wl_data_source_interface, wl_resource_get_version (resource), id); - source = meta_wayland_data_source_new (&meta_wayland_source_funcs, - source_resource, NULL); - wl_resource_set_implementation (source_resource, &data_source_interface, - source, destroy_data_source); + meta_wayland_data_source_wayland_new (source_resource); } static void @@ -835,21 +952,15 @@ meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device) -drag_grab->drag_surface->offset_y); } -void -meta_wayland_data_source_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - source->funcs.send (source, mime_type, fd); -} - gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source, const gchar *mime_type) { + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); gchar **p; - wl_array_for_each (p, &source->mime_types) + wl_array_for_each (p, &priv->mime_types) { if (g_strcmp0 (mime_type, *p) == 0) return TRUE; @@ -858,45 +969,28 @@ meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source, return FALSE; } -MetaWaylandDataSource * -meta_wayland_data_source_new (const MetaWaylandDataSourceFuncs *funcs, - struct wl_resource *wl_resource, - gpointer user_data) +static MetaWaylandDataSource * +meta_wayland_data_source_wayland_new (struct wl_resource *resource) { - MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource); + MetaWaylandDataSourceWayland *source_wayland = + g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND, NULL); - source->funcs = *funcs; - source->resource = wl_resource; - source->user_data = user_data; - wl_array_init (&source->mime_types); + source_wayland->resource = resource; + wl_resource_set_implementation (resource, &data_source_interface, + source_wayland, destroy_data_source); - return source; -} - -void -meta_wayland_data_source_free (MetaWaylandDataSource *source) -{ - char **pos; - - if (source->resource) - wl_resource_destroy (source->resource); - - wl_array_for_each (pos, &source->mime_types) - { - g_free (*pos); - } - - wl_array_release (&source->mime_types); - g_slice_free (MetaWaylandDataSource, source); + return META_WAYLAND_DATA_SOURCE (source_wayland); } gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, const gchar *mime_type) { + MetaWaylandDataSourcePrivate *priv = + meta_wayland_data_source_get_instance_private (source); gchar **pos; - pos = wl_array_add (&source->mime_types, sizeof (*pos)); + pos = wl_array_add (&priv->mime_types, sizeof (*pos)); if (pos) { diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h index 5c8793bff..d23953f8b 100644 --- a/src/wayland/meta-wayland-data-device.h +++ b/src/wayland/meta-wayland-data-device.h @@ -24,12 +24,29 @@ #define META_WAYLAND_DATA_DEVICE_H #include +#include #include "meta-wayland-types.h" typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab; typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs; +#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ()) +G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, meta_wayland_data_source, + META, WAYLAND_DATA_SOURCE, GObject); + +struct _MetaWaylandDataSourceClass +{ + GObjectClass parent_class; + + void (* send) (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd); + void (* target) (MetaWaylandDataSource *source, + const gchar *mime_type); + void (* cancel) (MetaWaylandDataSource *source); +}; + struct _MetaWaylandDataDevice { uint32_t selection_serial; @@ -43,24 +60,7 @@ struct _MetaWaylandDataDevice struct wl_signal dnd_ownership_signal; }; -struct _MetaWaylandDataSourceFuncs -{ - void (* send) (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd); - void (* target) (MetaWaylandDataSource *source, - const gchar *mime_type); - void (* cancel) (MetaWaylandDataSource *source); -}; - -struct _MetaWaylandDataSource -{ - MetaWaylandDataSourceFuncs funcs; - struct wl_resource *resource; - struct wl_array mime_types; - gpointer user_data; - gboolean has_target; -}; +GType meta_wayland_data_source_get_type (void) G_GNUC_CONST; void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor); @@ -77,11 +77,6 @@ void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_de void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, MetaWaylandDataSource *source, guint32 serial); -MetaWaylandDataSource * - meta_wayland_data_source_new (const MetaWaylandDataSourceFuncs *funcs, - struct wl_resource *resource, - gpointer user_data); -void meta_wayland_data_source_free (MetaWaylandDataSource *source); gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, const gchar *mime_type); @@ -89,6 +84,14 @@ gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source, const gchar *mime_type); +struct wl_array * + meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source); + +gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source); + +void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, + gboolean has_target); + void meta_wayland_data_source_send (MetaWaylandDataSource *source, const gchar *mime_type, gint fd); diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h index 3ffd844d3..637af775a 100644 --- a/src/wayland/meta-wayland-types.h +++ b/src/wayland/meta-wayland-types.h @@ -32,7 +32,6 @@ typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard; typedef struct _MetaWaylandTouch MetaWaylandTouch; typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs; typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer; -typedef struct _MetaWaylandDataSource MetaWaylandDataSource; typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice; typedef struct _MetaWaylandBuffer MetaWaylandBuffer; diff --git a/src/wayland/meta-xwayland-selection-private.h b/src/wayland/meta-xwayland-selection-private.h new file mode 100644 index 000000000..b55b4f8d3 --- /dev/null +++ b/src/wayland/meta-xwayland-selection-private.h @@ -0,0 +1,34 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2015 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jonas Ådahl + */ + +#ifndef META_XWAYLAND_SELECTION_PRIVATE_H +#define META_XWAYLAND_SELECTION_PRIVATE_H + +#define META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND (meta_wayland_data_source_xwayland_get_type ()) +G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceXWayland, + meta_wayland_data_source_xwayland, + META, WAYLAND_DATA_SOURCE_XWAYLAND, + MetaWaylandDataSource); + +#endif /* META_XWAYLAND_SELECTION_PRIVATE_H */ diff --git a/src/wayland/meta-xwayland-selection.c b/src/wayland/meta-xwayland-selection.c index f0a136f33..99a541dcd 100644 --- a/src/wayland/meta-xwayland-selection.c +++ b/src/wayland/meta-xwayland-selection.c @@ -35,8 +35,11 @@ #include #include #include "meta-xwayland-private.h" +#include "meta-xwayland-selection-private.h" #include "meta-wayland-data-device.h" +GType meta_wayland_data_source_xwayland_get_type (void) G_GNUC_CONST; + #define INCR_CHUNK_SIZE (128 * 1024) #define XDND_VERSION 5 @@ -79,6 +82,13 @@ typedef struct { guint32 last_motion_time; } MetaDndBridge; +struct _MetaWaylandDataSourceXWayland +{ + MetaWaylandDataSource parent; + + MetaSelectionBridge *selection; +}; + struct _MetaXWaylandSelection { MetaSelectionBridge clipboard; MetaDndBridge dnd; @@ -121,6 +131,9 @@ const gchar *atom_names[] = { Atom xdnd_atoms[N_DND_ATOMS]; +G_DEFINE_TYPE (MetaWaylandDataSourceXWayland, meta_wayland_data_source_xwayland, + META_TYPE_WAYLAND_DATA_SOURCE); + /* XDND helpers */ static void xdnd_send_enter (MetaXWaylandSelection *selection_data, @@ -132,6 +145,7 @@ xdnd_send_enter (MetaXWaylandSelection *selection_data, MetaWaylandDataSource *data_source; XEvent xev = { 0 }; gchar **p; + struct wl_array *source_mime_types; data_source = compositor->seat->data_device.dnd_data_source; xev.xclient.type = ClientMessage; @@ -143,13 +157,14 @@ xdnd_send_enter (MetaXWaylandSelection *selection_data, xev.xclient.data.l[1] = XDND_VERSION << 24; /* version */ xev.xclient.data.l[2] = xev.xclient.data.l[3] = xev.xclient.data.l[4] = 0; - if (data_source->mime_types.size <= 3) + source_mime_types = meta_wayland_data_source_get_mime_types (data_source); + if (source_mime_types->size <= 3) { /* The mimetype atoms fit in this same message */ gchar **p; gint i = 2; - wl_array_for_each (p, &data_source->mime_types) + wl_array_for_each (p, source_mime_types) { xev.xclient.data.l[i++] = gdk_x11_get_xatom_by_name (*p); } @@ -163,9 +178,9 @@ xdnd_send_enter (MetaXWaylandSelection *selection_data, gint i = 0; xev.xclient.data.l[1] |= 1; - atomlist = g_new0 (Atom, data_source->mime_types.size); + atomlist = g_new0 (Atom, source_mime_types->size); - wl_array_for_each (p, &data_source->mime_types) + wl_array_for_each (p, source_mime_types) { atomlist[i++] = gdk_x11_get_xatom_by_name (*p); } @@ -684,9 +699,11 @@ meta_x11_source_send (MetaWaylandDataSource *source, const gchar *mime_type, gint fd) { + MetaWaylandDataSourceXWayland *source_xwayland = + META_WAYLAND_DATA_SOURCE_XWAYLAND (source); MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - MetaSelectionBridge *selection = source->user_data; + MetaSelectionBridge *selection = source_xwayland->selection; Atom type_atom; if (strcmp (mime_type, "text/plain;charset=utf-8") == 0) @@ -715,7 +732,9 @@ meta_x11_source_target (MetaWaylandDataSource *source, const gchar *mime_type) { MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaSelectionBridge *selection = source->user_data; + MetaWaylandDataSourceXWayland *source_xwayland = + META_WAYLAND_DATA_SOURCE_XWAYLAND (source); + MetaSelectionBridge *selection = source_xwayland->selection; if (selection->selection_atom == xdnd_atoms[ATOM_DND_SELECTION]) { @@ -727,17 +746,40 @@ meta_x11_source_target (MetaWaylandDataSource *source, static void meta_x11_source_cancel (MetaWaylandDataSource *source) { - MetaSelectionBridge *selection = source->user_data; + MetaWaylandDataSourceXWayland *source_xwayland = + META_WAYLAND_DATA_SOURCE_XWAYLAND (source); + MetaSelectionBridge *selection = source_xwayland->selection; g_clear_pointer (&selection->x11_selection, (GDestroyNotify) x11_selection_data_free); } -static const MetaWaylandDataSourceFuncs meta_x11_source_funcs = { - meta_x11_source_send, - meta_x11_source_target, - meta_x11_source_cancel -}; +static void +meta_wayland_data_source_xwayland_init (MetaWaylandDataSourceXWayland *source_xwayland) +{ +} + +static void +meta_wayland_data_source_xwayland_class_init (MetaWaylandDataSourceXWaylandClass *klass) +{ + MetaWaylandDataSourceClass *data_source_class = + META_WAYLAND_DATA_SOURCE_CLASS (klass); + + data_source_class->send = meta_x11_source_send; + data_source_class->target = meta_x11_source_target; + data_source_class->cancel = meta_x11_source_cancel; +} + +static MetaWaylandDataSource * +meta_wayland_data_source_xwayland_new (MetaSelectionBridge *selection) +{ + MetaWaylandDataSourceXWayland *source_xwayland; + + source_xwayland = g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND, NULL); + source_xwayland->selection = selection; + + return META_WAYLAND_DATA_SOURCE (source_xwayland); +} static void meta_x11_drag_dest_focus_in (MetaWaylandDataDevice *data_device, @@ -811,8 +853,10 @@ meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source, gulong nitems_ret, bytes_after_ret, i; Atom *atoms, type_ret, utf8_string; int format_ret; + struct wl_array *source_mime_types; - if (source->mime_types.size != 0) + source_mime_types = meta_wayland_data_source_get_mime_types (source); + if (source_mime_types->size != 0) return TRUE; utf8_string = gdk_x11_get_xatom_by_name ("UTF8_STRING"); @@ -856,13 +900,13 @@ meta_xwayland_selection_get_x11_targets (MetaWaylandCompositor *compositor, { MetaWaylandDataSource *data_source; - data_source = meta_wayland_data_source_new (&meta_x11_source_funcs, - NULL, selection); + data_source = meta_wayland_data_source_xwayland_new (selection); if (meta_xwayland_data_source_fetch_mimetype_list (data_source, selection->window, gdk_x11_get_xatom_by_name ("_META_SELECTION"))) { + g_clear_object (&selection->source); selection->source = data_source; if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD")) @@ -872,9 +916,7 @@ meta_xwayland_selection_get_x11_targets (MetaWaylandCompositor *compositor, } } else - { - meta_wayland_data_source_free (data_source); - } + g_object_unref (data_source); } static void @@ -951,17 +993,19 @@ meta_xwayland_selection_send_targets (MetaWaylandCompositor *compositor, Atom *targets; gchar **p; int i = 0; + struct wl_array *source_mime_types; if (!data_source) return; - if (data_source->mime_types.size == 0) + source_mime_types = meta_wayland_data_source_get_mime_types (data_source); + if (source_mime_types->size == 0) return; /* Make extra room for TIMESTAMP/TARGETS */ - targets = g_new (Atom, data_source->mime_types.size + 2); + targets = g_new (Atom, source_mime_types->size + 2); - wl_array_for_each (p, &data_source->mime_types) + wl_array_for_each (p, source_mime_types) { targets[i++] = gdk_x11_get_xatom_by_name (*p); } @@ -1211,7 +1255,8 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor if (event->message_type == xdnd_atoms[ATOM_DND_STATUS]) { /* The first bit in data.l[1] is set if the drag was accepted */ - data_source->has_target = (event->data.l[1] & 1) != 0; + meta_wayland_data_source_set_has_target (data_source, + (event->data.l[1] & 1) != 0); return TRUE; } @@ -1246,9 +1291,12 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor /* Mimetypes are contained in this message */ const gchar *mimetype; gint i; + struct wl_array *source_mime_types; /* We only need to fetch once */ - if (dnd->selection.source->mime_types.size == 0) + source_mime_types = + meta_wayland_data_source_get_mime_types (dnd->selection.source); + if (source_mime_types->size == 0) { for (i = 2; i <= 4; i++) { @@ -1287,7 +1335,8 @@ meta_xwayland_selection_handle_client_message (MetaWaylandCompositor *compositor meta_wayland_surface_drag_dest_motion (drag_focus, motion); xdnd_send_status (compositor->xwayland_manager.selection_data, (Window) event->data.l[0], - dnd->selection.source->has_target); + meta_wayland_data_source_has_target ( + dnd->selection.source)); clutter_event_free (motion); return TRUE; @@ -1327,9 +1376,7 @@ meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *c if (selection->source && selection->owner != selection->window) { /* An X client went away, clear the selection */ - meta_wayland_data_device_set_selection (&compositor->seat->data_device, NULL, - wl_display_next_serial (compositor->wayland_display)); - selection->source = NULL; + g_clear_object (&selection->source); } selection->owner = None; @@ -1369,8 +1416,7 @@ meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *c MetaWaylandSurface *focus; focus = compositor->seat->pointer.focus_surface; - selection->source = meta_wayland_data_source_new (&meta_x11_source_funcs, - NULL, selection); + selection->source = meta_wayland_data_source_xwayland_new (selection); meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device, selection->source); @@ -1520,11 +1566,7 @@ meta_xwayland_shutdown_selection (void) g_assert (selection != NULL); - if (selection->clipboard.source) - { - meta_wayland_data_device_set_selection (&compositor->seat->data_device, NULL, - wl_display_next_serial (compositor->wayland_display)); - } + g_clear_object (&selection->clipboard.source); meta_xwayland_shutdown_dnd (manager); shutdown_selection_bridge (&selection->clipboard);