1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
30 #include "gtkaccellabel.h"
32 #include "gtkmarshalers.h"
34 #include "gtkmenubar.h"
35 #include "gtkmenuprivate.h"
36 #include "gtkseparatormenuitem.h"
37 #include "gtkprivate.h"
38 #include "gtkbuildable.h"
39 #include "gtkactivatable.h"
45 gboolean use_action_appearance;
66 /* activatable properties */
67 PROP_ACTIVATABLE_RELATED_ACTION,
68 PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
72 static void gtk_menu_item_dispose (GObject *object);
73 static void gtk_menu_item_set_property (GObject *object,
77 static void gtk_menu_item_get_property (GObject *object,
81 static void gtk_menu_item_destroy (GtkObject *object);
82 static void gtk_menu_item_size_allocate (GtkWidget *widget,
83 GtkAllocation *allocation);
84 static void gtk_menu_item_realize (GtkWidget *widget);
85 static void gtk_menu_item_unrealize (GtkWidget *widget);
86 static void gtk_menu_item_map (GtkWidget *widget);
87 static void gtk_menu_item_unmap (GtkWidget *widget);
88 static gboolean gtk_menu_item_enter (GtkWidget *widget,
89 GdkEventCrossing *event);
90 static gboolean gtk_menu_item_leave (GtkWidget *widget,
91 GdkEventCrossing *event);
92 static gboolean gtk_menu_item_draw (GtkWidget *widget,
94 static void gtk_menu_item_parent_set (GtkWidget *widget,
95 GtkWidget *previous_parent);
98 static void gtk_real_menu_item_select (GtkMenuItem *item);
99 static void gtk_real_menu_item_deselect (GtkMenuItem *item);
100 static void gtk_real_menu_item_activate (GtkMenuItem *item);
101 static void gtk_real_menu_item_activate_item (GtkMenuItem *item);
102 static void gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
104 static void gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
106 static gboolean gtk_menu_item_mnemonic_activate (GtkWidget *widget,
107 gboolean group_cycling);
109 static void gtk_menu_item_ensure_label (GtkMenuItem *menu_item);
110 static gint gtk_menu_item_popup_timeout (gpointer data);
111 static void gtk_menu_item_position_menu (GtkMenu *menu,
116 static void gtk_menu_item_show_all (GtkWidget *widget);
117 static void gtk_menu_item_hide_all (GtkWidget *widget);
118 static void gtk_menu_item_forall (GtkContainer *container,
119 gboolean include_internals,
120 GtkCallback callback,
121 gpointer callback_data);
122 static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
125 static void gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
127 static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
129 static void gtk_menu_item_get_preferred_width (GtkWidget *widget,
132 static void gtk_menu_item_get_preferred_height (GtkWidget *widget,
135 static void gtk_menu_item_get_preferred_height_for_width (GtkWidget *widget,
140 static void gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface);
141 static void gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
145 static void gtk_menu_item_buildable_custom_finished(GtkBuildable *buildable,
148 const gchar *tagname,
151 static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface);
152 static void gtk_menu_item_update (GtkActivatable *activatable,
154 const gchar *property_name);
155 static void gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
157 static void gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
159 static void gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
160 gboolean use_appearance);
163 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
165 static GtkBuildableIface *parent_buildable_iface;
167 G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_BIN,
168 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
169 gtk_menu_item_buildable_interface_init)
170 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
171 gtk_menu_item_activatable_interface_init))
173 #define GET_PRIVATE(object) \
174 (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
177 gtk_menu_item_class_init (GtkMenuItemClass *klass)
179 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
180 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
181 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
182 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
184 gobject_class->dispose = gtk_menu_item_dispose;
185 gobject_class->set_property = gtk_menu_item_set_property;
186 gobject_class->get_property = gtk_menu_item_get_property;
188 object_class->destroy = gtk_menu_item_destroy;
190 widget_class->size_allocate = gtk_menu_item_size_allocate;
191 widget_class->draw = gtk_menu_item_draw;
192 widget_class->realize = gtk_menu_item_realize;
193 widget_class->unrealize = gtk_menu_item_unrealize;
194 widget_class->map = gtk_menu_item_map;
195 widget_class->unmap = gtk_menu_item_unmap;
196 widget_class->enter_notify_event = gtk_menu_item_enter;
197 widget_class->leave_notify_event = gtk_menu_item_leave;
198 widget_class->show_all = gtk_menu_item_show_all;
199 widget_class->hide_all = gtk_menu_item_hide_all;
200 widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
201 widget_class->parent_set = gtk_menu_item_parent_set;
202 widget_class->can_activate_accel = gtk_menu_item_can_activate_accel;
203 widget_class->get_preferred_width = gtk_menu_item_get_preferred_width;
204 widget_class->get_preferred_height = gtk_menu_item_get_preferred_height;
205 widget_class->get_preferred_height_for_width = gtk_menu_item_get_preferred_height_for_width;
207 container_class->forall = gtk_menu_item_forall;
209 klass->activate = gtk_real_menu_item_activate;
210 klass->activate_item = gtk_real_menu_item_activate_item;
211 klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
212 klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
213 klass->set_label = gtk_real_menu_item_set_label;
214 klass->get_label = gtk_real_menu_item_get_label;
215 klass->select = gtk_real_menu_item_select;
216 klass->deselect = gtk_real_menu_item_deselect;
218 klass->hide_on_activate = TRUE;
220 menu_item_signals[ACTIVATE] =
221 g_signal_new (I_("activate"),
222 G_OBJECT_CLASS_TYPE (gobject_class),
223 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
224 G_STRUCT_OFFSET (GtkMenuItemClass, activate),
226 _gtk_marshal_VOID__VOID,
228 widget_class->activate_signal = menu_item_signals[ACTIVATE];
230 menu_item_signals[ACTIVATE_ITEM] =
231 g_signal_new (I_("activate-item"),
232 G_OBJECT_CLASS_TYPE (gobject_class),
234 G_STRUCT_OFFSET (GtkMenuItemClass, activate_item),
236 _gtk_marshal_VOID__VOID,
239 menu_item_signals[TOGGLE_SIZE_REQUEST] =
240 g_signal_new (I_("toggle-size-request"),
241 G_OBJECT_CLASS_TYPE (gobject_class),
243 G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_request),
245 _gtk_marshal_VOID__POINTER,
249 menu_item_signals[TOGGLE_SIZE_ALLOCATE] =
250 g_signal_new (I_("toggle-size-allocate"),
251 G_OBJECT_CLASS_TYPE (gobject_class),
253 G_STRUCT_OFFSET (GtkMenuItemClass, toggle_size_allocate),
255 _gtk_marshal_VOID__INT,
259 menu_item_signals[SELECT] =
260 g_signal_new (I_("select"),
261 G_OBJECT_CLASS_TYPE (gobject_class),
263 G_STRUCT_OFFSET (GtkMenuItemClass, select),
265 _gtk_marshal_VOID__VOID,
268 menu_item_signals[DESELECT] =
269 g_signal_new (I_("deselect"),
270 G_OBJECT_CLASS_TYPE (gobject_class),
272 G_STRUCT_OFFSET (GtkMenuItemClass, deselect),
274 _gtk_marshal_VOID__VOID,
278 * GtkMenuItem:right-justified:
280 * Sets whether the menu item appears justified at the right side of a menu bar.
284 g_object_class_install_property (gobject_class,
285 PROP_RIGHT_JUSTIFIED,
286 g_param_spec_boolean ("right-justified",
287 P_("Right Justified"),
288 P_("Sets whether the menu item appears justified at the right side of a menu bar"),
290 GTK_PARAM_READWRITE));
293 * GtkMenuItem:submenu:
295 * The submenu attached to the menu item, or NULL if it has none.
299 g_object_class_install_property (gobject_class,
301 g_param_spec_object ("submenu",
303 P_("The submenu attached to the menu item, or NULL if it has none"),
305 GTK_PARAM_READWRITE));
309 * GtkMenuItem:accel-path:
311 * Sets the accelerator path of the menu item, through which runtime
312 * changes of the menu item's accelerator caused by the user can be
313 * identified and saved to persistant storage.
317 g_object_class_install_property (gobject_class,
319 g_param_spec_string ("accel-path",
321 P_("Sets the accelerator path of the menu item"),
323 GTK_PARAM_READWRITE));
328 * The text for the child label.
332 g_object_class_install_property (gobject_class,
334 g_param_spec_string ("label",
336 P_("The text for the child label"),
338 GTK_PARAM_READWRITE));
341 * GtkMenuItem:use-underline:
343 * %TRUE if underlines in the text indicate mnemonics
347 g_object_class_install_property (gobject_class,
349 g_param_spec_boolean ("use-underline",
351 P_("If set, an underline in the text indicates "
352 "the next character should be used for the "
353 "mnemonic accelerator key"),
355 GTK_PARAM_READWRITE));
357 g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
358 g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
360 gtk_widget_class_install_style_property_parser (widget_class,
361 g_param_spec_enum ("selected-shadow-type",
362 "Selected Shadow Type",
363 "Shadow type when item is selected",
364 GTK_TYPE_SHADOW_TYPE,
367 gtk_rc_property_parse_enum);
369 gtk_widget_class_install_style_property (widget_class,
370 g_param_spec_int ("horizontal-padding",
371 "Horizontal Padding",
372 "Padding to left and right of the menu item",
376 GTK_PARAM_READABLE));
378 gtk_widget_class_install_style_property (widget_class,
379 g_param_spec_int ("toggle-spacing",
381 "Space between icon and label",
385 GTK_PARAM_READABLE));
387 gtk_widget_class_install_style_property (widget_class,
388 g_param_spec_int ("arrow-spacing",
390 "Space between label and arrow",
394 GTK_PARAM_READABLE));
396 gtk_widget_class_install_style_property (widget_class,
397 g_param_spec_float ("arrow-scaling",
399 P_("Amount of space used up by arrow, relative to the menu item's font size"),
401 GTK_PARAM_READABLE));
404 * GtkMenuItem:width-chars:
406 * The minimum desired width of the menu item in characters.
410 gtk_widget_class_install_style_property (widget_class,
411 g_param_spec_int ("width-chars",
412 P_("Width in Characters"),
413 P_("The minimum desired width of the menu item in characters"),
415 GTK_PARAM_READABLE));
417 g_type_class_add_private (object_class, sizeof (GtkMenuItemPrivate));
421 gtk_menu_item_init (GtkMenuItem *menu_item)
423 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
425 gtk_widget_set_has_window (GTK_WIDGET (menu_item), FALSE);
428 priv->use_action_appearance = TRUE;
430 menu_item->submenu = NULL;
431 menu_item->toggle_size = 0;
432 menu_item->accelerator_width = 0;
433 menu_item->show_submenu_indicator = FALSE;
434 if (gtk_widget_get_direction (GTK_WIDGET (menu_item)) == GTK_TEXT_DIR_RTL)
435 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
437 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
438 menu_item->submenu_placement = GTK_TOP_BOTTOM;
439 menu_item->right_justify = FALSE;
441 menu_item->timer = 0;
445 gtk_menu_item_new (void)
447 return g_object_new (GTK_TYPE_MENU_ITEM, NULL);
451 gtk_menu_item_new_with_label (const gchar *label)
453 return g_object_new (GTK_TYPE_MENU_ITEM,
460 * gtk_menu_item_new_with_mnemonic:
461 * @label: The text of the button, with an underscore in front of the
463 * @returns: a new #GtkMenuItem
465 * Creates a new #GtkMenuItem containing a label. The label
466 * will be created using gtk_label_new_with_mnemonic(), so underscores
467 * in @label indicate the mnemonic for the menu item.
470 gtk_menu_item_new_with_mnemonic (const gchar *label)
472 return g_object_new (GTK_TYPE_MENU_ITEM,
473 "use-underline", TRUE,
479 gtk_menu_item_dispose (GObject *object)
481 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
482 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
486 gtk_action_disconnect_accelerator (priv->action);
487 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
491 G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
495 gtk_menu_item_set_property (GObject *object,
500 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
504 case PROP_RIGHT_JUSTIFIED:
505 gtk_menu_item_set_right_justified (menu_item, g_value_get_boolean (value));
508 gtk_menu_item_set_submenu (menu_item, g_value_get_object (value));
510 case PROP_ACCEL_PATH:
511 gtk_menu_item_set_accel_path (menu_item, g_value_get_string (value));
514 gtk_menu_item_set_label (menu_item, g_value_get_string (value));
516 case PROP_USE_UNDERLINE:
517 gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
519 case PROP_ACTIVATABLE_RELATED_ACTION:
520 gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
522 case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
523 gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
526 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
532 gtk_menu_item_get_property (GObject *object,
537 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
538 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
542 case PROP_RIGHT_JUSTIFIED:
543 g_value_set_boolean (value, gtk_menu_item_get_right_justified (menu_item));
546 g_value_set_object (value, gtk_menu_item_get_submenu (menu_item));
548 case PROP_ACCEL_PATH:
549 g_value_set_string (value, gtk_menu_item_get_accel_path (menu_item));
552 g_value_set_string (value, gtk_menu_item_get_label (menu_item));
554 case PROP_USE_UNDERLINE:
555 g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
557 case PROP_ACTIVATABLE_RELATED_ACTION:
558 g_value_set_object (value, priv->action);
560 case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
561 g_value_set_boolean (value, priv->use_action_appearance);
564 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
570 gtk_menu_item_destroy (GtkObject *object)
572 GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
574 if (menu_item->submenu)
575 gtk_widget_destroy (menu_item->submenu);
577 GTK_OBJECT_CLASS (gtk_menu_item_parent_class)->destroy (object);
581 gtk_menu_item_detacher (GtkWidget *widget,
584 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
586 g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
588 menu_item->submenu = NULL;
592 get_arrow_size (GtkWidget *widget,
596 PangoContext *context;
597 PangoFontMetrics *metrics;
598 gfloat arrow_scaling;
602 gtk_widget_style_get (widget,
603 "arrow-scaling", &arrow_scaling,
606 context = gtk_widget_get_pango_context (child);
607 metrics = pango_context_get_metrics (context,
608 gtk_widget_get_style (child)->font_desc,
609 pango_context_get_language (context));
611 *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
612 pango_font_metrics_get_descent (metrics)));
614 pango_font_metrics_unref (metrics);
616 *size = *size * arrow_scaling;
621 gtk_menu_item_accel_width_foreach (GtkWidget *widget,
626 if (GTK_IS_ACCEL_LABEL (widget))
630 w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
631 *width = MAX (*width, w);
633 else if (GTK_IS_CONTAINER (widget))
634 gtk_container_foreach (GTK_CONTAINER (widget),
635 gtk_menu_item_accel_width_foreach,
640 get_minimum_width (GtkWidget *widget)
642 PangoContext *context;
643 PangoFontMetrics *metrics;
647 context = gtk_widget_get_pango_context (widget);
648 metrics = pango_context_get_metrics (context,
649 gtk_widget_get_style (widget)->font_desc,
650 pango_context_get_language (context));
652 width = pango_font_metrics_get_approximate_char_width (metrics);
654 pango_font_metrics_unref (metrics);
656 gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
658 return PANGO_PIXELS (width_chars * width);
662 gtk_menu_item_get_preferred_width (GtkWidget *request,
666 GtkMenuItem *menu_item;
668 GtkWidget *child, *widget = GTK_WIDGET (request);
671 guint horizontal_padding;
673 GtkPackDirection pack_dir;
674 GtkPackDirection child_pack_dir;
675 gint min_width, nat_width;
677 min_width = nat_width = 0;
679 gtk_widget_style_get (widget,
680 "horizontal-padding", &horizontal_padding,
683 bin = GTK_BIN (widget);
684 menu_item = GTK_MENU_ITEM (widget);
685 parent = gtk_widget_get_parent (widget);
687 if (GTK_IS_MENU_BAR (parent))
689 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
690 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
694 pack_dir = GTK_PACK_DIRECTION_LTR;
695 child_pack_dir = GTK_PACK_DIRECTION_LTR;
698 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
700 min_width = (border_width + gtk_widget_get_style (widget)->xthickness) * 2;
702 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
703 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
704 min_width += 2 * horizontal_padding;
706 nat_width = min_width;
708 child = gtk_bin_get_child (bin);
710 if (child != NULL && gtk_widget_get_visible (child))
712 gint child_min, child_nat;
714 gtk_widget_get_preferred_width (child, &child_min, &child_nat);
716 if (menu_item->submenu && menu_item->show_submenu_indicator)
721 gtk_widget_style_get (widget,
722 "arrow-spacing", &arrow_spacing,
725 get_arrow_size (widget, child, &arrow_size);
727 min_width += arrow_size;
728 min_width += arrow_spacing;
730 min_width = MAX (min_width, get_minimum_width (widget));
732 nat_width = min_width;
736 min_width += child_min;
737 nat_width += child_nat;
743 gtk_container_foreach (GTK_CONTAINER (menu_item),
744 gtk_menu_item_accel_width_foreach,
746 menu_item->accelerator_width = accel_width;
749 *minimum_size = min_width;
752 *natural_size = nat_width;
756 gtk_menu_item_get_preferred_height (GtkWidget *request,
760 GtkMenuItem *menu_item;
763 GtkWidget *child, *widget = GTK_WIDGET (request);
766 guint horizontal_padding;
768 GtkPackDirection pack_dir;
769 GtkPackDirection child_pack_dir;
770 gint min_height, nat_height;
772 min_height = nat_height = 0;
774 style = gtk_widget_get_style (widget);
776 gtk_widget_style_get (widget,
777 "horizontal-padding", &horizontal_padding,
780 bin = GTK_BIN (widget);
781 menu_item = GTK_MENU_ITEM (widget);
782 parent = gtk_widget_get_parent (widget);
784 if (GTK_IS_MENU_BAR (parent))
786 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
787 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
791 pack_dir = GTK_PACK_DIRECTION_LTR;
792 child_pack_dir = GTK_PACK_DIRECTION_LTR;
795 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
796 min_height = (border_width + style->ythickness) * 2;
798 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
799 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
800 min_height += 2 * horizontal_padding;
802 nat_height = min_height;
804 child = gtk_bin_get_child (bin);
806 if (child != NULL && gtk_widget_get_visible (child))
808 gint child_min, child_nat;
810 gtk_widget_get_preferred_height (child, &child_min, &child_nat);
812 min_height += child_min;
813 nat_height += child_nat;
815 if (menu_item->submenu && menu_item->show_submenu_indicator)
819 get_arrow_size (widget, child, &arrow_size);
821 min_height = MAX (min_height, arrow_size);
822 nat_height = MAX (nat_height, arrow_size);
825 else /* separator item */
827 gboolean wide_separators;
828 gint separator_height;
830 gtk_widget_style_get (widget,
831 "wide-separators", &wide_separators,
832 "separator-height", &separator_height,
836 min_height += separator_height + style->ythickness;
838 min_height += style->ythickness * 2;
840 nat_height = min_height;
844 gtk_container_foreach (GTK_CONTAINER (menu_item),
845 gtk_menu_item_accel_width_foreach,
847 menu_item->accelerator_width = accel_width;
850 *minimum_size = min_height;
853 *natural_size = nat_height;
857 gtk_menu_item_get_preferred_height_for_width (GtkWidget *request,
862 GtkMenuItem *menu_item;
865 GtkWidget *child, *widget = GTK_WIDGET (request);
867 guint horizontal_padding;
869 GtkPackDirection pack_dir;
870 GtkPackDirection child_pack_dir;
871 gint min_height, nat_height;
874 min_height = nat_height = 0;
876 style = gtk_widget_get_style (widget);
878 gtk_widget_style_get (widget,
879 "horizontal-padding", &horizontal_padding,
882 bin = GTK_BIN (widget);
883 menu_item = GTK_MENU_ITEM (widget);
884 parent = gtk_widget_get_parent (widget);
886 if (GTK_IS_MENU_BAR (parent))
888 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
889 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
893 pack_dir = GTK_PACK_DIRECTION_LTR;
894 child_pack_dir = GTK_PACK_DIRECTION_LTR;
897 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
898 min_height = (border_width + style->ythickness) * 2;
900 avail_size = for_size;
901 avail_size -= (border_width + style->xthickness) * 2;
903 if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
904 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
905 min_height += 2 * horizontal_padding;
907 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
908 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
909 avail_size -= 2 * horizontal_padding;
911 nat_height = min_height;
913 child = gtk_bin_get_child (bin);
915 if (child != NULL && gtk_widget_get_visible (child))
917 gint child_min, child_nat;
920 if (menu_item->submenu && menu_item->show_submenu_indicator)
925 gtk_widget_style_get (widget,
926 "arrow-spacing", &arrow_spacing,
929 get_arrow_size (widget, child, &arrow_size);
931 avail_size -= arrow_size;
932 avail_size -= arrow_spacing;
935 gtk_widget_get_preferred_height_for_width (child,
940 min_height += child_min;
941 nat_height += child_nat;
943 if (menu_item->submenu && menu_item->show_submenu_indicator)
945 min_height = MAX (min_height, arrow_size);
946 nat_height = MAX (nat_height, arrow_size);
949 else /* separator item */
951 gboolean wide_separators;
952 gint separator_height;
954 gtk_widget_style_get (widget,
955 "wide-separators", &wide_separators,
956 "separator-height", &separator_height,
960 min_height += separator_height + style->ythickness;
962 min_height += style->ythickness * 2;
964 nat_height = min_height;
968 *minimum_size = min_height;
971 *natural_size = nat_height;
975 gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
977 parent_buildable_iface = g_type_interface_peek_parent (iface);
978 iface->add_child = gtk_menu_item_buildable_add_child;
979 iface->custom_finished = gtk_menu_item_buildable_custom_finished;
983 gtk_menu_item_buildable_add_child (GtkBuildable *buildable,
988 if (type && strcmp (type, "submenu") == 0)
989 gtk_menu_item_set_submenu (GTK_MENU_ITEM (buildable),
992 parent_buildable_iface->add_child (buildable, builder, child, type);
997 gtk_menu_item_buildable_custom_finished (GtkBuildable *buildable,
1000 const gchar *tagname,
1003 GtkWidget *toplevel;
1005 if (strcmp (tagname, "accelerator") == 0)
1007 GtkMenuShell *menu_shell;
1010 menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (buildable)));
1013 while (GTK_IS_MENU (menu_shell) &&
1014 (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL)
1015 menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (attach));
1017 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell));
1021 /* Fall back to something ... */
1022 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (buildable));
1024 g_warning ("found a GtkMenuItem '%s' without a parent GtkMenuShell, assigned accelerators wont work.",
1025 gtk_buildable_get_name (buildable));
1028 /* Feed the correct toplevel to the GtkWidget accelerator parsing code */
1029 _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
1032 parent_buildable_iface->custom_finished (buildable, builder, child, tagname, user_data);
1037 gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
1039 iface->update = gtk_menu_item_update;
1040 iface->sync_action_properties = gtk_menu_item_sync_action_properties;
1044 activatable_update_label (GtkMenuItem *menu_item, GtkAction *action)
1048 child = gtk_bin_get_child (GTK_BIN (menu_item));
1050 if (GTK_IS_LABEL (child))
1054 label = gtk_action_get_label (action);
1055 gtk_menu_item_set_label (menu_item, label);
1059 gboolean _gtk_menu_is_empty (GtkWidget *menu);
1062 gtk_menu_item_update (GtkActivatable *activatable,
1064 const gchar *property_name)
1066 GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
1067 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1069 if (strcmp (property_name, "visible") == 0)
1070 _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
1071 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
1072 else if (strcmp (property_name, "sensitive") == 0)
1073 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
1074 else if (priv->use_action_appearance)
1076 if (strcmp (property_name, "label") == 0)
1077 activatable_update_label (menu_item, action);
1082 gtk_menu_item_sync_action_properties (GtkActivatable *activatable,
1085 GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
1086 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1089 if (!priv->use_action_appearance || !action)
1091 label = gtk_bin_get_child (GTK_BIN (menu_item));
1093 if (GTK_IS_ACCEL_LABEL (label))
1094 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), GTK_WIDGET (menu_item));
1100 _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item),
1101 _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
1103 gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
1105 if (priv->use_action_appearance)
1107 label = gtk_bin_get_child (GTK_BIN (menu_item));
1109 /* make sure label is a label */
1110 if (label && !GTK_IS_LABEL (label))
1112 gtk_container_remove (GTK_CONTAINER (menu_item), label);
1116 gtk_menu_item_ensure_label (menu_item);
1117 gtk_menu_item_set_use_underline (menu_item, TRUE);
1119 if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
1121 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), NULL);
1122 gtk_accel_label_set_accel_closure (GTK_ACCEL_LABEL (label),
1123 gtk_action_get_accel_closure (action));
1126 activatable_update_label (menu_item, action);
1131 gtk_menu_item_set_related_action (GtkMenuItem *menu_item,
1134 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1136 if (priv->action == action)
1141 gtk_action_disconnect_accelerator (priv->action);
1146 const gchar *accel_path;
1148 accel_path = gtk_action_get_accel_path (action);
1151 gtk_action_connect_accelerator (action);
1152 gtk_menu_item_set_accel_path (menu_item, accel_path);
1156 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
1158 priv->action = action;
1162 gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item,
1163 gboolean use_appearance)
1165 GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
1167 if (priv->use_action_appearance != use_appearance)
1169 priv->use_action_appearance = use_appearance;
1171 gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (menu_item), priv->action);
1177 * gtk_menu_item_set_submenu:
1178 * @menu_item: a #GtkMenuItem
1179 * @submenu: (allow-none): the submenu, or %NULL
1181 * Sets or replaces the menu item's submenu, or removes it when a %NULL
1182 * submenu is passed.
1185 gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
1188 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1189 g_return_if_fail (submenu == NULL || GTK_IS_MENU (submenu));
1191 if (menu_item->submenu != submenu)
1193 if (menu_item->submenu)
1194 gtk_menu_detach (GTK_MENU (menu_item->submenu));
1198 menu_item->submenu = submenu;
1199 gtk_menu_attach_to_widget (GTK_MENU (submenu),
1200 GTK_WIDGET (menu_item),
1201 gtk_menu_item_detacher);
1204 if (gtk_widget_get_parent (GTK_WIDGET (menu_item)))
1205 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
1207 g_object_notify (G_OBJECT (menu_item), "submenu");
1212 * gtk_menu_item_get_submenu:
1213 * @menu_item: a #GtkMenuItem
1215 * Gets the submenu underneath this menu item, if any.
1216 * See gtk_menu_item_set_submenu().
1218 * Return value: (transfer none): submenu for this menu item, or %NULL if none.
1221 gtk_menu_item_get_submenu (GtkMenuItem *menu_item)
1223 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
1225 return menu_item->submenu;
1228 void _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
1229 GtkSubmenuPlacement placement);
1232 _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
1233 GtkSubmenuPlacement placement)
1235 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1237 menu_item->submenu_placement = placement;
1241 gtk_menu_item_select (GtkMenuItem *menu_item)
1245 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1247 g_signal_emit (menu_item, menu_item_signals[SELECT], 0);
1249 /* Enable themeing of the parent menu item depending on whether
1250 * something is selected in its submenu
1252 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1253 if (GTK_IS_MENU (parent))
1255 GtkMenu *menu = GTK_MENU (parent);
1257 if (menu->parent_menu_item)
1258 gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
1263 gtk_menu_item_deselect (GtkMenuItem *menu_item)
1267 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1269 g_signal_emit (menu_item, menu_item_signals[DESELECT], 0);
1271 /* Enable themeing of the parent menu item depending on whether
1272 * something is selected in its submenu
1274 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1275 if (GTK_IS_MENU (parent))
1277 GtkMenu *menu = GTK_MENU (parent);
1279 if (menu->parent_menu_item)
1280 gtk_widget_queue_draw (GTK_WIDGET (menu->parent_menu_item));
1285 gtk_menu_item_activate (GtkMenuItem *menu_item)
1287 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1289 g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
1293 gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1296 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1298 g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_REQUEST], 0, requisition);
1302 gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1305 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1307 g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
1311 gtk_menu_item_size_allocate (GtkWidget *widget,
1312 GtkAllocation *allocation)
1314 GtkMenuItem *menu_item;
1316 GtkAllocation child_allocation;
1317 GtkTextDirection direction;
1318 GtkPackDirection pack_dir;
1319 GtkPackDirection child_pack_dir;
1323 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
1324 g_return_if_fail (allocation != NULL);
1326 menu_item = GTK_MENU_ITEM (widget);
1327 bin = GTK_BIN (widget);
1329 direction = gtk_widget_get_direction (widget);
1331 parent = gtk_widget_get_parent (widget);
1332 if (GTK_IS_MENU_BAR (parent))
1334 pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (parent));
1335 child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent));
1339 pack_dir = GTK_PACK_DIRECTION_LTR;
1340 child_pack_dir = GTK_PACK_DIRECTION_LTR;
1343 gtk_widget_set_allocation (widget, allocation);
1345 child = gtk_bin_get_child (bin);
1348 GtkRequisition child_requisition;
1350 guint horizontal_padding;
1353 style = gtk_widget_get_style (widget);
1354 gtk_widget_style_get (widget,
1355 "horizontal-padding", &horizontal_padding,
1358 border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1359 child_allocation.x = border_width + style->xthickness;
1360 child_allocation.y = border_width + style->ythickness;
1362 if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
1363 (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
1364 child_allocation.x += horizontal_padding;
1365 else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
1366 (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
1367 child_allocation.y += horizontal_padding;
1369 child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
1370 child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
1372 if (child_pack_dir == GTK_PACK_DIRECTION_LTR ||
1373 child_pack_dir == GTK_PACK_DIRECTION_RTL)
1375 if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL))
1376 child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
1377 child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size;
1381 if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT))
1382 child_allocation.y += GTK_MENU_ITEM (widget)->toggle_size;
1383 child_allocation.height -= GTK_MENU_ITEM (widget)->toggle_size;
1386 child_allocation.x += allocation->x;
1387 child_allocation.y += allocation->y;
1389 gtk_widget_get_preferred_size (child, &child_requisition, NULL);
1390 if (menu_item->submenu && menu_item->show_submenu_indicator)
1392 if (direction == GTK_TEXT_DIR_RTL)
1393 child_allocation.x += child_requisition.height;
1394 child_allocation.width -= child_requisition.height;
1397 if (child_allocation.width < 1)
1398 child_allocation.width = 1;
1400 gtk_widget_size_allocate (child, &child_allocation);
1403 if (gtk_widget_get_realized (widget))
1404 gdk_window_move_resize (menu_item->event_window,
1405 allocation->x, allocation->y,
1406 allocation->width, allocation->height);
1408 if (menu_item->submenu)
1409 gtk_menu_reposition (GTK_MENU (menu_item->submenu));
1413 gtk_menu_item_realize (GtkWidget *widget)
1415 GtkAllocation allocation;
1416 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1418 GdkWindowAttr attributes;
1419 gint attributes_mask;
1421 gtk_widget_set_realized (widget, TRUE);
1423 window = gtk_widget_get_parent_window (widget);
1424 gtk_widget_set_window (widget, window);
1425 g_object_ref (window);
1427 gtk_widget_get_allocation (widget, &allocation);
1429 attributes.x = allocation.x;
1430 attributes.y = allocation.y;
1431 attributes.width = allocation.width;
1432 attributes.height = allocation.height;
1433 attributes.window_type = GDK_WINDOW_CHILD;
1434 attributes.wclass = GDK_INPUT_ONLY;
1435 attributes.event_mask = (gtk_widget_get_events (widget) |
1436 GDK_BUTTON_PRESS_MASK |
1437 GDK_BUTTON_RELEASE_MASK |
1438 GDK_ENTER_NOTIFY_MASK |
1439 GDK_LEAVE_NOTIFY_MASK |
1440 GDK_POINTER_MOTION_MASK);
1442 attributes_mask = GDK_WA_X | GDK_WA_Y;
1444 menu_item->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1445 &attributes, attributes_mask);
1446 gdk_window_set_user_data (menu_item->event_window, widget);
1448 gtk_widget_style_attach (widget);
1452 gtk_menu_item_unrealize (GtkWidget *widget)
1454 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1456 gdk_window_set_user_data (menu_item->event_window, NULL);
1457 gdk_window_destroy (menu_item->event_window);
1458 menu_item->event_window = NULL;
1460 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unrealize (widget);
1464 gtk_menu_item_map (GtkWidget *widget)
1466 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1468 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->map (widget);
1470 gdk_window_show (menu_item->event_window);
1474 gtk_menu_item_unmap (GtkWidget *widget)
1476 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1478 gdk_window_hide (menu_item->event_window);
1480 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->unmap (widget);
1484 gtk_menu_item_enter (GtkWidget *widget,
1485 GdkEventCrossing *event)
1487 g_return_val_if_fail (event != NULL, FALSE);
1489 return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event);
1493 gtk_menu_item_leave (GtkWidget *widget,
1494 GdkEventCrossing *event)
1496 g_return_val_if_fail (event != NULL, FALSE);
1498 return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent*) event);
1502 gtk_menu_item_draw (GtkWidget *widget,
1505 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1506 GtkStateType state_type;
1507 GtkShadowType shadow_type, selected_shadow_type;
1511 gint x, y, w, h, width, height;
1512 guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
1514 state_type = gtk_widget_get_state (widget);
1515 style = gtk_widget_get_style (widget);
1516 window = gtk_widget_get_window (widget);
1517 width = gtk_widget_get_allocated_width (widget);
1518 height = gtk_widget_get_allocated_height (widget);
1522 w = width - border_width * 2;
1523 h = height - border_width * 2;
1525 child = gtk_bin_get_child (GTK_BIN (menu_item));
1527 if (child && state_type == GTK_STATE_PRELIGHT)
1529 gtk_widget_style_get (widget,
1530 "selected-shadow-type", &selected_shadow_type,
1532 gtk_paint_box (style,
1535 selected_shadow_type,
1540 if (menu_item->submenu && menu_item->show_submenu_indicator)
1542 gint arrow_x, arrow_y;
1544 guint horizontal_padding;
1545 GtkTextDirection direction;
1546 GtkArrowType arrow_type;
1548 direction = gtk_widget_get_direction (widget);
1550 gtk_widget_style_get (widget,
1551 "horizontal-padding", &horizontal_padding,
1554 get_arrow_size (widget, child, &arrow_size);
1556 shadow_type = GTK_SHADOW_OUT;
1557 if (state_type == GTK_STATE_PRELIGHT)
1558 shadow_type = GTK_SHADOW_IN;
1560 if (direction == GTK_TEXT_DIR_LTR)
1562 arrow_x = x + w - horizontal_padding - arrow_size;
1563 arrow_type = GTK_ARROW_RIGHT;
1567 arrow_x = x + horizontal_padding;
1568 arrow_type = GTK_ARROW_LEFT;
1571 arrow_y = y + (h - arrow_size) / 2;
1573 gtk_paint_arrow (style, cr,
1574 state_type, shadow_type,
1578 arrow_size, arrow_size);
1582 gboolean wide_separators;
1583 gint separator_height;
1584 guint horizontal_padding;
1586 gtk_widget_style_get (widget,
1587 "wide-separators", &wide_separators,
1588 "separator-height", &separator_height,
1589 "horizontal-padding", &horizontal_padding,
1592 if (wide_separators)
1593 gtk_paint_box (style, cr,
1594 GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
1595 widget, "hseparator",
1596 horizontal_padding + style->xthickness,
1597 (height - separator_height - style->ythickness) / 2,
1598 width - 2 * (horizontal_padding + style->xthickness),
1601 gtk_paint_hline (style, cr,
1602 GTK_STATE_NORMAL, widget, "menuitem",
1603 horizontal_padding + style->xthickness,
1604 width - horizontal_padding - style->xthickness - 1,
1605 (height - style->ythickness) / 2);
1608 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->draw (widget, cr);
1614 gtk_real_menu_item_select (GtkMenuItem *menu_item)
1616 gboolean touchscreen_mode;
1618 g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_item)),
1619 "gtk-touchscreen-mode", &touchscreen_mode,
1622 if (!touchscreen_mode &&
1623 menu_item->submenu &&
1624 (!gtk_widget_get_mapped (menu_item->submenu) ||
1625 GTK_MENU (menu_item->submenu)->tearoff_active))
1627 _gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1630 gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
1631 gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1635 gtk_real_menu_item_deselect (GtkMenuItem *menu_item)
1637 if (menu_item->submenu)
1638 _gtk_menu_item_popdown_submenu (GTK_WIDGET (menu_item));
1640 gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
1641 gtk_widget_queue_draw (GTK_WIDGET (menu_item));
1645 gtk_menu_item_mnemonic_activate (GtkWidget *widget,
1646 gboolean group_cycling)
1650 parent = gtk_widget_get_parent (widget);
1652 if (GTK_IS_MENU_SHELL (parent))
1653 _gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (parent), TRUE);
1655 if (group_cycling &&
1657 GTK_IS_MENU_SHELL (parent) &&
1658 GTK_MENU_SHELL (parent)->active)
1660 gtk_menu_shell_select_item (GTK_MENU_SHELL (parent),
1664 g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0);
1670 gtk_real_menu_item_activate (GtkMenuItem *menu_item)
1672 GtkMenuItemPrivate *priv;
1674 priv = GET_PRIVATE (menu_item);
1677 gtk_action_activate (priv->action);
1682 gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
1684 GtkMenuItemPrivate *priv;
1688 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1690 priv = GET_PRIVATE (menu_item);
1691 widget = GTK_WIDGET (menu_item);
1692 parent = gtk_widget_get_parent (widget);
1694 if (parent && GTK_IS_MENU_SHELL (parent))
1696 GtkMenuShell *menu_shell = GTK_MENU_SHELL (parent);
1698 if (menu_item->submenu == NULL)
1699 gtk_menu_shell_activate_item (menu_shell,
1703 _gtk_menu_shell_activate (menu_shell);
1705 gtk_menu_shell_select_item (menu_shell, widget);
1706 _gtk_menu_item_popup_submenu (widget, FALSE);
1708 gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
1714 gtk_real_menu_item_toggle_size_request (GtkMenuItem *menu_item,
1717 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1723 gtk_real_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
1726 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1728 menu_item->toggle_size = allocation;
1732 gtk_real_menu_item_set_label (GtkMenuItem *menu_item,
1737 gtk_menu_item_ensure_label (menu_item);
1739 child = gtk_bin_get_child (GTK_BIN (menu_item));
1740 if (GTK_IS_LABEL (child))
1742 gtk_label_set_label (GTK_LABEL (child), label ? label : "");
1744 g_object_notify (G_OBJECT (menu_item), "label");
1748 static G_CONST_RETURN gchar *
1749 gtk_real_menu_item_get_label (GtkMenuItem *menu_item)
1753 gtk_menu_item_ensure_label (menu_item);
1755 child = gtk_bin_get_child (GTK_BIN (menu_item));
1756 if (GTK_IS_LABEL (child))
1757 return gtk_label_get_label (GTK_LABEL (child));
1763 free_timeval (GTimeVal *val)
1765 g_slice_free (GTimeVal, val);
1769 gtk_menu_item_real_popup_submenu (GtkWidget *widget,
1770 gboolean remember_exact_time)
1772 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1775 parent = gtk_widget_get_parent (widget);
1777 if (gtk_widget_is_sensitive (menu_item->submenu) && parent)
1779 gboolean take_focus;
1780 GtkMenuPositionFunc menu_position_func;
1782 take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent));
1783 gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (menu_item->submenu),
1786 if (remember_exact_time)
1788 GTimeVal *popup_time = g_slice_new0 (GTimeVal);
1790 g_get_current_time (popup_time);
1792 g_object_set_data_full (G_OBJECT (menu_item->submenu),
1793 "gtk-menu-exact-popup-time", popup_time,
1794 (GDestroyNotify) free_timeval);
1798 g_object_set_data (G_OBJECT (menu_item->submenu),
1799 "gtk-menu-exact-popup-time", NULL);
1802 /* gtk_menu_item_position_menu positions the submenu from the
1803 * menuitems position. If the menuitem doesn't have a window,
1804 * that doesn't work. In that case we use the default
1805 * positioning function instead which places the submenu at the
1808 if (gtk_widget_get_window (widget))
1809 menu_position_func = gtk_menu_item_position_menu;
1811 menu_position_func = NULL;
1813 gtk_menu_popup (GTK_MENU (menu_item->submenu),
1818 GTK_MENU_SHELL (parent)->button,
1822 /* Enable themeing of the parent menu item depending on whether
1823 * its submenu is shown or not.
1825 gtk_widget_queue_draw (widget);
1829 gtk_menu_item_popup_timeout (gpointer data)
1831 GtkMenuItem *menu_item;
1834 menu_item = GTK_MENU_ITEM (data);
1836 parent = gtk_widget_get_parent (GTK_WIDGET (menu_item));
1838 if ((GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active) ||
1839 (GTK_IS_MENU (parent) && GTK_MENU (parent)->torn_off))
1841 gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), TRUE);
1842 if (menu_item->timer_from_keypress && menu_item->submenu)
1843 GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
1846 menu_item->timer = 0;
1852 get_popup_delay (GtkWidget *widget)
1856 parent = gtk_widget_get_parent (widget);
1857 if (GTK_IS_MENU_SHELL (parent))
1859 return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (parent));
1865 g_object_get (gtk_widget_get_settings (widget),
1866 "gtk-menu-popup-delay", &popup_delay,
1874 _gtk_menu_item_popup_submenu (GtkWidget *widget,
1875 gboolean with_delay)
1877 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
1879 if (menu_item->timer)
1881 g_source_remove (menu_item->timer);
1882 menu_item->timer = 0;
1888 gint popup_delay = get_popup_delay (widget);
1890 if (popup_delay > 0)
1892 GdkEvent *event = gtk_get_current_event ();
1894 menu_item->timer = gdk_threads_add_timeout (popup_delay,
1895 gtk_menu_item_popup_timeout,
1899 event->type != GDK_BUTTON_PRESS &&
1900 event->type != GDK_ENTER_NOTIFY)
1901 menu_item->timer_from_keypress = TRUE;
1903 menu_item->timer_from_keypress = FALSE;
1906 gdk_event_free (event);
1912 gtk_menu_item_real_popup_submenu (widget, FALSE);
1916 _gtk_menu_item_popdown_submenu (GtkWidget *widget)
1918 GtkMenuItem *menu_item;
1920 menu_item = GTK_MENU_ITEM (widget);
1922 if (menu_item->submenu)
1924 g_object_set_data (G_OBJECT (menu_item->submenu),
1925 "gtk-menu-exact-popup-time", NULL);
1927 if (menu_item->timer)
1929 g_source_remove (menu_item->timer);
1930 menu_item->timer = 0;
1933 gtk_menu_popdown (GTK_MENU (menu_item->submenu));
1935 gtk_widget_queue_draw (widget);
1940 get_offsets (GtkMenu *menu,
1941 gint *horizontal_offset,
1942 gint *vertical_offset)
1944 gint vertical_padding;
1945 gint horizontal_padding;
1947 gtk_widget_style_get (GTK_WIDGET (menu),
1948 "horizontal-offset", horizontal_offset,
1949 "vertical-offset", vertical_offset,
1950 "horizontal-padding", &horizontal_padding,
1951 "vertical-padding", &vertical_padding,
1954 *vertical_offset -= gtk_widget_get_style (GTK_WIDGET (menu))->ythickness;
1955 *vertical_offset -= vertical_padding;
1956 *horizontal_offset += horizontal_padding;
1960 gtk_menu_item_position_menu (GtkMenu *menu,
1966 GtkAllocation allocation;
1967 GtkMenuItem *menu_item;
1969 GtkMenuItem *parent_menu_item;
1970 GtkRequisition requisition;
1973 gint twidth, theight;
1975 GtkTextDirection direction;
1976 GdkRectangle monitor;
1978 gint horizontal_offset;
1979 gint vertical_offset;
1980 gint parent_xthickness;
1981 gint available_left, available_right;
1983 g_return_if_fail (menu != NULL);
1984 g_return_if_fail (x != NULL);
1985 g_return_if_fail (y != NULL);
1987 menu_item = GTK_MENU_ITEM (user_data);
1988 widget = GTK_WIDGET (user_data);
1993 direction = gtk_widget_get_direction (widget);
1995 gtk_widget_get_preferred_size (GTK_WIDGET (menu), &requisition, NULL);
1996 twidth = requisition.width;
1997 theight = requisition.height;
1999 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
2000 monitor_num = gdk_screen_get_monitor_at_window (screen, menu_item->event_window);
2001 if (monitor_num < 0)
2003 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
2005 if (!gdk_window_get_origin (gtk_widget_get_window (widget),
2008 g_warning ("Menu not on screen");
2012 gtk_widget_get_allocation (widget, &allocation);
2017 get_offsets (menu, &horizontal_offset, &vertical_offset);
2019 available_left = tx - monitor.x;
2020 available_right = monitor.x + monitor.width - (tx + allocation.width);
2022 parent = gtk_widget_get_parent (widget);
2023 if (GTK_IS_MENU_BAR (parent))
2025 menu_item->from_menubar = TRUE;
2027 else if (GTK_IS_MENU (parent))
2029 if (GTK_MENU (parent)->parent_menu_item)
2030 menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (parent)->parent_menu_item)->from_menubar;
2032 menu_item->from_menubar = FALSE;
2036 menu_item->from_menubar = FALSE;
2039 switch (menu_item->submenu_placement)
2041 case GTK_TOP_BOTTOM:
2042 if (direction == GTK_TEXT_DIR_LTR)
2043 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
2046 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
2047 tx += allocation.width - twidth;
2049 if ((ty + allocation.height + theight) <= monitor.y + monitor.height)
2050 ty += allocation.height;
2051 else if ((ty - theight) >= monitor.y)
2053 else if (monitor.y + monitor.height - (ty + allocation.height) > ty)
2054 ty += allocation.height;
2059 case GTK_LEFT_RIGHT:
2060 if (GTK_IS_MENU (parent))
2061 parent_menu_item = GTK_MENU_ITEM (GTK_MENU (parent)->parent_menu_item);
2063 parent_menu_item = NULL;
2065 parent_xthickness = gtk_widget_get_style (parent)->xthickness;
2067 if (parent_menu_item && !GTK_MENU (parent)->torn_off)
2069 menu_item->submenu_direction = parent_menu_item->submenu_direction;
2073 if (direction == GTK_TEXT_DIR_LTR)
2074 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
2076 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
2079 switch (menu_item->submenu_direction)
2081 case GTK_DIRECTION_LEFT:
2082 if (tx - twidth - parent_xthickness - horizontal_offset >= monitor.x ||
2083 available_left >= available_right)
2084 tx -= twidth + parent_xthickness + horizontal_offset;
2087 menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
2088 tx += allocation.width + parent_xthickness + horizontal_offset;
2092 case GTK_DIRECTION_RIGHT:
2093 if (tx + allocation.width + parent_xthickness + horizontal_offset + twidth <= monitor.x + monitor.width ||
2094 available_right >= available_left)
2095 tx += allocation.width + parent_xthickness + horizontal_offset;
2098 menu_item->submenu_direction = GTK_DIRECTION_LEFT;
2099 tx -= twidth + parent_xthickness + horizontal_offset;
2104 ty += vertical_offset;
2106 /* If the height of the menu doesn't fit we move it upward. */
2107 ty = CLAMP (ty, monitor.y, MAX (monitor.y, monitor.y + monitor.height - theight));
2111 /* If we have negative, tx, here it is because we can't get
2112 * the menu all the way on screen. Favor the left portion.
2114 *x = CLAMP (tx, monitor.x, MAX (monitor.x, monitor.x + monitor.width - twidth));
2117 gtk_menu_set_monitor (menu, monitor_num);
2119 if (!gtk_widget_get_visible (menu->toplevel))
2121 gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar?
2122 GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU);
2127 * gtk_menu_item_set_right_justified:
2128 * @menu_item: a #GtkMenuItem.
2129 * @right_justified: if %TRUE the menu item will appear at the
2130 * far right if added to a menu bar.
2132 * Sets whether the menu item appears justified at the right
2133 * side of a menu bar. This was traditionally done for "Help" menu
2134 * items, but is now considered a bad idea. (If the widget
2135 * layout is reversed for a right-to-left language like Hebrew
2136 * or Arabic, right-justified-menu-items appear at the left.)
2139 gtk_menu_item_set_right_justified (GtkMenuItem *menu_item,
2140 gboolean right_justified)
2142 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2144 right_justified = right_justified != FALSE;
2146 if (right_justified != menu_item->right_justify)
2148 menu_item->right_justify = right_justified;
2149 gtk_widget_queue_resize (GTK_WIDGET (menu_item));
2154 * gtk_menu_item_get_right_justified:
2155 * @menu_item: a #GtkMenuItem
2157 * Gets whether the menu item appears justified at the right
2158 * side of the menu bar.
2160 * Return value: %TRUE if the menu item will appear at the
2161 * far right if added to a menu bar.
2164 gtk_menu_item_get_right_justified (GtkMenuItem *menu_item)
2166 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2168 return menu_item->right_justify;
2173 gtk_menu_item_show_all (GtkWidget *widget)
2175 GtkMenuItem *menu_item;
2177 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
2179 menu_item = GTK_MENU_ITEM (widget);
2181 /* show children including submenu */
2182 if (menu_item->submenu)
2183 gtk_widget_show_all (menu_item->submenu);
2184 gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_show_all, NULL);
2186 gtk_widget_show (widget);
2190 gtk_menu_item_hide_all (GtkWidget *widget)
2192 GtkMenuItem *menu_item;
2194 g_return_if_fail (GTK_IS_MENU_ITEM (widget));
2196 gtk_widget_hide (widget);
2198 menu_item = GTK_MENU_ITEM (widget);
2200 /* hide children including submenu */
2201 gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_hide_all, NULL);
2202 if (menu_item->submenu)
2203 gtk_widget_hide_all (menu_item->submenu);
2207 gtk_menu_item_can_activate_accel (GtkWidget *widget,
2212 parent = gtk_widget_get_parent (widget);
2213 /* Chain to the parent GtkMenu for further checks */
2214 return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) &&
2215 parent && gtk_widget_can_activate_accel (parent, signal_id));
2219 gtk_menu_item_accel_name_foreach (GtkWidget *widget,
2222 const gchar **path_p = data;
2226 if (GTK_IS_LABEL (widget))
2228 *path_p = gtk_label_get_text (GTK_LABEL (widget));
2229 if (*path_p && (*path_p)[0] == 0)
2232 else if (GTK_IS_CONTAINER (widget))
2233 gtk_container_foreach (GTK_CONTAINER (widget),
2234 gtk_menu_item_accel_name_foreach,
2240 gtk_menu_item_parent_set (GtkWidget *widget,
2241 GtkWidget *previous_parent)
2243 GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
2247 parent = gtk_widget_get_parent (widget);
2248 menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL;
2251 _gtk_menu_item_refresh_accel_path (menu_item,
2256 if (GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set)
2257 GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent);
2261 _gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item,
2262 const gchar *prefix,
2263 GtkAccelGroup *accel_group,
2264 gboolean group_changed)
2269 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2270 g_return_if_fail (!accel_group || GTK_IS_ACCEL_GROUP (accel_group));
2272 widget = GTK_WIDGET (menu_item);
2276 gtk_widget_set_accel_path (widget, NULL, NULL);
2280 path = _gtk_widget_get_accel_path (widget, NULL);
2281 if (!path) /* no active accel_path yet */
2283 path = menu_item->accel_path;
2284 if (!path && prefix)
2286 const gchar *postfix = NULL;
2289 /* try to construct one from label text */
2290 gtk_container_foreach (GTK_CONTAINER (menu_item),
2291 gtk_menu_item_accel_name_foreach,
2295 new_path = g_strconcat (prefix, "/", postfix, NULL);
2296 path = menu_item->accel_path = (char*)g_intern_string (new_path);
2301 gtk_widget_set_accel_path (widget, path, accel_group);
2303 else if (group_changed) /* reinstall accelerators */
2304 gtk_widget_set_accel_path (widget, path, accel_group);
2308 * gtk_menu_item_set_accel_path
2309 * @menu_item: a valid #GtkMenuItem
2310 * @accel_path: (allow-none): accelerator path, corresponding to this menu item's
2311 * functionality, or %NULL to unset the current path.
2313 * Set the accelerator path on @menu_item, through which runtime changes of the
2314 * menu item's accelerator caused by the user can be identified and saved to
2315 * persistant storage (see gtk_accel_map_save() on this).
2316 * To setup a default accelerator for this menu item, call
2317 * gtk_accel_map_add_entry() with the same @accel_path.
2318 * See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
2319 * and gtk_menu_set_accel_path() for a more convenient variant of this function.
2321 * This function is basically a convenience wrapper that handles calling
2322 * gtk_widget_set_accel_path() with the appropriate accelerator group for
2325 * Note that you do need to set an accelerator on the parent menu with
2326 * gtk_menu_set_accel_group() for this to work.
2328 * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
2329 * pass a static string, you can save some memory by interning it first with
2330 * g_intern_static_string().
2333 gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
2334 const gchar *accel_path)
2339 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2340 g_return_if_fail (accel_path == NULL ||
2341 (accel_path[0] == '<' && strchr (accel_path, '/')));
2343 widget = GTK_WIDGET (menu_item);
2345 /* store new path */
2346 menu_item->accel_path = (char*)g_intern_string (accel_path);
2348 /* forget accelerators associated with old path */
2349 gtk_widget_set_accel_path (widget, NULL, NULL);
2351 /* install accelerators associated with new path */
2352 parent = gtk_widget_get_parent (widget);
2353 if (GTK_IS_MENU (parent))
2355 GtkMenu *menu = GTK_MENU (parent);
2357 if (menu->accel_group)
2358 _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
2366 * gtk_menu_item_get_accel_path
2367 * @menu_item: a valid #GtkMenuItem
2369 * Retrieve the accelerator path that was previously set on @menu_item.
2371 * See gtk_menu_item_set_accel_path() for details.
2373 * Returns: the accelerator path corresponding to this menu item's
2374 * functionality, or %NULL if not set
2378 G_CONST_RETURN gchar *
2379 gtk_menu_item_get_accel_path (GtkMenuItem *menu_item)
2381 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2383 return menu_item->accel_path;
2387 gtk_menu_item_forall (GtkContainer *container,
2388 gboolean include_internals,
2389 GtkCallback callback,
2390 gpointer callback_data)
2394 g_return_if_fail (GTK_IS_MENU_ITEM (container));
2395 g_return_if_fail (callback != NULL);
2397 child = gtk_bin_get_child (GTK_BIN (container));
2399 callback (child, callback_data);
2403 _gtk_menu_item_is_selectable (GtkWidget *menu_item)
2405 if ((!gtk_bin_get_child (GTK_BIN (menu_item)) &&
2406 G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
2407 GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
2408 !gtk_widget_is_sensitive (menu_item) ||
2409 !gtk_widget_get_visible (menu_item))
2416 gtk_menu_item_ensure_label (GtkMenuItem *menu_item)
2418 GtkWidget *accel_label;
2420 if (!gtk_bin_get_child (GTK_BIN (menu_item)))
2422 accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
2423 gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
2425 gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
2426 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label),
2427 GTK_WIDGET (menu_item));
2428 gtk_widget_show (accel_label);
2433 * gtk_menu_item_set_label:
2434 * @menu_item: a #GtkMenuItem
2435 * @label: the text you want to set
2437 * Sets @text on the @menu_item label
2442 gtk_menu_item_set_label (GtkMenuItem *menu_item,
2445 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2447 GTK_MENU_ITEM_GET_CLASS (menu_item)->set_label (menu_item, label);
2451 * gtk_menu_item_get_label:
2452 * @menu_item: a #GtkMenuItem
2454 * Sets @text on the @menu_item label
2456 * Returns: The text in the @menu_item label. This is the internal
2457 * string used by the label, and must not be modified.
2461 G_CONST_RETURN gchar *
2462 gtk_menu_item_get_label (GtkMenuItem *menu_item)
2464 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), NULL);
2466 return GTK_MENU_ITEM_GET_CLASS (menu_item)->get_label (menu_item);
2470 * gtk_menu_item_set_use_underline:
2471 * @menu_item: a #GtkMenuItem
2472 * @setting: %TRUE if underlines in the text indicate mnemonics
2474 * If true, an underline in the text indicates the next character should be
2475 * used for the mnemonic accelerator key.
2480 gtk_menu_item_set_use_underline (GtkMenuItem *menu_item,
2485 g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
2487 gtk_menu_item_ensure_label (menu_item);
2489 child = gtk_bin_get_child (GTK_BIN (menu_item));
2490 if (GTK_IS_LABEL (child))
2492 gtk_label_set_use_underline (GTK_LABEL (child), setting);
2494 g_object_notify (G_OBJECT (menu_item), "use-underline");
2499 * gtk_menu_item_get_use_underline:
2500 * @menu_item: a #GtkMenuItem
2502 * Checks if an underline in the text indicates the next character should be
2503 * used for the mnemonic accelerator key.
2505 * Return value: %TRUE if an embedded underline in the label indicates
2506 * the mnemonic accelerator key.
2511 gtk_menu_item_get_use_underline (GtkMenuItem *menu_item)
2515 g_return_val_if_fail (GTK_IS_MENU_ITEM (menu_item), FALSE);
2517 gtk_menu_item_ensure_label (menu_item);
2519 child = gtk_bin_get_child (GTK_BIN (menu_item));
2520 if (GTK_IS_LABEL (child))
2521 return gtk_label_get_use_underline (GTK_LABEL (child));