don't add the same menu to different menuitems/ optionmenus.

Tue Feb  3 15:09:55 1998  Tim Janik  <timj@gimp.org>

        * gtk/testgtk.c: don't add the same menu to different menuitems/
          optionmenus.

        * gtk/gtkmenuitem.h:
        * gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
          be consistent with optionmenu. use gtk_menu_attach_to_widget/
          gtk_menu_detach for setting/removing the submenu.
          invoke gtk_widget_destroy(submenu) in destructor to be consistent
          with other destructors.

        * gtk/gtkoptionmenu.h:
        * gtk/gtkoptionmenu.c: attach/detach to menu widget via
          gtk_menu_attach_to_widget/gtk_menu_detach.
          invoke gtk_widget_destroy(menu) in destructor to be consistent
          with other destructors.
This commit is contained in:
Tim Janik 1998-02-03 15:14:35 +00:00 committed by Tim Janik
parent b45cd0430c
commit 5842311062
14 changed files with 132 additions and 88 deletions

49
BUGS
View File

@ -1,49 +0,0 @@
From timj@gimp.org Sat Jan 24 19:15:22 1998
Date: Sat, 24 Jan 1998 18:25:10 +0100 (CET)
From: Tim Janik <timj@gimp.org>
To: Peter Mattis <petm@xcf.berkeley.edu>
Cc: Gtk+ Devils <gtkdev@gimp.org>
Subject: widget destruction while in call
hi peter and gtk+ devils ;)
i've got the following problem, when double clicking on a list item
it's window should be destroyed, because the selection is made.
now this doesn't work 'cause the program is aborted with a
BadWindow error (from X).
this happens because the function that is connected to the lists
button_press_event calls gtk_widget_destroy () on the main window.
then the widget destruction is propagated through the tree until
the list widget should be destroyed. but since the list widget is
still GTK_IN_CALL (from the button_press_event) it isn't destroyed
but only flagged as GTK_NEED_DESTROY. at this point the propagation
stops, and nothing happends to the list widgets children.
after the return of the button_press_event handler, the clicked
list item is now selected/unselected (depends on the previous state).
it therefore updates its GdkWindow (XWindow) by setting the new
backgroundcolor (selected->blue/unselected->white). since it's
parent XWindows are destroyed already the window which the list item
wants to draw on is also destroyed. at this point the BadWindow error
occours cause the XWindow handle has become invalid (the application
already received a destroy notify).
now, solutions might be:
1) check for private->destroyed on *all* gdk call as it's done
it a lot of places already, or
2) propagate a widget unrealize signal through the tree before
destroying a widget, or
3) propagate GTK_NEED_DESTROY down the tree (not only flag the
list container), this would require gtk_object_destroy() to
return wether the object got actually destroyed or flagged
only. then prohibit gdk operations on widgets flagged as
GTK_NEED_DESTROY.
i'm not sure what the best solution might be, but i tend to favour
1) or 3).
---
ciaoTJ

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

View File

@ -1,7 +1,20 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/testgtk.c: don't add the same menu to different menuitems/
optionmenus.
* gtk/gtkmenuitem.h:
* gtk/gtkmenuitem.c: new function gtk_menu_item_remove_submenu ro
be consistent with optionmenu. use gtk_menu_attach_to_widget/
gtk_menu_detach for setting/removing the submenu.
invoke gtk_widget_destroy(submenu) in destructor to be consistent
with other destructors.
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
gtk_menu_attach_to_widget/gtk_menu_detach.
invoke gtk_widget_destroy(menu) in destructor to be consistent
with other destructors.
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget

3
TODO
View File

@ -42,9 +42,6 @@ BUGS
the deactivation, but not the destruction of it's submenu.
this is not a bug in the fileselection code but in the optionmenu
code.
* Look also at ./BUGS (i added it, because it describes some bugs in
a more specific way -timj).
NEW FEATURES

View File

