From 368d6c50b71e3fa2b6052c4a6549c81923521e2d Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Fri, 13 Jan 2012 15:05:00 +0000 Subject: [PATCH] wayland: Add basic API for setting and clearing the selection on the device --- gdk/wayland/gdkdevice-wayland.c | 145 ++++++++++++++++++++++++++++++++ gdk/wayland/gdkwayland.h | 13 +++ 2 files changed, 158 insertions(+) diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index f25c1570d1..c7ea5aa8f4 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -52,6 +52,8 @@ typedef struct _GdkWaylandDevice GdkWaylandDevice; typedef struct _DataOffer DataOffer; +typedef struct _GdkWaylandSelectionOffer GdkWaylandSelectionOffer; + struct _GdkWaylandDevice { GdkDisplay *display; @@ -69,6 +71,8 @@ struct _GdkWaylandDevice DataOffer *drag_offer; DataOffer *selection_offer; + + GdkWaylandSelectionOffer *selection_offer_out; }; struct _GdkDeviceCore @@ -1071,3 +1075,144 @@ error: return FALSE; } + +struct _GdkWaylandSelectionOffer { + GdkDeviceWaylandOfferContentCallback cb; + gpointer userdata; + struct wl_data_source *source; + GdkWaylandDevice *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;; + const gchar *buf; + gssize len, bytes_written; + + 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, len); + if (bytes_written == -1) + goto error; + len -= bytes_written; + } + + close (fd); + + return; +error: + + g_warning (G_STRLOC ": Error writing data to client: %s", + g_strerror (errno)); + + close (fd); +} + +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; + GdkDisplayWayland *display_wayland; + GdkWaylandSelectionOffer *offer; + GdkWaylandDevice *device; + gint i; + + g_return_val_if_fail (GDK_IS_DEVICE_CORE (gdk_device), 0); + device = GDK_DEVICE_CORE (gdk_device)->device; + + display = device->display; + display_wayland = GDK_DISPLAY_WAYLAND (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, + _wl_time_now ()); + + device->selection_offer_out = offer; + + return TRUE; +} + +gboolean +gdk_wayland_device_clear_selection_content (GdkDevice *gdk_device) +{ + GdkWaylandDevice *device; + + g_return_val_if_fail (GDK_IS_DEVICE_CORE (gdk_device), 0); + device = GDK_DEVICE_CORE (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; +} diff --git a/gdk/wayland/gdkwayland.h b/gdk/wayland/gdkwayland.h index e7028cd5b5..8c964c99b9 100644 --- a/gdk/wayland/gdkwayland.h +++ b/gdk/wayland/gdkwayland.h @@ -48,6 +48,19 @@ gdk_wayland_device_request_selection_content (GdkDevice GdkDeviceWaylandRequestContentCallback cb, gpointer userdata); +typedef const gchar *(*GdkDeviceWaylandOfferContentCallback) (GdkDevice *device, const gchar *mime_type, gssize *len, gpointer userdata); + +#define gdk_wayland_device_offer_selection_content gdk_wayland_device_offer_selection_content_libgtk_only +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 +gboolean +gdk_wayland_device_clear_selection_content (GdkDevice *gdk_device); #endif G_END_DECLS