From 8ae3bae9a9a7836edcb412f8c4019a2d2da0fc9b Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 29 Apr 2013 19:25:21 +0200 Subject: [PATCH] Find tooltip/dnd widget running through container children in inverse order Usually, educated GtkContainers' forall() implementation returns children in an order that's safe for the default draw() implementation in GtkContainer. So for widgets with some stacking notions (eg. GtkOverlay), _gtk_widget_find_at_coords() needs to recurse within containers in reverse order so it finds the topmost widget. As this function is used in both tooltips and DnD code, this improves behavior of "floating" widgets wrt those two. This could for example be seen in the "Transparent" GTK+ demo, where dropping text on the entry results on the text going to the textview. https://bugzilla.gnome.org/show_bug.cgi?id=699239 --- gtk/gtktooltip.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c index aba9ffb38a..0914641c5d 100644 --- a/gtk/gtktooltip.c +++ b/gtk/gtktooltip.c @@ -691,6 +691,15 @@ struct ChildLocation gint y; }; +static void +prepend_and_ref_widget (GtkWidget *widget, + gpointer data) +{ + GSList **slist_p = data; + + *slist_p = g_slist_prepend (*slist_p, g_object_ref (widget)); +} + static void child_location_foreach (GtkWidget *child, gpointer data) @@ -735,6 +744,7 @@ child_location_foreach (GtkWidget *child, if (GTK_IS_CONTAINER (child)) { struct ChildLocation tmp = { NULL, NULL, 0, 0 }; + GSList *children = NULL, *tmp_list; /* Take (x, y) relative the child's allocation and * recurse. @@ -744,12 +754,20 @@ child_location_foreach (GtkWidget *child, tmp.container = child; gtk_container_forall (GTK_CONTAINER (child), - child_location_foreach, &tmp); + prepend_and_ref_widget, &children); + + for (tmp_list = children; tmp_list; tmp_list = tmp_list->next) + { + child_location_foreach (tmp_list->data, &tmp); + g_object_unref (tmp_list->data); + } if (tmp.child) child_loc->child = tmp.child; else child_loc->child = child; + + g_slist_free (children); } else child_loc->child = child;