From ff577e6c2cc3cacfb7e3d504bafffa20ae45733b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 3 Dec 2017 05:39:08 +0100 Subject: [PATCH] wayland: Add primary clipboard subclass I decided to put this in a custom subclass, because then I could keep the whole gtk primary protocol self-contained. The other option would have been reusing GdkWaylandClipboard, but that didn't seem worth it, especially because that code needs to interact with the DND machinery, while the primary doesn't. --- gdk/wayland/gdkdevice-wayland.c | 65 +---- gdk/wayland/gdkprimary-wayland.c | 398 +++++++++++++++++++++++++++++ gdk/wayland/gdkprimary-wayland.h | 41 +++ gdk/wayland/gdkprivate-wayland.h | 3 - gdk/wayland/gdkselection-wayland.c | 188 +------------- gdk/wayland/meson.build | 1 + 6 files changed, 454 insertions(+), 242 deletions(-) create mode 100644 gdk/wayland/gdkprimary-wayland.c create mode 100644 gdk/wayland/gdkprimary-wayland.h diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index ca2ea3e6a9..4f0641f226 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -34,6 +34,7 @@ #include "gdkdeviceprivate.h" #include "gdkdevicepadprivate.h" #include "gdkdevicetoolprivate.h" +#include "gdkprimary-wayland.h" #include "gdkseatprivate.h" #include "pointer-gestures-unstable-v1-client-protocol.h" #include "tablet-unstable-v2-client-protocol.h" @@ -233,7 +234,6 @@ struct _GdkWaylandSeat GdkClipboard *clipboard; GdkClipboard *primary_clipboard; - struct gtk_primary_selection_device *primary_data_device; struct wl_data_device *data_device; GdkDragContext *drop_context; @@ -1211,45 +1211,6 @@ static const struct wl_data_device_listener data_device_listener = { data_device_selection }; -static void -primary_selection_data_offer (void *data, - struct gtk_primary_selection_device *gtk_primary_selection_device, - struct gtk_primary_selection_offer *gtk_primary_offer) -{ - GdkWaylandSeat *seat = data; - - GDK_NOTE (EVENTS, - g_message ("primary selection offer, device %p, data offer %p", - gtk_primary_selection_device, gtk_primary_offer)); - - gdk_wayland_selection_ensure_primary_offer (seat->display, gtk_primary_offer); -} - -static void -primary_selection_selection (void *data, - struct gtk_primary_selection_device *gtk_primary_selection_device, - struct gtk_primary_selection_offer *gtk_primary_offer) -{ - GdkWaylandSeat *seat = data; - GdkAtom selection; - - if (!seat->keyboard_focus) - return; - - GDK_NOTE (EVENTS, - g_message ("primary selection selection, device %p, data offer %p", - gtk_primary_selection_device, gtk_primary_offer)); - - selection = gdk_atom_intern_static_string ("PRIMARY"); - gdk_wayland_selection_set_offer (seat->display, selection, gtk_primary_offer); - /* emit_selection_owner_change (seat->keyboard_focus, selection); */ -} - -static const struct gtk_primary_selection_device_listener primary_selection_device_listener = { - primary_selection_data_offer, - primary_selection_selection, -}; - static GdkDevice * get_scroll_device (GdkWaylandSeat *seat, enum wl_pointer_axis_source source); @@ -4796,12 +4757,7 @@ _gdk_wayland_display_create_seat (GdkWaylandDisplay *display_wayland, if (display_wayland->primary_selection_manager) { - seat->primary_data_device = - gtk_primary_selection_device_manager_get_device (display_wayland->primary_selection_manager, - seat->wl_seat); - gtk_primary_selection_device_add_listener (seat->primary_data_device, - &primary_selection_device_listener, seat); - seat->primary_clipboard = gdk_wayland_clipboard_new (display); + seat->primary_clipboard = gdk_wayland_primary_new (seat); } else { @@ -5016,23 +4972,6 @@ gdk_wayland_device_set_selection (GdkDevice *gdk_device, _gdk_wayland_display_get_serial (display_wayland)); } -void -gdk_wayland_seat_set_primary (GdkSeat *seat, - struct gtk_primary_selection_source *source) -{ - GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); - GdkWaylandDisplay *display_wayland; - guint32 serial; - - if (source) - { - display_wayland = GDK_WAYLAND_DISPLAY (gdk_seat_get_display (seat)); - serial = _gdk_wayland_display_get_serial (display_wayland); - gtk_primary_selection_device_set_selection (wayland_seat->primary_data_device, - source, serial); - } -} - /** * gdk_wayland_seat_get_wl_seat: * @device: (type GdkWaylandDevice): a #GdkDevice diff --git a/gdk/wayland/gdkprimary-wayland.c b/gdk/wayland/gdkprimary-wayland.c new file mode 100644 index 0000000000..b83f41aeae --- /dev/null +++ b/gdk/wayland/gdkprimary-wayland.c @@ -0,0 +1,398 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2017 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gdkprimary-wayland.h" + +#include "gdkclipboardprivate.h" +#include "gdkcontentformats.h" +#include "gdkintl.h" +#include "gdkprivate-wayland.h" +#include "gdk-private.h" + +#include +#include +#include + +typedef struct _GdkWaylandPrimaryClass GdkWaylandPrimaryClass; + +struct _GdkWaylandPrimary +{ + GdkClipboard parent; + + struct gtk_primary_selection_device *primary_data_device; + + struct gtk_primary_selection_offer *pending; + GdkContentFormatsBuilder *pending_builder; + + struct gtk_primary_selection_offer *offer; + GdkContentFormats *offer_formats; + + struct gtk_primary_selection_source *source; +}; + +struct _GdkWaylandPrimaryClass +{ + GdkClipboardClass parent_class; +}; + +G_DEFINE_TYPE (GdkWaylandPrimary, gdk_wayland_primary, GDK_TYPE_CLIPBOARD) + +static void +gdk_wayland_primary_discard_pending (GdkWaylandPrimary *cb) +{ + if (cb->pending_builder) + { + GdkContentFormats *ignore = gdk_content_formats_builder_free (cb->pending_builder); + gdk_content_formats_unref (ignore); + cb->pending_builder = NULL; + } + g_clear_pointer (&cb->pending, (GDestroyNotify) gtk_primary_selection_offer_destroy); +} + +static void +gdk_wayland_primary_discard_offer (GdkWaylandPrimary *cb) +{ + g_clear_pointer (&cb->offer_formats, gdk_content_formats_unref); + g_clear_pointer (&cb->offer, (GDestroyNotify) gtk_primary_selection_offer_destroy); +} + +static void +gdk_wayland_primary_discard_source (GdkWaylandPrimary *cb) +{ + g_clear_pointer (&cb->source, (GDestroyNotify) wl_data_source_destroy); +} + +static void +gdk_wayland_primary_finalize (GObject *object) +{ + GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (object); + + gdk_wayland_primary_discard_pending (cb); + gdk_wayland_primary_discard_offer (cb); + gdk_wayland_primary_discard_source (cb); + + G_OBJECT_CLASS (gdk_wayland_primary_parent_class)->finalize (object); +} + +static void +gdk_wayland_primary_claim_remote (GdkWaylandPrimary *cb, + struct gtk_primary_selection_offer *offer, + GdkContentFormats *formats) +{ + g_return_if_fail (GDK_IS_WAYLAND_PRIMARY (cb)); + + if (cb->source) + { + GDK_NOTE (CLIPBOARD, g_printerr ("%p: Ignoring clipboard offer for self\n", cb)); + return; + } + + gdk_wayland_primary_discard_offer (cb); + + GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats); + g_printerr ("%p: remote clipboard claim for %s\n", cb, s); + g_free (s); ); + cb->offer_formats = formats; + cb->offer = offer; + + gdk_clipboard_claim_remote (GDK_CLIPBOARD (cb), + cb->offer_formats); +} + +static void +primary_offer_offer (void *data, + struct gtk_primary_selection_offer *offer, + const char *type) +{ + GdkWaylandPrimary *cb = data; + + if (cb->pending != offer) + { + GDK_NOTE (SELECTION, g_printerr ("%p: offer for unknown selection %p of %s\n", + cb, offer, type)); + return; + } + + gdk_content_formats_builder_add_mime_type (cb->pending_builder, type); +} + +static const struct gtk_primary_selection_offer_listener primary_offer_listener = { + primary_offer_offer, +}; + +static void +primary_selection_data_offer (void *data, + struct gtk_primary_selection_device *device, + struct gtk_primary_selection_offer *offer) +{ + GdkWaylandPrimary *cb = data; + + GDK_NOTE (SELECTION, g_printerr ("%p: new primary offer %p\n", + cb, offer)); + + gdk_wayland_primary_discard_pending (cb); + + cb->pending = offer; + gtk_primary_selection_offer_add_listener (offer, + &primary_offer_listener, + cb); + + cb->pending_builder = gdk_content_formats_builder_new (); +} + +static void +primary_selection_selection (void *data, + struct gtk_primary_selection_device *device, + struct gtk_primary_selection_offer *offer) +{ + GdkWaylandPrimary *cb = data; + GdkContentFormats *formats; + + if (offer == NULL) + { + gdk_wayland_primary_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0)); + return; + } + + if (cb->pending != offer) + { + GDK_NOTE (SELECTION, g_printerr ("%p: ignoring unknown data offer %p\n", + cb, offer)); + return; + } + + formats = gdk_content_formats_builder_free (cb->pending_builder); + cb->pending_builder = NULL; + cb->pending = NULL; + + gdk_wayland_primary_claim_remote (cb, offer, formats); +} + +static const struct gtk_primary_selection_device_listener primary_selection_device_listener = { + primary_selection_data_offer, + primary_selection_selection, +}; + +static void +gdk_wayland_primary_write_done (GObject *clipboard, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + + if (!gdk_clipboard_write_finish (GDK_CLIPBOARD (clipboard), result, &error)) + { + GDK_NOTE (SELECTION, g_printerr ("%p: failed to write stream: %s\n", clipboard, error->message)); + g_error_free (error); + } +} + +static void +gdk_wayland_primary_data_source_send (void *data, + struct gtk_primary_selection_source *source, + const char *mime_type, + int32_t fd) +{ + GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (data); + GOutputStream *stream; + + GDK_NOTE (SELECTION, g_printerr ("%p: data source send request for %s on fd %d\n", + source, mime_type, fd)); + + mime_type = gdk_intern_mime_type (mime_type); + stream = g_unix_output_stream_new (fd, TRUE); + + gdk_clipboard_write_async (GDK_CLIPBOARD (cb), + mime_type, + stream, + G_PRIORITY_DEFAULT, + NULL, + gdk_wayland_primary_write_done, + cb); + g_object_unref (stream); +} + +static void +gdk_wayland_primary_data_source_cancelled (void *data, + struct gtk_primary_selection_source *source) +{ + GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (data); + + GDK_NOTE (CLIPBOARD, g_printerr ("%p: data source cancelled\n", data)); + + if (cb->source == source) + { + gdk_wayland_primary_discard_source (cb); + gdk_wayland_primary_claim_remote (cb, NULL, gdk_content_formats_new (NULL, 0)); + } +} + +static const struct gtk_primary_selection_source_listener primary_source_listener = { + gdk_wayland_primary_data_source_send, + gdk_wayland_primary_data_source_cancelled, +}; + +static gboolean +gdk_wayland_primary_claim (GdkClipboard *clipboard, + GdkContentFormats *formats, + gboolean local, + GdkContentProvider *content) +{ + GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard); + + if (local) + { + GdkWaylandDisplay *wdisplay = GDK_WAYLAND_DISPLAY (gdk_clipboard_get_display (clipboard)); + const char * const *mime_types; + gsize i, n_mime_types; + + gdk_wayland_primary_discard_offer (cb); + gdk_wayland_primary_discard_source (cb); + + cb->source = gtk_primary_selection_device_manager_create_source (wdisplay->primary_selection_manager); + gtk_primary_selection_source_add_listener (cb->source, &primary_source_listener, cb); + + mime_types = gdk_content_formats_get_mime_types (formats, &n_mime_types); + for (i = 0; i < n_mime_types; i++) + { + gtk_primary_selection_source_offer (cb->source, mime_types[i]); + } + + gtk_primary_selection_device_set_selection (cb->primary_data_device, + cb->source, + _gdk_wayland_display_get_serial (wdisplay)); + } + + return GDK_CLIPBOARD_CLASS (gdk_wayland_primary_parent_class)->claim (clipboard, formats, local, content); +} + +static void +gdk_wayland_primary_read_async (GdkClipboard *clipboard, + GdkContentFormats *formats, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GdkWaylandPrimary *cb = GDK_WAYLAND_PRIMARY (clipboard); + GInputStream *stream; + const char *mime_type; + int pipe_fd[2]; + GError *error = NULL; + GTask *task; + + task = g_task_new (clipboard, cancellable, callback, user_data); + g_task_set_priority (task, io_priority); + g_task_set_source_tag (task, gdk_wayland_primary_read_async); + + GDK_NOTE (CLIPBOARD, char *s = gdk_content_formats_to_string (formats); + g_printerr ("%p: read for %s\n", cb, s); + g_free (s); ); + mime_type = gdk_content_formats_match_mime_type (formats, cb->offer_formats); + if (mime_type == NULL) + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("No compatible transfer format found")); + return; + } + /* offer formats should be empty if we have no offer */ + g_assert (cb->offer); + + g_task_set_task_data (task, (gpointer) mime_type, NULL); + + if (!g_unix_open_pipe (pipe_fd, FD_CLOEXEC, &error)) + { + g_task_return_error (task, error); + return; + } + + gtk_primary_selection_offer_receive (cb->offer, mime_type, pipe_fd[1]); + stream = g_unix_input_stream_new (pipe_fd[0], TRUE); + close (pipe_fd[1]); + g_task_return_pointer (task, stream, g_object_unref); +} + +static GInputStream * +gdk_wayland_primary_read_finish (GdkClipboard *clipboard, + const char **out_mime_type, + GAsyncResult *result, + GError **error) +{ + GInputStream *stream; + GTask *task; + + g_return_val_if_fail (g_task_is_valid (result, G_OBJECT (clipboard)), NULL); + task = G_TASK (result); + g_return_val_if_fail (g_task_get_source_tag (task) == gdk_wayland_primary_read_async, NULL); + + stream = g_task_propagate_pointer (task, error); + + if (stream) + { + if (out_mime_type) + *out_mime_type = g_task_get_task_data (task); + g_object_ref (stream); + } + else + { + if (out_mime_type) + *out_mime_type = NULL; + } + + return stream; +} + +static void +gdk_wayland_primary_class_init (GdkWaylandPrimaryClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class); + + object_class->finalize = gdk_wayland_primary_finalize; + + clipboard_class->claim = gdk_wayland_primary_claim; + clipboard_class->read_async = gdk_wayland_primary_read_async; + clipboard_class->read_finish = gdk_wayland_primary_read_finish; +} + +static void +gdk_wayland_primary_init (GdkWaylandPrimary *cb) +{ +} + +GdkClipboard * +gdk_wayland_primary_new (GdkWaylandSeat *seat) +{ + GdkWaylandDisplay *wdisplay; + GdkWaylandPrimary *cb; + + wdisplay = GDK_WAYLAND_DISPLAY (gdk_seat_get_display (GDK_SEAT (seat))); + + cb = g_object_new (GDK_TYPE_WAYLAND_PRIMARY, + "display", wdisplay, + NULL); + + cb->primary_data_device = + gtk_primary_selection_device_manager_get_device (wdisplay->primary_selection_manager, + gdk_wayland_seat_get_wl_seat (GDK_SEAT (seat))); + gtk_primary_selection_device_add_listener (cb->primary_data_device, + &primary_selection_device_listener, cb); + + return GDK_CLIPBOARD (cb); +} diff --git a/gdk/wayland/gdkprimary-wayland.h b/gdk/wayland/gdkprimary-wayland.h new file mode 100644 index 0000000000..106ef5ee83 --- /dev/null +++ b/gdk/wayland/gdkprimary-wayland.h @@ -0,0 +1,41 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2017 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GDK_PRIMARY_WAYLAND_H__ +#define __GDK_PRIMARY_WAYLAND_H__ + +#include "gdk/gdkclipboard.h" + +#include "gdkseat-wayland.h" +#include +#include "gtk-primary-selection-client-protocol.h" + +G_BEGIN_DECLS + +#define GDK_TYPE_WAYLAND_PRIMARY (gdk_wayland_primary_get_type ()) +#define GDK_WAYLAND_PRIMARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WAYLAND_PRIMARY, GdkWaylandPrimary)) +#define GDK_IS_WAYLAND_PRIMARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WAYLAND_PRIMARY)) + +typedef struct _GdkWaylandPrimary GdkWaylandPrimary; + +GType gdk_wayland_primary_get_type (void) G_GNUC_CONST; + +GdkClipboard * gdk_wayland_primary_new (GdkWaylandSeat *seat); + +G_END_DECLS + +#endif /* __GDK_PRIMARY_WAYLAND_H__ */ diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 2f991047de..ef7f52a0bb 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -184,9 +184,6 @@ 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 gtk_primary_selection_source *source); - GdkDragContext * gdk_wayland_device_get_drop_context (GdkDevice *gdk_device); void gdk_wayland_device_unset_touch_grab (GdkDevice *device, diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c index 1a20148dca..cb888f0bbc 100644 --- a/gdk/wayland/gdkselection-wayland.c +++ b/gdk/wayland/gdkselection-wayland.c @@ -82,7 +82,6 @@ struct _SelectionData }; enum { - ATOM_PRIMARY, ATOM_DND, N_ATOMS }; @@ -100,9 +99,6 @@ struct _GdkWaylandSelection GArray *source_targets; GdkAtom requested_target; - struct gtk_primary_selection_source *primary_source; - GdkWindow *primary_owner; - struct wl_data_source *dnd_source; /* Owned by the GdkDragContext */ GdkWindow *dnd_owner; }; @@ -307,7 +303,6 @@ gdk_wayland_selection_new (void) gint i; /* init atoms */ - atoms[ATOM_PRIMARY] = gdk_atom_intern_static_string ("PRIMARY"); atoms[ATOM_DND] = gdk_atom_intern_static_string ("GdkWaylandSelection"); selection = g_new0 (GdkWaylandSelection, 1); @@ -348,8 +343,6 @@ gdk_wayland_selection_free (GdkWaylandSelection *selection) if (selection->stored_selection.fd > 0) close (selection->stored_selection.fd); - if (selection->primary_source) - gtk_primary_selection_source_destroy (selection->primary_source); if (selection->dnd_source) wl_data_source_destroy (selection->dnd_source); @@ -448,41 +441,11 @@ static const struct wl_data_offer_listener data_offer_listener = { data_offer_action }; -static void -primary_offer_offer (void *data, - struct gtk_primary_selection_offer *gtk_offer, - const char *type) -{ - GdkWaylandSelection *selection = data; - GdkContentFormatsBuilder *builder; - DataOfferData *info; - - info = g_hash_table_lookup (selection->offers, gtk_offer); - - if (!info || gdk_content_formats_contain_mime_type (info->targets, type)) - return; - - GDK_NOTE (EVENTS, - g_message ("primary offer offer, offer %p, type = %s", gtk_offer, type)); - - builder = gdk_content_formats_builder_new (); - gdk_content_formats_builder_add_formats (builder, info->targets); - gdk_content_formats_builder_add_mime_type (builder, type); - gdk_content_formats_unref (info->targets); - info->targets = gdk_content_formats_builder_free (builder); -} - -static const struct gtk_primary_selection_offer_listener primary_offer_listener = { - primary_offer_offer, -}; - static SelectionData * selection_lookup_offer_by_atom (GdkWaylandSelection *selection, GdkAtom selection_atom) { - if (selection_atom == atoms[ATOM_PRIMARY]) - return &selection->selections[ATOM_PRIMARY]; - else if (selection_atom == atoms[ATOM_DND]) + if (selection_atom == atoms[ATOM_DND]) return &selection->selections[ATOM_DND]; else return NULL; @@ -508,26 +471,6 @@ gdk_wayland_selection_ensure_offer (GdkDisplay *display, } } -void -gdk_wayland_selection_ensure_primary_offer (GdkDisplay *display, - struct gtk_primary_selection_offer *gtk_offer) -{ - GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display); - DataOfferData *info; - - info = g_hash_table_lookup (selection->offers, gtk_offer); - - if (!info) - { - info = data_offer_data_new (gtk_offer, - (GDestroyNotify) gtk_primary_selection_offer_destroy); - g_hash_table_insert (selection->offers, gtk_offer, info); - gtk_primary_selection_offer_add_listener (gtk_offer, - &primary_offer_listener, - selection); - } -} - GdkContentFormats * gdk_wayland_selection_steal_offer (GdkDisplay *display, gpointer wl_offer) @@ -1006,55 +949,6 @@ static const struct wl_data_source_listener data_source_listener = { data_source_action, }; -static void -primary_source_send (void *data, - struct gtk_primary_selection_source *source, - const char *mime_type, - int32_t fd) -{ - GdkWaylandSelection *wayland_selection = data; - - GDK_NOTE (EVENTS, - g_message ("primary source send, source = %p, mime_type = %s, fd = %d", - source, mime_type, fd)); - - if (!mime_type || !wayland_selection->primary_owner) - { - close (fd); - return; - } - - if (!gdk_wayland_selection_request_target (wayland_selection, - wayland_selection->primary_owner, - atoms[ATOM_PRIMARY], - gdk_atom_intern (mime_type, FALSE), - fd)) - gdk_wayland_selection_check_write (wayland_selection); -} - -static void -primary_source_cancelled (void *data, - struct gtk_primary_selection_source *source) -{ - GdkDisplay *display; - GdkAtom atom; - - GDK_NOTE (EVENTS, - g_message ("primary source cancelled, source = %p", source)); - - display = gdk_display_get_default (); - - atom = atoms[ATOM_PRIMARY]; - emit_selection_clear (display, atom); - gdk_selection_owner_set (NULL, atom, GDK_CURRENT_TIME, TRUE); - gdk_wayland_selection_unset_data_source (display, atom); -} - -static const struct gtk_primary_selection_source_listener primary_source_listener = { - primary_source_send, - primary_source_cancelled, -}; - struct wl_data_source * gdk_wayland_selection_get_data_source (GdkWindow *owner, GdkAtom selection) @@ -1070,18 +964,6 @@ 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) - { - gtk_primary_selection_source_destroy (wayland_selection->primary_source); - wayland_selection->primary_source = NULL; - } - } else return NULL; @@ -1090,28 +972,13 @@ gdk_wayland_selection_get_data_source (GdkWindow *owner, display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (owner)); - if (selection == atoms[ATOM_PRIMARY]) - { - if (display_wayland->primary_selection_manager) - { - source = gtk_primary_selection_device_manager_create_source (display_wayland->primary_selection_manager); - gtk_primary_selection_source_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); - } + 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; return source; } @@ -1122,19 +989,7 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display, { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); - 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) - { - gtk_primary_selection_source_destroy (wayland_selection->primary_source); - wayland_selection->primary_source = NULL; - } - } - else if (selection == atoms[ATOM_DND]) + if (selection == atoms[ATOM_DND]) { wayland_selection->dnd_source = NULL; } @@ -1146,9 +1001,7 @@ _gdk_wayland_display_get_selection_owner (GdkDisplay *display, { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); - if (selection == atoms[ATOM_PRIMARY]) - return wayland_selection->primary_owner; - else if (selection == atoms[ATOM_DND]) + if (selection == atoms[ATOM_DND]) return wayland_selection->dnd_owner; return NULL; @@ -1163,12 +1016,7 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display, { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); - if (selection == atoms[ATOM_PRIMARY]) - { - wayland_selection->primary_owner = owner; - return TRUE; - } - else if (selection == atoms[ATOM_DND]) + if (selection == atoms[ATOM_DND]) { wayland_selection->dnd_owner = owner; return TRUE; @@ -1311,10 +1159,9 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display, return; } - if (selection != atoms[ATOM_PRIMARY]) - wl_data_offer_accept (offer, - _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)), - mimetype); + wl_data_offer_accept (offer, + _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)), + mimetype); } buffer_data = g_hash_table_lookup (selection_data->buffers, target); @@ -1336,10 +1183,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display, { g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL); - if (selection == atoms[ATOM_PRIMARY]) - gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]); - else - wl_data_offer_receive (offer, mimetype, pipe_fd[1]); + wl_data_offer_receive (offer, mimetype, pipe_fd[1]); stream = g_unix_input_stream_new (pipe_fd[0], TRUE); close (pipe_fd[1]); @@ -1501,14 +1345,6 @@ gdk_wayland_display_add_selection_targets (GdkDisplay *display, wl_data_source_offer (data_source, mimetype); g_free (mimetype); } - - if (selection == atoms[ATOM_PRIMARY]) - { - GdkSeat *seat; - - seat = gdk_display_get_default_seat (display); - gdk_wayland_seat_set_primary (seat, data_source); - } } void diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index c395631f37..fec3d2c74e 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -9,6 +9,7 @@ gdk_wayland_sources = files([ 'gdkglcontext-wayland.c', 'gdkkeys-wayland.c', 'gdkmonitor-wayland.c', + 'gdkprimary-wayland.c', 'gdkselection-wayland.c', 'gdkvulkancontext-wayland.c', 'gdkwindow-wayland.c',