[mutter/wip/carlosg/primary-wayland-protocols] wayland: Add support for wayland-protocols primary selection protocol



commit 2becb3dd29f8b62f4b68938ecbfa1ec41a0d9fca
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed May 13 18:07:27 2020 +0200

    wayland: Add support for wayland-protocols primary selection protocol
    
    This protocol was added some time ago. Supporting it fell through the
    cracks. Add new data device/source/offer implementations for it,
    interoperation between primary selection protocols (and X11 primary
    selection for that matter) comes for free.
    
    Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/943
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1255

 src/meson.build                                |   6 +
 src/wayland/meta-wayland-data-device-primary.c | 353 +++++++++++++++++++++++++
 src/wayland/meta-wayland-data-device-primary.h |  55 ++++
 src/wayland/meta-wayland-data-offer-primary.c  | 138 ++++++++++
 src/wayland/meta-wayland-data-offer-primary.h  |  31 +++
 src/wayland/meta-wayland-data-source-primary.c | 117 ++++++++
 src/wayland/meta-wayland-data-source-primary.h |  37 +++
 src/wayland/meta-wayland-seat.c                |   2 +
 src/wayland/meta-wayland-seat.h                |   2 +
 src/wayland/meta-wayland-types.h               |   1 +
 src/wayland/meta-wayland.c                     |   1 +
 11 files changed, 743 insertions(+)
---
diff --git a/src/meson.build b/src/meson.build
index bd790516f..2b5b90217 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -502,14 +502,20 @@ if have_wayland
     'wayland/meta-wayland-cursor-surface.h',
     'wayland/meta-wayland-data-device.c',
     'wayland/meta-wayland-data-device.h',
+    'wayland/meta-wayland-data-device-primary.c',
+    'wayland/meta-wayland-data-device-primary.h',
     'wayland/meta-wayland-data-device-primary-legacy.c',
     'wayland/meta-wayland-data-device-primary-legacy.h',
     'wayland/meta-wayland-data-offer.c',
     'wayland/meta-wayland-data-offer.h',
+    'wayland/meta-wayland-data-offer-primary.c',
+    'wayland/meta-wayland-data-offer-primary.h',
     'wayland/meta-wayland-data-offer-primary-legacy.c',
     'wayland/meta-wayland-data-offer-primary-legacy.h',
     'wayland/meta-wayland-data-source.c',
     'wayland/meta-wayland-data-source.h',
+    'wayland/meta-wayland-data-source-primary.c',
+    'wayland/meta-wayland-data-source-primary.h',
     'wayland/meta-wayland-data-source-primary-legacy.c',
     'wayland/meta-wayland-data-source-primary-legacy.h',
     'wayland/meta-wayland-dma-buf.c',
