diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2014-10-10 18:40:43 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2015-05-15 17:43:46 +0200 |
commit | 4b5f5abb4fd99e7d05ea4e8dc149d21c3b5871c4 (patch) | |
tree | 2674c0b5fcd8da2cb3e8ec3805da17a1358fad4f | |
parent | 95ad52ba581c5568335e547f709d198f9fed6631 (diff) |
wayland: refactor MetaWaylandDataSource
Expose it partly (in internal headers anyway), and pass a vtable for the
data source functions, the wayland vfuncs just delegate operations on the
wl_data_source resource. The resource has been also made optional, although
it'll be present on all data sources from wayland clients.
The ownership/lifetime of the DnD data source has also changed a bit,
belonging now to the MetaWaylandDataDevice like the selection one does, as
we can't guarantee how long it will be needed after the grab is finished,
it will be left inert and replaced the next time DnD is started at worst.
This allows the creation of custom/proxy data sources, which will turn out
useful for X11 selection interoperation.
https://bugzilla.gnome.org/show_bug.cgi?id=738312
-rw-r--r-- | src/wayland/meta-wayland-data-device.c | 201 | ||||
-rw-r--r-- | src/wayland/meta-wayland-data-device.h | 45 |
2 files changed, 205 insertions, 41 deletions
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index 4c072980..99f1bdb0 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -43,13 +43,6 @@ typedef struct struct wl_listener source_destroy_listener; } MetaWaylandDataOffer; -struct _MetaWaylandDataSource -{ - struct wl_resource *resource; - struct wl_array mime_types; - gboolean has_target; -}; - static void unbind_resource (struct wl_resource *resource) { @@ -70,7 +63,7 @@ data_offer_accept (struct wl_client *client, if (offer->source) { - wl_data_source_send_target (offer->source->resource, mime_type); + offer->source->funcs.target (offer->source, mime_type); offer->source->has_target = mime_type != NULL; } } @@ -82,9 +75,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource, MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); if (offer->source) - wl_data_source_send_send (offer->source->resource, mime_type, fd); - - close (fd); + meta_wayland_data_source_send (offer->source, mime_type, fd); + else + close (fd); } static void @@ -104,7 +97,7 @@ destroy_data_offer (struct wl_resource *resource) { MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - if (offer->source) + if (offer->source && offer->source->resource) wl_list_remove (&offer->source_destroy_listener.link); g_slice_free (MetaWaylandDataOffer, offer); @@ -116,7 +109,6 @@ destroy_offer_data_source (struct wl_listener *listener, void *data) MetaWaylandDataOffer *offer; offer = wl_container_of (listener, offer, source_destroy_listener); - offer->source = NULL; } @@ -128,11 +120,14 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source, char **p; offer->source = source; - offer->source_destroy_listener.notify = destroy_offer_data_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_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener); + + if (source->resource) + { + offer->source_destroy_listener.notify = destroy_offer_data_source; + wl_resource_add_destroy_listener (source->resource, &offer->source_destroy_listener); + } wl_data_device_send_data_offer (target, offer->resource); @@ -147,12 +142,8 @@ data_source_offer (struct wl_client *client, struct wl_resource *resource, const char *type) { MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - char **p; - p = wl_array_add (&source->mime_types, sizeof *p); - if (p) - *p = strdup (type); - if (!p || !*p) + if (!meta_wayland_data_source_add_mime_type (source, type)) wl_resource_post_no_memory (resource); } @@ -291,10 +282,7 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) } if (drag_grab->drag_data_source) - { - drag_grab->drag_data_source->has_target = FALSE; - wl_list_remove (&drag_grab->drag_data_source_listener.link); - } + wl_list_remove (&drag_grab->drag_data_source_listener.link); if (drag_grab->feedback_actor) { @@ -355,6 +343,7 @@ destroy_data_device_origin (struct wl_listener *listener, void *data) drag_grab->drag_origin = NULL; data_device_end_drag_grab (drag_grab); + meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL); } static void @@ -365,6 +354,7 @@ destroy_data_device_source (struct wl_listener *listener, void *data) drag_grab->drag_data_source = NULL; data_device_end_drag_grab (drag_grab); + meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL); } static void @@ -442,6 +432,9 @@ data_device_start_drag (struct wl_client *client, drag_grab->drag_data_source_listener.notify = destroy_data_device_source; wl_resource_add_destroy_listener (source_resource, &drag_grab->drag_data_source_listener); + + meta_wayland_data_device_set_dnd_source (data_device, + drag_grab->drag_data_source); } if (icon_resource) @@ -489,6 +482,48 @@ destroy_selection_data_source (struct wl_listener *listener, void *data) } static void +meta_wayland_source_send (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd) +{ + wl_data_source_send_send (source->resource, mime_type, fd); + close (fd); +} + +static void +meta_wayland_source_target (MetaWaylandDataSource *source, + const gchar *mime_type) +{ + wl_data_source_send_target (source->resource, mime_type); +} + +static void +meta_wayland_source_cancel (MetaWaylandDataSource *source) +{ + wl_data_source_send_cancelled (source->resource); +} + +static const MetaWaylandDataSourceFuncs meta_wayland_source_funcs = { + meta_wayland_source_send, + meta_wayland_source_target, + meta_wayland_source_cancel +}; + +void +meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device, + MetaWaylandDataSource *source) +{ + if (data_device->dnd_data_source == source) + return; + + if (data_device->dnd_data_source) + meta_wayland_data_source_free (data_device->dnd_data_source); + + data_device->dnd_data_source = source; + wl_signal_emit (&data_device->dnd_ownership_signal, source); +} + +void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, MetaWaylandDataSource *source, guint32 serial) @@ -503,8 +538,15 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, if (data_device->selection_data_source) { - wl_data_source_send_cancelled (data_device->selection_data_source->resource); - wl_list_remove (&data_device->selection_data_source_listener.link); + 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); data_device->selection_data_source = NULL; } @@ -531,8 +573,13 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, if (source) { - data_device->selection_data_source_listener.notify = destroy_selection_data_source; - wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener); + 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); + } + + wl_signal_emit (&data_device->selection_ownership_signal, source); } } @@ -570,25 +617,23 @@ static void destroy_data_source (struct wl_resource *resource) { MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - char **p; - - wl_array_for_each (p, &source->mime_types) free (*p); - wl_array_release (&source->mime_types); - - g_slice_free (MetaWaylandDataSource, source); + source->resource = NULL; } static void create_data_source (struct wl_client *client, struct wl_resource *resource, guint32 id) { - MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource); - - source->resource = wl_resource_create (client, &wl_data_source_interface, wl_resource_get_version (resource), id); - wl_resource_set_implementation (source->resource, &data_source_interface, source, destroy_data_source); - - wl_array_init (&source->mime_types); + 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); } static void @@ -632,6 +677,8 @@ void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device) { wl_list_init (&data_device->resource_list); + wl_signal_init (&data_device->selection_ownership_signal); + wl_signal_init (&data_device->dnd_ownership_signal); } void @@ -683,3 +730,75 @@ meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device) -drag_grab->drag_surface->offset_x, -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) +{ + gchar **p; + + wl_array_for_each (p, &source->mime_types) + { + if (g_strcmp0 (mime_type, *p) == 0) + return TRUE; + } + + return FALSE; +} + +MetaWaylandDataSource * +meta_wayland_data_source_new (const MetaWaylandDataSourceFuncs *funcs, + struct wl_resource *wl_resource, + gpointer user_data) +{ + MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource); + + source->funcs = *funcs; + source->resource = wl_resource; + source->user_data = user_data; + wl_array_init (&source->mime_types); + + 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); +} + +gboolean +meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, + const gchar *mime_type) +{ + gchar **pos; + + pos = wl_array_add (&source->mime_types, sizeof (*pos)); + + if (pos) + { + *pos = g_strdup (mime_type); + return *pos != NULL; + } + + return FALSE; +} diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h index b4b3900c..bdd4e215 100644 --- a/src/wayland/meta-wayland-data-device.h +++ b/src/wayland/meta-wayland-data-device.h @@ -28,14 +28,38 @@ #include "meta-wayland-types.h" typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab; +typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs; struct _MetaWaylandDataDevice { uint32_t selection_serial; MetaWaylandDataSource *selection_data_source; + MetaWaylandDataSource *dnd_data_source; struct wl_listener selection_data_source_listener; struct wl_list resource_list; MetaWaylandDragGrab *current_grab; + + struct wl_signal selection_ownership_signal; + 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; }; void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor); @@ -48,4 +72,25 @@ gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_de MetaWaylandSurface *surface); void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device); +void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device, + MetaWaylandDataSource *source); +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); + +gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source, + const gchar *mime_type); + +void meta_wayland_data_source_send (MetaWaylandDataSource *source, + const gchar *mime_type, + gint fd); + #endif /* META_WAYLAND_DATA_DEVICE_H */ |