[mutter/wip/carlosg/dnd-crash-fix: 79/79] wayland: Unset DnD selection on wl_data_offer destruction



commit 48585000b3f8332a197701f0e087c6836ea7b29b
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon May 13 17:18:28 2019 +0200

    wayland: Unset DnD selection on wl_data_offer destruction
    
    On a successful DnD operation we may expect the wl_data_source and
    wl_data_offer to live long enough to finish the data transfer, despite the
    grab operation (and other supporting data) being gone.
    
    When that happens, the compositor expects a wl_data_offer.finish request to
    notify that it finished. However the client may still chose not to send that
    and destroy the wl_data_offer instead, resulting in the MetaSelectionSource
    owner for the DnD selection not being unset.
    
    When that happens, the DnD MetaSelectionSource still exists but it's
    detached from any grab operation, so will not be unset if eg. the drag
    source client destroys the wl_data_source. This may result in crashes when
    the next drag operation tries to replace the owner DnD MetaSelectionSource.
    
    Check explicitly for this case, in order to ensure the DnD owner is unset
    after such operations.
    
    Closes: https://gitlab.gnome.org/GNOME/mutter/issues/591

 src/wayland/meta-wayland-data-device.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
---
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 1291945de..abdb615c8 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -95,6 +95,9 @@ G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
 G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
                META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND);
 
+static void unset_selection_source (MetaWaylandDataDevice *data_device,
+                                    MetaSelectionType      selection_type);
+
 static MetaWaylandDataSource *
 meta_wayland_data_source_wayland_new (struct wl_resource *resource);
 static MetaWaylandDataSource *
@@ -567,12 +570,14 @@ destroy_data_offer (struct wl_resource *resource)
 
       if (offer == meta_wayland_data_source_get_current_offer (offer->source))
         {
-          if (seat && seat->data_device.dnd_data_source == offer->source &&
+          if (seat->data_device.dnd_data_source == offer->source &&
               wl_resource_get_version (offer->resource) <
               WL_DATA_OFFER_ACTION_SINCE_VERSION)
             meta_wayland_data_source_notify_finish (offer->source);
           else
             {
+              if (seat->data_device.dnd_data_source == offer->source)
+                unset_selection_source (&seat->data_device, META_SELECTION_DND);
               meta_wayland_data_source_cancel (offer->source);
               meta_wayland_data_source_set_current_offer (offer->source, NULL);
             }
@@ -1038,7 +1043,6 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
         {
           /* Detach the data source from the grab, it's meant to live longer */
           meta_wayland_drag_grab_set_source (drag_grab, NULL);
-          meta_wayland_data_source_set_seat (source, NULL);
 
           meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
           meta_wayland_data_source_notify_drop_performed (source);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]