[gtk+] wayland: Expose basic mechanism for getting selection content by callback



commit cd795de6bf21107051842062f501094feda96232
Author: Rob Bradford <rob linux intel com>
Date:   Wed Dec 14 14:09:52 2011 +0000

    wayland: Expose basic mechanism for getting selection content by callback
    
    This version has a couple of TODOs/FIXMEs:
    
    * We should do something better than g_io_channel_read_to_end
    * Need to check the mime type is valid

 gdk/wayland/gdkdevice-wayland.c |  115 +++++++++++++++++++++++++++++++++++++++
 gdk/wayland/gdkwayland.h        |   13 ++++-
 2 files changed, 127 insertions(+), 1 deletions(-)
---
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index 73601db..f25c157 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -17,6 +17,11 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
 #include "config.h"
 
 #include <string.h>
@@ -32,6 +37,8 @@
 #include <X11/extensions/XKBcommon.h>
 #include <X11/keysym.h>
 
+#include <sys/time.h>
+
 #define GDK_TYPE_DEVICE_CORE         (gdk_device_core_get_type ())
 #define GDK_DEVICE_CORE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_CORE, GdkDeviceCore))
 #define GDK_DEVICE_CORE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_CORE, GdkDeviceCoreClass))
@@ -956,3 +963,111 @@ gdk_wayland_device_get_selection_type_atoms (GdkDevice  *gdk_device,
   *atoms_out = atoms;
   return device->selection_offer->types->len;
 }
+
+typedef struct
+{
+  GdkWaylandDevice *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);
+
+  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;
+  GdkWaylandDevice *device;
+  GError *error = NULL;
+
+  g_return_val_if_fail (GDK_IS_DEVICE_CORE (gdk_device), FALSE);
+  g_return_val_if_fail (requested_mime_type != NULL, FALSE);
+  g_return_val_if_fail (cb != NULL, FALSE);
+
+  device = GDK_DEVICE_CORE (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;
+}
diff --git a/gdk/wayland/gdkwayland.h b/gdk/wayland/gdkwayland.h
index d4616cd..e7028cd 100644
--- a/gdk/wayland/gdkwayland.h
+++ b/gdk/wayland/gdkwayland.h
@@ -37,7 +37,18 @@ GType      gdk_wayland_display_manager_get_type   (void);
 #define gdk_wayland_device_get_selection_type_atoms gdk_wayland_device_get_selection_type_atoms_libgtk_only
 int
 gdk_wayland_device_get_selection_type_atoms (GdkDevice  *device,
-                                                         GdkAtom   **atoms_out);
+                                             GdkAtom   **atoms_out);
+
+typedef void (*GdkDeviceWaylandRequestContentCallback) (GdkDevice *device, gchar *data, gsize len, gpointer userdata);
+
+#define gdk_wayland_device_request_selection_content gdk_wayland_device_request_selection_content_libgtk_only
+gboolean
+gdk_wayland_device_request_selection_content (GdkDevice                              *device,
+                                              const gchar                            *requested_mime_type,
+                                              GdkDeviceWaylandRequestContentCallback  cb,
+                                              gpointer                                userdata);
+
+
 #endif
 G_END_DECLS
 



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