[mutter/wip/primary-selection] WIP: Implement the primary selection protocol
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/primary-selection] WIP: Implement the primary selection protocol
- Date: Sat, 20 Feb 2016 00:37:59 +0000 (UTC)
commit 297d11b323253aad288dd1ad3d1f3f4556cd08e1
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Feb 3 18:39:58 2016 +0100
WIP: Implement the primary selection protocol
src/Makefile.am | 2 +
src/wayland/meta-wayland-data-device-private.h | 6 +
src/wayland/meta-wayland-data-device.c | 305 +++++++++++++++++++++++-
src/wayland/meta-wayland-data-device.h | 5 +
src/wayland/meta-wayland-pointer.c | 3 +
src/wayland/meta-xwayland-selection.c | 16 ++-
6 files changed, 327 insertions(+), 10 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 8dedc81..9e26738 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,8 @@ mutter_built_sources = \
if HAVE_WAYLAND
mutter_built_sources += \
+ primary-selection-unstable-v1-protocol.c \
+ primary-selection-unstable-v1-server-protocol.h \
pointer-gestures-unstable-v1-protocol.c \
pointer-gestures-unstable-v1-server-protocol.h \
gtk-shell-protocol.c \
diff --git a/src/wayland/meta-wayland-data-device-private.h b/src/wayland/meta-wayland-data-device-private.h
index 9f5377a..5e65130 100644
--- a/src/wayland/meta-wayland-data-device-private.h
+++ b/src/wayland/meta-wayland-data-device-private.h
@@ -31,4 +31,10 @@ G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
META, WAYLAND_DATA_SOURCE_WAYLAND,
MetaWaylandDataSource);
+#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
+ meta_wayland_data_source_primary,
+ META, WAYLAND_DATA_SOURCE_PRIMARY,
+ MetaWaylandDataSourceWayland);
+
#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 b0652a0..1d52c0d 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -37,6 +37,8 @@
#include "meta-wayland-private.h"
#include "meta-dnd-actor-private.h"
+#include "primary-selection-unstable-v1-server-protocol.h"
+
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
@@ -70,13 +72,22 @@ typedef struct _MetaWaylandDataSourceWayland
struct wl_resource *resource;
} MetaWaylandDataSourceWayland;
+typedef struct _MetaWaylandDataSourcePrimary
+{
+ MetaWaylandDataSourceWayland parent;
+} MetaWaylandDataSourcePrimary;
+
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);
+G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
+ META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND);
static MetaWaylandDataSource *
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
+static MetaWaylandDataSource *
+meta_wayland_data_source_primary_new (struct wl_resource *resource);
static void
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was);
@@ -160,7 +171,8 @@ static void
meta_wayland_data_source_target (MetaWaylandDataSource *source,
const char *mime_type)
{
- META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type);
+ if (META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target)
+ META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type);
}
void
@@ -431,6 +443,32 @@ static const struct wl_data_offer_interface data_offer_interface = {
};
static void
+primary_offer_receive (struct wl_client *client, struct wl_resource *resource,
+ const char *mime_type, int32_t fd, uint32_t serial)
+{
+ MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
+ MetaWaylandDataSource *source = offer->source;
+ MetaWaylandSeat *seat;
+
+ if (!source)
+ {
+ close (fd);
+ return;
+ }
+
+ seat = meta_wayland_data_source_get_seat (source);
+
+ if (serial == seat->keyboard.key_serial ||
+ serial == seat->pointer.click_serial)
+ meta_wayland_data_source_send (source, mime_type, fd);
+}
+
+static const struct zwp_primary_selection_offer_v1_interface primary_offer_interface = {
+ primary_offer_receive,
+ data_offer_destroy,
+};
+
+static void
meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source)
{
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source);
@@ -500,6 +538,35 @@ meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
return offer->resource;
}
+static struct wl_resource *
+meta_wayland_data_source_send_primary_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;
+ g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source);
+ offer->resource = wl_resource_create (wl_resource_get_client (target),
+ &zwp_primary_selection_offer_v1_interface,
+ wl_resource_get_version (target), 0);
+ wl_resource_set_implementation (offer->resource,
+ &primary_offer_interface,
+ offer,
+ destroy_data_offer);
+
+ zwp_primary_selection_device_v1_send_data_offer (target, offer->resource);
+
+ wl_array_for_each (p, &priv->mime_types)
+ zwp_primary_selection_offer_v1_send_offer (offer->resource, *p);
+
+ meta_wayland_data_source_set_current_offer (source, offer);
+
+ return offer->resource;
+}
+
static void
data_source_offer (struct wl_client *client,
struct wl_resource *resource, const char *type)
@@ -561,6 +628,11 @@ static struct wl_data_source_interface data_source_interface = {
data_source_set_actions
};
+static struct zwp_primary_selection_source_v1_interface primary_source_interface = {
+ data_source_offer,
+ data_source_destroy,
+};
+
struct _MetaWaylandDragGrab {
MetaWaylandPointerGrab generic;
@@ -1109,6 +1181,43 @@ meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *
}
static void
+meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
+ const gchar *mime_type,
+ gint fd)
+{
+ MetaWaylandDataSourceWayland *source_wayland;
+
+ source_wayland = (MetaWaylandDataSourceWayland *) source;
+ zwp_primary_selection_source_v1_send_send (source_wayland->resource,
+ mime_type, fd);
+}
+
+static void
+meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
+{
+ MetaWaylandDataSourceWayland *source_wayland;
+
+ source_wayland = (MetaWaylandDataSourceWayland *) source;
+ zwp_primary_selection_source_v1_send_cancelled (source_wayland->resource);
+}
+
+static void
+meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
+{
+}
+
+static void
+meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
+{
+ MetaWaylandDataSourceClass *data_source_class =
+ META_WAYLAND_DATA_SOURCE_CLASS (klass);
+
+ data_source_class->send = meta_wayland_data_source_primary_send;
+ data_source_class->cancel = meta_wayland_data_source_primary_cancel;
+ data_source_class->target = NULL;
+}
+
+static void
meta_wayland_data_source_finalize (GObject *object)
{
MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
@@ -1299,6 +1408,7 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (source)
{
+ meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source),
selection_data_source_destroyed,
data_device);
@@ -1352,6 +1462,93 @@ static const struct wl_data_device_interface data_device_interface = {
};
static void
+primary_source_destroyed (gpointer data,
+ GObject *object_was_here)
+{
+ MetaWaylandDataDevice *data_device = data;
+ MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
+ struct wl_client *focus_client = NULL;
+
+ data_device->primary_data_source = NULL;
+
+ focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
+ if (focus_client)
+ {
+ struct wl_resource *data_device_resource;
+
+ data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
+ if (data_device_resource)
+ zwp_primary_selection_device_v1_send_selection (data_device_resource, NULL);
+ }
+}
+
+void
+meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
+ MetaWaylandDataSource *source)
+{
+ MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
+ struct wl_resource *data_device_resource, *offer;
+ struct wl_client *focus_client;
+
+ if (data_device->primary_data_source)
+ {
+ meta_wayland_data_source_cancel (data_device->primary_data_source);
+ g_object_weak_unref (G_OBJECT (data_device->primary_data_source),
+ primary_source_destroyed,
+ data_device);
+ data_device->primary_data_source = NULL;
+ }
+
+ data_device->primary_data_source = source;
+
+ focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
+ if (focus_client)
+ {
+ data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
+ if (data_device_resource)
+ {
+ if (data_device->primary_data_source)
+ {
+ offer = meta_wayland_data_source_send_primary_offer (data_device->primary_data_source,
+ data_device_resource);
+ zwp_primary_selection_device_v1_send_selection (data_device_resource, offer);
+ }
+ else
+ {
+ zwp_primary_selection_device_v1_send_selection (data_device_resource, NULL);
+ }
+ }
+ }
+
+ if (source)
+ {
+ meta_wayland_data_source_set_seat (source, seat);
+ g_object_weak_ref (G_OBJECT (source),
+ primary_source_destroyed,
+ data_device);
+ }
+
+ wl_signal_emit (&data_device->primary_ownership_signal, source);
+}
+
+static void
+primary_device_set_selection (struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *source_resource)
+{
+ MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
+ MetaWaylandDataSource *source;
+
+ source = wl_resource_get_user_data (source_resource);
+ meta_wayland_data_device_set_primary (data_device, source);
+}
+
+static const struct zwp_primary_selection_device_v1_interface primary_device_interface = {
+ primary_device_set_selection,
+ data_device_release,
+};
+
+static void
destroy_data_source (struct wl_resource *resource)
{
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
@@ -1390,6 +1587,48 @@ static const struct wl_data_device_manager_interface manager_interface = {
};
static void
+primary_device_manager_create_source (struct wl_client *client,
+ struct wl_resource *manager_resource,
+ guint32 id)
+{
+ struct wl_resource *source_resource;
+
+ source_resource =
+ wl_resource_create (client, &zwp_primary_selection_source_v1_interface,
+ wl_resource_get_version (manager_resource),
+ id);
+ meta_wayland_data_source_primary_new (source_resource);
+}
+
+static void
+primary_device_manager_get_device (struct wl_client *client,
+ struct wl_resource *manager_resource,
+ guint32 id,
+ struct wl_resource *seat_resource)
+{
+ MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+ struct wl_resource *cr;
+
+ cr = wl_resource_create (client, &zwp_primary_selection_device_v1_interface,
+ wl_resource_get_version (manager_resource), id);
+ wl_resource_set_implementation (cr, &primary_device_interface,
+ &seat->data_device, unbind_resource);
+ wl_list_insert (&seat->data_device.primary_resource_list, wl_resource_get_link (cr));
+}
+
+static void
+primary_device_manager_destroy (struct wl_client *client,
+ struct wl_resource *manager_resource)
+{
+}
+
+static const struct zwp_primary_selection_device_manager_v1_interface primary_manager_interface = {
+ primary_device_manager_create_source,
+ primary_device_manager_get_device,
+ primary_device_manager_destroy
+};
+
+static void
bind_manager (struct wl_client *client,
void *data, guint32 version, guint32 id)
{
@@ -1398,6 +1637,19 @@ bind_manager (struct wl_client *client,
wl_resource_set_implementation (resource, &manager_interface, NULL, NULL);
}
+static void
+bind_primary_manager (struct wl_client *client,
+ void *data,
+ uint32_t version,
+ uint32_t id)
+{
+ struct wl_resource *resource;
+
+ resource = wl_resource_create (client, &zwp_primary_selection_device_manager_v1_interface,
+ version, id);
+ wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL);
+}
+
void
meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
{
@@ -1406,13 +1658,20 @@ meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
META_WL_DATA_DEVICE_MANAGER_VERSION,
NULL, bind_manager) == NULL)
g_error ("Could not create data_device");
+
+ if (wl_global_create (compositor->wayland_display,
+ &zwp_primary_selection_device_manager_v1_interface,
+ 1, NULL, bind_primary_manager) == NULL)
+ g_error ("Could not create data_device");
}
void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
{
wl_list_init (&data_device->resource_list);
+ wl_list_init (&data_device->primary_resource_list);
wl_signal_init (&data_device->selection_ownership_signal);
+ wl_signal_init (&data_device->primary_ownership_signal);
wl_signal_init (&data_device->dnd_ownership_signal);
}
@@ -1435,17 +1694,32 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
return;
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
- if (!data_device_resource)
- return;
+ if (data_device_resource)
+ {
+ source = data_device->selection_data_source;
+ if (source)
+ {
+ offer = meta_wayland_data_source_send_offer (source, data_device_resource);
+ wl_data_device_send_selection (data_device_resource, offer);
+ }
+ else
+ wl_data_device_send_selection (data_device_resource, NULL);
+ }
- source = data_device->selection_data_source;
- if (source)
+ data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
+ if (data_device_resource)
{
- offer = meta_wayland_data_source_send_offer (source, data_device_resource);
- wl_data_device_send_selection (data_device_resource, offer);
+ source = data_device->primary_data_source;
+ if (source)
+ {
+ offer = meta_wayland_data_source_send_primary_offer (source, data_device_resource);
+ zwp_primary_selection_device_v1_send_selection (data_device_resource, offer);
+ }
+ else
+ {
+ zwp_primary_selection_device_v1_send_selection (data_device_resource, NULL);
+ }
}
- else
- wl_data_device_send_selection (data_device_resource, NULL);
}
gboolean
@@ -1486,6 +1760,19 @@ meta_wayland_data_source_wayland_new (struct wl_resource *resource)
return META_WAYLAND_DATA_SOURCE (source_wayland);
}
+static MetaWaylandDataSource *
+meta_wayland_data_source_primary_new (struct wl_resource *resource)
+{
+ MetaWaylandDataSourceWayland *source_wayland =
+ g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
+
+ source_wayland->resource = resource;
+ wl_resource_set_implementation (resource, &primary_source_interface,
+ source_wayland, destroy_data_source);
+
+ return META_WAYLAND_DATA_SOURCE (source_wayland);
+}
+
gboolean
meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type)
diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h
index cdb4f05..d779502 100644
--- a/src/wayland/meta-wayland-data-device.h
+++ b/src/wayland/meta-wayland-data-device.h
@@ -57,13 +57,16 @@ struct _MetaWaylandDataDevice
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
MetaWaylandDataSource *dnd_data_source;
+ MetaWaylandDataSource *primary_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
+ struct wl_list primary_resource_list;
MetaWaylandDragGrab *current_grab;
struct wl_client *focus_client;
struct wl_signal selection_ownership_signal;
struct wl_signal dnd_ownership_signal;
+ struct wl_signal primary_ownership_signal;
};
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
@@ -80,6 +83,8 @@ 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);
+void meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
+ MetaWaylandDataSource *source);
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
const gchar *mime_type);
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 4fb32bb..c152bf9 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -400,6 +400,9 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
time = clutter_event_get_time (event);
serial = wl_display_next_serial (display);
+ if (event->type == CLUTTER_BUTTON_PRESS)
+ pointer->click_serial = serial;
+
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
wl_pointer_send_button (resource, serial,
diff --git a/src/wayland/meta-xwayland-selection.c b/src/wayland/meta-xwayland-selection.c
index 5d3405a..cbafbef 100644
--- a/src/wayland/meta-xwayland-selection.c
+++ b/src/wayland/meta-xwayland-selection.c
@@ -91,6 +91,7 @@ struct _MetaWaylandDataSourceXWayland
struct _MetaXWaylandSelection {
MetaSelectionBridge clipboard;
+ MetaSelectionBridge primary;
MetaDndBridge dnd;
};
@@ -396,6 +397,8 @@ atom_to_selection_bridge (MetaWaylandCompositor *compositor,
if (selection_atom == selection_data->clipboard.selection_atom)
return &selection_data->clipboard;
+ else if (selection_atom == selection_data->primary.selection_atom)
+ return &selection_data->primary;
else if (selection_atom == selection_data->dnd.selection.selection_atom)
return &selection_data->dnd.selection;
else
@@ -530,6 +533,8 @@ data_device_get_active_source_for_atom (MetaWaylandDataDevice *data_device,
{
if (selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
return data_device->selection_data_source;
+ else if (selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
+ return data_device->primary_data_source;
else if (selection_atom == xdnd_atoms[ATOM_DND_SELECTION])
return data_device->dnd_data_source;
else
@@ -1058,6 +1063,10 @@ meta_xwayland_selection_get_x11_targets (MetaWaylandCompositor *compositor,
meta_wayland_data_device_set_selection (&compositor->seat->data_device, data_source,
wl_display_next_serial (compositor->wayland_display));
}
+ else if (selection->selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
+ {
+ meta_wayland_data_device_set_primary (&compositor->seat->data_device, data_source);
+ }
}
else
g_object_unref (data_source);
@@ -1529,7 +1538,8 @@ meta_xwayland_selection_handle_xfixes_selection_notify (MetaWaylandCompositor *c
if (!selection)
return FALSE;
- if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD"))
+ if (selection->selection_atom == gdk_x11_get_xatom_by_name ("CLIPBOARD") ||
+ selection->selection_atom == gdk_x11_get_xatom_by_name ("PRIMARY"))
{
if (event->owner == None)
{
@@ -1712,6 +1722,9 @@ meta_xwayland_init_selection (void)
init_selection_bridge (&manager->selection_data->clipboard,
gdk_x11_get_xatom_by_name ("CLIPBOARD"),
&compositor->seat->data_device.selection_ownership_signal);
+ init_selection_bridge (&manager->selection_data->primary,
+ gdk_x11_get_xatom_by_name ("PRIMARY"),
+ &compositor->seat->data_device.primary_ownership_signal);
init_selection_bridge (&manager->selection_data->dnd.selection,
xdnd_atoms[ATOM_DND_SELECTION],
&compositor->seat->data_device.dnd_ownership_signal);
@@ -1730,6 +1743,7 @@ meta_xwayland_shutdown_selection (void)
meta_xwayland_shutdown_dnd (manager);
shutdown_selection_bridge (&selection->clipboard);
+ shutdown_selection_bridge (&selection->primary);
shutdown_selection_bridge (&selection->dnd.selection);
g_slice_free (MetaXWaylandSelection, selection);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]