@ -196,39 +196,58 @@ gtk_menu_item_destroy (GtkObject *object)
menu_item = GTK_MENU_ITEM (object);
if (menu_item->submenu)
{
gtk_widget_destroy (menu_item->submenu);
gtk_widget_unref (menu_item->submenu);
menu_item->submenu = NULL;
}
gtk_widget_destroy (menu_item->submenu);
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
static void
gtk_menu_item_detacher (GtkWidget *widget,
GtkMenu *menu)
{
GtkMenuItem *menu_item;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_MENU_ITEM (widget));
menu_item = GTK_MENU_ITEM (widget);
g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
menu_item->submenu = NULL;
}
void
gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
GtkWidget *submenu)
{
g_return_if_fail (menu_item != NULL);
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
if (menu_item->submenu != submenu)
{
if (menu_item->submenu)
{
g_return_if_fail (!GTK_WIDGET_VISIBLE (menu_item->submenu));
gtk_widget_unref (menu_item->submenu);
}
gtk_menu_item_remove_submenu (menu_item);
menu_item->submenu = submenu;
if (menu_item->submenu)
gtk_widget_ref (menu_item->submenu);
gtk_menu_attach_to_widget (GTK_MENU (submenu),
GTK_WIDGET (menu_item),
gtk_menu_item_detacher);
if (GTK_WIDGET (menu_item)->parent)
gtk_widget_queue_resize (GTK_WIDGET (menu_item));
}
}
void
gtk_menu_item_remove_submenu (GtkMenuItem *menu_item)
{
g_return_if_fail (menu_item != NULL);
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
if (menu_item->submenu)
gtk_menu_detach (GTK_MENU (menu_item->submenu));
}
void
gtk_menu_item_set_placement (GtkMenuItem *menu_item,
GtkSubmenuPlacement placement)

View File

@ -76,6 +76,7 @@ GtkWidget* gtk_menu_item_new (void);
GtkWidget* gtk_menu_item_new_with_label (const gchar *label);
void gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
GtkWidget *submenu);
void gtk_menu_item_remove_submenu (GtkMenuItem *menu_item);
void gtk_menu_item_set_placement (GtkMenuItem *menu_item,
GtkSubmenuPlacement placement);
void gtk_menu_item_accelerator_size (GtkMenuItem *menu_item);

View File

@ -230,7 +230,7 @@ gtk_option_menu_destroy (GtkObject *object)
option_menu = GTK_OPTION_MENU (object);
if (option_menu->menu)
gtk_menu_detach (GTK_MENU (option_menu->menu));
gtk_widget_destroy (option_menu->menu);
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@ -487,7 +487,6 @@ gtk_option_menu_remove_contents (GtkOptionMenu *option_menu)
if (GTK_WIDGET (option_menu->menu_item)->state != GTK_BUTTON (option_menu)->child->state)
gtk_widget_set_state (GTK_BUTTON (option_menu)->child,
GTK_WIDGET (option_menu->menu_item)->state);
/* GTK_WIDGET_UNSET_FLAGS (GTK_BUTTON (option_menu)->child, GTK_MAPPED | GTK_REALIZED); */
gtk_widget_unrealize (GTK_BUTTON (option_menu)->child);
gtk_widget_reparent (GTK_BUTTON (option_menu)->child, option_menu->menu_item);
gtk_widget_unref (option_menu->menu_item);

View File

@ -1111,7 +1111,6 @@ GtkWidget*
create_menu (int depth)
{
GtkWidget *menu;
GtkWidget *submenu;
GtkWidget *menuitem;
GSList *group;
char buf[32];
@ -1121,7 +1120,6 @@ create_menu (int depth)
return NULL;
menu = gtk_menu_new ();
submenu = NULL;
group = NULL;
for (i = 0, j = 1; i < 5; i++, j++)
@ -1134,12 +1132,7 @@ create_menu (int depth)
gtk_menu_append (GTK_MENU (menu), menuitem);
gtk_widget_show (menuitem);
if (depth > 0)
{
if (!submenu)
submenu = create_menu (depth - 1);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
}
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (depth - 1));
}
return menu;
@ -1190,12 +1183,12 @@ create_menus ()
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_label ("foo");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (3));
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_label ("bar");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (4));
gtk_menu_item_right_justify (GTK_MENU_ITEM (menuitem));
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);

View File

@ -1111,7 +1111,6 @@ GtkWidget*
create_menu (int depth)
{
GtkWidget *menu;
GtkWidget *submenu;
GtkWidget *menuitem;
GSList *group;
char buf[32];
@ -1121,7 +1120,6 @@ create_menu (int depth)
return NULL;
menu = gtk_menu_new ();
submenu = NULL;
group = NULL;
for (i = 0, j = 1; i < 5; i++, j++)
@ -1134,12 +1132,7 @@ create_menu (int depth)
gtk_menu_append (GTK_MENU (menu), menuitem);
gtk_widget_show (menuitem);
if (depth > 0)
{
if (!submenu)
submenu = create_menu (depth - 1);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
}
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (depth - 1));
}
return menu;
@ -1190,12 +1183,12 @@ create_menus ()
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_label ("foo");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (3));
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);
menuitem = gtk_menu_item_new_with_label ("bar");
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (4));
gtk_menu_item_right_justify (GTK_MENU_ITEM (menuitem));
gtk_menu_bar_append (GTK_MENU_BAR (menubar), menuitem);
gtk_widget_show (menuitem);