[mutter] wayland: refactor MetaWaylandDataSource
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] wayland: refactor MetaWaylandDataSource
- Date: Fri, 15 May 2015 15:45:23 +0000 (UTC)
commit 4b5f5abb4fd99e7d05ea4e8dc149d21c3b5871c4
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri Oct 10 18:40:43 2014 +0200
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
src/wayland/meta-wayland-data-device.c | 201 +++++++++++++++++++++++++-------
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 4c07298..99f1bdb 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 b4b3900..bdd4e21 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 */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]