[gtk+] widget: Remove parent-set signal



commit ff6cd8f75ea929e28e94c1ea295fe1c624d6f241
Author: Timm Bäder <mail baedert org>
Date:   Sun Oct 29 16:10:12 2017 +0100

    widget: Remove parent-set signal
    
    When a widget unparents its child widget manually in finalize, this can
    lead to the parent-set signal being emitted for those child widgets. The
    parent already has a ref_count of 0 though, so it can't be used in a
    meaningful way. Specifically, emitting the signal will already try to
    ref the parent which prints a critical.
    
    Since GtkWidget already has a "parent" property, one can use its notify
    signal instead to get notified when the parent widget changes.

 gtk/gtklistbox.c  |   41 ++++++++++++++++++++++++++++-------------
 gtk/gtkmenuitem.c |   20 ++++++++++----------
 gtk/gtktoolitem.c |   18 +++++++++++-------
 gtk/gtkwidget.c   |   23 -----------------------
 gtk/gtkwidget.h   |    4 ----
 5 files changed, 49 insertions(+), 57 deletions(-)
---
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index a206dcd..9acc954 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -100,6 +100,8 @@ typedef struct
 
   GtkSelectionMode selection_mode;
 
+  gulong adjustment_changed_id;
+  GtkWidget *scrollable_parent;
   GtkAdjustment *adjustment;
   gboolean activate_single_click;
 
@@ -217,8 +219,9 @@ static void                 gtk_list_box_move_cursor                  (GtkListBo
                                                                        GtkMovementStep      step,
                                                                        gint                 count);
 static void                 gtk_list_box_finalize                     (GObject             *obj);
-static void                 gtk_list_box_parent_set                   (GtkWidget           *widget,
-                                                                       GtkWidget           *prev_parent);
+static void                 gtk_list_box_parent_cb                    (GObject             *object,
+                                                                       GParamSpec          *pspec,
+                                                                       gpointer             user_data);
 static void                 gtk_list_box_select_row_internal            (GtkListBox          *box,
                                                                          GtkListBoxRow       *row);
 static void                 gtk_list_box_unselect_row_internal          (GtkListBox          *box,
@@ -378,7 +381,6 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
   widget_class->measure = gtk_list_box_measure;
   widget_class->size_allocate = gtk_list_box_size_allocate;
   widget_class->drag_leave = gtk_list_box_drag_leave;
-  widget_class->parent_set = gtk_list_box_parent_set;
   container_class->add = gtk_list_box_add;
   container_class->remove = gtk_list_box_remove;
   container_class->forall = gtk_list_box_forall;
@@ -597,6 +599,9 @@ gtk_list_box_init (GtkListBox *box)
                     G_CALLBACK (gtk_list_box_multipress_gesture_pressed), box);
   g_signal_connect (priv->multipress_gesture, "released",
                     G_CALLBACK (gtk_list_box_multipress_gesture_released), box);
