diff --git a/ChangeLog b/ChangeLog index 147110c4cb..a85d24a044 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 147110c4cb..a85d24a044 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 147110c4cb..a85d24a044 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 147110c4cb..a85d24a044 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 147110c4cb..a85d24a044 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 147110c4cb..a85d24a044 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 147110c4cb..a85d24a044 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,15 @@ +Tue Feb 3 15:09:55 1998 Tim Janik + + * gtk/gtkoptionmenu.h: + * gtk/gtkoptionmenu.c: attach/detach to menu widget via + + * gtk/gtkmenu.h: + * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget + and gtk_menu_detach that correspond to the action of + gtk_widget_set_parent and gtk_widget_unparent. + + * gtk/widget.c: few fixups. + Tue Feb 3 00:12:00 1998 Owen Taylor * gtk/gtktable.c Fixed problem with division by zero in row/column-spanned diff --git a/TODO b/TODO index 761c188828..942f8640ab 100644 --- a/TODO +++ b/TODO @@ -26,9 +26,6 @@ BUGS * GtkOptionMenu needs to reference its curent GtkMenuItem. - * Right after creation of an option menu, the first selected menu item is - placed too low (is this still true?). - * GtkMenu needs to properly unref() accelerator tables upon destroy. * Display of GtkToggleButton is messed up if GtkContainer::container_width diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c index a9ed0d7f6e..8b67766a3e 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -802,6 +802,7 @@ gtk_button_remove (GtkContainer *container, g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_BUTTON (container)); + g_return_if_fail (widget != NULL); button = GTK_BUTTON (container); diff --git a/gtk/gtkfilesel.c b/gtk/gtkfilesel.c index 8a9d123ad6..6ac0326598 100644 --- a/gtk/gtkfilesel.c +++ b/gtk/gtkfilesel.c @@ -1045,7 +1045,7 @@ gtk_file_selection_update_history_menu (GtkFileSelection *fs, fs->history_menu = gtk_menu_new(); - current_dir = g_strdup(current_directory); + current_dir = g_strdup (current_directory); dir_len = strlen (current_dir); diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index d932cb6c38..9e73d7732e 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1150,9 +1150,7 @@ gtk_propagate_event (GtkWidget *widget, while (!handled_event && tmp) { gtk_widget_ref (tmp); - handled_event = (GTK_OBJECT_DESTROYED (tmp) || - !GTK_WIDGET_IS_SENSITIVE (tmp) || - gtk_widget_event (tmp, event)); + handled_event = !GTK_WIDGET_IS_SENSITIVE (tmp) || gtk_widget_event (tmp, event); parent = tmp->parent; gtk_widget_unref (tmp); tmp = parent; diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index cf5b516399..753555ce50 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -26,6 +26,15 @@ #define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass) +typedef struct _GtkMenuAttachData GtkMenuAttachData; + +struct _GtkMenuAttachData +{ + GtkWidget *attach_widget; + GtkMenuDetachFunc detacher; +}; + + static void gtk_menu_class_init (GtkMenuClass *klass); static void gtk_menu_init (GtkMenu *menu); static void gtk_menu_destroy (GtkObject *object); @@ -52,6 +61,8 @@ static void gtk_menu_show_all (GtkWidget *widget); static void gtk_menu_hide_all (GtkWidget *widget); static GtkMenuShellClass *parent_class = NULL; +static const gchar *attach_data_key = "gtk-menu-attach-data"; + guint gtk_menu_get_type () @@ -125,19 +136,103 @@ gtk_menu_init (GtkMenu *menu) GTK_MENU_SHELL (menu)->menu_flag = TRUE; - gtk_container_register_toplevel (GTK_CONTAINER (menu)); + /* we don't need to register as toplevel anymore, + * since there is the attach/detach functionality in place. + * gtk_container_register_toplevel (GTK_CONTAINER (menu)); + */ } static void gtk_menu_destroy (GtkObject *object) { + GtkMenuAttachData *data; + g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_MENU (object)); - gtk_container_unregister_toplevel (GTK_CONTAINER (object)); + gtk_widget_ref (GTK_WIDGET (object)); + + data = gtk_object_get_data (object, attach_data_key); + if (data) + gtk_menu_detach (GTK_MENU (object)); + + /* we don't need this: + * gtk_container_unregister_toplevel (GTK_CONTAINER (object)); + */ if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); + + gtk_widget_unref (GTK_WIDGET (object)); +} + + +void +gtk_menu_attach_to_widget (GtkMenu *menu, + GtkWidget *attach_widget, + GtkMenuDetachFunc detacher) +{ + GtkMenuAttachData *data; + + g_return_if_fail (menu != NULL); + g_return_if_fail (GTK_IS_MENU (menu)); + g_return_if_fail (attach_widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (attach_widget)); + g_return_if_fail (detacher != NULL); + + /* keep this function in sync with gtk_widget_set_parent() + */ + + data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key); + if (data) + { + g_warning ("gtk_menu_attach_to_widget(): menu already attached to %s", + gtk_type_name (GTK_OBJECT_TYPE (data->attach_widget))); + return; + } + + gtk_widget_ref (menu); + gtk_object_sink (GTK_OBJECT (menu)); + + data = g_new (GtkMenuAttachData, 1); + data->attach_widget = attach_widget; + data->detacher = detacher; + gtk_object_set_data (GTK_OBJECT (menu), attach_data_key, data); + + if (GTK_WIDGET_STATE (menu) != GTK_STATE_NORMAL) + gtk_widget_set_state (GTK_WIDGET (menu), GTK_STATE_NORMAL); + + /* we don't need to set the style here, since + * we are a toplevel widget. + */ +} + +void +gtk_menu_detach (GtkMenu *menu) +{ + GtkMenuAttachData *data; + + g_return_if_fail (menu != NULL); + g_return_if_fail (GTK_IS_MENU (menu)); + + /* keep this function in sync with gtk_widget_unparent() + */ + data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key); + if (!data) + { + g_warning ("gtk_menu_detach(): menu is not attached"); + return; + } + gtk_object_remove_data (GTK_OBJECT (menu), attach_data_key); + + data->detacher (data->attach_widget, menu); + + if (GTK_WIDGET_REALIZED (menu)) + gtk_widget_unrealize (GTK_WIDGET (menu)); + + g_free (data); + + gtk_widget_unref (GTK_WIDGET (menu)); } GtkWidget* diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h index 5cd5d28fa9..371d371381 100644 --- a/gtk/gtkmenu.h +++ b/gtk/gtkmenu.h @@ -37,10 +37,12 @@ extern "C" { typedef struct _GtkMenu GtkMenu; typedef struct _GtkMenuClass GtkMenuClass; -typedef void (*GtkMenuPositionFunc) (GtkMenu *menu, - gint *x, - gint *y, - gpointer user_data); +typedef void (*GtkMenuPositionFunc) (GtkMenu *menu, + gint *x, + gint *y, + gpointer user_data); +typedef void (*GtkMenuDetachFunc) (GtkWidget *attach_widget, + GtkMenu *menu); struct _GtkMenu { @@ -84,6 +86,10 @@ void gtk_menu_set_active (GtkMenu *menu, gint index); void gtk_menu_set_accelerator_table (GtkMenu *menu, GtkAcceleratorTable *table); +void gtk_menu_attach_to_widget (GtkMenu *menu, + GtkWidget *attach_widget, + GtkMenuDetachFunc detacher); +void gtk_menu_detach (GtkMenu *menu); #ifdef __cplusplus diff --git a/gtk/gtkoptionmenu.c b/gtk/gtkoptionmenu.c index eca7660c4c..e9bb63ab2d 100644 --- a/gtk/gtkoptionmenu.c +++ b/gtk/gtkoptionmenu.c @@ -136,6 +136,25 @@ gtk_option_menu_get_menu (GtkOptionMenu *option_menu) return option_menu->menu; } +static void +gtk_option_menu_detacher (GtkWidget *widget, + GtkMenu *menu) +{ + GtkOptionMenu *option_menu; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_OPTION_MENU (widget)); + + option_menu = GTK_OPTION_MENU (widget); + g_return_if_fail (option_menu->menu == (GtkWidget*) menu); + + gtk_option_menu_remove_contents (option_menu); + gtk_signal_disconnect_by_data (GTK_OBJECT (option_menu->menu), + option_menu); + + option_menu->menu = NULL; +} + void gtk_option_menu_set_menu (GtkOptionMenu *option_menu, GtkWidget *menu) @@ -148,8 +167,11 @@ gtk_option_menu_set_menu (GtkOptionMenu *option_menu, if (option_menu->menu != menu) { gtk_option_menu_remove_menu (option_menu); + option_menu->menu = menu; - gtk_widget_ref (option_menu->menu); + gtk_menu_attach_to_widget (GTK_MENU (menu), + GTK_WIDGET (option_menu), + gtk_option_menu_detacher); gtk_option_menu_calc_size (option_menu); @@ -171,14 +193,7 @@ gtk_option_menu_remove_menu (GtkOptionMenu *option_menu) g_return_if_fail (GTK_IS_OPTION_MENU (option_menu)); if (option_menu->menu) - { - gtk_option_menu_remove_contents (option_menu); - gtk_signal_disconnect_by_data (GTK_OBJECT (option_menu->menu), - option_menu); - - gtk_widget_unref (option_menu->menu); - option_menu->menu = NULL; - } + gtk_menu_detach (GTK_MENU (option_menu->menu)); } void @@ -214,14 +229,8 @@ gtk_option_menu_destroy (GtkObject *object) option_menu = GTK_OPTION_MENU (object); - /* gtk_option_menu_remove_contents (option_menu); - */ if (option_menu->menu) - { - gtk_widget_destroy (option_menu->menu); - gtk_widget_unref (option_menu->menu); - option_menu->menu = NULL; - } + gtk_menu_detach (GTK_MENU (option_menu->menu)); if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); @@ -445,6 +454,7 @@ gtk_option_menu_update_contents (GtkOptionMenu *option_menu) option_menu->menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu)); if (option_menu->menu_item) { + gtk_widget_ref (option_menu->menu_item); child = GTK_BIN (option_menu->menu_item)->child; if (child) { @@ -477,10 +487,12 @@ 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_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_container_unblock_resize (GTK_CONTAINER (option_menu)); + gtk_widget_unref (option_menu->menu_item); option_menu->menu_item = NULL; + gtk_container_unblock_resize (GTK_CONTAINER (option_menu)); } } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index b174a1a761..45f896ae58 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -1054,9 +1054,7 @@ gtk_widget_setv (GtkWidget *widget, /***************************************** * gtk_widget_unparent: * do any cleanup necessary necessary - * before setting parent = NULL. - * In particular, remove the focus - * properly. + * for setting parent = NULL. * * arguments: * @@ -1073,6 +1071,9 @@ gtk_widget_unparent (GtkWidget *widget) if (widget->parent == NULL) return; + /* keep this function in sync with gtk_menu_detach() + */ + toplevel = gtk_widget_get_toplevel (widget); if (GTK_IS_WINDOW (toplevel)) { @@ -1680,7 +1681,7 @@ gtk_widget_event (GtkWidget *widget, return_val = FALSE; gtk_signal_emit (GTK_OBJECT (widget), widget_signals[EVENT], event, &return_val); - if (return_val) + if (return_val || GTK_OBJECT_DESTROYED (widget)) { gtk_widget_unref (widget); return TRUE; @@ -1783,13 +1784,16 @@ gtk_widget_event (GtkWidget *widget, default: g_warning ("could not determine signal number for event: %d", event->type); gtk_widget_unref (widget); - return return_val; + return TRUE; } if (signal_num != -1) gtk_signal_emit (GTK_OBJECT (widget), widget_signals[signal_num], event, &return_val); + return_val |= GTK_OBJECT_DESTROYED (widget); + gtk_widget_unref (widget); + return return_val; } @@ -1858,8 +1862,10 @@ gtk_widget_reparent (GtkWidget *widget, GtkWidget *new_parent) { g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (new_parent != NULL); g_return_if_fail (GTK_IS_CONTAINER (new_parent)); + g_return_if_fail (widget->parent != NULL); if (widget->parent != new_parent) { @@ -2224,8 +2230,11 @@ gtk_widget_set_parent (GtkWidget *widget, g_assert (widget->parent == NULL); g_return_if_fail (parent != NULL); + /* keep this function in sync with gtk_menu_attach_to_widget() + */ + gtk_widget_ref (widget); - gtk_object_sink (GTK_OBJECT(widget)); + gtk_object_sink (GTK_OBJECT (widget)); widget->parent = parent; if (GTK_WIDGET_STATE (parent) != GTK_STATE_NORMAL)