From ff6cd8f75ea929e28e94c1ea295fe1c624d6f241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 29 Oct 2017 16:10:12 +0100 Subject: 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 a206dcdd1f..9acc954254 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 0c98806f46..d9ef5bb7c5 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 c8092473e2..03ce5b88f2 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 e1e7d7332e..ebf5dbf147 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; @@ -1683,25 +1681,6 @@ gtk_widget_class_init (GtkWidgetClass *klass) G_TYPE_NONE, 1, 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 @@ -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 ff2aa771ba..5ba1ffa15e 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, -- cgit v1.2.1