gtklistbox: Only unparent header rows if they haven’t been reused
authorPhilip Withnall <withnall@endlessm.com>
Fri, 4 Oct 2019 17:25:34 +0000 (18:25 +0100)
committerPhilip Withnall <withnall@endlessm.com>
Fri, 4 Oct 2019 17:48:53 +0000 (18:48 +0100)
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 <withnall@endlessm.com>
gtk/gtklistbox.c

index 54b8577af4bad9a469f3cb32ac24d5eb2a177bb2..857da444c75de30320ae3e0b5a7d2467b71c44e3 100644 (file)
@@ -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);
             }