[gtk+/wip/wayland-primary-selection] WIP: Implement primary selection protocol
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/wayland-primary-selection] WIP: Implement primary selection protocol
- Date: Thu, 4 Feb 2016 16:45:57 +0000 (UTC)
commit 677bf2554511b243005e0204eb43b532e507ad31
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Feb 4 17:33:51 2016 +0100
WIP: Implement primary selection protocol
gdk/wayland/Makefile.am | 2 +
gdk/wayland/gdkdevice-wayland.c | 46 ++++++-
gdk/wayland/gdkdisplay-wayland.c | 6 +
gdk/wayland/gdkdisplay-wayland.h | 1 +
gdk/wayland/gdkprivate-wayland.h | 7 +
gdk/wayland/gdkselection-wayland.c | 253 ++++++++++++++++++++++++++++--------
6 files changed, 253 insertions(+), 62 deletions(-)
---
diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am
index a56c407..d155db2 100644
--- a/gdk/wayland/Makefile.am
+++ b/gdk/wayland/Makefile.am
@@ -24,6 +24,8 @@ BUILT_SOURCES = \
pointer-gestures-unstable-v1-protocol.c \
xdg-shell-unstable-v5-client-protocol.h \
xdg-shell-unstable-v5-protocol.c \
+ primary-selection-unstable-v1-client-protocol.h \
+ primary-selection-unstable-v1-protocol.c \
gtk-shell-client-protocol.h \
gtk-shell-protocol.c
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index b8f92fe..9649474 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -96,7 +96,6 @@ struct _GdkWaylandSeat
GdkWindow *pointer_focus;
GdkWindow *keyboard_focus;
GdkAtom pending_selection;
- struct wl_data_device *data_device;
double surface_x, surface_y;
uint32_t time;
uint32_t enter_serial;
@@ -111,10 +110,8 @@ struct _GdkWaylandSeat
guint32 repeat_count;
GSettings *keyboard_settings;
- guint cursor_timeout_id;
- guint cursor_image_index;
- guint cursor_image_delay;
-
+ struct zwp_primary_selection_data_device_v1 *primary_data_device;
+ struct wl_data_device *data_device;
GdkDragContext *drop_context;
struct wl_surface *pointer_surface;
@@ -926,6 +923,28 @@ static const struct wl_data_device_listener data_device_listener = {
data_device_selection
};
+static void
+primary_selection_offer (void *data,
+ struct zwp_primary_selection_device_v1 *wp_primary_selection_device,
+ struct zwp_primary_selection_offer_v1 *wp_primary_offer)
+{
+ GdkWaylandDeviceData *device = (GdkWaylandDeviceData *) data;
+ GdkAtom selection;
+
+ GDK_NOTE (EVENTS,
+ g_message ("primary selection offer, device %p, data offer %p",
+ wp_primary_selection_device, wp_primary_offer));
+
+ selection = gdk_atom_intern_static_string ("PRIMARY");
+ gdk_wayland_selection_ensure_primary_offer (device->display, wp_primary_offer);
+ gdk_wayland_selection_set_offer (device->display, selection, wp_primary_offer);
+ emit_selection_owner_change (device->keyboard_focus, selection);
+}
+
+static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
+ primary_selection_offer,
+};
+
static GdkEvent *
create_scroll_event (GdkWaylandSeat *seat,
gboolean emulated)
@@ -2883,6 +2902,12 @@ _gdk_wayland_device_manager_add_seat (GdkDeviceManager *device_manager,
wl_seat_add_listener (seat->wl_seat, &seat_listener, seat);
wl_seat_set_user_data (seat->wl_seat, seat);
+ seat->primary_data_device =
+ zwp_primary_selection_device_manager_v1_get_primary_selection_device
(display_wayland->primary_selection_manager,
+ seat->wl_seat);
+ zwp_primary_selection_device_v1_add_listener (seat->primary_data_device,
+ &primary_selection_device_listener, seat);
+
seat->data_device =
wl_data_device_manager_get_data_device (display_wayland->data_device_manager,
seat->wl_seat);
@@ -3116,6 +3141,17 @@ gdk_wayland_device_set_selection (GdkDevice *gdk_device,
_gdk_wayland_display_get_serial (display_wayland));
}
+void
+gdk_wayland_seat_set_primary (GdkSeat *seat,
+ struct zwp_primary_selection_source_v1 *source)
+{
+ GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat);
+
+ if (source)
+ zwp_primary_selection_device_v1_set_selection (wayland_seat->primary_data_device,
+ source);
+}
+
struct wl_seat *
gdk_wayland_seat_get_wl_seat (GdkSeat *seat)
{
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index f200800..0ffaa80 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -333,6 +333,12 @@ gdk_registry_handle_global (void *data,
wl_registry_bind (display_wayland->wl_registry,
id, &zwp_pointer_gestures_v1_interface, version);
}
+ else if (strcmp (interface, "zwp_primary_selection_device_manager_v1") == 0)
+ {
+ display_wayland->primary_selection_manager =
+ wl_registry_bind(display_wayland->wl_registry, id,
+ &zwp_primary_selection_device_manager_v1_interface, 1);
+ }
else
handled = FALSE;
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 933464b..ed11185 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -74,6 +74,7 @@ struct _GdkWaylandDisplay
struct wl_data_device_manager *data_device_manager;
struct wl_subcompositor *subcompositor;
struct zwp_pointer_gestures_v1 *pointer_gestures;
+ struct zwp_primary_selection_device_manager_v1 *primary_selection_manager;
GList *async_roundtrips;
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 9e51517..1a27a24 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -37,6 +37,7 @@
#include <xkbcommon/xkbcommon.h>
#include "gdkinternals.h"
+#include "primary-selection-unstable-v1-client-protocol.h"
#include "config.h"
@@ -188,6 +189,9 @@ struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_devic
void gdk_wayland_device_set_selection (GdkDevice *gdk_device,
struct wl_data_source *source);
+void gdk_wayland_seat_set_primary (GdkSeat *seat,
+ struct zwp_primary_selection_source_v1 *source);
+
GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device);
void gdk_wayland_device_unset_touch_grab (GdkDevice *device,
@@ -242,6 +246,9 @@ void gdk_wayland_selection_free (GdkWaylandSelection *selection);
void gdk_wayland_selection_ensure_offer (GdkDisplay *display,
struct wl_data_offer *wl_offer);
+void gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
+ struct zwp_primary_selection_offer_v1 *wp_offer);
+
void gdk_wayland_selection_set_offer (GdkDisplay *display,
GdkAtom selection,
struct wl_data_offer *wl_offer);
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index 64aac27..e0e8bf3 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -33,6 +33,8 @@
#include <string.h>
+#define READ_BUFFER_SIZE 1000
+
typedef struct _SelectionBuffer SelectionBuffer;
typedef struct _StoredSelection StoredSelection;
typedef struct _AsyncWriteData AsyncWriteData;
@@ -67,7 +69,8 @@ struct _DataSourceData
struct _DataOfferData
{
- struct wl_data_offer *offer;
+ GDestroyNotify destroy_notify;
+ gpointer offer;
GList *targets; /* List of GdkAtom */
};
@@ -79,17 +82,19 @@ struct _AsyncWriteData
};
enum {
+ ATOM_PRIMARY,
ATOM_CLIPBOARD,
ATOM_DND
};
-static GdkAtom atoms[2] = { 0 };
+static GdkAtom atoms[3] = { 0 };
struct _GdkWaylandSelection
{
/* Destination-side data */
DataOfferData *dnd_offer;
DataOfferData *clipboard_offer;
+ DataOfferData *primary_offer;
GHashTable *offers; /* Currently alive offers, Hashtable of wl_data_offer->DataOfferData */
GHashTable *selection_buffers; /* Hashtable of target_atom->SelectionBuffer */
@@ -98,6 +103,9 @@ struct _GdkWaylandSelection
GArray *source_targets;
GdkAtom requested_target;
+ struct zwp_primary_selection_source_v1 *primary_source;
+ GdkWindow *primary_owner;
+
struct wl_data_source *clipboard_source;
GdkWindow *clipboard_owner;
@@ -224,19 +232,23 @@ selection_buffer_read_cb (GObject *object,
gpointer user_data)
{
SelectionBuffer *buffer = user_data;
+ gboolean finished = TRUE;
GError *error = NULL;
GBytes *bytes;
bytes = g_input_stream_read_bytes_finish (buffer->stream, result, &error);
- if (bytes && g_bytes_get_size (bytes) > 0)
+ if (bytes)
{
+ finished = g_bytes_get_size (bytes) < READ_BUFFER_SIZE;
selection_buffer_append_data (buffer,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes));
- selection_buffer_read (buffer);
g_bytes_unref (bytes);
}
+
+ if (!finished)
+ selection_buffer_read (buffer);
else
{
if (error)
@@ -250,9 +262,6 @@ selection_buffer_read_cb (GObject *object,
g_input_stream_close (buffer->stream, NULL, NULL);
g_clear_object (&buffer->stream);
g_clear_object (&buffer->cancellable);
-
- if (bytes)
- g_bytes_unref (bytes);
}
selection_buffer_unref (buffer);
@@ -262,18 +271,20 @@ static void
selection_buffer_read (SelectionBuffer *buffer)
{
selection_buffer_ref (buffer);
- g_input_stream_read_bytes_async (buffer->stream, 1000, G_PRIORITY_DEFAULT,
+ g_input_stream_read_bytes_async (buffer->stream, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
buffer->cancellable, selection_buffer_read_cb,
buffer);
}
static DataOfferData *
-data_offer_data_new (struct wl_data_offer *offer)
+data_offer_data_new (gpointer offer,
+ GDestroyNotify destroy_notify)
{
DataOfferData *info;
info = g_slice_new0 (DataOfferData);
info->offer = offer;
+ info->destroy_notify = destroy_notify;
return info;
}
@@ -281,7 +292,7 @@ data_offer_data_new (struct wl_data_offer *offer)
static void
data_offer_data_free (DataOfferData *info)
{
- wl_data_offer_destroy (info->offer);
+ info->destroy_notify (info->offer);
g_list_free (info->targets);
g_slice_free (DataOfferData, info);
}
@@ -292,6 +303,7 @@ gdk_wayland_selection_new (void)
GdkWaylandSelection *selection;
/* init atoms */
+ atoms[ATOM_PRIMARY] = gdk_atom_intern_static_string ("PRIMARY");
atoms[ATOM_CLIPBOARD] = gdk_atom_intern_static_string ("CLIPBOARD");
atoms[ATOM_DND] = gdk_atom_intern_static_string ("GdkWaylandSelection");
@@ -325,6 +337,8 @@ gdk_wayland_selection_free (GdkWaylandSelection *selection)
if (selection->stored_selection.fd > 0)
close (selection->stored_selection.fd);
+ if (selection->primary_source)
+ zwp_primary_selection_source_v1_destroy (selection->primary_source);
if (selection->clipboard_source)
wl_data_source_destroy (selection->clipboard_source);
if (selection->dnd_source)
@@ -415,11 +429,24 @@ static const struct wl_data_offer_listener data_offer_listener = {
data_offer_action
};
+static void
+primary_offer_end_offers (void *data,
+ struct zwp_primary_selection_offer_v1 *wp_offer)
+{
+}
+
+static const struct zwp_primary_selection_offer_v1_listener primary_offer_listener = {
+ data_offer_offer,
+ primary_offer_end_offers,
+};
+
DataOfferData *
selection_lookup_offer_by_atom (GdkWaylandSelection *selection,
GdkAtom selection_atom)
{
- if (selection_atom == atoms[ATOM_CLIPBOARD])
+ if (selection_atom == atoms[ATOM_PRIMARY])
+ return selection->primary_offer;
+ else if (selection_atom == atoms[ATOM_CLIPBOARD])
return selection->clipboard_offer;
else if (selection_atom == atoms[ATOM_DND])
return selection->dnd_offer;
@@ -438,7 +465,8 @@ gdk_wayland_selection_ensure_offer (GdkDisplay *display,
if (!info)
{
- info = data_offer_data_new (wl_offer);
+ info = data_offer_data_new (wl_offer,
+ (GDestroyNotify) wl_data_offer_destroy);
g_hash_table_insert (selection->offers, wl_offer, info);
wl_data_offer_add_listener (wl_offer,
&data_offer_listener,
@@ -447,6 +475,26 @@ gdk_wayland_selection_ensure_offer (GdkDisplay *display,
}
void
+gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display,
+ struct zwp_primary_selection_offer_v1 *wp_offer)
+{
+ GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
+ DataOfferData *info;
+
+ info = g_hash_table_lookup (selection->offers, wp_offer);
+
+ if (!info)
+ {
+ info = data_offer_data_new (wp_offer,
+ (GDestroyNotify) zwp_primary_selection_offer_v1_destroy);
+ g_hash_table_insert (selection->offers, wp_offer, info);
+ zwp_primary_selection_offer_v1_add_listener (wp_offer,
+ &primary_offer_listener,
+ selection);
+ }
+}
+
+void
gdk_wayland_selection_set_offer (GdkDisplay *display,
GdkAtom selection_atom,
struct wl_data_offer *wl_offer)
@@ -462,7 +510,9 @@ gdk_wayland_selection_set_offer (GdkDisplay *display,
if (prev_offer)
g_hash_table_remove (selection->offers, prev_offer);
- if (selection_atom == atoms[ATOM_CLIPBOARD])
+ if (selection_atom == atoms[ATOM_PRIMARY])
+ selection->primary_offer = info;
+ else if (selection_atom == atoms[ATOM_CLIPBOARD])
selection->clipboard_offer = info;
else if (selection_atom == atoms[ATOM_DND])
selection->dnd_offer = info;
@@ -718,18 +768,10 @@ gdk_wayland_selection_source_handles_target (GdkWaylandSelection *wayland_select
static gboolean
gdk_wayland_selection_request_target (GdkWaylandSelection *wayland_selection,
GdkWindow *window,
+ GdkAtom selection,
GdkAtom target,
gint fd)
{
- GdkAtom selection;
-
- if (wayland_selection->clipboard_owner == window)
- selection = atoms[ATOM_CLIPBOARD];
- else if (wayland_selection->dnd_owner == window)
- selection = atoms[ATOM_DND];
- else
- return FALSE;
-
if (wayland_selection->stored_selection.fd == fd &&
wayland_selection->requested_target == target)
return FALSE;
@@ -748,7 +790,7 @@ gdk_wayland_selection_request_target (GdkWaylandSelection *wayland_selection,
gdk_wayland_selection_source_handles_target (wayland_selection, target))
{
gdk_wayland_selection_emit_request (window, selection, target);
- return TRUE;
+ return FALSE;
}
else
{
@@ -766,6 +808,7 @@ data_source_target (void *data,
{
GdkWaylandSelection *wayland_selection = data;
GdkWindow *window = NULL;
+ GdkAtom selection;
g_debug (G_STRLOC ": %s source = %p, mime_type = %s",
G_STRFUNC, source, mime_type);
@@ -774,14 +817,21 @@ data_source_target (void *data,
return;
if (source == wayland_selection->dnd_source)
- window = wayland_selection->dnd_owner;
+ {
+ selection = atoms[ATOM_DND];
+ window = wayland_selection->dnd_owner;
+ }
else if (source == wayland_selection->clipboard_source)
- window = wayland_selection->clipboard_owner;
+ {
+ selection = atoms[ATOM_CLIPBOARD];
+ window = wayland_selection->clipboard_owner;
+ }
if (!window)
return;
gdk_wayland_selection_request_target (wayland_selection, window,
+ selection,
gdk_atom_intern (mime_type, FALSE),
-1);
}
@@ -794,6 +844,7 @@ data_source_send (void *data,
{
GdkWaylandSelection *wayland_selection = data;
GdkWindow *window;
+ GdkAtom selection;
g_debug (G_STRLOC ": %s source = %p, mime_type = %s, fd = %d",
G_STRFUNC, source, mime_type, fd);
@@ -805,9 +856,20 @@ data_source_send (void *data,
}
if (source == wayland_selection->dnd_source)
- window = wayland_selection->dnd_owner;
+ {
+ window = wayland_selection->dnd_owner;
+ selection = atoms[ATOM_DND];
+ }
else if (source == wayland_selection->clipboard_source)
- window = wayland_selection->clipboard_owner;
+ {
+ window = wayland_selection->clipboard_owner;
+ selection = atoms[ATOM_CLIPBOARD];
+ }
+ else if (source == (gpointer) wayland_selection->primary_source)
+ {
+ window = wayland_selection->primary_owner;
+ selection = atoms[ATOM_PRIMARY];
+ }
else
{
close (fd);
@@ -818,6 +880,7 @@ data_source_send (void *data,
return;
if (!gdk_wayland_selection_request_target (wayland_selection, window,
+ selection,
gdk_atom_intern (mime_type, FALSE),
fd))
gdk_wayland_selection_check_write (wayland_selection);
@@ -839,6 +902,8 @@ data_source_cancelled (void *data,
if (source == wayland_selection->dnd_source)
atom = atoms[ATOM_DND];
+ else if (source == (gpointer) wayland_selection->primary_source)
+ atom = atoms[ATOM_PRIMARY];
else if (source == wayland_selection->clipboard_source)
atom = atoms[ATOM_CLIPBOARD];
else
@@ -919,15 +984,19 @@ static const struct wl_data_source_listener data_source_listener = {
data_source_action,
};
+static const struct zwp_primary_selection_source_v1_listener primary_source_listener = {
+ data_source_send,
+ data_source_cancelled,
+};
+
struct wl_data_source *
gdk_wayland_selection_get_data_source (GdkWindow *owner,
GdkAtom selection)
{
GdkDisplay *display = gdk_window_get_display (owner);
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
- struct wl_data_source *source = NULL;
+ gpointer source = NULL;
GdkWaylandDisplay *display_wayland;
- gboolean is_clipboard = FALSE;
if (selection == atoms[ATOM_DND])
{
@@ -935,6 +1004,18 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
(!owner || owner == wayland_selection->dnd_owner))
return wayland_selection->dnd_source;
}
+ else if (selection == atoms[ATOM_PRIMARY])
+ {
+ if (wayland_selection->primary_source &&
+ (!owner || owner == wayland_selection->primary_owner))
+ return (gpointer) wayland_selection->primary_source;
+
+ if (wayland_selection->primary_source)
+ {
+ zwp_primary_selection_source_v1_destroy (wayland_selection->primary_source);
+ wayland_selection->primary_source = NULL;
+ }
+ }
else if (selection == atoms[ATOM_CLIPBOARD])
{
if (wayland_selection->clipboard_source &&
@@ -946,8 +1027,6 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
wl_data_source_destroy (wayland_selection->clipboard_source);
wayland_selection->clipboard_source = NULL;
}
-
- is_clipboard = TRUE;
}
else
return NULL;
@@ -957,15 +1036,27 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner,
display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (owner));
- source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
- wl_data_source_add_listener (source,
- &data_source_listener,
- wayland_selection);
-
- if (is_clipboard)
- wayland_selection->clipboard_source = source;
+ if (selection == atoms[ATOM_PRIMARY])
+ {
+ source = zwp_primary_selection_device_manager_v1_create_primary_selection_source
(display_wayland->primary_selection_manager);
+ zwp_primary_selection_source_v1_add_listener (source,
+ &primary_source_listener,
+ wayland_selection);
+ }
else
+ {
+ source = wl_data_device_manager_create_data_source (display_wayland->data_device_manager);
+ wl_data_source_add_listener (source,
+ &data_source_listener,
+ wayland_selection);
+ }
+
+ if (selection == atoms[ATOM_DND])
wayland_selection->dnd_source = source;
+ else if (selection == atoms[ATOM_PRIMARY])
+ wayland_selection->primary_source = source;
+ else if (selection == atoms[ATOM_CLIPBOARD])
+ wayland_selection->clipboard_source = source;
return source;
}
@@ -990,6 +1081,18 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display,
wayland_selection->clipboard_source = NULL;
}
}
+ else if (selection == atoms[ATOM_PRIMARY])
+ {
+ GdkSeat *seat = gdk_display_get_default_seat (display);
+
+ gdk_wayland_seat_set_primary (seat, NULL);
+
+ if (wayland_selection->primary_source)
+ {
+ zwp_primary_selection_source_v1_destroy (wayland_selection->primary_source);
+ wayland_selection->primary_source = NULL;
+ }
+ }
else if (selection == atoms[ATOM_DND])
{
wayland_selection->dnd_source = NULL;
@@ -1004,6 +1107,8 @@ _gdk_wayland_display_get_selection_owner (GdkDisplay *display,
if (selection == atoms[ATOM_CLIPBOARD])
return wayland_selection->clipboard_owner;
+ else if (selection == atoms[ATOM_PRIMARY])
+ return wayland_selection->primary_owner;
else if (selection == atoms[ATOM_DND])
return wayland_selection->dnd_owner;
@@ -1024,6 +1129,11 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display,
wayland_selection->clipboard_owner = owner;
return TRUE;
}
+ else if (selection == atoms[ATOM_PRIMARY])
+ {
+ wayland_selection->primary_owner = owner;
+ return TRUE;
+ }
else if (selection == atoms[ATOM_DND])
{
wayland_selection->dnd_owner = owner;
@@ -1088,6 +1198,26 @@ _gdk_wayland_display_get_selection_property (GdkDisplay *display,
return len;
}
+static void
+emit_empty_selection_notify (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target)
+{
+ GdkEvent *event;
+
+ event = gdk_event_new (GDK_SELECTION_NOTIFY);
+ event->selection.window = g_object_ref (requestor);
+ event->selection.send_event = FALSE;
+ event->selection.selection = selection;
+ event->selection.target = target;
+ event->selection.property = GDK_NONE;
+ event->selection.time = GDK_CURRENT_TIME;
+ event->selection.requestor = g_object_ref (requestor);
+
+ gdk_event_put (event);
+ gdk_event_free (event);
+}
+
void
_gdk_wayland_display_convert_selection (GdkDisplay *display,
GdkWindow *requestor,
@@ -1097,7 +1227,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
{
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
SelectionBuffer *buffer_data;
- struct wl_data_offer *offer;
+ gpointer offer;
gchar *mimetype;
GList *target_list;
@@ -1106,28 +1236,25 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
if (!offer || target == gdk_atom_intern_static_string ("DELETE"))
{
- GdkEvent *event;
-
- event = gdk_event_new (GDK_SELECTION_NOTIFY);
- event->selection.window = g_object_ref (requestor);
- event->selection.send_event = FALSE;
- event->selection.selection = selection;
- event->selection.target = target;
- event->selection.property = GDK_NONE;
- event->selection.time = GDK_CURRENT_TIME;
- event->selection.requestor = g_object_ref (requestor);
-
- gdk_event_put (event);
- gdk_event_free (event);
+ emit_empty_selection_notify (requestor, selection, target);
return;
}
mimetype = gdk_atom_name (target);
if (target != gdk_atom_intern_static_string ("TARGETS"))
- wl_data_offer_accept (offer,
- _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
- mimetype);
+ {
+ if (!g_list_find (target_list, GDK_ATOM_TO_POINTER (target)))
+ {
+ emit_empty_selection_notify (requestor, selection, target);
+ return;
+ }
+
+ if (selection != atoms[ATOM_PRIMARY])
+ wl_data_offer_accept (offer,
+ _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
+ mimetype);
+ }
buffer_data = g_hash_table_lookup (wayland_selection->selection_buffers,
target);
@@ -1154,7 +1281,12 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
else
{
g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL);
- wl_data_offer_receive (offer, mimetype, pipe_fd[1]);
+
+ if (selection == atoms[ATOM_PRIMARY])
+ zwp_primary_selection_offer_v1_receive (offer, mimetype, pipe_fd[1]);
+ else
+ wl_data_offer_receive (offer, mimetype, pipe_fd[1]);
+
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
}
@@ -1239,7 +1371,7 @@ gdk_wayland_selection_add_targets (GdkWindow *window,
{
GdkDisplay *display = gdk_window_get_display (window);
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
- struct wl_data_source *data_source;
+ gpointer data_source;
guint i;
g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1268,6 +1400,13 @@ gdk_wayland_selection_add_targets (GdkWindow *window,
device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
gdk_wayland_device_set_selection (device, data_source);
}
+ else if (selection == atoms[ATOM_PRIMARY])
+ {
+ GdkSeat *seat;
+
+ seat = gdk_display_get_default_seat (display);
+ gdk_wayland_seat_set_primary (seat, data_source);
+ }
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]