[mutter] x11: Let selection input streams create their own window



commit dbd6e74d3c3fcfde45fd561814a71d35f40f48f5
Author: Sebastian Keller <skeller gnome org>
Date:   Mon Apr 5 01:06:38 2021 +0200

    x11: Let selection input streams create their own window
    
    When there are two (or more) concurrent XConvertSelection requests with
    the same target, selection and window and the data is large enough for
    SelectionNotify events to overlap. This can result in the affected streams
    being considered completed without any data being transferred.
    
    While regular mutter/shell code does not make use of concurrent
    XConvertSelection requests with the same targets, some extensions might.
    Such as for example a clipboard manager that like the built-in clipboard
    manager tries to read the selection on owner-changed.
    
    One potential solution would be to make sure the event is for the correct
    property, but not all clients seem to support concurrent requests for the
    same targets but different properties on the same window.
    
    This commit instead changes the streams to use their own window which
    seems to be more widely supported.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4034
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1812>

 src/x11/meta-selection-source-x11.c               |  2 --
 src/x11/meta-x11-selection-input-stream-private.h |  1 -
 src/x11/meta-x11-selection-input-stream.c         | 20 +++++++++++++++++---
 3 files changed, 17 insertions(+), 6 deletions(-)
---
diff --git a/src/x11/meta-selection-source-x11.c b/src/x11/meta-selection-source-x11.c
index c9fc8fbc6c..15f46a1440 100644
--- a/src/x11/meta-selection-source-x11.c
+++ b/src/x11/meta-selection-source-x11.c
@@ -92,7 +92,6 @@ meta_selection_source_x11_read_async (MetaSelectionSource *source,
     mimetype = "UTF8_STRING";
 
   meta_x11_selection_input_stream_new_async (source_x11->x11_display,
-                                             source_x11->x11_display->selection.xwindow,
                                              gdk_x11_get_xatom_name (source_x11->xselection),
                                              mimetype,
                                              source_x11->timestamp,
@@ -251,7 +250,6 @@ meta_selection_source_x11_new_async (MetaX11Display      *x11_display,
   g_task_set_task_data (task, source, g_object_unref);
 
   meta_x11_selection_input_stream_new_async (x11_display,
-                                             x11_display->selection.xwindow,
                                              gdk_x11_get_xatom_name (xselection),
                                              "TARGETS",
                                              timestamp,
diff --git a/src/x11/meta-x11-selection-input-stream-private.h 
b/src/x11/meta-x11-selection-input-stream-private.h
index 3fcf9ffd16..a2b74ea99e 100644
--- a/src/x11/meta-x11-selection-input-stream-private.h
+++ b/src/x11/meta-x11-selection-input-stream-private.h
@@ -33,7 +33,6 @@ G_DECLARE_FINAL_TYPE (MetaX11SelectionInputStream,
                       GInputStream)
 
 void           meta_x11_selection_input_stream_new_async     (MetaX11Display             *x11_display,
-                                                              Window                      window,
                                                               const char                 *selection,
                                                               const char                 *target,
                                                               guint32                     timestamp,
diff --git a/src/x11/meta-x11-selection-input-stream.c b/src/x11/meta-x11-selection-input-stream.c
index 74552679f6..8a1318a89f 100644
--- a/src/x11/meta-x11-selection-input-stream.c
+++ b/src/x11/meta-x11-selection-input-stream.c
@@ -287,6 +287,7 @@ meta_x11_selection_input_stream_finalize (GObject *object)
     META_X11_SELECTION_INPUT_STREAM (object);
   MetaX11SelectionInputStreamPrivate *priv =
     meta_x11_selection_input_stream_get_instance_private (stream);
+  Display *xdisplay = priv->x11_display->xdisplay;
 
   g_async_queue_unref (priv->chunks);
 
@@ -294,6 +295,8 @@ meta_x11_selection_input_stream_finalize (GObject *object)
   g_free (priv->target);
   g_free (priv->property);
 
+  XDestroyWindow (xdisplay, priv->window);
+
   G_OBJECT_CLASS (meta_x11_selection_input_stream_parent_class)->finalize (object);
 }
 
@@ -504,7 +507,6 @@ meta_x11_selection_input_stream_xevent (MetaX11SelectionInputStream *stream,
 
 void
 meta_x11_selection_input_stream_new_async (MetaX11Display      *x11_display,
-                                           Window               window,
                                            const char          *selection,
                                            const char          *target,
                                            guint32              timestamp,
@@ -515,10 +517,14 @@ meta_x11_selection_input_stream_new_async (MetaX11Display      *x11_display,
 {
   MetaX11SelectionInputStream *stream;
   MetaX11SelectionInputStreamPrivate *priv;
+  XSetWindowAttributes attributes = { 0 };
 
   stream = g_object_new (META_TYPE_X11_SELECTION_INPUT_STREAM, NULL);
   priv = meta_x11_selection_input_stream_get_instance_private (stream);
 
+  attributes.event_mask = PropertyChangeMask;
+  attributes.override_redirect = True;
+
   priv->x11_display = x11_display;
   x11_display->selection.input_streams =
     g_list_prepend (x11_display->selection.input_streams, stream);
@@ -528,13 +534,21 @@ meta_x11_selection_input_stream_new_async (MetaX11Display      *x11_display,
   priv->xtarget = XInternAtom (x11_display->xdisplay, priv->target, False);
   priv->property = g_strdup_printf ("META_SELECTION_%p", stream);
   priv->xproperty = XInternAtom (x11_display->xdisplay, priv->property, False);
-  priv->window = window;
+  priv->window = XCreateWindow (x11_display->xdisplay,
+                                x11_display->xroot,
+                                -1, -1, 1, 1,
+                                0, /* border width */
+                                0, /* depth */
+                                InputOnly, /* class */
+                                CopyFromParent, /* visual */
+                                CWEventMask | CWOverrideRedirect,
+                                &attributes);
 
   XConvertSelection (x11_display->xdisplay,
                      priv->xselection,
                      priv->xtarget,
                      priv->xproperty,
-                     window,
+                     priv->window,
                      timestamp);
 
   priv->pending_task = g_task_new (NULL, cancellable, callback, user_data);


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