summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastian Keller <skeller@gnome.org>2021-04-05 01:06:38 +0200
committerSebastian Keller <skeller@gnome.org>2022-01-07 02:21:28 +0100
commitdbd6e74d3c3fcfde45fd561814a71d35f40f48f5 (patch)
treeb052a6f044e2e3b516b749744f975a49655bad18 /src
parentd25175b91ca92f65a5628e7757b759b4052b495c (diff)
downloadmutter-dbd6e74d3c3fcfde45fd561814a71d35f40f48f5.tar.gz
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>
Diffstat (limited to 'src')
-rw-r--r--src/x11/meta-selection-source-x11.c2
-rw-r--r--src/x11/meta-x11-selection-input-stream-private.h1
-rw-r--r--src/x11/meta-x11-selection-input-stream.c20
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 c9fc8fbc6..15f46a144 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 3fcf9ffd1..a2b74ea99 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 74552679f..8a1318a89 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);