From f43f6900c93cc59092cff3f3d771c1fba92ae2e1 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 20 Aug 2019 23:04:01 +0200 Subject: [PATCH 1/2] gdk/wayland: Emit GDK_SELECTION_NOTIFY on all failure/unset paths Either on failure, or when replacing a selection buffer due to a new wl_offer. We should emit one event for each pending requestor then. --- gdk/wayland/gdkselection-wayland.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c index 12737d672e..973f90cff3 100644 --- a/gdk/wayland/gdkselection-wayland.c +++ b/gdk/wayland/gdkselection-wayland.c @@ -114,6 +114,9 @@ struct _GdkWaylandSelection static void selection_buffer_read (SelectionBuffer *buffer); static void async_write_data_write (AsyncWriteData *write_data); static void emit_selection_clear (GdkDisplay *display, GdkAtom selection); +static void emit_empty_selection_notify (GdkWindow *requestor, + GdkAtom selection, + GdkAtom target); static void selection_buffer_notify (SelectionBuffer *buffer) @@ -168,11 +171,22 @@ selection_buffer_ref (SelectionBuffer *buffer) static void selection_buffer_unref (SelectionBuffer *buffer_data) { + GList *l; + buffer_data->ref_count--; if (buffer_data->ref_count != 0) return; + for (l = buffer_data->requestors; l; l = l->next) + { + emit_empty_selection_notify (l->data, buffer_data->selection, + buffer_data->target); + } + + g_list_free (buffer_data->requestors); + buffer_data->requestors = NULL; + if (buffer_data->cancellable) g_object_unref (buffer_data->cancellable); @@ -1313,7 +1327,10 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display, selection_data = selection_lookup_offer_by_atom (wayland_selection, selection); if (!selection_data) - return; + { + emit_empty_selection_notify (requestor, selection, target); + return; + } offer = gdk_wayland_selection_get_offer (display, selection); target_list = gdk_wayland_selection_get_targets (display, selection); From 6841c73808f4a72ef27ef803059c93ecc1dfc4b8 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 20 Aug 2019 23:14:50 +0200 Subject: [PATCH 2/2] gdk/wayland: Unset clipboard/primary if giving up selection ownership If gdk_selection_owner_set() is called with a NULL window, we should unset the related data source for the current selection. --- gdk/wayland/gdkdevice-wayland.c | 13 +++++-------- gdk/wayland/gdkprivate-wayland.h | 4 ++-- gdk/wayland/gdkselection-wayland.c | 18 +++++++++--------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 0d06141ff2..f65ade802f 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -5323,18 +5323,15 @@ gdk_wayland_device_get_data_device (GdkDevice *gdk_device) } void -gdk_wayland_device_set_selection (GdkDevice *gdk_device, - struct wl_data_source *source) +gdk_wayland_seat_set_selection (GdkSeat *seat, + struct wl_data_source *source) { - GdkWaylandSeat *seat; + GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (seat); GdkWaylandDisplay *display_wayland; - g_return_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device)); + display_wayland = GDK_WAYLAND_DISPLAY (wayland_seat->display); - seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (gdk_device)); - display_wayland = GDK_WAYLAND_DISPLAY (seat->display); - - wl_data_device_set_selection (seat->data_device, source, + wl_data_device_set_selection (wayland_seat->data_device, source, _gdk_wayland_display_get_serial (display_wayland)); } diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 49db8d5f19..fc8e9fe280 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -188,8 +188,8 @@ uint32_t _gdk_wayland_device_get_implicit_grab_serial(GdkWaylandDevice *device, uint32_t _gdk_wayland_seat_get_last_implicit_grab_serial (GdkSeat *seat, GdkEventSequence **seqence); struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_device); -void gdk_wayland_device_set_selection (GdkDevice *gdk_device, - struct wl_data_source *source); +void gdk_wayland_seat_set_selection (GdkSeat *seat, + struct wl_data_source *source); void gdk_wayland_seat_set_primary (GdkSeat *seat, struct gtk_primary_selection_source *source); diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c index 973f90cff3..cb799e53e0 100644 --- a/gdk/wayland/gdkselection-wayland.c +++ b/gdk/wayland/gdkselection-wayland.c @@ -1140,11 +1140,9 @@ gdk_wayland_selection_unset_data_source (GdkDisplay *display, if (selection == atoms[ATOM_CLIPBOARD]) { - GdkDevice *device; + GdkSeat *seat = gdk_display_get_default_seat (display); - device = gdk_seat_get_pointer (gdk_display_get_default_seat (display)); - - gdk_wayland_device_set_selection (device, NULL); + gdk_wayland_seat_set_selection (seat, NULL); if (wayland_selection->clipboard_source) { @@ -1198,11 +1196,15 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display, if (selection == atoms[ATOM_CLIPBOARD]) { wayland_selection->clipboard_owner = owner; + if (send_event && !owner) + gdk_wayland_selection_unset_data_source (display, selection); return TRUE; } else if (selection == atoms[ATOM_PRIMARY]) { wayland_selection->primary_owner = owner; + if (send_event && !owner) + gdk_wayland_selection_unset_data_source (display, selection); return TRUE; } else if (selection == atoms[ATOM_DND]) @@ -1551,12 +1553,10 @@ gdk_wayland_selection_add_targets (GdkWindow *window, if (selection == atoms[ATOM_CLIPBOARD]) { - GdkDisplay *display; - GdkDevice *device; + GdkSeat *seat; - display = gdk_window_get_display (window); - device = gdk_seat_get_pointer (gdk_display_get_default_seat (display)); - gdk_wayland_device_set_selection (device, data_source); + seat = gdk_display_get_default_seat (display); + gdk_wayland_seat_set_selection (seat, data_source); } else if (selection == atoms[ATOM_PRIMARY]) {