]> Pileus Git - ~andy/gtk/blob - gtk/gtkmenuitem.c
Made buildable and added support for adding children of type "submenu"
[~andy/gtk] / gtk / gtkmenuitem.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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27 #define GTK_MENU_INTERNALS
28
29 #include "config.h"
30 #include <string.h>
31
32 #include "gtkaccellabel.h"
33 #include "gtkmain.h"
34 #include "gtkmarshalers.h"
35 #include "gtkmenu.h"
36 #include "gtkmenubar.h"
37 #include "gtkseparatormenuitem.h"
38 #include "gtkprivate.h"
39 #include "gtkbuildable.h"
40 #include "gtkintl.h"
41 #include "gtkalias.h"
42
43 enum {
44   ACTIVATE,
45   ACTIVATE_ITEM,
46   TOGGLE_SIZE_REQUEST,
47   TOGGLE_SIZE_ALLOCATE,
48   LAST_SIGNAL
49 };
50
51 enum {
52   PROP_0,
53   PROP_RIGHT_JUSTIFIED,
54   PROP_SUBMENU,
55   PROP_ACCEL_PATH,
56   PROP_LABEL,
57   PROP_USE_UNDERLINE
58 };
59
60
61 static void gtk_menu_item_set_property   (GObject          *object,
62                                           guint             prop_id,
63                                           const GValue     *value,
64                                           GParamSpec       *pspec);
65 static void gtk_menu_item_get_property   (GObject          *object,
66                                           guint             prop_id,
67                                           GValue           *value,
68                                           GParamSpec       *pspec);
69 static void gtk_menu_item_destroy        (GtkObject        *object);
70 static void gtk_menu_item_size_request   (GtkWidget        *widget,
71                                           GtkRequisition   *requisition);
72 static void gtk_menu_item_size_allocate  (GtkWidget        *widget,
73                                           GtkAllocation    *allocation);
74 static void gtk_menu_item_realize        (GtkWidget        *widget);
75 static void gtk_menu_item_unrealize      (GtkWidget        *widget);
76 static void gtk_menu_item_map            (GtkWidget        *widget);
77 static void gtk_menu_item_unmap          (GtkWidget        *widget);
78 static void gtk_menu_item_paint          (GtkWidget        *widget,
79                                           GdkRectangle     *area);
80 static gint gtk_menu_item_expose         (GtkWidget        *widget,
81                                           GdkEventExpose   *event);
82 static void gtk_menu_item_parent_set     (GtkWidget        *widget,
83                                           GtkWidget        *previous_parent);
84
85
86 static void gtk_real_menu_item_select               (GtkItem     *item);
87 static void gtk_real_menu_item_deselect             (GtkItem     *item);
88 static void gtk_real_menu_item_activate_item        (GtkMenuItem *item);
89 static void gtk_real_menu_item_toggle_size_request  (GtkMenuItem *menu_item,
90                                                      gint        *requisition);
91 static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
92                                                      gint         allocation);
93 static gboolean gtk_menu_item_mnemonic_activate     (GtkWidget   *widget,
94                                                      gboolean     group_cycling);
95
96 static void gtk_menu_item_ensure_label   (GtkMenuItem      *menu_item);
97 static gint gtk_menu_item_popup_timeout  (gpointer          data);
98 static void gtk_menu_item_position_menu  (GtkMenu          *menu,
99                                           gint             *x,
100                                           gint             *y,
101                                           gboolean         *push_in,
102                                           gpointer          user_data);
103 static void gtk_menu_item_show_all       (GtkWidget        *widget);
104 static void gtk_menu_item_hide_all       (GtkWidget        *widget);
105 static void gtk_menu_item_forall         (GtkContainer    *container,
106                                           gboolean         include_internals,
107                                           GtkCallback      callback,
108                                           gpointer         callback_data);
109 static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
110                                                   guint      signal_id);
111
112 static void gtk_real_menu_item_set_label (GtkMenuItem     *menu_item,
113                                           const gchar     *label);
114 static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
115
116
117 static void gtk_menu_item_buildable_interface_init (GtkBuildableIface   *iface);
118 static void gtk_menu_item_buildable_add_child      (GtkBuildable        *buildable,
119                                                     GtkBuilder          *builder,
120                                                     GObject             *child,
121                                                     const gchar         *type);
122
123 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
124
125 static GtkBuildableIface *parent_buildable_iface;
126
127 G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
128                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
129                                                 gtk_menu_item_buildable_interface_init))
130
131 static void
132 gtk_menu_item_class_init (GtkMenuItemClass *klass)
133 {
134   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
135   GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
136   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
137   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
138   GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
139
140   gobject_class->set_property = gtk_menu_item_set_property;
141   gobject_class->get_property = gtk_menu_item_get_property;
142
143   object_class->destroy = gtk_menu_item_destroy;
144
145   widget_class->size_request = gtk_menu_item_size_request;
146   widget_class->size_allocate = gtk_menu_item_size_allocate;
147   widget_class->expose_event = gtk_menu_item_expose;
148   widget_class->realize = gtk_menu_item_realize;
149   widget_class->unrealize = gtk_menu_item_unrealize;
150   widget_class->map = gtk_menu_item_map;
151   widget_class->unmap = gtk_menu_item_unmap;
152   widget_class->show_all = gtk_menu_item_show_all;
153   widget_class->hide_all = gtk_menu_item_hide_all;
154   widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
155   widget_class->parent_set = gtk_menu_item_parent_set;
156   widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
157   
158   container_class->forall = gtk_menu_item_forall;
159
160   item_class->select = gtk_real_menu_item_select;
161   item_class->deselect = gtk_real_menu_item_deselect;
162
163   klass->activate = NULL;
164   klass->activate_item = gtk_real_menu_item_activate_item;
165   klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
166   klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
167   klass->set_label = gtk_real_menu_item_set_label;
168   klass->get_label = gtk_real_menu_item_get_label;
169
170   klass->hide_on_activate = TRUE;
171
172   menu_item_signals[ACTIVATE] =
173     g_signal_new (I_("activate"),
174                   G_OBJECT_CLASS_TYPE (gobject_class),
175                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
176                   G_STRUCT_OFFSET (GtkMenuItemClass, activate),
177                   NULL, NULL,
178                   _gtk_marshal_VOID__VOID,
179                   G_TYPE_NONE, 0);
180   widget_class->activate_signal = menu_item_signals[ACTIVATE];
181
182   menu_item_signals[ACTIVATE_ITEM] =
183     g_signal_new (I_("activate-item"),
184                   G_OBJECT_CLASS_TYPE (gobject_class),
185                   G_SIGNAL_RUN_FIRST,
186                   G_STRUCT_OFFSET (GtkMenuItemClass, activate_item),
187                   NULL, NULL,
188                   _gtk_marshal_VOID__VOID,
189                   G_TYPE_NONE, 0);
190
191   menu_item_signals[TOGGLE_SIZE_REQUEST] =
192     g_signal_new (I_("toggle-size-request"),
193                   G_OBJECT_CLASS_TYPE (gobject_class),
194                   G_SIGNAL_RUN_FIRST,
195                   G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_request),
196                   NULL, NULL,
197                   _gtk_marshal_VOID__POINTER,
198                   G_TYPE_NONE, 1,
199                   G_TYPE_POINTER);
200
201   menu_item_signals[TOGGLE_SIZE_ALLOCATE] =
202     g_signal_new (I_("toggle-size-allocate"),
203                   G_OBJECT_CLASS_TYPE (gobject_class),
204                   G_SIGNAL_RUN_FIRST,
205                   G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_allocate),
206                   NULL, NULL,
207                   _gtk_marshal_VOID__INT,
208                   G_TYPE_NONE, 1,
209                   G_TYPE_INT);
210
211   /**
212    * GtkMenuItem:right-justified:
213    *
214    * Sets whether the menu item appears justified at the right side of a menu bar.
215    *
216    * Since: 2.14
217    **/
218   g_object_class_install_property (gobject_class,
219                                    PROP_RIGHT_JUSTIFIED,
220                                    g_param_spec_boolean ("right-justified",
221                                                          P_("Right Justified"),
222                                                          P_("Sets whether the menu item appears justified at the right side of a menu bar"),
223                                                          FALSE,
224                                                          GTK_PARAM_READWRITE));
225
226   /**
227    * GtkMenuItem:submenu:
228    *
229    * The submenu attached to the menu item, or NULL if it has none.
230    *
231    * Since: 2.12
232    **/
233   g_object_class_install_property (gobject_class,
234                                    PROP_SUBMENU,
235                                    g_param_spec_object ("submenu",
236                                                         P_("Submenu"),
237                                                         P_("The submenu attached to the menu item, or NULL if it has none"),
238                                                         GTK_TYPE_MENU,
239                                                         GTK_PARAM_READWRITE));
240   
241
242   /**
243    * GtkMenuItem:accel-path:
244    *
245    * Sets the accelerator path of the menu item, through which runtime
246    * changes of the menu item's accelerator caused by the user can be
247    * identified and saved to persistant storage.
248    *
249    * Since: 2.14
250    **/
251   g_object_class_install_property (gobject_class,
252                                    PROP_ACCEL_PATH,
253                                    g_param_spec_string ("accel-path",
254                                                         P_("Accel Path"),
255                                                         P_("Sets the accelerator path of the menu item"),
256                                                         NULL,
257                                                         GTK_PARAM_READWRITE));
258
259   /**
260    * GtkMenuItem:label:
261    *
262    * The text for the child label.
263    *
264    * Since: 2.16
265    **/
266   g_object_class_install_property (gobject_class,
267                                    PROP_LABEL,
268                                    g_param_spec_string ("label",
269                                                         P_("Label"),
270                                                         P_("The text for the child label"),
271                                                         NULL,
272                                                         GTK_PARAM_READWRITE));
273
274   /**
275    * GtkMenuItem:use-underline:
276    *
277    * %TRUE if underlines in the text indicate mnemonics  
278    *
279    * Since: 2.16
280    **/
281   g_object_class_install_property (gobject_class,
282                                    PROP_USE_UNDERLINE,
283                                    g_param_spec_boolean ("use-underline",
284                                                          P_("Use underline"),
285                                                          P_("If set, an underline in the text indicates "
286                                                             "the next character should be used for the "
287                                                             "mnemonic accelerator key"),
288                                                          FALSE,
289                                                          GTK_PARAM_READWRITE));
290
291   gtk_widget_class_install_style_property_parser (widget_class,
292                                                   g_param_spec_enum ("selected-shadow-type",
293                                                                      "Selected Shadow Type",
294                                                                      "Shadow type when item is selected",
295                                                                      GTK_TYPE_SHADOW_TYPE,
296                                                                      GTK_SHADOW_NONE,
297                                                                      GTK_PARAM_READABLE),
298                                                   gtk_rc_property_parse_enum);
299
300   gtk_widget_class_install_style_property (widget_class,
301                                            g_param_spec_int ("horizontal-padding",
302                                                              "Horizontal Padding",
303                                                              "Padding to left and right of the menu item",
304                                                              0,
305                                                              G_MAXINT,
306                                                              3,
307                                                              GTK_PARAM_READABLE));
308
309   gtk_widget_class_install_style_property (widget_class,
310                                            g_param_spec_int ("toggle-spacing",
311                                                              "Icon Spacing",
312                                                              "Space between icon and label",
313                                                              0,
314                                                              G_MAXINT,
315                                                              5,
316                                                              GTK_PARAM_READABLE));
317
318   gtk_widget_class_install_style_property (widget_class,
319                                            g_param_spec_int ("arrow-spacing",
320                                                              "Arrow Spacing",
321                                                              "Space between label and arrow",
322                                                              0,
323                                                              G_MAXINT,
324                                                              10,
325                                                              GTK_PARAM_READABLE));
326
327   gtk_widget_class_install_style_property (widget_class,
328                                            g_param_spec_float ("arrow-scaling",
329                                                                P_("Arrow Scaling"),
330                                                                P_("Amount of space used up by arrow, relative to the menu item's font size"),
331                                                                0.0, 2.0, 0.8,
332                                                                GTK_PARAM_READABLE));
333
334   /**
335    * GtkMenuItem:width-chars:
336    *
337    * The minimum desired width of the menu item in characters.
338    *
339    * Since: 2.14
340    **/
341   gtk_widget_class_install_style_property (widget_class,
342                                            g_param_spec_int ("width-chars",
343                                                              P_("Width in Characters"),
344                                                              P_("The minimum desired width of the menu item in characters"),
345                                                              0, G_MAXINT, 12,
346                                                              GTK_PARAM_READABLE));
347 }
348
349 static void
350 gtk_menu_item_init (GtkMenuItem *menu_item)
351 {
352   GTK_WIDGET_SET_FLAGS (menu_item, GTK_NO_WINDOW);
353   
354   menu_item->submenu = NULL;
355   menu_item->toggle_size = 0;
356   menu_item->accelerator_width = 0;
357   menu_item->show_submenu_indicator = FALSE;
358   if (gtk_widget_get_direction (GTK_WIDGET (menu_item)) == GTK_TEXT_DIR_RTL)
359     menu_item->submenu_direction = GTK_DIRECTION_LEFT;
360   else
361     menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
362   menu_item->submenu_placement = GTK_TOP_BOTTOM;
363   menu_item->right_justify = FALSE;
364
365   menu_item->timer = 0;
366 }
367
368 GtkWidget*
369 gtk_menu_item_new (void)
370 {
371   return g_object_new (GTK_TYPE_MENU_ITEM, NULL);
372 }
373
374 GtkWidget*
375 gtk_menu_item_new_with_label (const gchar *label)
376 {
377   return g_object_new (GTK_TYPE_MENU_ITEM, 
378                        "label", label,
379                        NULL);
380 }
381
382
383 /**
384  * gtk_menu_item_new_with_mnemonic:
385  * @label: The text of the button, with an underscore in front of the
386  *         mnemonic character
387  * @returns: a new #GtkMenuItem
388  *
389  * Creates a new #GtkMenuItem containing a label. The label
390  * will be created using gtk_label_new_with_mnemonic(), so underscores
391  * in @label indicate the mnemonic for the menu item.
392  **/
393 GtkWidget*
394 gtk_menu_item_new_with_mnemonic (const gchar *label)
395 {
396   return g_object_new (GTK_TYPE_MENU_ITEM, 
397                        "use-underline", TRUE,
398                        "label", label,
399                        NULL);
400 }
401
402 static void 
403 gtk_menu_item_set_property (GObject      *object,
404                             guint         prop_id,
405                             const GValue *value,
406                             GParamSpec   *pspec)
407 {
408   GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
409   
410   switch (prop_id)
411     {
412     case PROP_RIGHT_JUSTIFIED:
413       gtk_menu_item_set_right_justified (menu_item, g_value_get_boolean (value));
414       break;
415     case PROP_SUBMENU:
416       gtk_menu_item_set_submenu (menu_item, g_value_get_object (value));
417       break;
418     case PROP_ACCEL_PATH:
419       gtk_menu_item_set_accel_path (menu_item, g_value_get_string (value));
420       break;
421     case PROP_LABEL:
422       gtk_menu_item_set_label (menu_item, g_value_get_string (value));
423       break;
424     case PROP_USE_UNDERLINE:
425       gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
426       break;
427
428     default:
429       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430       break;
431     }
432 }
433
434 static void 
435 gtk_menu_item_get_property (GObject    *object,
436                             guint       prop_id,
437                             GValue     *value,
438                             GParamSpec *pspec)
439 {
440   GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
441   
442   switch (prop_id)
443     {
444     case PROP_RIGHT_JUSTIFIED:
445       g_value_set_boolean (value, gtk_menu_item_get_right_justified (menu_item));
446       break;
447     case PROP_SUBMENU:
448       g_value_set_object (value, gtk_menu_item_get_submenu (menu_item));
449       break;
450     case PROP_ACCEL_PATH:
451       g_value_set_string (value, gtk_menu_item_get_accel_path (menu_item));
452       break;
453     case PROP_LABEL:
454       g_value_set_string (value, gtk_menu_item_get_label (menu_item));
455       break;
456     case PROP_USE_UNDERLINE:
457       g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
458       break;
459
460     default:
461       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
462       break;
463     }
464 }
465
466 static void
467 gtk_menu_item_destroy (GtkObject *object)
468 {
469   GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
470
471   if (menu_item->submenu)
472     gtk_widget_destroy (menu_item->submenu);
473
474   GTK_OBJECT_CLASS (gtk_menu_item_parent_class)->destroy (object);
475 }
476
477 static void
478 gtk_menu_item_detacher (GtkWidget *widget,
479                         GtkMenu   *menu)
480 {
481   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
482
483   g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
484
485   menu_item->submenu = NULL;
486 }
487
488 static void
489 gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
490 {
491   parent_buildable_iface = g_type_interface_peek_parent (iface);
492   iface->add_child = gtk_menu_item_buildable_add_child;
493 }
494
495 static void 
496 gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
497                                    GtkBuilder   *builder,
498                                    GObject      *child,
499                                    const gchar  *type)
500 {
501   if (type && strcmp (type, "submenu") == 0)
502         gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
503                                    GTK_WIDGET (child));
504   else
505     parent_buildable_iface->add_child (buildable, builder, child, type);
506 }
507
508 /**
509  * gtk_menu_item_set_submenu:
510  * @menu_item: a #GtkMenuItem
511  * @submenu: the submenu, or %NULL
512  *
513  * Sets or replaces the menu item's submenu, or removes it when a %NULL
514  * submenu is passed.
515  **/
516 void
517 gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
518                            GtkWidget   *submenu)
519 {
520   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
521   g_return_if_fail (submenu == NULL || GTK_IS_MENU (submenu));
522   
523   if (menu_item->submenu != submenu)
524     {
525       if (menu_item->submenu)
526         gtk_menu_detach (GTK_MENU (menu_item->submenu));
527
528       if (submenu)
529         {
530           menu_item->submenu = submenu;
531           gtk_menu_attach_to_widget (GTK_MENU (submenu),
532                                      GTK_WIDGET (menu_item),
533                                      gtk_menu_item_detacher);
534         }
535
536       if (GTK_WIDGET (menu_item)->parent)
537         gtk_widget_queue_resize (GTK_WIDGET (menu_item));
538
539       g_object_notify (G_OBJECT (menu_item), "submenu");
540     }
541 }
542
543 /**
544  * gtk_menu_item_get_submenu:
545  * @menu_item: a #GtkMenuItem
546  *
547  * Gets the submenu underneath this menu item, if any. See
548  * gtk_menu_item_set_submenu().
549  *
550  * Return value: submenu for this menu item, or %NULL if none.
551  **/
552 GtkWidget *
553 gtk_menu_item_get_submenu (GtkMenuItem *menu_item)
554 {
555   g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
556
557   return menu_item->submenu;
558 }
559
560 /**
561  * gtk_menu_item_remove_submenu:
562  * @menu_item: a #GtkMenuItem
563  *
564  * Removes the widget's submenu.
565  *
566  * Deprecated: 2.12: gtk_menu_item_remove_submenu() is deprecated and
567  *                   should not be used in newly written code. Use
568  *                   gtk_menu_item_set_submenu() instead.
569  **/
570 void
571 gtk_menu_item_remove_submenu (GtkMenuItem *menu_item)
572 {
573   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
574
575   gtk_menu_item_set_submenu (menu_item, NULL);
576 }
577
578 void _gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
579                                    GtkSubmenuPlacement  placement);
580
581 void
582 _gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
583                              GtkSubmenuPlacement  placement)
584 {
585   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
586
587   menu_item->submenu_placement = placement;
588 }
589
590 void
591 gtk_menu_item_select (GtkMenuItem *menu_item)
592 {
593   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
594
595   gtk_item_select (GTK_ITEM (menu_item));
596
597   /* Enable themeing of the parent menu item depending on whether
598    * something is selected in its submenu
599    */
600   if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
601     {
602       GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
603
604       if (menu->parent_menu_item)
605         gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
606     }
607 }
608
609 void
610 gtk_menu_item_deselect (GtkMenuItem *menu_item)
611 {
612   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
613
614   gtk_item_deselect (GTK_ITEM (menu_item));
615
616   /* Enable themeing of the parent menu item depending on whether
617    * something is selected in its submenu
618    */
619   if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
620     {
621       GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
622
623       if (menu->parent_menu_item)
624         gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
625     }
626 }
627
628 void
629 gtk_menu_item_activate (GtkMenuItem *menu_item)
630 {
631   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
632   
633   g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
634 }
635
636 void
637 gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
638                                    gint        *requisition)
639 {
640   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
641
642   g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
643 }
644
645 void
646 gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
647                                     gint         allocation)
648 {
649   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
650
651   g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
652 }
653
654 static void
655 gtk_menu_item_accel_width_foreach (GtkWidget *widget,
656                                    gpointer data)
657 {
658   guint *width = data;
659
660   if (GTK_IS_ACCEL_LABEL (widget))
661     {
662       guint w;
663
664       w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
665       *width = MAX (*width, w);
666     }
667   else if (GTK_IS_CONTAINER (widget))
668     gtk_container_foreach (GTK_CONTAINER (widget),
669                            gtk_menu_item_accel_width_foreach,
670                            data);
671 }
672
673 static gint
674 get_minimum_width (GtkWidget *widget)
675 {
676   PangoContext *context;
677   PangoFontMetrics *metrics;
678   gint width;
679   gint width_chars;
680
681   context = gtk_widget_get_pango_context (widget);
682   metrics = pango_context_get_metrics (context,
683                                        widget->style->font_desc,
684                                        pango_context_get_language (context));
685
686   width = pango_font_metrics_get_approximate_char_width (metrics);
687
688   pango_font_metrics_unref (metrics);
689
690   gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
691
692   return PANGO_PIXELS (width_chars * width);
693 }
694
695 static void
696 gtk_menu_item_size_request (GtkWidget      *widget,
697                             GtkRequisition *requisition)
698 {
699   GtkMenuItem *menu_item;
700   GtkBin *bin;
701   guint accel_width;
702   guint horizontal_padding;
703   GtkPackDirection pack_dir;
704   GtkPackDirection child_pack_dir;
705
706   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
707   g_return_if_fail (requisition != NULL);
708
709   gtk_widget_style_get (widget,
710                         "horizontal-padding", &horizontal_padding,
711                         NULL);
712   
713   bin = GTK_BIN (widget);
714   menu_item = GTK_MENU_ITEM (widget);
715
716   if (GTK_IS_MENU_BAR (widget->parent))
717     {
718       pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
719       child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
720     }
721   else
722     {
723       pack_dir = GTK_PACK_DIRECTION_LTR;
724       child_pack_dir = GTK_PACK_DIRECTION_LTR;
725     }
726
727   requisition->width = (GTK_CONTAINER (widget)->border_width +
728                         widget->style->xthickness) * 2;
729   requisition->height = (GTK_CONTAINER (widget)->border_width +
730                          widget->style->ythickness) * 2;
731
732   if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
733       (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
734     requisition->width += 2 * horizontal_padding;
735   else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
736       (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
737     requisition->height += 2 * horizontal_padding;
738
739   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
740     {
741       GtkRequisition child_requisition;
742       
743       gtk_widget_size_request (bin->child, &child_requisition);
744
745       requisition->width += child_requisition.width;
746       requisition->height += child_requisition.height;
747
748       if (menu_item->submenu && menu_item->show_submenu_indicator)
749         {
750           guint arrow_spacing;
751           
752           gtk_widget_style_get (widget,
753                                 "arrow-spacing", &arrow_spacing,
754                                 NULL);
755
756           requisition->width += child_requisition.height;
757           requisition->width += arrow_spacing;
758
759           requisition->width = MAX (requisition->width, get_minimum_width (widget));
760         }
761     }
762   else /* separator item */
763     {
764       gboolean wide_separators;
765       gint     separator_height;
766
767       gtk_widget_style_get (widget,
768                             "wide-separators",  &wide_separators,
769                             "separator-height", &separator_height,
770                             NULL);
771
772       if (wide_separators)
773         requisition->height += separator_height + widget->style->ythickness;
774       else
775         requisition->height += widget->style->ythickness * 2;
776     }
777
778   accel_width = 0;
779   gtk_container_foreach (GTK_CONTAINER (menu_item),
780                          gtk_menu_item_accel_width_foreach,
781                          &accel_width);
782   menu_item->accelerator_width = accel_width;
783 }
784
785 static void
786 gtk_menu_item_size_allocate (GtkWidget     *widget,
787                              GtkAllocation *allocation)
788 {
789   GtkMenuItem *menu_item;
790   GtkBin *bin;
791   GtkAllocation child_allocation;
792   GtkTextDirection direction;
793   GtkPackDirection pack_dir;
794   GtkPackDirection child_pack_dir;
795
796   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
797   g_return_if_fail (allocation != NULL);
798
799   menu_item = GTK_MENU_ITEM (widget);
800   bin = GTK_BIN (widget);
801   
802   direction = gtk_widget_get_direction (widget);
803
804   if (GTK_IS_MENU_BAR (widget->parent))
805     {
806       pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
807       child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
808     }
809   else
810     {
811       pack_dir = GTK_PACK_DIRECTION_LTR;
812       child_pack_dir = GTK_PACK_DIRECTION_LTR;
813     }
814     
815   widget->allocation = *allocation;
816
817   if (bin->child)
818     {
819       GtkRequisition child_requisition;
820       guint horizontal_padding;
821
822       gtk_widget_style_get (widget,
823                             "horizontal-padding", &horizontal_padding,
824                             NULL);
825
826       child_allocation.x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
827       child_allocation.y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness;
828
829       if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
830           (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
831         child_allocation.x += horizontal_padding;
832       else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
833                (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
834         child_allocation.y += horizontal_padding;
835       
836       child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
837       child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
838
839       if (child_pack_dir == GTK_PACK_DIRECTION_LTR ||
840           child_pack_dir == GTK_PACK_DIRECTION_RTL)
841         {
842           if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL))
843             child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
844           child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size;
845         }
846       else
847         {
848           if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT))
849             child_allocation.y += GTK_MENU_ITEM (widget)->toggle_size;
850           child_allocation.height -= GTK_MENU_ITEM (widget)->toggle_size;
851         }
852
853       child_allocation.x += widget->allocation.x;
854       child_allocation.y += widget->allocation.y;
855
856       gtk_widget_get_child_requisition (bin->child, &child_requisition);
857       if (menu_item->submenu && menu_item->show_submenu_indicator) 
858         {
859           if (direction == GTK_TEXT_DIR_RTL)
860             child_allocation.x += child_requisition.height;
861           child_allocation.width -= child_requisition.height;
862         }
863       
864       if (child_allocation.width < 1)
865         child_allocation.width = 1;
866
867       gtk_widget_size_allocate (bin->child, &child_allocation);
868     }
869
870   if (GTK_WIDGET_REALIZED (widget))
871     gdk_window_move_resize (menu_item->event_window,
872                             allocation->x, allocation->y,
873                             allocation->width, allocation->height);
874
875   if (menu_item->submenu)
876     gtk_menu_reposition (GTK_MENU (menu_item->submenu));
877 }
878
879 static void
880 gtk_menu_item_realize (GtkWidget *widget)
881 {
882   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
883   GdkWindowAttr attributes;
884   gint attributes_mask;
885
886   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
887
888   widget->window = gtk_widget_get_parent_window (widget);
889   g_object_ref (widget->window);
890   
891   attributes.x = widget->allocation.x;
892   attributes.y = widget->allocation.y;
893   attributes.width = widget->allocation.width;
894   attributes.height = widget->allocation.height;
895   attributes.window_type = GDK_WINDOW_CHILD;
896   attributes.wclass = GDK_INPUT_ONLY;
897   attributes.event_mask = (gtk_widget_get_events (widget) |
898                            GDK_BUTTON_PRESS_MASK |
899                            GDK_BUTTON_RELEASE_MASK |
900                            GDK_ENTER_NOTIFY_MASK |
901                            GDK_LEAVE_NOTIFY_MASK |
902                            GDK_POINTER_MOTION_MASK);
903
904   attributes_mask = GDK_WA_X | GDK_WA_Y;
905   menu_item->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
906   gdk_window_set_user_data (menu_item->event_window, widget);
907
908   widget->style = gtk_style_attach (widget->style, widget->window);
909 }
910
911 static void
912 gtk_menu_item_unrealize (GtkWidget *widget)
913 {
914   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
915
916   gdk_window_set_user_data (menu_item->event_window, NULL);
917   gdk_window_destroy (menu_item->event_window);
918   menu_item->event_window = NULL;
919
920   GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize (widget);
921 }
922
923 static void
924 gtk_menu_item_map (GtkWidget *widget)
925 {
926   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
927   
928   GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->map (widget);
929
930   gdk_window_show (menu_item->event_window);
931 }
932
933 static void
934 gtk_menu_item_unmap (GtkWidget *widget)
935 {
936   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
937     
938   gdk_window_hide (menu_item->event_window);
939
940   GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unmap (widget);
941 }
942
943 static void
944 gtk_menu_item_paint (GtkWidget    *widget,
945                      GdkRectangle *area)
946 {
947   GtkMenuItem *menu_item;
948   GtkStateType state_type;
949   GtkShadowType shadow_type, selected_shadow_type;
950   gint width, height;
951   gint x, y;
952   gint border_width = GTK_CONTAINER (widget)->border_width;
953
954   if (GTK_WIDGET_DRAWABLE (widget))
955     {
956       menu_item = GTK_MENU_ITEM (widget);
957
958       state_type = widget->state;
959       
960       x = widget->allocation.x + border_width;
961       y = widget->allocation.y + border_width;
962       width = widget->allocation.width - border_width * 2;
963       height = widget->allocation.height - border_width * 2;
964       
965       if ((state_type == GTK_STATE_PRELIGHT) &&
966           (GTK_BIN (menu_item)->child))
967         {
968           gtk_widget_style_get (widget,
969                                 "selected-shadow-type", &selected_shadow_type,
970                                 NULL);
971           gtk_paint_box (widget->style,
972                          widget->window,
973                          GTK_STATE_PRELIGHT,
974                          selected_shadow_type,
975                          area, widget, "menuitem",
976                          x, y, width, height);
977         }
978   
979       if (menu_item->submenu && menu_item->show_submenu_indicator)
980         {
981           gint arrow_x, arrow_y;
982           gint arrow_size;
983           gint arrow_extent;
984           guint horizontal_padding;
985           gfloat arrow_scaling;
986           GtkTextDirection direction;
987           GtkArrowType arrow_type;
988           PangoContext *context;
989           PangoFontMetrics *metrics;
990
991           direction = gtk_widget_get_direction (widget);
992       
993           gtk_widget_style_get (widget,
994                                 "horizontal-padding", &horizontal_padding,
995                                 "arrow-scaling", &arrow_scaling,
996                                 NULL);
997           
998           context = gtk_widget_get_pango_context (GTK_BIN (menu_item)->child);
999           metrics = pango_context_get_metrics (context, 
1000                                                GTK_WIDGET (GTK_BIN (menu_item)->child)->style->font_desc,
1001                                                pango_context_get_language (context));
1002
1003           arrow_size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
1004                                       pango_font_metrics_get_descent (metrics)));
1005
1006           pango_font_metrics_unref (metrics);
1007
1008           arrow_extent = arrow_size * arrow_scaling;
1009
1010           shadow_type = GTK_SHADOW_OUT;
1011           if (state_type == GTK_STATE_PRELIGHT)
1012             shadow_type = GTK_SHADOW_IN;
1013
1014           if (direction == GTK_TEXT_DIR_LTR)
1015             {
1016               arrow_x = x + width - horizontal_padding - arrow_extent;
1017               arrow_type = GTK_ARROW_RIGHT;
1018             }
1019           else
1020             {
1021               arrow_x = x + horizontal_padding;
1022               arrow_type = GTK_ARROW_LEFT;
1023             }
1024
1025           arrow_y = y + (height - arrow_extent) / 2;
1026
1027           gtk_paint_arrow (widget->style, widget->window,
1028                            state_type, shadow_type, 
1029                            area, widget, "menuitem", 
1030                            arrow_type, TRUE,
1031                            arrow_x, arrow_y,
1032                            arrow_extent, arrow_extent);
1033         }
1034       else if (!GTK_BIN (menu_item)->child)
1035         {
1036           gboolean wide_separators;
1037           gint     separator_height;
1038           guint    horizontal_padding;
1039
1040           gtk_widget_style_get (widget,
1041                                 "wide-separators",    &wide_separators,
1042                                 "separator-height",   &separator_height,
1043                                 "horizontal-padding", &horizontal_padding,
1044                                 NULL);
1045
1046           if (wide_separators)
1047             gtk_paint_box (widget->style, widget->window,
1048                            GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
1049                            area, widget, "hseparator",
1050                            widget->allocation.x + horizontal_padding + widget->style->xthickness,
1051                            widget->allocation.y + (widget->allocation.height -
1052                                                    separator_height -
1053                                                    widget->style->ythickness) / 2,
1054                            widget->allocation.width -
1055                            2 * (horizontal_padding + widget->style->xthickness),
1056                            separator_height);
1057           else
1058             gtk_paint_hline (widget->style, widget->window,
1059                              GTK_STATE_NORMAL, area, widget, "menuitem",
1060                              widget->allocation.x + horizontal_padding + widget->style->xthickness,
1061                              widget->allocation.x + widget->allocation.width - horizontal_padding - widget->style->xthickness - 1,
1062                              widget->allocation.y + (widget->allocation.height -
1063                                                      widget->style->ythickness) / 2);
1064         }
1065     }
1066 }
1067
1068 static gint
1069 gtk_menu_item_expose (GtkWidget      *widget,
1070                       GdkEventExpose *event)
1071 {
1072   g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
1073   g_return_val_if_fail (event != NULL, FALSE);
1074
1075   if (GTK_WIDGET_DRAWABLE (widget))
1076     {
1077       gtk_menu_item_paint (widget, &event->area);
1078
1079       GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->expose_event (widget, event);
1080     }
1081
1082   return FALSE;
1083 }
1084
1085 static void
1086 gtk_real_menu_item_select (GtkItem *item)
1087 {
1088   GtkMenuItem *menu_item;
1089   gboolean touchscreen_mode;
1090
1091   g_return_if_fail (GTK_IS_MENU_ITEM (item));
1092
1093   menu_item = GTK_MENU_ITEM (item);
1094
1095   g_object_get (gtk_widget_get_settings (GTK_WIDGET (item)),
1096                 "gtk-touchscreen-mode", &touchscreen_mode,
1097                 NULL);
1098
1099   if (!touchscreen_mode &&
1100       menu_item->submenu &&
1101       (!GTK_WIDGET_MAPPED (menu_item->submenu) ||
1102        GTK_MENU (menu_item->submenu)->tearoff_active))
1103     {
1104       _gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1105     }
1106
1107   gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
1108   gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1109 }
1110
1111 static void
1112 gtk_real_menu_item_deselect (GtkItem *item)
1113 {
1114   GtkMenuItem *menu_item;
1115
1116   g_return_if_fail (GTK_IS_MENU_ITEM (item));
1117
1118   menu_item = GTK_MENU_ITEM (item);
1119
1120   if (menu_item->submenu)
1121     _gtk_menu_item_popdown_submenu (GTK_WIDGET (menu_item));
1122
1123   gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
1124   gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1125 }
1126
1127 static gboolean
1128 gtk_menu_item_mnemonic_activate (GtkWidget *widget,
1129                                  gboolean   group_cycling)
1130 {
1131   if (group_cycling &&
1132       widget->parent &&
1133       GTK_IS_MENU_SHELL (widget->parent) &&
1134       GTK_MENU_SHELL (widget->parent)->active)
1135     {
1136       gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent),
1137                                   widget);
1138     }
1139   else
1140     g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0);
1141   
1142   return TRUE;
1143 }
1144
1145 static void
1146 gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
1147 {
1148   GtkWidget *widget;
1149
1150   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1151
1152   widget = GTK_WIDGET (menu_item);
1153   
1154   if (widget->parent &&
1155       GTK_IS_MENU_SHELL (widget->parent))
1156     {
1157       if (menu_item->submenu == NULL)
1158         gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget->parent),
1159                                       widget, TRUE);
1160       else
1161         {
1162           GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget->parent);
1163
1164           _gtk_menu_shell_activate (menu_shell);
1165
1166           gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent), widget);
1167           _gtk_menu_item_popup_submenu (widget, FALSE);
1168
1169           gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
1170         }
1171     }
1172 }
1173
1174 static void
1175 gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1176                                         gint        *requisition)
1177 {
1178   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1179
1180   *requisition = 0;
1181 }
1182
1183 static void
1184 gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1185                                          gint         allocation)
1186 {
1187   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1188
1189   menu_item->toggle_size = allocation;
1190 }
1191
1192 static void
1193 gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
1194                               const gchar *label)
1195 {
1196   gtk_menu_item_ensure_label (menu_item);
1197
1198   if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
1199     {
1200       gtk_label_set_label (GTK_LABEL (GTK_BIN (menu_item)->child), label ? label : "");
1201       
1202       g_object_notify (G_OBJECT (menu_item), "label");
1203     }
1204 }
1205
1206 static G_CONST_RETURN gchar *
1207 gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
1208 {
1209   gtk_menu_item_ensure_label (menu_item);
1210
1211   if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
1212     return gtk_label_get_label (GTK_LABEL (GTK_BIN (menu_item)->child));
1213
1214   return NULL;
1215 }
1216
1217 static void
1218 free_timeval (GTimeVal *val)
1219 {
1220   g_slice_free (GTimeVal, val);
1221 }
1222
1223 static void
1224 gtk_menu_item_real_popup_submenu (GtkWidget *widget,
1225                                   gboolean   remember_exact_time)
1226 {
1227   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1228
1229   if (GTK_WIDGET_IS_SENSITIVE (menu_item->submenu) && widget->parent)
1230     {
1231       gboolean take_focus;
1232       GtkMenuPositionFunc menu_position_func;
1233
1234       take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (widget->parent));
1235       gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (menu_item->submenu),
1236                                      take_focus);
1237
1238       if (remember_exact_time)
1239         {
1240           GTimeVal *popup_time = g_slice_new0 (GTimeVal);
1241
1242           g_get_current_time (popup_time);
1243
1244           g_object_set_data_full (G_OBJECT (menu_item->submenu),
1245                                   "gtk-menu-exact-popup-time", popup_time,
1246                                   (GDestroyNotify) free_timeval);
1247         }
1248       else
1249         {
1250           g_object_set_data (G_OBJECT (menu_item->submenu),
1251                              "gtk-menu-exact-popup-time", NULL);
1252         }
1253
1254       /* gtk_menu_item_position_menu positions the submenu from the
1255        * menuitems position. If the menuitem doesn't have a window,
1256        * that doesn't work. In that case we use the default
1257        * positioning function instead which places the submenu at the
1258        * mouse cursor.
1259        */
1260       if (widget->window)
1261         menu_position_func = gtk_menu_item_position_menu;
1262       else
1263         menu_position_func = NULL;
1264
1265       gtk_menu_popup (GTK_MENU (menu_item->submenu),
1266                       widget->parent,
1267                       widget,
1268                       menu_position_func,
1269                       menu_item,
1270                       GTK_MENU_SHELL (widget->parent)->button,
1271                       0);
1272     }
1273
1274   /* Enable themeing of the parent menu item depending on whether
1275    * its submenu is shown or not.
1276    */
1277   gtk_widget_queue_draw (widget);
1278 }
1279
1280 static gint
1281 gtk_menu_item_popup_timeout (gpointer data)
1282 {
1283   GtkMenuItem *menu_item;
1284   GtkWidget *parent;
1285   
1286   menu_item = GTK_MENU_ITEM (data);
1287
1288   parent = GTK_WIDGET (menu_item)->parent;
1289
1290   if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active) || 
1291       (GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off))
1292     {
1293       gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1294       if (menu_item->timer_from_keypress && menu_item->submenu)
1295         GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
1296     }
1297
1298   menu_item->timer = 0;
1299
1300   return FALSE;  
1301 }
1302
1303 static gint
1304 get_popup_delay (GtkWidget *widget)
1305 {
1306   if (GTK_IS_MENU_SHELL (widget->parent))
1307     {
1308       return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (widget->parent));
1309     }
1310   else
1311     {
1312       gint popup_delay;
1313
1314       g_object_get (gtk_widget_get_settings (widget),
1315                     "gtk-menu-popup-delay", &popup_delay,
1316                     NULL);
1317
1318       return popup_delay;
1319     }
1320 }
1321
1322 void
1323 _gtk_menu_item_popup_submenu (GtkWidget *widget,
1324                               gboolean   with_delay)
1325 {
1326   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1327
1328   if (menu_item->timer)
1329     {
1330       g_source_remove (menu_item->timer);
1331       menu_item->timer = 0;
1332       with_delay = FALSE;
1333     }
1334
1335   if (with_delay)
1336     {
1337       gint popup_delay = get_popup_delay (widget);
1338
1339       if (popup_delay > 0)
1340         {
1341           GdkEvent *event = gtk_get_current_event ();
1342
1343           menu_item->timer = gdk_threads_add_timeout (popup_delay,
1344                                                       gtk_menu_item_popup_timeout,
1345                                                       menu_item);
1346
1347           if (event &&
1348               event->type != GDK_BUTTON_PRESS &&
1349               event->type != GDK_ENTER_NOTIFY)
1350             menu_item->timer_from_keypress = TRUE;
1351           else
1352             menu_item->timer_from_keypress = FALSE;
1353
1354           if (event)
1355             gdk_event_free (event);
1356
1357           return;
1358         }
1359     }
1360
1361   gtk_menu_item_real_popup_submenu (widget, FALSE);
1362 }
1363
1364 void
1365 _gtk_menu_item_popdown_submenu (GtkWidget *widget)
1366 {
1367   GtkMenuItem *menu_item;
1368
1369   menu_item = GTK_MENU_ITEM (widget);
1370
1371   if (menu_item->submenu)
1372     {
1373       g_object_set_data (G_OBJECT (menu_item->submenu),
1374                          "gtk-menu-exact-popup-time", NULL);
1375
1376       if (menu_item->timer)
1377         {
1378           g_source_remove (menu_item->timer);
1379           menu_item->timer = 0;
1380         }
1381       else
1382         gtk_menu_popdown (GTK_MENU (menu_item->submenu));
1383
1384       gtk_widget_queue_draw (widget);
1385     }
1386 }
1387
1388 static void
1389 get_offsets (GtkMenu *menu,
1390              gint    *horizontal_offset,
1391              gint    *vertical_offset)
1392 {
1393   gint vertical_padding;
1394   gint horizontal_padding;
1395   
1396   gtk_widget_style_get (GTK_WIDGET (menu),
1397                         "horizontal-offset", horizontal_offset,
1398                         "vertical-offset", vertical_offset,
1399                         "horizontal-padding", &horizontal_padding,
1400                         "vertical-padding", &vertical_padding,
1401                         NULL);
1402
1403   *vertical_offset -= GTK_WIDGET (menu)->style->ythickness;
1404   *vertical_offset -= vertical_padding;
1405   *horizontal_offset += horizontal_padding;
1406 }
1407
1408 static void
1409 gtk_menu_item_position_menu (GtkMenu  *menu,
1410                              gint     *x,
1411                              gint     *y,
1412                              gboolean *push_in,
1413                              gpointer  user_data)
1414 {
1415   GtkMenuItem *menu_item;
1416   GtkWidget *widget;
1417   GtkMenuItem *parent_menu_item;
1418   GdkScreen *screen;
1419   gint twidth, theight;
1420   gint tx, ty;
1421   GtkTextDirection direction;
1422   GdkRectangle monitor;
1423   gint monitor_num;
1424   gint horizontal_offset;
1425   gint vertical_offset;
1426   gint parent_xthickness;
1427   gint available_left, available_right;
1428
1429   g_return_if_fail (menu != NULL);
1430   g_return_if_fail (x != NULL);
1431   g_return_if_fail (y != NULL);
1432
1433   menu_item = GTK_MENU_ITEM (user_data);
1434   widget = GTK_WIDGET (user_data);
1435
1436   if (push_in)
1437     *push_in = FALSE;
1438
1439   direction = gtk_widget_get_direction (widget);
1440
1441   twidth = GTK_WIDGET (menu)->requisition.width;
1442   theight = GTK_WIDGET (menu)->requisition.height;
1443
1444   screen = gtk_widget_get_screen (GTK_WIDGET (menu));
1445   monitor_num = gdk_screen_get_monitor_at_window (screen, menu_item->event_window);
1446   if (monitor_num < 0)
1447     monitor_num = 0;
1448   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1449
1450   if (!gdk_window_get_origin (widget->window, &tx, &ty))
1451     {
1452       g_warning ("Menu not on screen");
1453       return;
1454     }
1455
1456   tx += widget->allocation.x;
1457   ty += widget->allocation.y;
1458
1459   get_offsets (menu, &horizontal_offset, &vertical_offset);
1460
1461   available_left = tx - monitor.x;
1462   available_right = monitor.x + monitor.width - (tx + widget->allocation.width);
1463
1464   if (GTK_IS_MENU_BAR (widget->parent))
1465     {
1466       menu_item->from_menubar = TRUE;
1467     }
1468   else if (GTK_IS_MENU (widget->parent))
1469     {
1470       if (GTK_MENU (widget->parent)->parent_menu_item)
1471         menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item)->from_menubar;
1472       else
1473         menu_item->from_menubar = FALSE;
1474     }
1475   else
1476     {
1477       menu_item->from_menubar = FALSE;
1478     }
1479   
1480   switch (menu_item->submenu_placement)
1481     {
1482     case GTK_TOP_BOTTOM:
1483       if (direction == GTK_TEXT_DIR_LTR)
1484         menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
1485       else 
1486         {
1487           menu_item->submenu_direction = GTK_DIRECTION_LEFT;
1488           tx += widget->allocation.width - twidth;
1489         }
1490       if ((ty + widget->allocation.height + theight) <= monitor.y + monitor.height)
1491         ty += widget->allocation.height;
1492       else if ((ty - theight) >= monitor.y)
1493         ty -= theight;
1494       else if (monitor.y + monitor.height - (ty + widget->allocation.height) > ty)
1495         ty += widget->allocation.height;
1496       else
1497         ty -= theight;
1498       break;
1499
1500     case GTK_LEFT_RIGHT:
1501       if (GTK_IS_MENU (widget->parent))
1502         parent_menu_item = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item);
1503       else
1504         parent_menu_item = NULL;
1505       
1506       parent_xthickness = widget->parent->style->xthickness;
1507
1508       if (parent_menu_item && !GTK_MENU (widget->parent)->torn_off)
1509         {
1510           menu_item->submenu_direction = parent_menu_item->submenu_direction;
1511         }
1512       else
1513         {
1514           if (direction == GTK_TEXT_DIR_LTR)
1515             menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
1516           else
1517             menu_item->submenu_direction = GTK_DIRECTION_LEFT;
1518         }
1519
1520       switch (menu_item->submenu_direction)
1521         {
1522         case GTK_DIRECTION_LEFT:
1523           if (tx - twidth - parent_xthickness - horizontal_offset >= monitor.x ||
1524               available_left >= available_right)
1525             tx -= twidth + parent_xthickness + horizontal_offset;
1526           else
1527             {
1528               menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
1529               tx += widget->allocation.width + parent_xthickness + horizontal_offset;
1530             }
1531           break;
1532
1533         case GTK_DIRECTION_RIGHT:
1534           if (tx + widget->allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
1535               available_right >= available_left)
1536             tx += widget->allocation.width + parent_xthickness + horizontal_offset;
1537           else
1538             {
1539               menu_item->submenu_direction = GTK_DIRECTION_LEFT;
1540               tx -= twidth + parent_xthickness + horizontal_offset;
1541             }
1542           break;
1543         }
1544
1545       ty += vertical_offset;
1546       
1547       /* If the height of the menu doesn't fit we move it upward. */
1548       ty = CLAMP (ty, monitor.y, MAX (monitor.y, monitor.y + monitor.height - theight));
1549       break;
1550     }
1551
1552   /* If we have negative, tx, here it is because we can't get
1553    * the menu all the way on screen. Favor the left portion.
1554    */
1555   *x = CLAMP (tx, monitor.x, MAX (monitor.x, monitor.x + monitor.width - twidth));
1556   *y = ty;
1557
1558   gtk_menu_set_monitor (menu, monitor_num);
1559
1560   if (!GTK_WIDGET_VISIBLE (menu->toplevel))
1561     {
1562       gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar?
1563                                 GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
1564     }
1565 }
1566
1567 /**
1568  * gtk_menu_item_set_right_justified:
1569  * @menu_item: a #GtkMenuItem.
1570  * @right_justified: if %TRUE the menu item will appear at the 
1571  *   far right if added to a menu bar.
1572  * 
1573  * Sets whether the menu item appears justified at the right
1574  * side of a menu bar. This was traditionally done for "Help" menu
1575  * items, but is now considered a bad idea. (If the widget
1576  * layout is reversed for a right-to-left language like Hebrew
1577  * or Arabic, right-justified-menu-items appear at the left.)
1578  **/
1579 void
1580 gtk_menu_item_set_right_justified (GtkMenuItem *menu_item,
1581                                    gboolean     right_justified)
1582 {
1583   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1584
1585   right_justified = right_justified != FALSE;
1586
1587   if (right_justified != menu_item->right_justify)
1588     {
1589       menu_item->right_justify = right_justified;
1590       gtk_widget_queue_resize (GTK_WIDGET (menu_item));
1591     }
1592 }
1593
1594 /**
1595  * gtk_menu_item_get_right_justified:
1596  * @menu_item: a #GtkMenuItem
1597  * 
1598  * Gets whether the menu item appears justified at the right
1599  * side of the menu bar.
1600  * 
1601  * Return value: %TRUE if the menu item will appear at the
1602  *   far right if added to a menu bar.
1603  **/
1604 gboolean
1605 gtk_menu_item_get_right_justified (GtkMenuItem *menu_item)
1606 {
1607   g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
1608   
1609   return menu_item->right_justify;
1610 }
1611
1612
1613 static void
1614 gtk_menu_item_show_all (GtkWidget *widget)
1615 {
1616   GtkMenuItem *menu_item;
1617
1618   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1619
1620   menu_item = GTK_MENU_ITEM (widget);
1621
1622   /* show children including submenu */
1623   if (menu_item->submenu)
1624     gtk_widget_show_all (menu_item->submenu);
1625   gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_show_all, NULL);
1626
1627   gtk_widget_show (widget);
1628 }
1629
1630 static void
1631 gtk_menu_item_hide_all (GtkWidget *widget)
1632 {
1633   GtkMenuItem *menu_item;
1634
1635   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1636
1637   gtk_widget_hide (widget);
1638
1639   menu_item = GTK_MENU_ITEM (widget);
1640
1641   /* hide children including submenu */
1642   gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_hide_all, NULL);
1643   if (menu_item->submenu)
1644     gtk_widget_hide_all (menu_item->submenu);
1645 }
1646
1647 static gboolean
1648 gtk_menu_item_can_activate_accel (GtkWidget *widget,
1649                                   guint      signal_id)
1650 {
1651   /* Chain to the parent GtkMenu for further checks */
1652   return (GTK_WIDGET_IS_SENSITIVE (widget) && GTK_WIDGET_VISIBLE (widget) &&
1653           widget->parent && gtk_widget_can_activate_accel (widget->parent, signal_id));
1654 }
1655
1656 static void
1657 gtk_menu_item_accel_name_foreach (GtkWidget *widget,
1658                                   gpointer data)
1659 {
1660   const gchar **path_p = data;
1661
1662   if (!*path_p)
1663     {
1664       if (GTK_IS_LABEL (widget))
1665         {
1666           *path_p = gtk_label_get_text (GTK_LABEL (widget));
1667           if (*path_p && (*path_p)[0] == 0)
1668             *path_p = NULL;
1669         }
1670       else if (GTK_IS_CONTAINER (widget))
1671         gtk_container_foreach (GTK_CONTAINER (widget),
1672                                gtk_menu_item_accel_name_foreach,
1673                                data);
1674     }
1675 }
1676
1677 static void
1678 gtk_menu_item_parent_set (GtkWidget *widget,
1679                           GtkWidget *previous_parent)
1680 {
1681   GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1682   GtkMenu *menu = GTK_IS_MENU (widget->parent) ? GTK_MENU (widget->parent) : NULL;
1683
1684   if (menu)
1685     _gtk_menu_item_refresh_accel_path (menu_item,
1686                                        menu->accel_path,
1687                                        menu->accel_group,
1688                                        TRUE);
1689
1690   if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set)
1691     GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent);
1692 }
1693
1694 void
1695 _gtk_menu_item_refresh_accel_path (GtkMenuItem   *menu_item,
1696                                    const gchar   *prefix,
1697                                    GtkAccelGroup *accel_group,
1698                                    gboolean       group_changed)
1699 {
1700   const gchar *path;
1701   GtkWidget *widget;
1702
1703   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1704   g_return_if_fail (!accel_group || GTK_IS_ACCEL_GROUP (accel_group));
1705
1706   widget = GTK_WIDGET (menu_item);
1707
1708   if (!accel_group)
1709     {
1710       gtk_widget_set_accel_path (widget, NULL, NULL);
1711       return;
1712     }
1713
1714   path = _gtk_widget_get_accel_path (widget, NULL);
1715   if (!path)                                    /* no active accel_path yet */
1716     {
1717       path = menu_item->accel_path;
1718       if (!path && prefix)
1719         {
1720           const gchar *postfix = NULL;
1721           gchar *new_path;
1722
1723           /* try to construct one from label text */
1724           gtk_container_foreach (GTK_CONTAINER (menu_item),
1725                                  gtk_menu_item_accel_name_foreach,
1726                                  &postfix);
1727           if (postfix)
1728             {
1729               new_path = g_strconcat (prefix, "/", postfix, NULL);
1730               path = menu_item->accel_path = (char*)g_intern_string (new_path);
1731               g_free (new_path);
1732             }
1733         }
1734       if (path)
1735         gtk_widget_set_accel_path (widget, path, accel_group);
1736     }
1737   else if (group_changed)                       /* reinstall accelerators */
1738     gtk_widget_set_accel_path (widget, path, accel_group);
1739 }
1740
1741 /**
1742  * gtk_menu_item_set_accel_path
1743  * @menu_item:  a valid #GtkMenuItem
1744  * @accel_path: accelerator path, corresponding to this menu item's
1745  *              functionality, or %NULL to unset the current path.
1746  *
1747  * Set the accelerator path on @menu_item, through which runtime changes of the
1748  * menu item's accelerator caused by the user can be identified and saved to
1749  * persistant storage (see gtk_accel_map_save() on this).
1750  * To setup a default accelerator for this menu item, call
1751  * gtk_accel_map_add_entry() with the same @accel_path.
1752  * See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
1753  * and gtk_menu_set_accel_path() for a more convenient variant of this function.
1754  *
1755  * This function is basically a convenience wrapper that handles calling
1756  * gtk_widget_set_accel_path() with the appropriate accelerator group for
1757  * the menu item.
1758  *
1759  * Note that you do need to set an accelerator on the parent menu with
1760  * gtk_menu_set_accel_group() for this to work.
1761  *
1762  * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
1763  * pass a static string, you can save some memory by interning it first with 
1764  * g_intern_static_string().
1765  */
1766 void
1767 gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
1768                               const gchar *accel_path)
1769 {
1770   GtkWidget *widget;
1771
1772   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1773   g_return_if_fail (accel_path == NULL ||
1774                     (accel_path[0] == '<' && strchr (accel_path, '/')));
1775
1776   widget = GTK_WIDGET (menu_item);
1777
1778   /* store new path */
1779   menu_item->accel_path = (char*)g_intern_string (accel_path);
1780
1781   /* forget accelerators associated with old path */
1782   gtk_widget_set_accel_path (widget, NULL, NULL);
1783
1784   /* install accelerators associated with new path */
1785   if (GTK_IS_MENU (widget->parent))
1786     {
1787       GtkMenu *menu = GTK_MENU (widget->parent);
1788
1789       if (menu->accel_group)
1790         _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
1791                                            NULL,
1792                                            menu->accel_group,
1793                                            FALSE);
1794     }
1795 }
1796
1797 /**
1798  * gtk_menu_item_get_accel_path
1799  * @menu_item:  a valid #GtkMenuItem
1800  *
1801  * Retrieve the accelerator path that was previously set on @menu_item.
1802  *
1803  * See gtk_menu_item_set_accel_path() for details.
1804  *
1805  * Returns: the accelerator path corresponding to this menu item's
1806  *              functionality, or %NULL if not set
1807  *
1808  * Since: 2.14
1809  */
1810 G_CONST_RETURN gchar *
1811 gtk_menu_item_get_accel_path (GtkMenuItem *menu_item)
1812 {
1813   g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
1814
1815   return menu_item->accel_path;
1816 }
1817
1818 static void
1819 gtk_menu_item_forall (GtkContainer *container,
1820                       gboolean      include_internals,
1821                       GtkCallback   callback,
1822                       gpointer      callback_data)
1823 {
1824   GtkBin *bin;
1825
1826   g_return_if_fail (GTK_IS_MENU_ITEM (container));
1827   g_return_if_fail (callback != NULL);
1828
1829   bin = GTK_BIN (container);
1830
1831   if (bin->child)
1832     callback (bin->child, callback_data);
1833 }
1834
1835 gboolean
1836 _gtk_menu_item_is_selectable (GtkWidget *menu_item)
1837 {
1838   if ((!GTK_BIN (menu_item)->child &&
1839        G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
1840       GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
1841       !GTK_WIDGET_IS_SENSITIVE (menu_item) ||
1842       !GTK_WIDGET_VISIBLE (menu_item))
1843     return FALSE;
1844
1845   return TRUE;
1846 }
1847
1848 static void
1849 gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
1850 {
1851   GtkWidget *accel_label;
1852
1853   if (!GTK_BIN (menu_item)->child)
1854     {
1855       accel_label = (GtkWidget *)g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
1856       gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
1857
1858       gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
1859       gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), 
1860                                         GTK_WIDGET (menu_item));
1861       gtk_widget_show (accel_label);
1862     }
1863 }
1864
1865 /**
1866  * gtk_menu_item_set_label:
1867  * @menu_item: a #GtkMenuItem
1868  * @label: the text you want to set
1869  *
1870  * Sets @text on the @menu_item label
1871  *
1872  * Since: 2.16
1873  **/
1874 void
1875 gtk_menu_item_set_label (GtkMenuItem *menu_item,
1876                          const gchar *label)
1877 {
1878   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1879
1880   GTK_MENU_ITEM_GET_CLASS (menu_item)->set_label (menu_item, label);
1881 }
1882
1883 /**
1884  * gtk_menu_item_get_label:
1885  * @menu_item: a #GtkMenuItem
1886  *
1887  * Sets @text on the @menu_item label
1888  *
1889  * Returns: The text in the @menu_item label. This is the internal
1890  *   string used by the label, and must not be modified.
1891  *
1892  * Since: 2.16
1893  **/
1894 G_CONST_RETURN gchar *
1895 gtk_menu_item_get_label (GtkMenuItem *menu_item)
1896 {
1897   g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
1898
1899   return GTK_MENU_ITEM_GET_CLASS (menu_item)->get_label (menu_item);
1900 }
1901
1902 /**
1903  * gtk_menu_item_set_use_underline:
1904  * @menu_item: a #GtkMenuItem
1905  * @setting: %TRUE if underlines in the text indicate mnemonics  
1906  *
1907  * If true, an underline in the text indicates the next character should be
1908  * used for the mnemonic accelerator key.
1909  *
1910  * Since: 2.16
1911  **/
1912 void
1913 gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
1914                                  gboolean     setting)
1915 {
1916   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1917
1918   gtk_menu_item_ensure_label (menu_item);
1919
1920   if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
1921     {
1922       gtk_label_set_use_underline (GTK_LABEL (GTK_BIN (menu_item)->child), setting);
1923
1924       g_object_notify (G_OBJECT (menu_item), "use-underline");
1925     }
1926 }
1927
1928 /**
1929  * gtk_menu_item_get_use_underline:
1930  * @menu_item: a #GtkMenuItem
1931  *
1932  * Checks if an underline in the text indicates the next character should be
1933  * used for the mnemonic accelerator key.
1934  *
1935  * Return value: %TRUE if an embedded underline in the label indicates
1936  *               the mnemonic accelerator key.
1937  *
1938  * Since: 2.16
1939  **/
1940 gboolean
1941 gtk_menu_item_get_use_underline (GtkMenuItem *menu_item)
1942 {
1943   g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
1944
1945   gtk_menu_item_ensure_label (menu_item);
1946   
1947   if (GTK_IS_LABEL (GTK_BIN (menu_item)->child))
1948     return gtk_label_get_use_underline (GTK_LABEL (GTK_BIN (menu_item)->child));
1949
1950   return FALSE;
1951 }
1952
1953
1954
1955 #define __GTK_MENU_ITEM_C__
1956 #include "gtkaliasdef.c"