From 1c73edd9b0bffdd41ebb010a09037a6aacfb09b2 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 4 Oct 2019 18:25:16 +0100 Subject: [PATCH 1/2] gtklistbox: Factor the new header out into a separate variable Makes the code a little clearer, but makes no functional changes. Signed-off-by: Philip Withnall --- gtk/gtklistbox.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c index 0f3a42a931..54b8577af4 100644 --- a/gtk/gtklistbox.c +++ b/gtk/gtklistbox.c @@ -2221,7 +2221,7 @@ gtk_list_box_update_header (GtkListBox *box, GtkListBoxRow *row; GSequenceIter *before_iter; GtkListBoxRow *before_row; - GtkWidget *old_header; + GtkWidget *old_header, *new_header; if (iter == NULL || g_sequence_iter_is_end (iter)) return; @@ -2247,18 +2247,20 @@ gtk_list_box_update_header (GtkListBox *box, priv->update_header_func (row, before_row, priv->update_header_func_target); - if (old_header != ROW_PRIV (row)->header) + new_header = ROW_PRIV (row)->header; + if (old_header != new_header) { if (old_header != NULL) { gtk_widget_unparent (old_header); g_hash_table_remove (priv->header_hash, old_header); } - if (ROW_PRIV (row)->header != NULL) + if (new_header != NULL) { - g_hash_table_insert (priv->header_hash, ROW_PRIV (row)->header, row); - gtk_widget_set_parent (ROW_PRIV (row)->header, GTK_WIDGET (box)); - gtk_widget_show (ROW_PRIV (row)->header); + g_hash_table_insert (priv->header_hash, new_header, row); + gtk_widget_unparent (new_header); + gtk_widget_set_parent (new_header, GTK_WIDGET (box)); + gtk_widget_show (new_header); } gtk_widget_queue_resize (GTK_WIDGET (box)); } From b70f389b6418ec953c6995f36ff0c3ad0e26ddc3 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 4 Oct 2019 18:25:34 +0100 Subject: [PATCH 2/2] =?UTF-8?q?gtklistbox:=20Only=20unparent=20header=20ro?= =?UTF-8?q?ws=20if=20they=20haven=E2=80=99t=20been=20reused?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s possible for code which uses a `GtkListBox` to reuse a single header row, and move it around between rows. For example, this might happen if the code has interactive widgets (like buttons) in the row, and doesn’t want to continually recreate them and reattach signals to them whenever the row headers change. Unfortunately, this was broken, as the old header widget was unconditionally unparented, even if it had just been set as the header for a different row in the same `GtkListBox`. This left it assigned as a child widget in the `GtkListBox` (so it was iterated over by `forall`), but without its parent widget set. Fix that by only unparenting the header if it hasn’t already been assigned as the parent of a different row. Signed-off-by: Philip Withnall --- gtk/gtklistbox.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c index 54b8577af4..857da444c7 100644 --- a/gtk/gtklistbox.c +++ b/gtk/gtklistbox.c @@ -2250,8 +2250,11 @@ gtk_list_box_update_header (GtkListBox *box, new_header = ROW_PRIV (row)->header; if (old_header != new_header) { - if (old_header != NULL) + if (old_header != NULL && + g_hash_table_lookup (priv->header_hash, old_header) == row) { + /* Only unparent the @old_header if it hasn’t been re-used as the + * header for a different row. */ gtk_widget_unparent (old_header); g_hash_table_remove (priv->header_hash, old_header); }