summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorTim Janik <timj@gimp.org>1998-02-03 14:13:05 +0000
committerTim Janik <timj@src.gnome.org>1998-02-03 14:13:05 +0000
commitb45cd0430c79f9426036ced2809427e0920dd855 (patch)
treed278a375e959b28d1f59e87cdffcfaa06dd11273 /gtk
parenta8629917ae91588cea02e0e8a20afc593a263cd7 (diff)
downloadgtk+-b45cd0430c79f9426036ced2809427e0920dd855.tar.gz
attach/detach to menu widget via
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org> * 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.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkbutton.c1
-rw-r--r--gtk/gtkfilesel.c2
-rw-r--r--gtk/gtkmain.c4
-rw-r--r--gtk/gtkmenu.c99
-rw-r--r--gtk/gtkmenu.h14
-rw-r--r--gtk/gtkoptionmenu.c48
-rw-r--r--gtk/gtkwidget.c21
7 files changed, 155 insertions, 34 deletions
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)