[gtk/gtk-3-24: 1/2] wayland: Ensure clipboard handling doesn't lock up in certain corner cases




commit e23b4dd21b41329a804fadf6a89c79be17dffcdf
Author: msizanoen1 <qtmlabs protonmail com>
Date:   Fri Oct 8 07:08:24 2021 +0700

    wayland: Ensure clipboard handling doesn't lock up in certain corner cases
    
    When a selection request fails to be converted to the requested format in the
    GTK layers, the wayland backend would miss bumping the machinery to handle
    further pending selection requests. Fix this by reacting to
    GdkDisplay::send_selection_notify with target=GDK_NONE (i.e. a failed
    conversion as hinted from the upper layers) to do that.
    
    This ensures the clipboard handling doesn't lock up in the following
    scenarios:
      - GTK returned with a mismatching type to the one requested
      - GTK fails to convert to the requested type
    
    Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4340

 gdk/wayland/gdkselection-wayland.c | 48 +++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 19 deletions(-)
---
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index f85f595616..d7f3332fa2 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -100,7 +100,7 @@ struct _GdkWaylandSelection
 
   /* Source-side data */
   GPtrArray *stored_selections; /* Array of StoredSelection */
-  GdkAtom current_request_selection;
+  StoredSelection *current_request_selection;
   GArray *source_targets;
   GdkAtom requested_target;
 
@@ -858,7 +858,12 @@ gdk_wayland_selection_reset_selection (GdkWaylandSelection *wayland_selection,
       stored_selection = g_ptr_array_index (wayland_selection->stored_selections, i);
 
       if (stored_selection->selection_atom == selection)
-        g_ptr_array_remove_index_fast (wayland_selection->stored_selections, i);
+        {
+          if (wayland_selection->current_request_selection == stored_selection)
+            wayland_selection->current_request_selection = NULL;
+
+          g_ptr_array_remove_index_fast (wayland_selection->stored_selections, i);
+        }
       else
         i++;
     }
@@ -877,21 +882,10 @@ gdk_wayland_selection_store (GdkWindow    *window,
 
   if (type == gdk_atom_intern_static_string ("NULL"))
     return;
-  if (selection->current_request_selection == GDK_NONE)
+  if (!selection->current_request_selection)
     return;
 
-  stored_selection =
-    gdk_wayland_selection_find_stored_selection (selection, window,
-                                                 selection->current_request_selection,
-                                                 type);
-
-  if (!stored_selection)
-    {
-      stored_selection = stored_selection_new (selection, window,
-                                               selection->current_request_selection,
-                                               type);
-      g_ptr_array_add (selection->stored_selections, stored_selection);
-    }
+  stored_selection = selection->current_request_selection;
 
   if ((mode == GDK_PROP_MODE_PREPEND ||
        mode == GDK_PROP_MODE_REPLACE) &&
@@ -915,7 +909,7 @@ gdk_wayland_selection_store (GdkWindow    *window,
     }
 
   /* Handle the next GDK_SELECTION_REQUEST / store, if any */
-  selection->current_request_selection = GDK_NONE;
+  selection->current_request_selection = NULL;
   gdk_wayland_selection_handle_next_request (selection);
 }
 
@@ -979,7 +973,7 @@ gdk_wayland_selection_handle_next_request (GdkWaylandSelection *wayland_selectio
           gdk_wayland_selection_emit_request (stored_selection->source,
                                               stored_selection->selection_atom,
                                               stored_selection->type);
-          wayland_selection->current_request_selection = stored_selection->selection_atom;
+          wayland_selection->current_request_selection = stored_selection;
           break;
         }
     }
@@ -1023,7 +1017,7 @@ gdk_wayland_selection_request_target (GdkWaylandSelection *wayland_selection,
 
   write_data = async_write_data_new (stored_selection, fd);
 
-  if (wayland_selection->current_request_selection == GDK_NONE)
+  if (!wayland_selection->current_request_selection)
     gdk_wayland_selection_handle_next_request (wayland_selection);
 
   return TRUE;
@@ -1435,13 +1429,29 @@ _gdk_wayland_display_set_selection_owner (GdkDisplay *display,
 }
 
 void
-_gdk_wayland_display_send_selection_notify (GdkDisplay *dispay,
+_gdk_wayland_display_send_selection_notify (GdkDisplay *display,
                                             GdkWindow  *requestor,
                                             GdkAtom     selection,
                                             GdkAtom     target,
                                             GdkAtom     property,
                                             guint32     time)
 {
+  GdkWaylandSelection *wayland_selection;
+
+  if (property != GDK_NONE)
+    return;
+
+  wayland_selection = gdk_wayland_display_get_selection (display);
+
+  if (!wayland_selection->current_request_selection)
+    return;
+
+  g_ptr_array_remove_fast (wayland_selection->stored_selections,
+                           wayland_selection->current_request_selection);
+
+  /* Handle the next GDK_SELECTION_REQUEST / store, if any */
+  wayland_selection->current_request_selection = NULL;
+  gdk_wayland_selection_handle_next_request (wayland_selection);
 }
 
 gint


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