wayland: Set dummy selection source on .set_selection(null)

Requesting a selection with a NULL data source means "unset the clipboard",
but internally we use an unset clipboard as the indication that the
clipboard manager should take over.

Moreover, this unset request may go unheard if the current owner is someone
else than the MetaWaylandDataDevice.

Instead, set a dummy data source with no mimetypes nor data, this both
prevents the clipboard manager from taking over and ensures the selection
is replaced with it.

The MetaSelectionSourceMemory was also added some checks to allow for this
dummy mode.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/793
This commit is contained in:
Carlos Garnacho 2019-10-11 18:43:00 +02:00
parent ea4665bf51
commit 84cc89e19a
2 changed files with 17 additions and 13 deletions

View File

@ -76,6 +76,9 @@ meta_selection_source_memory_get_mimetypes (MetaSelectionSource *source)
{
MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (source);
if (!source_mem->mimetype)
return NULL;
return g_list_prepend (NULL, g_strdup (source_mem->mimetype));
}
@ -84,7 +87,7 @@ meta_selection_source_memory_finalize (GObject *object)
{
MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (object);
g_bytes_unref (source_mem->content);
g_clear_pointer (&source_mem->content, g_bytes_unref);
g_free (source_mem->mimetype);
G_OBJECT_CLASS (meta_selection_source_memory_parent_class)->finalize (object);

View File

@ -36,6 +36,7 @@
#include <unistd.h>
#include "compositor/meta-dnd-actor-private.h"
#include "meta/meta-selection-source-memory.h"
#include "wayland/meta-selection-source-wayland-private.h"
#include "wayland/meta-wayland-dnd-surface.h"
#include "wayland/meta-wayland-pointer.h"
@ -1627,6 +1628,7 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client;
MetaSelectionSource *selection_source;
if (data_device->selection_data_source &&
data_device->selection_serial - serial < UINT32_MAX / 2)
@ -1646,23 +1648,22 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (source)
{
MetaSelectionSource *selection_source;
meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source),
selection_data_source_destroyed,
data_device);
selection_source = meta_selection_source_wayland_new (source);
set_selection_source (data_device, META_SELECTION_CLIPBOARD,
selection_source);
g_object_unref (selection_source);
}
else
{
unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
}
set_selection_source (data_device, META_SELECTION_CLIPBOARD,
selection_source);
g_object_unref (selection_source);
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{
@ -1748,6 +1749,7 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client;
MetaSelectionSource *selection_source;
if (META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source))
{
@ -1777,23 +1779,22 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
if (source)
{
MetaSelectionSource *selection_source;
meta_wayland_data_source_set_seat (source, seat);
g_object_weak_ref (G_OBJECT (source),
primary_source_destroyed,
data_device);
selection_source = meta_selection_source_wayland_new (source);
set_selection_source (data_device, META_SELECTION_PRIMARY,
selection_source);
g_object_unref (selection_source);
}
else
{
unset_selection_source (data_device, META_SELECTION_PRIMARY);
selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
}
set_selection_source (data_device, META_SELECTION_PRIMARY,
selection_source);
g_object_unref (selection_source);
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{