[gtk+/wayland-selections: 7/14] wayland: Replace clipboard implementation



commit 19dabfb47f137f43346f92b4db1c0094f311808d
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Aug 21 19:41:48 2014 +0200

    wayland: Replace clipboard implementation
    
    The wayland specific clipboard functions have been replaced by something
    more similar to the hooking the win32 backend does, which allows for just
    using the default GtkClipboard code in GTK+. As a consequence, the
    wayland-specific GtkClipboard implementation is now gone.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=697855

 gdk/wayland/gdkdevice-wayland.c    |  375 +-----------------------------------
 gdk/wayland/gdkselection-wayland.c |   38 ++++
 gdk/wayland/gdkwaylandselection.h  |   36 +---
 gtk/Makefile.am                    |    2 -
 gtk/gtkclipboard-wayland.c         |  365 -----------------------------------
 gtk/gtkclipboard-waylandprivate.h  |   60 ------
 gtk/gtkclipboard.c                 |   10 +-
 gtk/gtkselection.c                 |   27 +++
 8 files changed, 77 insertions(+), 836 deletions(-)
---
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index 36980b3..dd64f2f 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -35,10 +35,6 @@
 #include <sys/time.h>
 #include <sys/mman.h>
 
-typedef struct _DataOffer DataOffer;
-
-typedef struct _GdkWaylandSelectionOffer GdkWaylandSelectionOffer;
-
 typedef struct _GdkWaylandTouchData GdkWaylandTouchData;
 
 struct _GdkWaylandTouchData
@@ -93,10 +89,6 @@ struct _GdkWaylandDeviceData
   guint cursor_timeout_id;
   guint cursor_image_index;
 
-  DataOffer *drag_offer;
-  DataOffer *selection_offer;
-
-  GdkWaylandSelectionOffer *selection_offer_out;
 
   struct wl_surface *pointer_surface;
 };
@@ -512,61 +504,12 @@ _gdk_wayland_device_get_keymap (GdkDevice *device)
   return GDK_WAYLAND_DEVICE (device)->device->keymap;
 }
 
-struct _DataOffer {
-  struct wl_data_offer *offer;
-  gint ref_count;
-  GPtrArray *types;
-};
-
-static void
-data_offer_offer (void                 *data,
-                  struct wl_data_offer *wl_data_offer,
-                  const char           *type)
-{
-  DataOffer *offer = (DataOffer *)data;
-  g_debug (G_STRLOC ": %s wl_data_offer = %p type = %s",
-           G_STRFUNC, wl_data_offer, type);
-
-  g_ptr_array_add (offer->types, g_strdup (type));
-}
-
-static void
-data_offer_unref (DataOffer *offer)
-{
-  offer->ref_count--;
-
-  if (offer->ref_count == 0)
-    {
-      g_ptr_array_free (offer->types, TRUE);
-      g_free (offer);
-    }
-}
-
-static const struct wl_data_offer_listener data_offer_listener = {
-  data_offer_offer,
-};
-
 static void
 data_device_data_offer (void                  *data,
                         struct wl_data_device *data_device,
                         struct wl_data_offer  *_offer)
 {
-  DataOffer *offer;
-
-  /* This structure is reference counted to handle the case where you get a
-   * leave but are in the middle of transferring data
-   */
-  offer = g_new0 (DataOffer, 1);
-  offer->ref_count = 1;
-  offer->types = g_ptr_array_new_with_free_func (g_free);
-  offer->offer = _offer;
-
-  /* The DataOffer structure is then retrieved later since this sets the user
-   * data.
-   */
-  wl_data_offer_add_listener (offer->offer,
-                              &data_offer_listener,
-                              offer);
+  gdk_wayland_selection_set_offer (_offer);
 }
 
 static void
@@ -583,11 +526,6 @@ data_device_enter (void                  *data,
   g_debug (G_STRLOC ": %s data_device = %p serial = %u, surface = %p, x = %d y = %d, offer = %p",
            G_STRFUNC, data_device, serial, surface, x, y, offer);
 
-  /* Retrieve the DataOffer associated with with the wl_data_offer - this
-   * association is made when the listener is attached.
-   */
-  g_assert (device->drag_offer == NULL);
-  device->drag_offer = wl_data_offer_get_user_data (offer);
 }
 
 static void
@@ -599,8 +537,6 @@ data_device_leave (void                  *data,
   g_debug (G_STRLOC ": %s data_device = %p",
            G_STRFUNC, data_device);
 
-  data_offer_unref (device->drag_offer);
-  device->drag_offer = NULL;
 }
 
 static void
