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.
This commit is contained in:
Timm Bäder 2017-10-29 16:10:12 +01:00
parent 0be4166b89
commit ff6cd8f75e
5 changed files with 49 additions and 57 deletions

View File

@ -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;
}
}
/**

View File

@ -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

View File

@ -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

View File

@ -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]);

View File

@ -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,