[gtk+] wayland: Separate selection buffers and other per-selection atom data
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] wayland: Separate selection buffers and other per-selection atom data
- Date: Thu, 30 Jun 2016 12:11:53 +0000 (UTC)
commit 0d30ad279f0ed1a60abf123693981d42b57090d2
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Jun 29 17:13:55 2016 +0200
wayland: Separate selection buffers and other per-selection atom data
This has most notably impact in selection buffers, because those were
shared across all selection atoms. This turned out wrong on 2 situations:
- Because the selection atom was set at SelectionBuffer creation time, the
GDK_SELECTION_NOTIFY events generated will have unexpected info if the
buffer is attempted to be reused for another selection.
- Anytime different selections imply different stored content for the same
target.
This is better separated into per-selection buffers, so it's not possible
to get collisions if a same target is used across different selections.
https://bugzilla.gnome.org/show_bug.cgi?id=768177
gdk/wayland/gdkselection-wayland.c | 98 ++++++++++++++++++++++--------------
1 files changed, 60 insertions(+), 38 deletions(-)
---
diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c
index c21cafd..5dc6319 100644
--- a/gdk/wayland/gdkselection-wayland.c
+++ b/gdk/wayland/gdkselection-wayland.c
@@ -35,6 +35,7 @@
#include <string.h>
typedef struct _SelectionBuffer SelectionBuffer;
+typedef struct _SelectionData SelectionData;
typedef struct _StoredSelection StoredSelection;
typedef struct _AsyncWriteData AsyncWriteData;
typedef struct _DataOfferData DataOfferData;
@@ -80,22 +81,26 @@ struct _AsyncWriteData
gsize index;
};
+struct _SelectionData
+{
+ DataOfferData *offer;
+ GHashTable *buffers; /* Hashtable of target_atom->SelectionBuffer */
+};
+
enum {
ATOM_PRIMARY,
ATOM_CLIPBOARD,
- ATOM_DND
+ ATOM_DND,
+ N_ATOMS
};
-static GdkAtom atoms[3] = { 0 };
+static GdkAtom atoms[N_ATOMS] = { 0 };
struct _GdkWaylandSelection
{
/* Destination-side data */
- DataOfferData *dnd_offer;
- DataOfferData *clipboard_offer;
- DataOfferData *primary_offer;
+ SelectionData selections[N_ATOMS];
GHashTable *offers; /* Currently alive offers, Hashtable of wl_data_offer->DataOfferData */
- GHashTable *selection_buffers; /* Hashtable of target_atom->SelectionBuffer */
/* Source-side data */
StoredSelection stored_selection;
@@ -307,6 +312,7 @@ GdkWaylandSelection *
gdk_wayland_selection_new (void)
{
GdkWaylandSelection *selection;
+ gint i;
/* init atoms */
atoms[ATOM_PRIMARY] = gdk_atom_intern_static_string ("PRIMARY");
@@ -314,9 +320,13 @@ gdk_wayland_selection_new (void)
atoms[ATOM_DND] = gdk_atom_intern_static_string ("GdkWaylandSelection");
selection = g_new0 (GdkWaylandSelection, 1);
- selection->selection_buffers =
- g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) selection_buffer_cancel_and_unref);
+ for (i = 0; i < G_N_ELEMENTS (selection->selections); i++)
+ {
+ selection->selections[i].buffers =
+ g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) selection_buffer_cancel_and_unref);
+ }
+
selection->offers =
g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) data_offer_data_free);
@@ -328,7 +338,11 @@ gdk_wayland_selection_new (void)
void
gdk_wayland_selection_free (GdkWaylandSelection *selection)
{
- g_hash_table_destroy (selection->selection_buffers);
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (selection->selections); i++)
+ g_hash_table_destroy (selection->selections[i].buffers);
+
g_array_unref (selection->source_targets);
g_hash_table_destroy (selection->offers);
@@ -456,16 +470,16 @@ static const struct gtk_primary_selection_offer_listener primary_offer_listener
primary_offer_offer,
};
-DataOfferData *
+SelectionData *
selection_lookup_offer_by_atom (GdkWaylandSelection *selection,
GdkAtom selection_atom)
{
if (selection_atom == atoms[ATOM_PRIMARY])
- return selection->primary_offer;
+ return &selection->selections[ATOM_PRIMARY];
else if (selection_atom == atoms[ATOM_CLIPBOARD])
- return selection->clipboard_offer;
+ return &selection->selections[ATOM_CLIPBOARD];
else if (selection_atom == atoms[ATOM_DND])
- return selection->dnd_offer;
+ return &selection->selections[ATOM_DND];
else
return NULL;
}
@@ -517,6 +531,7 @@ gdk_wayland_selection_set_offer (GdkDisplay *display,
{
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
struct wl_data_offer *prev_offer;
+ SelectionData *selection_data;
DataOfferData *info;
info = g_hash_table_lookup (selection->offers, wl_offer);
@@ -526,15 +541,14 @@ gdk_wayland_selection_set_offer (GdkDisplay *display,
if (prev_offer)
g_hash_table_remove (selection->offers, prev_offer);
- if (selection_atom == atoms[ATOM_PRIMARY])
- selection->primary_offer = info;
- else if (selection_atom == atoms[ATOM_CLIPBOARD])
- selection->clipboard_offer = info;
- else if (selection_atom == atoms[ATOM_DND])
- selection->dnd_offer = info;
+ selection_data = selection_lookup_offer_by_atom (selection, selection_atom);
- /* Clear all buffers */
- g_hash_table_remove_all (selection->selection_buffers);
+ if (selection_data)
+ {
+ selection_data->offer = info;
+ /* Clear all buffers */
+ g_hash_table_remove_all (selection_data->buffers);
+ }
}
gpointer
@@ -542,12 +556,12 @@ gdk_wayland_selection_get_offer (GdkDisplay *display,
GdkAtom selection_atom)
{
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
- const DataOfferData *info;
+ const SelectionData *data;
- info = selection_lookup_offer_by_atom (selection, selection_atom);
+ data = selection_lookup_offer_by_atom (selection, selection_atom);
- if (info)
- return info->offer_data;
+ if (data && data->offer)
+ return data->offer->offer_data;
return NULL;
}
@@ -557,12 +571,12 @@ gdk_wayland_selection_get_targets (GdkDisplay *display,
GdkAtom selection_atom)
{
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
- const DataOfferData *info;
+ const SelectionData *data;
- info = selection_lookup_offer_by_atom (selection, selection_atom);
+ data = selection_lookup_offer_by_atom (selection, selection_atom);
- if (info)
- return info->targets;
+ if (data && data->offer)
+ return data->offer->targets;
return NULL;
}
@@ -749,13 +763,17 @@ gdk_wayland_selection_lookup_requestor_buffer (GdkWindow *requestor)
GdkWaylandSelection *selection = gdk_wayland_display_get_selection (display);
SelectionBuffer *buffer_data;
GHashTableIter iter;
+ gint i;
- g_hash_table_iter_init (&iter, selection->selection_buffers);
-
- while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &buffer_data))
+ for (i = 0; i < G_N_ELEMENTS (selection->selections); i++)
{
- if (g_list_find (buffer_data->requestors, requestor))
- return buffer_data;
+ g_hash_table_iter_init (&iter, selection->selections[i].buffers);
+
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &buffer_data))
+ {
+ if (g_list_find (buffer_data->requestors, requestor))
+ return buffer_data;
+ }
}
return NULL;
@@ -1255,11 +1273,16 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
guint32 time)
{
GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
+ const SelectionData *selection_data;
SelectionBuffer *buffer_data;
gpointer offer;
gchar *mimetype;
GList *target_list;
+ selection_data = selection_lookup_offer_by_atom (wayland_selection, selection);
+ if (!selection_data)
+ return;
+
offer = gdk_wayland_selection_get_offer (display, selection);
target_list = gdk_wayland_selection_get_targets (display, selection);
@@ -1285,8 +1308,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
mimetype);
}
- buffer_data = g_hash_table_lookup (wayland_selection->selection_buffers,
- target);
+ buffer_data = g_hash_table_lookup (selection_data->buffers, target);
if (buffer_data)
selection_buffer_add_requestor (buffer_data, requestor);
@@ -1333,7 +1355,7 @@ _gdk_wayland_display_convert_selection (GdkDisplay *display,
g_free (targets);
}
- g_hash_table_insert (wayland_selection->selection_buffers,
+ g_hash_table_insert (selection_data->buffers,
GDK_ATOM_TO_POINTER (target),
buffer_data);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]