@@ -627,33 +563,10 @@ data_device_selection (void                  *data,
                        struct wl_data_device *wl_data_device,
                        struct wl_data_offer  *offer)
 {
-  GdkWaylandDeviceData *device = (GdkWaylandDeviceData *)data;
-
   g_debug (G_STRLOC ": %s wl_data_device = %p wl_data_offer = %p",
            G_STRFUNC, wl_data_device, offer);
 
-  if (!offer)
-    {
-      if (device->selection_offer)
-        {
-          data_offer_unref (device->selection_offer);
-          device->selection_offer = NULL;
-        }
-
-      return;
-    }
-
-  if (device->selection_offer)
-    {
-      data_offer_unref (device->selection_offer);
-      device->selection_offer = NULL;
-    }
-
-  /* Retrieve the DataOffer associated with with the wl_data_offer -
-   * this association is made when the listener is attached.
-   */
-  g_assert (device->selection_offer == NULL);
-  device->selection_offer = wl_data_offer_get_user_data (offer);
+  gdk_wayland_selection_set_offer (offer);
 }
 
 static const struct wl_data_device_listener data_device_listener = {
@@ -1876,290 +1789,6 @@ _gdk_wayland_device_get_last_implicit_grab_serial (GdkWaylandDevice  *device,
   return serial;
 }
 
-static GdkAtom
-mime_type_to_gdk_atom (char *mime_type)
-{
-  if (strcmp (mime_type, "text/plain;charset=utf8"))
-    return gdk_atom_intern_static_string ("UTF8_STRING");
-
-  return GDK_NONE;
-}
-
-gint
-gdk_wayland_device_get_selection_type_atoms (GdkDevice  *gdk_device,
-                                             GdkAtom   **atoms_out)
-{
-  gint i;
-  GdkAtom *atoms;
-  GdkWaylandDeviceData *device;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), 0);
-  g_return_val_if_fail (atoms_out != NULL, 0);
-
-  device = GDK_WAYLAND_DEVICE (gdk_device)->device;
-
-  if (!device->selection_offer || device->selection_offer->types->len == 0)
-    {
-      *atoms_out = NULL;
-      return 0;
-    }
-
-  atoms = g_new0 (GdkAtom, device->selection_offer->types->len);
-
-  /* Convert list of targets to atoms */
-  for (i = 0; i < device->selection_offer->types->len; i++)
-    atoms[i] = mime_type_to_gdk_atom (device->selection_offer->types->pdata[i]);
-
-  *atoms_out = atoms;
-  return device->selection_offer->types->len;
-}
-
-typedef struct
-{
-  GdkWaylandDeviceData *device;
-  DataOffer *offer;
-  GIOChannel *channel;
-  GdkDeviceWaylandRequestContentCallback cb;
-  gpointer userdata;
-} RequestContentClosure;
-
-static gboolean
-_request_content_io_func (GIOChannel   *channel,
-                          GIOCondition  condition,
-                          gpointer      userdata)
-{
-  RequestContentClosure *closure = (RequestContentClosure *)userdata;
-  gchar *data = NULL;
-  gsize len = 0;
-  GError *error = NULL;
-
-  /* FIXME: We probably want to do something better than this
-   * to avoid blocking on the transfer of large pieces of data:
-   * call the callback multiple times I should think.
-   */
-  if (g_io_channel_read_to_end (channel, &data, &len, &error) != G_IO_STATUS_NORMAL)
-    {
-      g_warning (G_STRLOC ": Error reading content from pipe: %s", error->message);
-      g_clear_error (&error);
-    }
-
-  /* Since we use _read_to_end we've got a guaranteed EOF and thus can go
-   * ahead and close the fd
-   */
-  g_io_channel_shutdown (channel, TRUE, NULL);
-
-  closure->cb (closure->device->pointer, data, len, closure->userdata);
-
-  g_free (data);
-  data_offer_unref (closure->offer);
-  g_io_channel_unref (channel);
-  g_free (closure);
-
-  return FALSE;
-}
-
-gboolean
-gdk_wayland_device_request_selection_content (GdkDevice                              *gdk_device,
-                                              const gchar                            *requested_mime_type,
-                                              GdkDeviceWaylandRequestContentCallback  cb,
-                                              gpointer                                userdata)
-{
-  int pipe_fd[2];
-  RequestContentClosure *closure;
-  GdkWaylandDeviceData *device;
-  GError *error = NULL;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), FALSE);
-  g_return_val_if_fail (requested_mime_type != NULL, FALSE);
-  g_return_val_if_fail (cb != NULL, FALSE);
-
-  device = GDK_WAYLAND_DEVICE (gdk_device)->device;
-
-  if (!device->selection_offer)
-    return FALSE;
-
-  /* TODO: Check mimetypes */
-
-  closure = g_new0 (RequestContentClosure, 1);
-
-  device->selection_offer->ref_count++;
-
-  pipe2 (pipe_fd, O_CLOEXEC);
-  wl_data_offer_receive (device->selection_offer->offer,
-                         requested_mime_type,
-                         pipe_fd[1]);
-  close (pipe_fd[1]);
-
-  closure->device = device;
-  closure->offer = device->selection_offer;
-  closure->channel = g_io_channel_unix_new (pipe_fd[0]);
-  closure->cb = cb;
-  closure->userdata = userdata;
-
-  if (!g_io_channel_set_encoding (closure->channel, NULL, &error))
-    {
-      g_warning (G_STRLOC ": Error setting encoding on channel: %s",
-                 error->message);
-      g_clear_error (&error);
-      goto error;
-    }
-
-  g_io_add_watch (closure->channel,
-                  G_IO_IN,
-                  _request_content_io_func,
-                  closure);
-
-  return TRUE;
-
- error:
-  data_offer_unref (closure->offer);
-  g_io_channel_unref (closure->channel);
-  close (pipe_fd[1]);
-  g_free (closure);
-
-  return FALSE;
-}
-
-struct _GdkWaylandSelectionOffer {
-  GdkDeviceWaylandOfferContentCallback cb;
-  gpointer userdata;
-  struct wl_data_source *source;
-  GdkWaylandDeviceData *device;
-};
-
-static void
-data_source_target (void                  *data,
-                    struct wl_data_source *source,
-                    const char            *mime_type)
-{
-  g_debug (G_STRLOC ": %s source = %p, mime_type = %s",
-           G_STRFUNC, source, mime_type);
-}
-
-static void
-data_source_send (void                  *data,
-                  struct wl_data_source *source,
-                  const char            *mime_type,
-                  int32_t                fd)
-{
-  GdkWaylandSelectionOffer *offer = (GdkWaylandSelectionOffer *)data;
-  gchar *buf;
-  gssize len, bytes_written = 0;
-
-  g_debug (G_STRLOC ": %s source = %p, mime_type = %s fd = %d",
-           G_STRFUNC, source, mime_type, fd);
-
-  buf = offer->cb (offer->device->pointer, mime_type, &len, offer->userdata);
-
-  while (len > 0)
-    {
-      bytes_written += write (fd, buf + bytes_written, len);
-      if (bytes_written == -1)
-        goto error;
-      len -= bytes_written;
-    }
-
-  close (fd);
-  g_free (buf);
-
-  return;
- error:
-
-  g_warning (G_STRLOC ": Error writing data to client: %s",
-             g_strerror (errno));
-
-  close (fd);
-  g_free (buf);
-}
-
-static void
-data_source_cancelled (void                  *data,
-                       struct wl_data_source *source)
-{
-  g_debug (G_STRLOC ": %s source = %p",
-           G_STRFUNC, source);
-}
-
-static const struct wl_data_source_listener data_source_listener = {
-  data_source_target,
-  data_source_send,
-  data_source_cancelled
-};
-
-static guint32
-_wl_time_now (void)
-{
-  struct timeval tv;
-
-  gettimeofday (&tv, NULL);
-
-  return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
-gboolean
-gdk_wayland_device_offer_selection_content (GdkDevice                             *gdk_device,
-                                            const gchar                          **mime_types,
-                                            gint                                   nr_mime_types,
-                                            GdkDeviceWaylandOfferContentCallback   cb,
-                                            gpointer                               userdata)
-{
-  GdkDisplay *display;
-  GdkWaylandDisplay *display_wayland;
-  GdkWaylandSelectionOffer *offer;
-  GdkWaylandDeviceData *device;
-  gint i;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), 0);
-  device = GDK_WAYLAND_DEVICE (gdk_device)->device;
-
-  display = device->display;
-  display_wayland = GDK_WAYLAND_DISPLAY (display);
-
-  offer = g_new0 (GdkWaylandSelectionOffer, 1);
-  offer->cb = cb;
-  offer->userdata = userdata;
-  offer->source =
-    wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
-  offer->device = device;
-
-  for (i = 0; i < nr_mime_types; i++)
-    wl_data_source_offer (offer->source, mime_types[i]);
-
-  wl_data_source_add_listener (offer->source,
-                               &data_source_listener,
-                               offer);
-
-  wl_data_device_set_selection (device->data_device,
-                                offer->source,
-                                _gdk_wayland_display_get_serial (display_wayland));
-
-  device->selection_offer_out = offer;
-
-  return TRUE;
-}
-
-gboolean
-gdk_wayland_device_clear_selection_content (GdkDevice *gdk_device)
-{
-  GdkWaylandDeviceData *device;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), 0);
-  device = GDK_WAYLAND_DEVICE (gdk_device)->device;
-
-  if (!device->selection_offer_out)
-    return FALSE;
-
-  wl_data_device_set_selection (device->data_device,
-                                NULL,
-                                _wl_time_now ());
-
-  wl_data_source_destroy (device->selection_offer_out->source);
-  g_free (device->selection_offer_out);
-  device->selection_offer_out = NULL;
-
-  return TRUE;
-}
-
 void
 gdk_wayland_device_unset_touch_grab (GdkDevice        *gdk_device,
                                      GdkEventSequence *sequence)
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index f089132..677ec4e 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -906,3 +906,41 @@ _gdk_wayland_display_utf8_to_string_target (GdkDisplay  *display,
 {
   return NULL;
 }
+
+void
+gdk_wayland_selection_add_targets (GdkWindow *window,
+                                   GdkAtom    selection,
+                                   guint      ntargets,
+                                   GdkAtom   *targets)
+{
+  struct wl_data_source *data_source;
+  guint i;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  data_source = gdk_wayland_selection_get_data_source (window, selection);
+
+  if (!data_source)
+    return;
+
+  for (i = 0; i < ntargets; i++)
+    wl_data_source_offer (data_source, gdk_atom_name (targets[i]));
+
+  if (selection == atoms[ATOM_CLIPBOARD])
+    {
+      GdkDeviceManager *device_manager;
+      GdkDisplay *display;
+      GdkDevice *device;
+
+      display = gdk_display_get_default ();
+      device_manager = gdk_display_get_device_manager (display);
+      device = gdk_device_manager_get_client_pointer (device_manager);
+      gdk_wayland_device_set_selection (device, data_source);
+    }
+}
+
+void
+gdk_wayland_selection_clear_targets (GdkAtom selection)
+{
+  gdk_wayland_selection_unset_data_source (selection);
+}
diff --git a/gdk/wayland/gdkwaylandselection.h b/gdk/wayland/gdkwaylandselection.h
index 7c5d5d2..90474c0 100644
--- a/gdk/wayland/gdkwaylandselection.h
+++ b/gdk/wayland/gdkwaylandselection.h
@@ -34,37 +34,19 @@
 G_BEGIN_DECLS
 
 #if defined (GTK_COMPILATION) || defined (GDK_COMPILATION)
-#define gdk_wayland_device_get_selection_type_atoms gdk_wayland_device_get_selection_type_atoms_libgtk_only
+#define gdk_wayland_selection_add_targets gdk_wayland_selection_add_targets_libgtk_only
 GDK_AVAILABLE_IN_ALL
-int
-gdk_wayland_device_get_selection_type_atoms (GdkDevice  *device,
-                                             GdkAtom   **atoms_out);
+void
+gdk_wayland_selection_add_targets (GdkWindow *window,
+                                   GdkAtom    selection,
+                                   guint      ntargets,
+                                   GdkAtom   *targets);
 
-typedef void (*GdkDeviceWaylandRequestContentCallback) (GdkDevice *device, const gchar *data, gsize len, 
gpointer userdata);
-
-#define gdk_wayland_device_request_selection_content gdk_wayland_device_request_selection_content_libgtk_only
+#define gdk_wayland_selection_clear_targets gdk_wayland_selection_clear_targets_libgtk_only
 GDK_AVAILABLE_IN_ALL
-gboolean
-gdk_wayland_device_request_selection_content (GdkDevice                              *device,
-                                              const gchar                            *requested_mime_type,
-                                              GdkDeviceWaylandRequestContentCallback  cb,
-                                              gpointer                                userdata);
-
-typedef gchar *(*GdkDeviceWaylandOfferContentCallback) (GdkDevice *device, const gchar *mime_type, gssize 
*len, gpointer userdata);
+void
+gdk_wayland_selection_clear_targets (GdkAtom selection);
 
-#define gdk_wayland_device_offer_selection_content gdk_wayland_device_offer_selection_content_libgtk_only
-GDK_AVAILABLE_IN_ALL
-gboolean
-gdk_wayland_device_offer_selection_content (GdkDevice                             *gdk_device,
-                                            const gchar                          **mime_types,
-                                            gint                                   nr_mime_types,
-                                            GdkDeviceWaylandOfferContentCallback   cb,
-                                            gpointer                               userdata);
-
-#define gdk_wayland_device_clear_selection_content gdk_wayland_device_clear_selection_content_libgtk_only
-GDK_AVAILABLE_IN_ALL
-gboolean
-gdk_wayland_device_clear_selection_content (GdkDevice *gdk_device);
 
 #endif
 
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 1168852..f099a55 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -526,7 +526,6 @@ gtk_private_h_sources =             \
        gtkcairoblurprivate.h   \
        gtkcellareaboxcontextprivate.h  \
        gtkclipboardprivate.h           \
-       gtkclipboard-waylandprivate.h   \
        gtkcolorswatchprivate.h \
        gtkcoloreditorprivate.h \
        gtkcolorplaneprivate.h  \
@@ -1237,7 +1236,6 @@ else
 # No wayland gtkdnd-wayland.c yet
 gtk_clipboard_dnd_c_sources =  \
        gtkclipboard.c \
-       gtkclipboard-wayland.c \
        gtkdnd.c
 endif
 
diff --git a/gtk/gtkclipboard.c b/gtk/gtkclipboard.c
index 6826346..302f7f7 100644
--- a/gtk/gtkclipboard.c
+++ b/gtk/gtkclipboard.c
@@ -23,9 +23,6 @@
 
 #include "gtkclipboard.h"
 #include "gtkclipboardprivate.h"
-#ifdef GDK_WINDOWING_WAYLAND
-#include "gtkclipboard-waylandprivate.h"
-#endif
 #include "gtkinvisible.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
@@ -1917,12 +1914,7 @@ clipboard_peek (GdkDisplay *display,
 
   if (!tmp_list && !only_if_exists)
     {
-#ifdef GDK_WINDOWING_WAYLAND
-      if (GDK_IS_WAYLAND_DISPLAY (display))
-        clipboard = g_object_new (GTK_TYPE_CLIPBOARD_WAYLAND, NULL);
-      else
-#endif
-        clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
+      clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL);
 
       clipboard->selection = selection;
       clipboard->display = display;
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
index bd9d22b..2adba2e 100644
--- a/gtk/gtkselection.c
+++ b/gtk/gtkselection.c
@@ -98,6 +98,10 @@
 #include "win32/gdkwin32.h"
 #endif
 
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/wayland/gdkwayland.h>
+#endif
+
 #undef DEBUG_SELECTION
 
 /* Maximum size of a sent chunk, in bytes. Also the default size of
@@ -879,6 +883,11 @@ gtk_selection_clear_targets (GtkWidget *widget,
   g_return_if_fail (GTK_IS_WIDGET (widget));
   g_return_if_fail (selection != GDK_NONE);
 
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    gdk_wayland_selection_clear_targets (selection);
+#endif
+
   lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
   
   tmp_list = lists;
@@ -923,6 +932,10 @@ gtk_selection_add_target (GtkWidget            *widget,
 
   list = gtk_selection_target_list_get (widget, selection);
   gtk_target_list_add (list, target, 0, info);
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    gdk_wayland_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target);
+#endif
 #ifdef GDK_WINDOWING_WIN32
   gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target);
 #endif
@@ -953,6 +966,20 @@ gtk_selection_add_targets (GtkWidget            *widget,
   list = gtk_selection_target_list_get (widget, selection);
   gtk_target_list_add_table (list, targets, ntargets);
 
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    {
+      GdkAtom *atoms = g_new (GdkAtom, ntargets);
+      guint i;
+
+      for (i = 0; i < ntargets; i++)
+        atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
+
+      gdk_wayland_selection_add_targets (gtk_widget_get_window (widget), selection, ntargets, atoms);
+      g_free (atoms);
+    }
+#endif
+
 #ifdef GDK_WINDOWING_WIN32
   {
     int i;


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