diff --git a/src/wayland/meta-wayland-data-device-primary.c b/src/wayland/meta-wayland-data-device-primary.c
new file mode 100644
index 000000000..fb6417cfe
--- /dev/null
+++ b/src/wayland/meta-wayland-data-device-primary.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/* The file is based on src/data-device.c from Weston */
+
+#include "config.h"
+
+#include "wayland/meta-wayland-data-device-primary.h"
+
+#include "compositor/meta-dnd-actor-private.h"
+#include "meta/meta-selection-source-memory.h"
+#include "wayland/meta-selection-source-wayland-private.h"
+#include "wayland/meta-wayland-data-offer-primary.h"
+#include "wayland/meta-wayland-data-source-primary.h"
+#include "wayland/meta-wayland-dnd-surface.h"
+#include "wayland/meta-wayland-pointer.h"
+#include "wayland/meta-wayland-private.h"
+#include "wayland/meta-wayland-seat.h"
+
+#include "primary-selection-unstable-v1-server-protocol.h"
+
+static struct wl_resource * create_and_send_primary_offer   (MetaWaylandDataDevicePrimary *data_device,
+                                                             struct wl_resource           *target);
+
+static void
+move_resources (struct wl_list *destination,
+                struct wl_list *source)
+{
+  wl_list_insert_list (destination, source);
+  wl_list_init (source);
+}
+
+static void
+move_resources_for_client (struct wl_list   *destination,
+                          struct wl_list   *source,
+                          struct wl_client *client)
+{
+  struct wl_resource *resource, *tmp;
+  wl_resource_for_each_safe (resource, tmp, source)
+    {
+      if (wl_resource_get_client (resource) == client)
+        {
+          wl_list_remove (wl_resource_get_link (resource));
+          wl_list_insert (destination, wl_resource_get_link (resource));
+        }
+    }
+}
+
+static void
+unbind_resource (struct wl_resource *resource)
+{
+  wl_list_remove (wl_resource_get_link (resource));
+}
+
+static void
+default_destructor (struct wl_client   *client,
+                    struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static void
+set_selection_source (MetaWaylandDataDevicePrimary *data_device,
+                      MetaSelectionSource          *selection_source)
+
+{
+  MetaDisplay *display = meta_get_display ();
+
+  meta_selection_set_owner (meta_display_get_selection (display),
+                            META_SELECTION_PRIMARY,
+                            selection_source);
+  g_set_object (&data_device->owner, selection_source);
+}
+
+static void
+unset_selection_source (MetaWaylandDataDevicePrimary *data_device)
+{
+  MetaDisplay *display = meta_get_display ();
+
+  if (!data_device->owner)
+    return;
+
+  meta_selection_unset_owner (meta_display_get_selection (display),
+                              META_SELECTION_PRIMARY,
+                              data_device->owner);
+  g_clear_object (&data_device->owner);
+}
+
+static void
+primary_source_destroyed (gpointer  data,
+                          GObject  *object_was_here)
+{
+  MetaWaylandDataDevicePrimary *data_device = data;
+
+  data_device->data_source = NULL;
+  unset_selection_source (data_device);
+}
+
+static void
+meta_wayland_data_device_primary_set_selection (MetaWaylandDataDevicePrimary *data_device,
+                                                MetaWaylandDataSource        *source,
+                                                uint32_t                      serial)
+{
+  MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device);
+  MetaSelectionSource *selection_source;
+
+  g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source));
+
+  if (data_device->data_source &&
+      data_device->serial - serial < UINT32_MAX / 2)
+    return;
+
+  if (data_device->data_source)
+    {
+      g_object_weak_unref (G_OBJECT (data_device->data_source),
+                           primary_source_destroyed,
+                           data_device);
+    }
+
+  data_device->data_source = source;
+  data_device->serial = serial;
+
+  if (source)
+    {
+      meta_wayland_data_source_set_seat (source, seat);
+      g_object_weak_ref (G_OBJECT (source),
+                         primary_source_destroyed,
+                         data_device);
+
+      selection_source = meta_selection_source_wayland_new (source);
+    }
+  else
+    {
+      selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
+    }
+
+  set_selection_source (data_device, selection_source);
+  g_object_unref (selection_source);
+}
+
+static void
+primary_device_set_selection (struct wl_client   *client,
+                              struct wl_resource *resource,
+                              struct wl_resource *source_resource,
+                              uint32_t            serial)
+{
+  MetaWaylandDataDevicePrimary *data_device = wl_resource_get_user_data (resource);
+  MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device);
+  MetaWaylandDataSource *source = NULL;
+
+  if (source_resource)
+    source = wl_resource_get_user_data (source_resource);
+
+  if (wl_resource_get_client (resource) !=
+      meta_wayland_keyboard_get_focus_client (seat->keyboard))
+    return;
+
+  meta_wayland_data_device_primary_set_selection (data_device, source, serial);
+}
+
+static const struct zwp_primary_selection_device_v1_interface primary_device_interface = {
+  primary_device_set_selection,
+  default_destructor,
+};
+
+static void
+owner_changed_cb (MetaSelection                *selection,
+                  MetaSelectionType             selection_type,
+                  MetaSelectionSource          *new_owner,
+                  MetaWaylandDataDevicePrimary *data_device)
+{
+  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+  MetaWaylandSeat *seat = compositor->seat;
+  struct wl_resource *data_device_resource;
+  struct wl_client *focus_client;
+
+  focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
+  if (!focus_client)
+    return;
+
+  if (selection_type == META_SELECTION_PRIMARY)
+    {
+      wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
+        {
+          struct wl_resource *offer = NULL;
+
+          if (new_owner)
+            {
+              offer = create_and_send_primary_offer (data_device,
+                                                     data_device_resource);
+            }
+
+          zwp_primary_selection_device_v1_send_selection (data_device_resource,
+                                                          offer);
+        }
+    }
+}
+
+static void
+ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimary *data_device)
+{
+  if (data_device->selection_owner_signal_id != 0)
+    return;
+
+  data_device->selection_owner_signal_id =
+    g_signal_connect (meta_display_get_selection (meta_get_display ()),
+                      "owner-changed",
+                      G_CALLBACK (owner_changed_cb), data_device);
+}
+
+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->primary_data_device, unbind_resource);
+  wl_list_insert (&seat->primary_data_device.resource_list, wl_resource_get_link (cr));
+
+  ensure_owners_changed_handler_connected (&seat->primary_data_device);
+}
+
+static const struct zwp_primary_selection_device_manager_v1_interface primary_manager_interface = {
+  primary_device_manager_create_source,
+  primary_device_manager_get_device,
+  default_destructor,
+};
+
+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_primary_manager_init (MetaWaylandCompositor *compositor)
+{
+  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_primary_init (MetaWaylandDataDevicePrimary *data_device)
+{
+  wl_list_init (&data_device->resource_list);
+  wl_list_init (&data_device->focus_resource_list);
+}
+
+static struct wl_resource *
+create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device,
+                               struct wl_resource           *target)
+{
+  MetaWaylandDataOffer *offer;
+  MetaDisplay *display = meta_get_display ();
+  struct wl_resource *resource;
+  GList *mimetypes, *l;
+
+  mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display),
+                                            META_SELECTION_PRIMARY);
+  if (!mimetypes)
+    return NULL;
+
+  offer = meta_wayland_data_offer_primary_new (target);
+  resource = meta_wayland_data_offer_get_resource (offer);
+
+  zwp_primary_selection_device_v1_send_data_offer (target, resource);
+
+  for (l = mimetypes; l; l = l->next)
+    zwp_primary_selection_offer_v1_send_offer (resource, l->data);
+
+  g_list_free_full (mimetypes, g_free);
+
+  return resource;
+}
+
+void
+meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device)
+{
+  MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device);
+  struct wl_client *focus_client;
+  struct wl_resource *data_device_resource;
+
+  focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
+
+  if (focus_client == data_device->focus_client)
+    return;
+
+  data_device->focus_client = focus_client;
+  move_resources (&data_device->resource_list,
+                  &data_device->focus_resource_list);
+
+  if (!focus_client)
+    return;
+
+  move_resources_for_client (&data_device->focus_resource_list,
+                             &data_device->resource_list,
+                             focus_client);
+
+  wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
+    {
+      struct wl_resource *offer;
+      offer = create_and_send_primary_offer (data_device, data_device_resource);
+      zwp_primary_selection_device_v1_send_selection (data_device_resource, offer);
+    }
+}
diff --git a/src/wayland/meta-wayland-data-device-primary.h b/src/wayland/meta-wayland-data-device-primary.h
new file mode 100644
index 000000000..77fcbf97e
--- /dev/null
+++ b/src/wayland/meta-wayland-data-device-primary.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ *             2020 Red Hat Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_H
+#define META_WAYLAND_DATA_DEVICE_PRIMARY_H
+
+#include <glib-object.h>
+#include <wayland-server.h>
+
+#include "clutter/clutter.h"
+#include "meta/meta-selection-source.h"
+#include "wayland/meta-wayland-data-offer.h"
+#include "wayland/meta-wayland-data-source.h"
+#include "wayland/meta-wayland-types.h"
+
+struct _MetaWaylandDataDevicePrimary
+{
+  uint32_t serial;
+  MetaWaylandDataSource *data_source;
+  struct wl_list resource_list;
+  struct wl_list focus_resource_list;
+  struct wl_client *focus_client;
+
+  guint selection_owner_signal_id;
+
+  MetaSelectionSource *owner;
+};
+
+void meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor);
+
+void meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device);
+
+void meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device);
+
+#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_H */
diff --git a/src/wayland/meta-wayland-data-offer-primary.c b/src/wayland/meta-wayland-data-offer-primary.c
new file mode 100644
index 000000000..98b7b0910
--- /dev/null
+++ b/src/wayland/meta-wayland-data-offer-primary.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *             2020 Red Hat Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "meta-wayland-data-offer-primary.h"
+
+#include <gio/gunixoutputstream.h>
+#include <glib-unix.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "core/display-private.h"
+#include "primary-selection-unstable-v1-server-protocol.h"
+#include "wayland/meta-wayland-data-offer.h"
+
+static void
+transfer_cb (MetaSelection *selection,
+             GAsyncResult  *res,
+             GOutputStream *stream)
+{
+  GError *error = NULL;
+
+  if (!meta_selection_transfer_finish (selection, res, &error))
+    {
+      g_warning ("Could not fetch selection data: %s", error->message);
+      g_error_free (error);
+    }
+
+  g_output_stream_close (stream, NULL, NULL);
+}
+
+static void
+primary_offer_receive (struct wl_client   *client,
+                      struct wl_resource *resource,
+                       const char         *mime_type,
+                      int32_t             fd)
+{
+  MetaDisplay *display = meta_get_display ();
+  GOutputStream *stream;
+  GList *mime_types;
+  gboolean found;
+
+  mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display),
+                                             META_SELECTION_PRIMARY);
+  found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL;
+  g_list_free_full (mime_types, g_free);
+
+  if (!found)
+    {
+      close (fd);
+      return;
+    }
+
+  stream = g_unix_output_stream_new (fd, TRUE);
+  meta_selection_transfer_async (meta_display_get_selection (display),
+                                 META_SELECTION_PRIMARY,
+                                 mime_type,
+                                 -1,
+                                 stream,
+                                 NULL,
+                                 (GAsyncReadyCallback) transfer_cb,
+                                 stream);
+}
+
+static void
+primary_offer_destroy (struct wl_client   *client,
+                       struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static const struct zwp_primary_selection_offer_v1_interface primary_offer_interface = {
+  primary_offer_receive,
+  primary_offer_destroy,
+};
+
+static void
+destroy_primary_offer (struct wl_resource *resource)
+{
+  MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
+
+  if (offer->source)
+    {
+      if (offer == meta_wayland_data_source_get_current_offer (offer->source))
+        {
+          meta_wayland_data_source_cancel (offer->source);
+          meta_wayland_data_source_set_current_offer (offer->source, NULL);
+        }
+
+      g_object_remove_weak_pointer (G_OBJECT (offer->source),
+                                    (gpointer *)&offer->source);
+      offer->source = NULL;
+    }
+
+  meta_display_sync_wayland_input_focus (meta_get_display ());
+  g_slice_free (MetaWaylandDataOffer, offer);
+}
+
+MetaWaylandDataOffer *
+meta_wayland_data_offer_primary_new (struct wl_resource *target)
+{
+  MetaWaylandDataOffer *offer;
+
+  offer = g_slice_new0 (MetaWaylandDataOffer);
+  offer->selection_type = META_SELECTION_PRIMARY;
+  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_primary_offer);
+  return offer;
+}
diff --git a/src/wayland/meta-wayland-data-offer-primary.h b/src/wayland/meta-wayland-data-offer-primary.h
new file mode 100644
index 000000000..cf59fb5c7
--- /dev/null
+++ b/src/wayland/meta-wayland-data-offer-primary.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *             2020 Red Hat Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_H
+#define META_WAYLAND_DATA_OFFER_PRIMARY_H
+
+#include "meta-wayland-data-offer.h"
+
+MetaWaylandDataOffer * meta_wayland_data_offer_primary_new (struct wl_resource *target);
+
+#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_H */
diff --git a/src/wayland/meta-wayland-data-source-primary.c b/src/wayland/meta-wayland-data-source-primary.c
new file mode 100644
index 000000000..0229c840a
--- /dev/null
+++ b/src/wayland/meta-wayland-data-source-primary.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *             2020 Red Hat Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+
+#include "primary-selection-unstable-v1-server-protocol.h"
+#include "wayland/meta-wayland-data-source-primary.h"
+
+typedef struct _MetaWaylandDataSourcePrimary
+{
+  MetaWaylandDataSource parent;
+} MetaWaylandDataSourcePrimary;
+
+G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
+               META_TYPE_WAYLAND_DATA_SOURCE);
+
+static void
+primary_source_offer (struct wl_client   *client,
+                      struct wl_resource *resource,
+                      const char         *type)
+{
+  MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
+
+  if (!meta_wayland_data_source_add_mime_type (source, type))
+    wl_resource_post_no_memory (resource);
+}
+
+static void
+primary_source_destroy (struct wl_client   *client,
+                        struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static struct zwp_primary_selection_source_v1_interface primary_source_interface = {
+  primary_source_offer,
+  primary_source_destroy,
+};
+
+static void
+destroy_primary_source (struct wl_resource *resource)
+{
+  MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
+
+  meta_wayland_data_source_set_resource (source, NULL);
+  g_object_unref (source);
+}
+
+static void
+meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
+                                       const gchar           *mime_type,
+                                       gint                   fd)
+{
+  struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
+
+  zwp_primary_selection_source_v1_send_send (resource, mime_type, fd);
+  close (fd);
+}
+
+static void
+meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
+{
+  struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
+
+  if (resource)
+    zwp_primary_selection_source_v1_send_cancelled (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;
+}
+
+MetaWaylandDataSource *
+meta_wayland_data_source_primary_new (struct wl_resource *resource)
+{
+  MetaWaylandDataSource *source_primary =
+    g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
+
+  meta_wayland_data_source_set_resource (source_primary, resource);
+  wl_resource_set_implementation (resource, &primary_source_interface,
+                                  source_primary, destroy_primary_source);
+
+  return source_primary;
+}
diff --git a/src/wayland/meta-wayland-data-source-primary.h b/src/wayland/meta-wayland-data-source-primary.h
new file mode 100644
index 000000000..78ab55c19
--- /dev/null
+++ b/src/wayland/meta-wayland-data-source-primary.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *             2020 Red Hat Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_H
+#define META_WAYLAND_DATA_SOURCE_PRIMARY_H
+
+#include "meta-wayland-data-source.h"
+
+#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,
+                      MetaWaylandDataSource);
+
+MetaWaylandDataSource * meta_wayland_data_source_primary_new (struct wl_resource *resource);
+
+#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_H */
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 2c2c3caf0..3a76a1b5b 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -232,6 +232,7 @@ meta_wayland_seat_new (MetaWaylandCompositor *compositor,
   seat->gtk_text_input = meta_wayland_gtk_text_input_new (seat);
 
   meta_wayland_data_device_init (&seat->data_device);
+  meta_wayland_data_device_primary_init (&seat->primary_data_device);
   meta_wayland_data_device_primary_legacy_init (&seat->primary_legacy_data_device);
 
   clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
@@ -433,6 +434,7 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat    *seat,
     {
       meta_wayland_keyboard_set_focus (seat->keyboard, surface);
       meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
+      meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device);
       meta_wayland_data_device_primary_legacy_set_keyboard_focus (&seat->primary_legacy_data_device);
     }
 
diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h
index 885ecd46a..f41c44207 100644
--- a/src/wayland/meta-wayland-seat.h
+++ b/src/wayland/meta-wayland-seat.h
@@ -26,6 +26,7 @@
 
 #include "clutter/clutter.h"
 #include "wayland/meta-wayland-data-device.h"
+#include "wayland/meta-wayland-data-device-primary.h"
 #include "wayland/meta-wayland-data-device-primary-legacy.h"
 #include "wayland/meta-wayland-input-device.h"
 #include "wayland/meta-wayland-keyboard.h"
@@ -46,6 +47,7 @@ struct _MetaWaylandSeat
   MetaWaylandTouch *touch;
 
   MetaWaylandDataDevice data_device;
+  MetaWaylandDataDevicePrimary primary_data_device;
   MetaWaylandDataDevicePrimaryLegacy primary_legacy_data_device;
 
   MetaWaylandGtkTextInput *gtk_text_input;
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 29ce9aa99..00712ad1f 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -37,6 +37,7 @@ typedef struct _MetaWaylandTouch MetaWaylandTouch;
 typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
 typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
 typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
+typedef struct _MetaWaylandDataDevicePrimary MetaWaylandDataDevicePrimary;
 typedef struct _MetaWaylandDataDevicePrimaryLegacy MetaWaylandDataDevicePrimaryLegacy;
 
 typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager;
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 32c0d04c3..f3f922635 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -395,6 +395,7 @@ meta_wayland_init (void)
 
   meta_wayland_outputs_init (compositor);
   meta_wayland_data_device_manager_init (compositor);
+  meta_wayland_data_device_primary_manager_init (compositor);
   meta_wayland_data_device_primary_legacy_manager_init (compositor);
   meta_wayland_subsurfaces_init (compositor);
   meta_wayland_shell_init (compositor);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]