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
This commit is contained in:
Rob Bradford 2011-12-14 14:09:52 +00:00
parent 9d90a17a7c
commit cd795de6bf
2 changed files with 127 additions and 1 deletions

View File

@ -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;
}

View File

@ -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