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
This commit is contained in:
parent
95ad52ba58
commit
4b5f5abb4f
@ -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);
|
||||
MetaWaylandDataSource *source;
|
||||
struct wl_resource *source_resource;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user