[patch] widget_hide, widget_destroy and ref_count
- From: Tim Janik <Tim Janik Hamburg Netsurf DE>
- To: Peter Mattis <petm XCF Berkeley EDU>
- cc: gtk-list redhat com, Tim Janik <timj psynet net>
- Subject: [patch] widget_hide, widget_destroy and ref_count
- Date: Thu, 18 Sep 1997 04:41:40 +0200 (CEST)
hi folks [especially peter],
as i mentioned before, i'm having problems with deletions of widgets in GUBI.
you should know that GUBI is very sensible about the execution of a widgets
"destroy" handler, i.e. if gtk_widget_destroy(test_widget) will not invoke
the destroy handlers of a widget (e.g. due to a widgets ref_count being != 0),
GUBI will certainly notice this one line after, or may be a little bit later
and complain (and i experienced that every time i got this complain, something
else will fail later on in the toolkit...).
now if GUBI destroyes a widget, it will gtk_widget_hide it before. this leads
to the following situation:
let's say we create a window with an arrow in it and destroy the arrow...
[...]
> arrow = gtk_arrow_new();
> gtk_container_add (window, arrow);
> gtk_widget_show (arrow);
[...]
now arrow->ref_count == 1 because of gtk_widget_set_parent() (after being
incremented and decremented for each of gtk_widget_queue_draw() and
gtk_widget_queue_resize()).
if now the widget is hidden, the hiding will queue it again for resizing.
[peter: why is there a gtk_widget_queue_resize() in gtk_real_widget_hide()?]
now the widget should be destroyed, which won't happen because of the
resize ref_count...
i therefore added a call to a new function
gtk_idle_remove_by_data(widget) and did a gtk_object_unref() for
GTK_WIDGET_REDRAW_PENDING() and/or GTK_WIDGET_RESIZE_NEEDED() in
gtk_widget_destroy() and gtk_widget_unparent().
now hide, unparent and destroy will work.
basicaly i'm having a few questions now:
- is it ok to assume gtk_widget_destroy() will call the destroy handler
in the normal case?
- is it ok to assume i'm allowed to do a gtk_widget_hide() before a call
to gtk_widget_destroy()?
from Radek Doulik's patch mail (regarding "desktop property patch") to
the gnome mailing list, i figured the hiding must have been a problem
there as well.
i realy think the answer to both questions should be yes, otherwise i would
be in the needs to come up with some very strange programming approaches...
folks: regarding the aplied patch you should notice, i will not upload it to
ftp.gimp.org and if you don't know too much about the resizing/queueing
stuff you probably do not want to aply it, as this is not my final word
on this issue (i'm still getting "resize pending") and i guess it won't
be peter's either...
peter: please take a close look at this patch even if you don't aply it,
the `if (widget)' and `if (resize_container)' conditions in
gtkwindow.c are needed because these might be NULL (look at the
`while (widget && ...)' condition).
also the `g_return_if_fail (widget != NULL);' in gtk_widget_destroy()
should stay, and i think having a gtk_idle_remove_by_data() is not a
bad idea...
---
ciaoTJ
diff -ru gtk+970916/gtk/gtkmain.c /usr/src/gtk+/gtk/gtkmain.c
--- gtk+970916/gtk/gtkmain.c Mon Sep 15 08:23:35 1997
+++ /usr/src/gtk+/gtk/gtkmain.c Thu Sep 18 01:34:24 1997
@@ -104,6 +104,7 @@
static GList *pending_idles = NULL;
static GList *remove_timeouts = NULL;
static GList *remove_idles = NULL;
+static GList *remove_idles_by_data = NULL;
static gint handling_timeouts = FALSE;
static gint handling_idle = FALSE;
static GMemChunk *timeout_mem_chunk = NULL;
@@ -575,6 +576,61 @@
}
void
+gtk_idle_remove_by_data (gpointer data)
+{
+ GtkIdleFunction *idlef;
+ GList *tmp_list;
+
+ if (!handling_idle)
+ {
+ tmp_list = idle_functions;
+ while (tmp_list)
+ {
+ idlef = tmp_list->data;
+
+ if (idlef->data == data)
+ {
+ idle_functions = g_list_remove_link (idle_functions, tmp_list);
+ g_list_free (tmp_list);
+ g_mem_chunk_free (idle_mem_chunk, idlef);
+
+ gtk_handle_timer ();
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ tmp_list = pending_idles;
+ while (tmp_list)
+ {
+ idlef = tmp_list->data;
+
+ if (idlef->data == data)
+ {
+ idle_functions = g_list_remove_link (idle_functions, tmp_list);
+ g_list_free (tmp_list);
+ g_mem_chunk_free (idle_mem_chunk, idlef);
+
+ gtk_handle_timer ();
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+ }
+ else
+ {
+ gpointer *d;
+
+ d = g_new (gpointer, 1);
+ *d = data;
+
+ remove_idles_by_data = g_list_prepend (remove_idles_by_data, d);
+ }
+}
+
+void
gtk_get_current_event (GdkEvent *event)
{
g_assert (event != NULL);
@@ -816,6 +872,20 @@
g_list_free (remove_idles);
remove_idles = NULL;
+ }
+
+ if (remove_idles_by_data)
+ {
+ tmp_list = remove_idles_by_data;
+ while (tmp_list)
+ {
+ gtk_idle_remove_by_data (*((gpointer*) tmp_list->data));
+ g_free (tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_free (remove_idles_by_data);
+ remove_idles_by_data = NULL;
}
}
}
diff -ru gtk+970916/gtk/gtkmain.h /usr/src/gtk+/gtk/gtkmain.h
--- gtk+970916/gtk/gtkmain.h Tue Sep 2 04:30:56 1997
+++ /usr/src/gtk+/gtk/gtkmain.h Thu Sep 18 01:26:26 1997
@@ -53,6 +53,8 @@
gpointer data);
void gtk_idle_remove (gint tag);
+void gtk_idle_remove_by_data (gpointer data);
+
void gtk_get_current_event (GdkEvent *event);
GtkWidget* gtk_get_event_widget (GdkEvent *event);
diff -ru gtk+970916/gtk/gtkwidget.c /usr/src/gtk+/gtk/gtkwidget.c
--- gtk+970916/gtk/gtkwidget.c Tue Sep 16 00:12:58 1997
+++ /usr/src/gtk+/gtk/gtkwidget.c Thu Sep 18 04:19:15 1997
@@ -803,6 +803,33 @@
void
gtk_widget_destroy (GtkWidget *widget)
{
+ g_return_if_fail (widget != NULL);
+
+ if (GTK_WIDGET_REDRAW_PENDING (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_REDRAW_PENDING);
+ gtk_object_unref (GTK_OBJECT (widget));
+ gtk_idle_remove_by_data (widget);
+ }
+ if (GTK_WIDGET_RESIZE_NEEDED (widget))
+ {
+ GtkWidget *toplevel;
+ GSList *resize_widgets;
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ gtk_object_unref (GTK_OBJECT (widget));
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (toplevel), resize_widgets_key);
+
+ if (resize_widgets)
+ {
+ resize_widgets = g_slist_remove (resize_widgets, widget);
+
+ gtk_object_set_data (GTK_OBJECT (toplevel), resize_widgets_key, resize_widgets);
+ }
+ }
+
if (widget->parent)
{
if (!GTK_OBJECT_BEING_DESTROYED (widget->parent))
@@ -843,6 +870,25 @@
gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
}
+ if (GTK_WIDGET_RESIZE_NEEDED (widget))
+ {
+ GtkWidget *toplevel;
+ GSList *resize_widgets;
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_RESIZE_NEEDED);
+ gtk_object_unref (GTK_OBJECT (widget));
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ resize_widgets = gtk_object_get_data (GTK_OBJECT (toplevel), resize_widgets_key);
+
+ if (resize_widgets)
+ {
+ resize_widgets = g_slist_remove (resize_widgets, widget);
+
+ gtk_object_set_data (GTK_OBJECT (toplevel), resize_widgets_key, resize_widgets);
+ }
+ }
+
if (widget->window &&
GTK_WIDGET_NO_WINDOW (widget) &&
GTK_WIDGET_DRAWABLE (widget))
diff -ru gtk+970916/gtk/gtkwindow.c /usr/src/gtk+/gtk/gtkwindow.c
--- gtk+970916/gtk/gtkwindow.c Mon Sep 15 07:29:30 1997
+++ /usr/src/gtk+/gtk/gtkwindow.c Thu Sep 18 03:24:51 1997
@@ -917,7 +917,8 @@
(widget->allocation.height < widget->requisition.height)))
widget = widget->parent;
- GTK_WIDGET_SET_FLAGS (widget, GTK_RESIZE_PENDING);
+ if (widget)
+ GTK_WIDGET_SET_FLAGS (widget, GTK_RESIZE_PENDING);
}
resize_containers = NULL;
@@ -933,19 +934,23 @@
!GTK_WIDGET_RESIZE_PENDING (resize_container))
resize_container = resize_container->parent;
- widget = resize_container->parent;
- while (widget)
+ if (resize_container)
{
- if (GTK_WIDGET_RESIZE_PENDING (widget))
+ widget = resize_container->parent;
+
+ while (widget)
{
- GTK_WIDGET_UNSET_FLAGS (resize_container, GTK_RESIZE_PENDING);
- resize_container = widget;
+ if (GTK_WIDGET_RESIZE_PENDING (widget))
+ {
+ GTK_WIDGET_UNSET_FLAGS (resize_container, GTK_RESIZE_PENDING);
+ resize_container = widget;
+ }
+ widget = widget->parent;
}
- widget = widget->parent;
+
+ if (g_slist_find (resize_containers, resize_container) == NULL)
+ resize_containers = g_slist_prepend (resize_containers, resize_container);
}
-
- if (g_slist_find (resize_containers, resize_container) == NULL)
- resize_containers = g_slist_prepend (resize_containers, resize_container);
}
g_slist_free (resize_widgets);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]