+
+
+  g_signal_connect (box, "notify::parent", G_CALLBACK (gtk_list_box_parent_cb), NULL);
 }
 
 /**
@@ -977,25 +982,35 @@ adjustment_changed (GObject    *object,
 }
 
 static void
-gtk_list_box_parent_set (GtkWidget *widget,
-                         GtkWidget *prev_parent)
+gtk_list_box_parent_cb (GObject    *object,
+                        GParamSpec *pspec,
+                        gpointer    user_data)
 {
+  GtkListBoxPrivate *priv = BOX_PRIV (object);
   GtkWidget *parent;
 
-  parent = gtk_widget_get_parent (widget);
+  parent = gtk_widget_get_parent (GTK_WIDGET (object));
 
-  if (prev_parent && GTK_IS_SCROLLABLE (prev_parent))
-    g_signal_handlers_disconnect_by_func (prev_parent,
-                                          G_CALLBACK (adjustment_changed), widget);
+  if (priv->adjustment_changed_id != 0 &&
+      priv->scrollable_parent != NULL)
+    {
+      g_signal_handler_disconnect (priv->scrollable_parent,
+                                   priv->adjustment_changed_id);
+    }
 
   if (parent && GTK_IS_SCROLLABLE (parent))
     {
-      adjustment_changed (G_OBJECT (parent), NULL, widget);
-      g_signal_connect (parent, "notify::vadjustment",
-                        G_CALLBACK (adjustment_changed), widget);
+      adjustment_changed (G_OBJECT (parent), NULL, object);
+      priv->scrollable_parent = parent;
+      priv->adjustment_changed_id = g_signal_connect (parent, "notify::vadjustment",
+                                                      G_CALLBACK (adjustment_changed), object);
     }
   else
-    gtk_list_box_set_adjustment (GTK_LIST_BOX (widget), NULL);
+    {
+      gtk_list_box_set_adjustment (GTK_LIST_BOX (object), NULL);
+      priv->adjustment_changed_id = 0;
+      priv->scrollable_parent = NULL;
+    }
 }
 
 /**
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index 0c98806..d9ef5bb 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -140,8 +140,9 @@ static gboolean gtk_menu_item_enter      (GtkWidget        *widget,
                                           GdkEventCrossing *event);
 static gboolean gtk_menu_item_leave      (GtkWidget        *widget,
                                           GdkEventCrossing *event);
-static void gtk_menu_item_parent_set     (GtkWidget        *widget,
-                                          GtkWidget        *previous_parent);
+static void gtk_menu_item_parent_cb      (GObject          *object,
+                                          GParamSpec       *pspec,
+                                          gpointer          user_data);
 static void gtk_menu_item_direction_changed (GtkWidget        *widget,
                                              GtkTextDirection  previous_dir);
 
@@ -510,7 +511,6 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
   widget_class->enter_notify_event = gtk_menu_item_enter;
   widget_class->leave_notify_event = gtk_menu_item_leave;
   widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
-  widget_class->parent_set = gtk_menu_item_parent_set;
   widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
   widget_class->measure = gtk_menu_item_measure;
   widget_class->direction_changed = gtk_menu_item_direction_changed;
@@ -678,6 +678,8 @@ gtk_menu_item_init (GtkMenuItem *menu_item)
 
   gtk_widget_set_has_window (GTK_WIDGET (menu_item), FALSE);
 
+  g_signal_connect (menu_item, "notify::parent", G_CALLBACK (gtk_menu_item_parent_cb), NULL);
+
   priv->submenu = NULL;
   priv->toggle_size = 0;
   priv->accelerator_width = 0;
@@ -1627,14 +1629,15 @@ gtk_menu_item_accel_name_foreach (GtkWidget *widget,
 }
 
 static void
-gtk_menu_item_parent_set (GtkWidget *widget,
-                          GtkWidget *previous_parent)
+gtk_menu_item_parent_cb (GObject    *object,
+                         GParamSpec *pspec,
+                         gpointer    user_data)
 {
-  GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
+  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
   GtkMenu *menu;
   GtkWidget *parent;
 
-  parent = gtk_widget_get_parent (widget);
+  parent = gtk_widget_get_parent (GTK_WIDGET (object));
   menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
 
   if (menu)
@@ -1644,9 +1647,6 @@ gtk_menu_item_parent_set (GtkWidget *widget,
                                        TRUE);
 
   update_arrow_widget (menu_item);
-
-  if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set)
-    GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent);
 }
 
 static void
diff --git a/gtk/gtktoolitem.c b/gtk/gtktoolitem.c
index c809247..03ce5b8 100644
--- a/gtk/gtktoolitem.c
+++ b/gtk/gtktoolitem.c
@@ -87,8 +87,9 @@ struct _GtkToolItemPrivate
 };
 
 static void gtk_tool_item_finalize     (GObject         *object);
-static void gtk_tool_item_parent_set   (GtkWidget       *toolitem,
-                                       GtkWidget       *parent);
+static void gtk_tool_item_parent_cb    (GObject         *object,
+                                        GParamSpec      *pspec,
+                                        gpointer         user_data);
 static void gtk_tool_item_set_property (GObject         *object,
                                        guint            prop_id,
                                        const GValue    *value,
@@ -119,8 +120,6 @@ gtk_tool_item_class_init (GtkToolItemClass *klass)
   object_class->finalize     = gtk_tool_item_finalize;
   object_class->notify       = gtk_tool_item_property_notify;
 
-  widget_class->parent_set    = gtk_tool_item_parent_set;
-
   klass->create_menu_proxy = _gtk_tool_item_create_menu_proxy;
   
   g_object_class_install_property (object_class,
@@ -215,6 +214,8 @@ gtk_tool_item_init (GtkToolItem *toolitem)
   toolitem->priv->visible_vertical = TRUE;
   toolitem->priv->homogeneous = FALSE;
   toolitem->priv->expand = FALSE;
+
+  g_signal_connect (toolitem, "notify::parent", G_CALLBACK (gtk_tool_item_parent_cb), NULL);
 }
 
 static void
@@ -231,11 +232,14 @@ gtk_tool_item_finalize (GObject *object)
 }
 
 static void
-gtk_tool_item_parent_set (GtkWidget   *toolitem,
-                         GtkWidget   *prev_parent)
+gtk_tool_item_parent_cb (GObject    *object,
+                         GParamSpec *pspec,
+                         gpointer    user_data)
 {
+  GtkToolItem *toolitem = GTK_TOOL_ITEM (object);
+
   if (gtk_widget_get_parent (GTK_WIDGET (toolitem)) != NULL)
-    gtk_tool_item_toolbar_reconfigured (GTK_TOOL_ITEM (toolitem));
+    gtk_tool_item_toolbar_reconfigured (toolitem);
 }
 
 static void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index e1e7d73..ebf5dbf 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -494,7 +494,6 @@ enum {
   UNREALIZE,
   SIZE_ALLOCATE,
   STATE_FLAGS_CHANGED,
-  PARENT_SET,
   HIERARCHY_CHANGED,
   DIRECTION_CHANGED,
   GRAB_NOTIFY,
@@ -1025,7 +1024,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   klass->get_request_mode = gtk_widget_real_get_request_mode;
   klass->measure = gtk_widget_real_measure;
   klass->state_flags_changed = gtk_widget_real_state_flags_changed;
-  klass->parent_set = NULL;
   klass->hierarchy_changed = NULL;
   klass->direction_changed = gtk_widget_real_direction_changed;
   klass->grab_notify = NULL;
@@ -1684,25 +1682,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                   GTK_TYPE_STATE_FLAGS);
 
   /**
-   * GtkWidget::parent-set:
-   * @widget: the object on which the signal is emitted
-   * @old_parent: (allow-none): the previous parent, or %NULL if the widget
-   *   just got its initial parent.
-   *
-   * The ::parent-set signal is emitted when a new parent
-   * has been set on a widget.
-   */
-  widget_signals[PARENT_SET] =
-    g_signal_new (I_("parent-set"),
-                 G_TYPE_FROM_CLASS (gobject_class),
-                 G_SIGNAL_RUN_FIRST,
-                 G_STRUCT_OFFSET (GtkWidgetClass, parent_set),
-                 NULL, NULL,
-                 NULL,
-                 G_TYPE_NONE, 1,
-                 GTK_TYPE_WIDGET);
-
-  /**
    * GtkWidget::hierarchy-changed:
    * @widget: the object on which the signal is emitted
    * @previous_toplevel: (allow-none): the previous toplevel ancestor, or %NULL
@@ -4081,7 +4060,6 @@ gtk_widget_unparent (GtkWidget *widget)
 
   _gtk_widget_update_parent_muxer (widget);
 
-  g_signal_emit (widget, widget_signals[PARENT_SET], 0, old_parent);
   if (toplevel)
     {
       _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
@@ -8380,7 +8358,6 @@ gtk_widget_reposition_after (GtkWidget *widget,
 
   _gtk_widget_update_parent_muxer (widget);
 
-  g_signal_emit (widget, widget_signals[PARENT_SET], 0, NULL);
   if (priv->parent->priv->anchored && prev_parent == NULL)
     _gtk_widget_propagate_hierarchy_changed (widget, NULL);
   g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index ff2aa77..5ba1ffa 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -157,8 +157,6 @@ struct _GtkWidget
  * @size_allocate: Signal emitted to get the widget allocation.
  * @state_flags_changed: Signal emitted when the widget state changes,
  *   see gtk_widget_get_state_flags().
- * @parent_set: Signal emitted when a new parent has been set on a
- *   widget.
  * @hierarchy_changed: Signal emitted when the anchored state of a
  *   widget changes.
  * @direction_changed: Signal emitted when the text direction of a
@@ -306,8 +304,6 @@ struct _GtkWidgetClass
                                 GtkAllocation       *out_clip);
   void (* state_flags_changed) (GtkWidget        *widget,
                                GtkStateFlags     previous_state_flags);
-  void (* parent_set)         (GtkWidget        *widget,
-                               GtkWidget        *previous_parent);
   void (* hierarchy_changed)   (GtkWidget        *widget,
                                GtkWidget        *previous_toplevel);
   void (* direction_changed)   (GtkWidget        *widget,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]