summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2014-10-10 18:40:43 +0200
committerCarlos Garnacho <carlosg@gnome.org>2015-05-15 17:43:46 +0200
commit4b5f5abb4fd99e7d05ea4e8dc149d21c3b5871c4 (patch)
tree2674c0b5fcd8da2cb3e8ec3805da17a1358fad4f
parent95ad52ba581c5568335e547f709d198f9fed6631 (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.c201
-rw-r--r--src/wayland/meta-wayland-data-device.h45
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 */