forked from AuroraMiddleware/gtk
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
This commit is contained in:
parent
0d0c9c918e
commit
e23b4dd21b
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user