]> Pileus Git - ~andy/gtk/blob - gtk/gtkmenu.c
main part for GtkArgSetFunc/GtkArgGetFunc implementation.
[~andy/gtk] / gtk / gtkmenu.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <ctype.h>
19 #include "gdk/gdkkeysyms.h"
20 #include "gtkmain.h"
21 #include "gtkmenu.h"
22 #include "gtkmenuitem.h"
23 #include "gtksignal.h"
24
25
26 #define MENU_ITEM_CLASS(w)  GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
27
28
29 static void gtk_menu_class_init     (GtkMenuClass      *klass);
30 static void gtk_menu_init           (GtkMenu           *menu);
31 static void gtk_menu_show           (GtkWidget         *widget);
32 static void gtk_menu_map            (GtkWidget         *widget);
33 static void gtk_menu_unmap          (GtkWidget         *widget);
34 static void gtk_menu_realize        (GtkWidget         *widget);
35 static void gtk_menu_size_request   (GtkWidget         *widget,
36                                      GtkRequisition    *requisition);
37 static void gtk_menu_size_allocate  (GtkWidget         *widget,
38                                      GtkAllocation     *allocation);
39 static void gtk_menu_paint          (GtkWidget         *widget);
40 static void gtk_menu_draw           (GtkWidget         *widget,
41                                      GdkRectangle      *area);
42 static gint gtk_menu_expose         (GtkWidget         *widget,
43                                      GdkEventExpose    *event);
44 static gint gtk_menu_configure      (GtkWidget         *widget,
45                                      GdkEventConfigure *event);
46 static gint gtk_menu_key_press      (GtkWidget         *widget,
47                                      GdkEventKey       *event);
48 static gint gtk_menu_need_resize    (GtkContainer      *container);
49 static void gtk_menu_deactivate     (GtkMenuShell      *menu_shell);
50 static void gtk_menu_show_all       (GtkWidget         *widget);
51 static void gtk_menu_hide_all       (GtkWidget         *widget);
52
53
54 guint
55 gtk_menu_get_type ()
56 {
57   static guint menu_type = 0;
58
59   if (!menu_type)
60     {
61       GtkTypeInfo menu_info =
62       {
63         "GtkMenu",
64         sizeof (GtkMenu),
65         sizeof (GtkMenuClass),
66         (GtkClassInitFunc) gtk_menu_class_init,
67         (GtkObjectInitFunc) gtk_menu_init,
68         (GtkArgSetFunc) NULL,
69         (GtkArgGetFunc) NULL,
70       };
71
72       menu_type = gtk_type_unique (gtk_menu_shell_get_type (), &menu_info);
73     }
74
75   return menu_type;
76 }
77
78 static void
79 gtk_menu_class_init (GtkMenuClass *class)
80 {
81   GtkWidgetClass *widget_class;
82   GtkContainerClass *container_class;
83   GtkMenuShellClass *menu_shell_class;
84
85   widget_class = (GtkWidgetClass*) class;
86   container_class = (GtkContainerClass*) class;
87   menu_shell_class = (GtkMenuShellClass*) class;
88
89   widget_class->show = gtk_menu_show;
90   widget_class->map = gtk_menu_map;
91   widget_class->unmap = gtk_menu_unmap;
92   widget_class->realize = gtk_menu_realize;
93   widget_class->draw = gtk_menu_draw;
94   widget_class->size_request = gtk_menu_size_request;
95   widget_class->size_allocate = gtk_menu_size_allocate;
96   widget_class->expose_event = gtk_menu_expose;
97   widget_class->configure_event = gtk_menu_configure;
98   widget_class->key_press_event = gtk_menu_key_press;
99   widget_class->show_all = gtk_menu_show_all;
100   widget_class->hide_all = gtk_menu_hide_all;  
101   
102   container_class->need_resize = gtk_menu_need_resize;
103
104   menu_shell_class->submenu_placement = GTK_LEFT_RIGHT;
105   menu_shell_class->deactivate = gtk_menu_deactivate;
106 }
107
108 static void
109 gtk_menu_init (GtkMenu *menu)
110 {
111   GTK_WIDGET_SET_FLAGS (menu, GTK_ANCHORED);
112
113   menu->parent_menu_item = NULL;
114   menu->old_active_menu_item = NULL;
115   menu->accelerator_table = NULL;
116   menu->position_func = NULL;
117   menu->position_func_data = NULL;
118
119   GTK_MENU_SHELL (menu)->menu_flag = TRUE;
120 }
121
122 GtkWidget*
123 gtk_menu_new ()
124 {
125   return GTK_WIDGET (gtk_type_new (gtk_menu_get_type ()));
126 }
127
128 void
129 gtk_menu_append (GtkMenu   *menu,
130                  GtkWidget *child)
131 {
132   gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
133 }
134
135 void
136 gtk_menu_prepend (GtkMenu   *menu,
137                   GtkWidget *child)
138 {
139   gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), child);
140 }
141
142 void
143 gtk_menu_insert (GtkMenu   *menu,
144                  GtkWidget *child,
145                  gint       position)
146 {
147   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), child, position);
148 }
149
150 void
151 gtk_menu_popup (GtkMenu             *menu,
152                 GtkWidget           *parent_menu_shell,
153                 GtkWidget           *parent_menu_item,
154                 GtkMenuPositionFunc  func,
155                 gpointer             data,
156                 gint                 button,
157                 guint32              activate_time)
158 {
159   g_return_if_fail (menu != NULL);
160   g_return_if_fail (GTK_IS_MENU (menu));
161
162   GTK_MENU_SHELL (menu)->parent_menu_shell = parent_menu_shell;
163   GTK_MENU_SHELL (menu)->active = TRUE;
164   GTK_MENU_SHELL (menu)->button = button;
165
166   menu->parent_menu_item = parent_menu_item;
167   menu->position_func = func;
168   menu->position_func_data = data;
169   GTK_MENU_SHELL (menu)->activate_time = activate_time;
170
171   gtk_widget_show (GTK_WIDGET (menu));
172   gtk_grab_add (GTK_WIDGET (menu));
173 }
174
175 void
176 gtk_menu_popdown (GtkMenu *menu)
177 {
178   GtkMenuShell *menu_shell;
179
180   g_return_if_fail (menu != NULL);
181   g_return_if_fail (GTK_IS_MENU (menu));
182
183   menu_shell = GTK_MENU_SHELL (menu);
184
185   menu_shell->parent_menu_shell = NULL;
186   menu_shell->active = FALSE;
187
188   if (menu_shell->active_menu_item)
189     {
190       menu->old_active_menu_item = menu_shell->active_menu_item;
191       gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
192       menu_shell->active_menu_item = NULL;
193     }
194
195   gtk_widget_hide (GTK_WIDGET (menu));
196   gtk_grab_remove (GTK_WIDGET (menu));
197 }
198
199 GtkWidget*
200 gtk_menu_get_active (GtkMenu *menu)
201 {
202   GtkWidget *child;
203   GList *children;
204
205   g_return_val_if_fail (menu != NULL, NULL);
206   g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
207
208   if (!menu->old_active_menu_item)
209     {
210       child = NULL;
211       children = GTK_MENU_SHELL (menu)->children;
212
213       while (children)
214         {
215           child = children->data;
216           children = children->next;
217
218           if (GTK_BIN (child)->child)
219             break;
220           child = NULL;
221         }
222
223       menu->old_active_menu_item = child;
224     }
225
226   return menu->old_active_menu_item;
227 }
228
229 void
230 gtk_menu_set_active (GtkMenu *menu,
231                      gint     index)
232 {
233   GtkWidget *child;
234   GList *tmp_list;
235
236   g_return_if_fail (menu != NULL);
237   g_return_if_fail (GTK_IS_MENU (menu));
238
239   tmp_list = g_list_nth (GTK_MENU_SHELL (menu)->children, index);
240   if (tmp_list)
241     {
242       child = tmp_list->data;
243       if (GTK_BIN (child)->child)
244         menu->old_active_menu_item = child;
245     }
246 }
247
248 void
249 gtk_menu_set_accelerator_table (GtkMenu             *menu,
250                                 GtkAcceleratorTable *table)
251 {
252   g_return_if_fail (menu != NULL);
253   g_return_if_fail (GTK_IS_MENU (menu));
254
255   if (menu->accelerator_table != table)
256     {
257       if (menu->accelerator_table)
258         gtk_accelerator_table_unref (menu->accelerator_table);
259       menu->accelerator_table = table;
260       if (menu->accelerator_table)
261         gtk_accelerator_table_ref (menu->accelerator_table);
262     }
263 }
264
265
266 static void
267 gtk_menu_show (GtkWidget *widget)
268 {
269   g_return_if_fail (widget != NULL);
270   g_return_if_fail (GTK_IS_MENU (widget));
271
272   GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
273   gtk_widget_map (widget);
274 }
275
276 static void
277 gtk_menu_map (GtkWidget *widget)
278 {
279   GtkMenu *menu;
280   GtkMenuShell *menu_shell;
281   GtkWidget *child;
282   GList *children;
283   GtkAllocation allocation;
284   gint x, y;
285
286   g_return_if_fail (widget != NULL);
287   g_return_if_fail (GTK_IS_MENU (widget));
288
289   menu = GTK_MENU (widget);
290   menu_shell = GTK_MENU_SHELL (widget);
291   GTK_WIDGET_SET_FLAGS (menu_shell, GTK_MAPPED);
292   GTK_WIDGET_UNSET_FLAGS (menu_shell, GTK_UNMAPPED);
293
294   gtk_widget_size_request (widget, &widget->requisition);
295
296   if (menu_shell->menu_flag)
297     {
298       menu_shell->menu_flag = FALSE;
299
300       allocation.x = widget->allocation.x;
301       allocation.y = widget->allocation.y;
302       allocation.width = widget->requisition.width;
303       allocation.height = widget->requisition.height;
304
305       gtk_widget_size_allocate (widget, &allocation);
306     }
307
308   gdk_window_get_pointer (NULL, &x, &y, NULL);
309
310   if (menu->position_func)
311     (* menu->position_func) (menu, &x, &y, menu->position_func_data);
312   else
313     {
314       gint screen_width;
315       gint screen_height;
316
317       screen_width = gdk_screen_width ();
318       screen_height = gdk_screen_height ();
319
320       x -= 2;
321       y -= 2;
322
323       if ((x + widget->requisition.width) > screen_width)
324         x -= ((x + widget->requisition.width) - screen_width);
325       if (x < 0)
326         x = 0;
327       if ((y + widget->requisition.height) > screen_height)
328         y -= ((y + widget->requisition.height) - screen_height);
329       if (y < 0)
330         y = 0;
331     }
332
333   gdk_window_move_resize (widget->window, x, y,
334                           widget->requisition.width,
335                           widget->requisition.height);
336
337   children = menu_shell->children;
338   while (children)
339     {
340       child = children->data;
341       children = children->next;
342
343       if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
344         gtk_widget_map (child);
345     }
346
347   gdk_window_show (widget->window);
348 }
349
350 static void
351 gtk_menu_unmap (GtkWidget *widget)
352 {
353   g_return_if_fail (widget != NULL);
354   g_return_if_fail (GTK_IS_MENU (widget));
355
356   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
357   GTK_WIDGET_SET_FLAGS (widget, GTK_UNMAPPED);
358   gdk_window_hide (widget->window);
359 }
360
361 static void
362 gtk_menu_realize (GtkWidget *widget)
363 {
364   GdkWindowAttr attributes;
365   gint attributes_mask;
366
367   g_return_if_fail (widget != NULL);
368   g_return_if_fail (GTK_IS_MENU (widget));
369
370   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
371
372   attributes.x = widget->allocation.x;
373   attributes.y = widget->allocation.y;
374   attributes.width = widget->allocation.width;
375   attributes.height = widget->allocation.height;
376   attributes.wclass = GDK_INPUT_OUTPUT;
377   attributes.visual = gtk_widget_get_visual (widget);
378   attributes.colormap = gtk_widget_get_colormap (widget);
379   attributes.window_type = GDK_WINDOW_TEMP;
380   attributes.event_mask = gtk_widget_get_events (widget);
381   attributes.event_mask |= (GDK_EXPOSURE_MASK |
382                             GDK_KEY_PRESS_MASK |
383                             GDK_STRUCTURE_MASK);
384
385   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
386   widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
387   gdk_window_set_user_data (widget->window, widget);
388
389   widget->style = gtk_style_attach (widget->style, widget->window);
390   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
391 }
392
393 static void
394 gtk_menu_size_request (GtkWidget      *widget,
395                        GtkRequisition *requisition)
396 {
397   GtkMenu *menu;
398   GtkMenuShell *menu_shell;
399   GtkWidget *child;
400   GList *children;
401   gint max_accelerator_size;
402   gint max_toggle_size;
403
404   g_return_if_fail (widget != NULL);
405   g_return_if_fail (GTK_IS_MENU (widget));
406   g_return_if_fail (requisition != NULL);
407
408   menu = GTK_MENU (widget);
409   menu_shell = GTK_MENU_SHELL (widget);
410
411   requisition->width = 0;
412   requisition->height = 0;
413
414   max_accelerator_size = 0;
415   max_toggle_size = 0;
416
417   children = menu_shell->children;
418   while (children)
419     {
420       child = children->data;
421       children = children->next;
422
423       if (GTK_WIDGET_VISIBLE (child))
424         {
425           GTK_MENU_ITEM (child)->show_submenu_indicator = TRUE;
426           gtk_widget_size_request (child, &child->requisition);
427
428           requisition->width = MAX (requisition->width, child->requisition.width);
429           requisition->height += child->requisition.height;
430
431           max_accelerator_size = MAX (max_accelerator_size, GTK_MENU_ITEM (child)->accelerator_size);
432           max_toggle_size = MAX (max_toggle_size, MENU_ITEM_CLASS (child)->toggle_size);
433         }
434     }
435
436   requisition->width += max_toggle_size + max_accelerator_size;
437   requisition->width += (GTK_CONTAINER (menu)->border_width +
438                          widget->style->klass->xthickness) * 2;
439   requisition->height += (GTK_CONTAINER (menu)->border_width +
440                           widget->style->klass->ythickness) * 2;
441
442   children = menu_shell->children;
443   while (children)
444     {
445       child = children->data;
446       children = children->next;
447
448       GTK_MENU_ITEM (child)->accelerator_size = max_accelerator_size;
449       GTK_MENU_ITEM (child)->toggle_size = max_toggle_size;
450     }
451 }
452
453 static void
454 gtk_menu_size_allocate (GtkWidget     *widget,
455                         GtkAllocation *allocation)
456 {
457   GtkMenu *menu;
458   GtkMenuShell *menu_shell;
459   GtkWidget *child;
460   GtkAllocation child_allocation;
461   GList *children;
462
463   g_return_if_fail (widget != NULL);
464   g_return_if_fail (GTK_IS_MENU (widget));
465   g_return_if_fail (allocation != NULL);
466
467   menu = GTK_MENU (widget);
468   menu_shell = GTK_MENU_SHELL (widget);
469
470   widget->allocation = *allocation;
471
472   if (menu_shell->children)
473     {
474       child_allocation.x = (GTK_CONTAINER (menu)->border_width +
475                             widget->style->klass->xthickness);
476       child_allocation.y = (GTK_CONTAINER (menu)->border_width +
477                             widget->style->klass->ythickness);
478       child_allocation.width = allocation->width - child_allocation.x * 2;
479
480       children = menu_shell->children;
481       while (children)
482         {
483           child = children->data;
484           children = children->next;
485
486           if (GTK_WIDGET_VISIBLE (child))
487             {
488               child_allocation.height = child->requisition.height;
489
490               gtk_widget_size_allocate (child, &child_allocation);
491
492               child_allocation.y += child_allocation.height;
493             }
494         }
495     }
496 }
497
498 static void
499 gtk_menu_paint (GtkWidget *widget)
500 {
501   g_return_if_fail (widget != NULL);
502   g_return_if_fail (GTK_IS_MENU (widget));
503
504   if (GTK_WIDGET_DRAWABLE (widget))
505     {
506       gtk_draw_shadow (widget->style,
507                        widget->window,
508                        GTK_STATE_NORMAL,
509                        GTK_SHADOW_OUT,
510                        0, 0,
511                        widget->allocation.width,
512                        widget->allocation.height);
513     }
514 }
515
516 static void
517 gtk_menu_draw (GtkWidget    *widget,
518                GdkRectangle *area)
519 {
520   GtkMenuShell *menu_shell;
521   GtkWidget *child;
522   GdkRectangle child_area;
523   GList *children;
524
525   g_return_if_fail (widget != NULL);
526   g_return_if_fail (GTK_IS_MENU (widget));
527   g_return_if_fail (area != NULL);
528
529   if (GTK_WIDGET_DRAWABLE (widget))
530     {
531       gtk_menu_paint (widget);
532
533       menu_shell = GTK_MENU_SHELL (widget);
534
535       children = menu_shell->children;
536       while (children)
537         {
538           child = children->data;
539           children = children->next;
540
541           if (gtk_widget_intersect (child, area, &child_area))
542             gtk_widget_draw (child, &child_area);
543         }
544     }
545 }
546
547 static gint
548 gtk_menu_expose (GtkWidget      *widget,
549                  GdkEventExpose *event)
550 {
551   GtkMenuShell *menu_shell;
552   GtkWidget *child;
553   GdkEventExpose child_event;
554   GList *children;
555
556   g_return_val_if_fail (widget != NULL, FALSE);
557   g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
558   g_return_val_if_fail (event != NULL, FALSE);
559
560   if (!GTK_WIDGET_UNMAPPED (widget))
561     GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
562
563   if (GTK_WIDGET_DRAWABLE (widget))
564     {
565       gtk_menu_paint (widget);
566
567       menu_shell = GTK_MENU_SHELL (widget);
568       child_event = *event;
569
570       children = menu_shell->children;
571       while (children)
572         {
573           child = children->data;
574           children = children->next;
575
576           if (GTK_WIDGET_NO_WINDOW (child) &&
577               gtk_widget_intersect (child, &event->area, &child_event.area))
578             gtk_widget_event (child, (GdkEvent*) &child_event);
579         }
580     }
581
582   return FALSE;
583 }
584
585 static gint
586 gtk_menu_configure (GtkWidget         *widget,
587                     GdkEventConfigure *event)
588 {
589   GtkAllocation allocation;
590
591   g_return_val_if_fail (widget != NULL, FALSE);
592   g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
593   g_return_val_if_fail (event != NULL, FALSE);
594
595   if (GTK_MENU_SHELL (widget)->menu_flag)
596     {
597       GTK_MENU_SHELL (widget)->menu_flag = FALSE;
598
599       allocation.x = 0;
600       allocation.y = 0;
601       allocation.width = event->width;
602       allocation.height = event->height;
603
604       gtk_widget_size_allocate (widget, &allocation);
605     }
606
607   return FALSE;
608 }
609
610 static gint
611 gtk_menu_key_press (GtkWidget   *widget,
612                     GdkEventKey *event)
613 {
614   GtkAllocation allocation;
615   GtkAcceleratorTable *table;
616   GtkMenuShell *menu_shell;
617   GtkMenuItem *menu_item;
618   gchar *signame;
619   int delete;
620
621   g_return_val_if_fail (widget != NULL, FALSE);
622   g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
623   g_return_val_if_fail (event != NULL, FALSE);
624
625   delete = ((event->keyval == GDK_Delete) ||
626             (event->keyval == GDK_BackSpace));
627
628   if (delete || ((event->keyval >= 0x20) && (event->keyval <= 0xFF)))
629     {
630       menu_shell = GTK_MENU_SHELL (widget);
631       menu_item = GTK_MENU_ITEM (menu_shell->active_menu_item);
632
633       if (menu_item && GTK_BIN (menu_item)->child)
634         {
635           /* block resizes */
636           gtk_container_block_resize (GTK_CONTAINER (widget));
637
638           table = NULL;
639           /* if the menu item currently has an accelerator then we'll
640            *  remove it before we do anything else.
641            */
642           if (menu_item->accelerator_signal)
643             {
644               signame = gtk_signal_name (menu_item->accelerator_signal);
645               table = gtk_accelerator_table_find (GTK_OBJECT (widget),
646                                                   signame,
647                                                   menu_item->accelerator_key,
648                                                   menu_item->accelerator_mods);
649               if (!table)
650                 table = GTK_MENU (widget)->accelerator_table;
651               gtk_widget_remove_accelerator (GTK_WIDGET (menu_item),
652                                              table, signame);
653             }
654
655           if (!table)
656             table = GTK_MENU (widget)->accelerator_table;
657
658           /* if we aren't simply deleting the accelerator, then we'll install
659            *  the new one now.
660            */
661           if (!delete)
662             gtk_widget_install_accelerator (GTK_WIDGET (menu_item),
663                                             table, "activate",
664                                             toupper (event->keyval),
665                                             event->state);
666
667           /* check and see if the menu has changed size. */
668           gtk_widget_size_request (widget, &widget->requisition);
669
670           allocation.x = widget->allocation.x;
671           allocation.y = widget->allocation.y;
672           allocation.width = widget->requisition.width;
673           allocation.height = widget->requisition.height;
674
675           if ((allocation.width == widget->allocation.width) &&
676               (allocation.height == widget->allocation.height))
677             {
678               gtk_widget_queue_draw (widget);
679             }
680           else
681             {
682               gtk_widget_size_allocate (GTK_WIDGET (widget), &allocation);
683               gtk_menu_map (widget);
684             }
685
686           /* unblock resizes */
687           gtk_container_unblock_resize (GTK_CONTAINER (widget));
688         }
689     }
690
691   return FALSE;
692 }
693
694 static gint
695 gtk_menu_need_resize (GtkContainer *container)
696 {
697   GtkAllocation allocation;
698
699   g_return_val_if_fail (container != NULL, FALSE);
700   g_return_val_if_fail (GTK_IS_MENU (container), FALSE);
701
702   if (GTK_WIDGET_VISIBLE (container))
703     {
704       GTK_MENU_SHELL (container)->menu_flag = FALSE;
705
706       gtk_widget_size_request (GTK_WIDGET (container),
707                                &GTK_WIDGET (container)->requisition);
708
709       allocation.x = GTK_WIDGET (container)->allocation.x;
710       allocation.y = GTK_WIDGET (container)->allocation.y;
711       allocation.width = GTK_WIDGET (container)->requisition.width;
712       allocation.height = GTK_WIDGET (container)->requisition.height;
713
714       gtk_widget_size_allocate (GTK_WIDGET (container), &allocation);
715     }
716   else
717     {
718       GTK_MENU_SHELL (container)->menu_flag = TRUE;
719     }
720
721   return FALSE;
722 }
723
724 static void
725 gtk_menu_deactivate (GtkMenuShell *menu_shell)
726 {
727   GtkMenuShell *parent;
728
729   g_return_if_fail (menu_shell != NULL);
730   g_return_if_fail (GTK_IS_MENU (menu_shell));
731
732   parent = GTK_MENU_SHELL (menu_shell->parent_menu_shell);
733
734   menu_shell->activate_time = 0;
735   gtk_menu_popdown (GTK_MENU (menu_shell));
736
737   if (parent)
738     gtk_menu_shell_deactivate (parent);
739 }
740
741
742 static void
743 gtk_menu_show_all (GtkWidget *widget)
744 {
745   GtkContainer *container;
746
747   g_return_if_fail (widget != NULL);
748   g_return_if_fail (GTK_IS_MENU (widget));
749   container = GTK_CONTAINER (widget);
750
751   /* Show children, but not self. */
752   gtk_container_foreach (container, (GtkCallback) gtk_widget_show_all, NULL);
753 }
754
755
756 static void
757 gtk_menu_hide_all (GtkWidget *widget)
758 {
759   GtkContainer *container;
760
761   g_return_if_fail (widget != NULL);
762   g_return_if_fail (GTK_IS_MENU (widget));
763   container = GTK_CONTAINER (widget);
764
765   /* Hide children, but not self. */
766   gtk_container_foreach (container, (GtkCallback) gtk_widget_hide_all, NULL);
767 }
768