Can't unset selection
This is on Mutter 3.34.0 on Fedora 31.
Here's what happens upon calling wl_data_device.set_selection(nil, ...)
:
[3629559.891] -> wl_data_device@3.set_selection(nil, 12)
[3629560.090] wl_data_device@3.data_offer(new id wl_data_offer@26408800)
[3629560.103] wl_data_offer@4278190081.offer("text/plain;charset=utf-8")
[3629560.114] wl_data_device@3.selection(wl_data_offer@4278190081)
There are three things that are wrong here:
- First, the old selection gets resent to the focused client (i.e. the very same client that just tried to clear the selection), because in
meta_wayland_data_device_set_selection()
the old selection is sent out before actually changing it:
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
{
struct wl_resource *offer;
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
}
}
if (source)
{
/* ...snip... */
set_selection_source (data_device, META_SELECTION_CLIPBOARD,
selection_source);
}
else
{
unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
}
- Second, the selection actually remains set. This is because setting the selection to
nil
via Wayland only clears_MetaWaylandDataDevice.owners[selection_type]
, but not_MetaSelection.owners[selection_type]
, which is claimed bymeta_clipboard_manager
. But the clipboard manager should only take over selection ownership when the selection gets unset due to the owner client exiting, not when it is unset explicitly by callingset_selection(nil)
— in that case, the clipboard manager should rather delete (and preferably reliably zero out) its internal buffer. - Third, if we're in a situation where the
_MetaWaylandDataDevice.owners[selection_type]
isNULL
but_MetaSelection.owners[selection_type]
is claimed by the something else (such as the clipboard manager), any attempts to unset the selection will silently fail, because of this check only allowing unsetting the selection via Wayland when it was set via Wayland:
static void
unset_selection_source (MetaWaylandDataDevice *data_device,
MetaSelectionType selection_type)
{
MetaDisplay *display = meta_get_display ();
if (!data_device->owners[selection_type])
return;
meta_selection_unset_owner (meta_display_get_selection (display),
selection_type,
data_device->owners[selection_type]);
g_clear_object (&data_device->owners[selection_type]);
}
This may be related to #789 (closed) and !320 (merged), so cc @carlosg
Edited by Sergey Bugaev