]> Pileus Git - ~andy/gtk/blob - gtk/gtkmenushell.c
Update about dialog design to not use a swarm of dialogs
[~andy/gtk] / gtk / gtkmenushell.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 #include "config.h"
28 #include "gdk/gdkkeysyms.h"
29 #include "gtkbindings.h"
30 #include "gtkkeyhash.h"
31 #include "gtklabel.h"
32 #include "gtkmain.h"
33 #include "gtkmarshalers.h"
34 #include "gtkmenu.h"
35 #include "gtkmenubar.h"
36 #include "gtkmenuitem.h"
37 #include "gtkmenushell.h"
38 #include "gtkmenuprivate.h"
39 #include "gtkmnemonichash.h"
40 #include "gtktearoffmenuitem.h"
41 #include "gtkwindow.h"
42 #include "gtkprivate.h"
43 #include "gtkintl.h"
44
45 #define MENU_SHELL_TIMEOUT   500
46
47 #define PACK_DIRECTION(m)                                 \
48    (GTK_IS_MENU_BAR (m)                                   \
49      ? gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (m)) \
50      : GTK_PACK_DIRECTION_LTR)
51
52 enum {
53   DEACTIVATE,
54   SELECTION_DONE,
55   MOVE_CURRENT,
56   ACTIVATE_CURRENT,
57   CANCEL,
58   CYCLE_FOCUS,
59   MOVE_SELECTED,
60   LAST_SIGNAL
61 };
62
63 enum {
64   PROP_0,
65   PROP_TAKE_FOCUS
66 };
67
68 /* Terminology:
69  * 
70  * A menu item can be "selected", this means that it is displayed
71  * in the prelight state, and if it has a submenu, that submenu
72  * will be popped up. 
73  * 
74  * A menu is "active" when it is visible onscreen and the user
75  * is selecting from it. A menubar is not active until the user
76  * clicks on one of its menuitems. When a menu is active,
77  * passing the mouse over a submenu will pop it up.
78  *
79  * menu_shell->active_menu_item, is however, not an "active"
80  * menu item (there is no such thing) but rather, the selected
81  * menu item in that MenuShell, if there is one.
82  *
83  * There is also is a concept of the current menu and a current
84  * menu item. The current menu item is the selected menu item
85  * that is furthest down in the hierarchy. (Every active menu_shell
86  * does not necessarily contain a selected menu item, but if
87  * it does, then menu_shell->parent_menu_shell must also contain
88  * a selected menu item. The current menu is the menu that 
89  * contains the current menu_item. It will always have a GTK
90  * grab and receive all key presses.
91  *
92  *
93  * Action signals:
94  *
95  *  ::move_current (GtkMenuDirection *dir)
96  *     Moves the current menu item in direction 'dir':
97  *
98  *       GTK_MENU_DIR_PARENT: To the parent menu shell
99  *       GTK_MENU_DIR_CHILD: To the child menu shell (if this item has
100  *          a submenu.
101  *       GTK_MENU_DIR_NEXT/PREV: To the next or previous item
102  *          in this menu.
103  * 
104  *     As a a bit of a hack to get movement between menus and
105  *     menubars working, if submenu_placement is different for
106  *     the menu and its MenuShell then the following apply:
107  * 
108  *       - For 'parent' the current menu is not just moved to
109  *         the parent, but moved to the previous entry in the parent
110  *       - For 'child', if there is no child, then current is
111  *         moved to the next item in the parent.
112  *
113  *    Note that the above explanation of ::move_current was written
114  *    before menus and menubars had support for RTL flipping and
115  *    different packing directions, and therefore only applies for
116  *    when text direction and packing direction are both left-to-right.
117  * 
118  *  ::activate_current (GBoolean *force_hide)
119  *     Activate the current item. If 'force_hide' is true, hide
120  *     the current menu item always. Otherwise, only hide
121  *     it if menu_item->klass->hide_on_activate is true.
122  *
123  *  ::cancel ()
124  *     Cancels the current selection
125  */
126
127 #define GTK_MENU_SHELL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_MENU_SHELL, GtkMenuShellPrivate))
128
129 typedef struct _GtkMenuShellPrivate GtkMenuShellPrivate;
130
131 struct _GtkMenuShellPrivate
132 {
133   GtkMnemonicHash *mnemonic_hash;
134   GtkKeyHash *key_hash;
135
136   GdkDevice *grab_pointer;
137
138   guint take_focus : 1;
139   guint activated_submenu : 1;
140   /* This flag is a crutch to keep mnemonics in the same menu
141    * if the user moves the mouse over an unselectable menuitem.
142    */
143   guint in_unselectable_item : 1;
144 };
145
146 static void gtk_menu_shell_set_property      (GObject           *object,
147                                               guint              prop_id,
148                                               const GValue      *value,
149                                               GParamSpec        *pspec);
150 static void gtk_menu_shell_get_property      (GObject           *object,
151                                               guint              prop_id,
152                                               GValue            *value,
153                                               GParamSpec        *pspec);
154 static void gtk_menu_shell_realize           (GtkWidget         *widget);
155 static void gtk_menu_shell_finalize          (GObject           *object);
156 static void gtk_menu_shell_dispose           (GObject           *object);
157 static gint gtk_menu_shell_button_press      (GtkWidget         *widget,
158                                               GdkEventButton    *event);
159 static gint gtk_menu_shell_button_release    (GtkWidget         *widget,
160                                               GdkEventButton    *event);
161 static gint gtk_menu_shell_key_press         (GtkWidget         *widget,
162                                               GdkEventKey       *event);
163 static gint gtk_menu_shell_enter_notify      (GtkWidget         *widget,
164                                               GdkEventCrossing  *event);
165 static gint gtk_menu_shell_leave_notify      (GtkWidget         *widget,
166                                               GdkEventCrossing  *event);
167 static void gtk_menu_shell_screen_changed    (GtkWidget         *widget,
168                                               GdkScreen         *previous_screen);
169 static gboolean gtk_menu_shell_grab_broken       (GtkWidget         *widget,
170                                               GdkEventGrabBroken *event);
171 static void gtk_menu_shell_add               (GtkContainer      *container,
172                                               GtkWidget         *widget);
173 static void gtk_menu_shell_remove            (GtkContainer      *container,
174                                               GtkWidget         *widget);
175 static void gtk_menu_shell_forall            (GtkContainer      *container,
176                                               gboolean           include_internals,
177                                               GtkCallback        callback,
178                                               gpointer           callback_data);
179 static void gtk_menu_shell_real_insert       (GtkMenuShell *menu_shell,
180                                               GtkWidget    *child,
181                                               gint          position);
182 static void gtk_real_menu_shell_deactivate   (GtkMenuShell      *menu_shell);
183 static gint gtk_menu_shell_is_item           (GtkMenuShell      *menu_shell,
184                                               GtkWidget         *child);
185 static GtkWidget *gtk_menu_shell_get_item    (GtkMenuShell      *menu_shell,
186                                               GdkEvent          *event);
187 static GType    gtk_menu_shell_child_type  (GtkContainer      *container);
188 static void gtk_menu_shell_real_select_item  (GtkMenuShell      *menu_shell,
189                                               GtkWidget         *menu_item);
190 static gboolean gtk_menu_shell_select_submenu_first (GtkMenuShell   *menu_shell); 
191
192 static void gtk_real_menu_shell_move_current (GtkMenuShell      *menu_shell,
193                                               GtkMenuDirectionType direction);
194 static void gtk_real_menu_shell_activate_current (GtkMenuShell      *menu_shell,
195                                                   gboolean           force_hide);
196 static void gtk_real_menu_shell_cancel           (GtkMenuShell      *menu_shell);
197 static void gtk_real_menu_shell_cycle_focus      (GtkMenuShell      *menu_shell,
198                                                   GtkDirectionType   dir);
199
200 static void     gtk_menu_shell_reset_key_hash    (GtkMenuShell *menu_shell);
201 static gboolean gtk_menu_shell_activate_mnemonic (GtkMenuShell *menu_shell,
202                                                   GdkEventKey  *event);
203 static gboolean gtk_menu_shell_real_move_selected (GtkMenuShell  *menu_shell, 
204                                                    gint           distance);
205
206 static guint menu_shell_signals[LAST_SIGNAL] = { 0 };
207
208 G_DEFINE_ABSTRACT_TYPE (GtkMenuShell, gtk_menu_shell, GTK_TYPE_CONTAINER)
209
210 static void
211 gtk_menu_shell_class_init (GtkMenuShellClass *klass)
212 {
213   GObjectClass *object_class;
214   GtkWidgetClass *widget_class;
215   GtkContainerClass *container_class;
216
217   GtkBindingSet *binding_set;
218
219   object_class = (GObjectClass*) klass;
220   widget_class = (GtkWidgetClass*) klass;
221   container_class = (GtkContainerClass*) klass;
222
223   object_class->set_property = gtk_menu_shell_set_property;
224   object_class->get_property = gtk_menu_shell_get_property;
225   object_class->finalize = gtk_menu_shell_finalize;
226   object_class->dispose = gtk_menu_shell_dispose;
227
228   widget_class->realize = gtk_menu_shell_realize;
229   widget_class->button_press_event = gtk_menu_shell_button_press;
230   widget_class->button_release_event = gtk_menu_shell_button_release;
231   widget_class->grab_broken_event = gtk_menu_shell_grab_broken;
232   widget_class->key_press_event = gtk_menu_shell_key_press;
233   widget_class->enter_notify_event = gtk_menu_shell_enter_notify;
234   widget_class->leave_notify_event = gtk_menu_shell_leave_notify;
235   widget_class->screen_changed = gtk_menu_shell_screen_changed;
236
237   container_class->add = gtk_menu_shell_add;
238   container_class->remove = gtk_menu_shell_remove;
239   container_class->forall = gtk_menu_shell_forall;
240   container_class->child_type = gtk_menu_shell_child_type;
241
242   klass->submenu_placement = GTK_TOP_BOTTOM;
243   klass->deactivate = gtk_real_menu_shell_deactivate;
244   klass->selection_done = NULL;
245   klass->move_current = gtk_real_menu_shell_move_current;
246   klass->activate_current = gtk_real_menu_shell_activate_current;
247   klass->cancel = gtk_real_menu_shell_cancel;
248   klass->select_item = gtk_menu_shell_real_select_item;
249   klass->insert = gtk_menu_shell_real_insert;
250   klass->move_selected = gtk_menu_shell_real_move_selected;
251
252   menu_shell_signals[DEACTIVATE] =
253     g_signal_new (I_("deactivate"),
254                   G_OBJECT_CLASS_TYPE (object_class),
255                   G_SIGNAL_RUN_FIRST,
256                   G_STRUCT_OFFSET (GtkMenuShellClass, deactivate),
257                   NULL, NULL,
258                   _gtk_marshal_VOID__VOID,
259                   G_TYPE_NONE, 0);
260
261   menu_shell_signals[SELECTION_DONE] =
262     g_signal_new (I_("selection-done"),
263                   G_OBJECT_CLASS_TYPE (object_class),
264                   G_SIGNAL_RUN_FIRST,
265                   G_STRUCT_OFFSET (GtkMenuShellClass, selection_done),
266                   NULL, NULL,
267                   _gtk_marshal_VOID__VOID,
268                   G_TYPE_NONE, 0);
269
270   menu_shell_signals[MOVE_CURRENT] =
271     g_signal_new (I_("move-current"),
272                   G_OBJECT_CLASS_TYPE (object_class),
273                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
274                   G_STRUCT_OFFSET (GtkMenuShellClass, move_current),
275                   NULL, NULL,
276                   _gtk_marshal_VOID__ENUM,
277                   G_TYPE_NONE, 1,
278                   GTK_TYPE_MENU_DIRECTION_TYPE);
279
280   menu_shell_signals[ACTIVATE_CURRENT] =
281     g_signal_new (I_("activate-current"),
282                   G_OBJECT_CLASS_TYPE (object_class),
283                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
284                   G_STRUCT_OFFSET (GtkMenuShellClass, activate_current),
285                   NULL, NULL,
286                   _gtk_marshal_VOID__BOOLEAN,
287                   G_TYPE_NONE, 1,
288                   G_TYPE_BOOLEAN);
289
290   menu_shell_signals[CANCEL] =
291     g_signal_new (I_("cancel"),
292                   G_OBJECT_CLASS_TYPE (object_class),
293                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
294                   G_STRUCT_OFFSET (GtkMenuShellClass, cancel),
295                   NULL, NULL,
296                   _gtk_marshal_VOID__VOID,
297                   G_TYPE_NONE, 0);
298
299   menu_shell_signals[CYCLE_FOCUS] =
300     g_signal_new_class_handler (I_("cycle-focus"),
301                                 G_OBJECT_CLASS_TYPE (object_class),
302                                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
303                                 G_CALLBACK (gtk_real_menu_shell_cycle_focus),
304                                 NULL, NULL,
305                                 _gtk_marshal_VOID__ENUM,
306                                 G_TYPE_NONE, 1,
307                                 GTK_TYPE_DIRECTION_TYPE);
308
309   /**
310    * GtkMenuShell::move-selected:
311    * @menu_shell: the object on which the signal is emitted
312    * @distance: +1 to move to the next item, -1 to move to the previous
313    *
314    * The ::move-selected signal is emitted to move the selection to
315    * another item.
316    *
317    * Returns: %TRUE to stop the signal emission, %FALSE to continue
318    *
319    * Since: 2.12
320    */
321   menu_shell_signals[MOVE_SELECTED] =
322     g_signal_new (I_("move-selected"),
323                   G_OBJECT_CLASS_TYPE (object_class),
324                   G_SIGNAL_RUN_LAST,
325                   G_STRUCT_OFFSET (GtkMenuShellClass, move_selected),
326                   _gtk_boolean_handled_accumulator, NULL,
327                   _gtk_marshal_BOOLEAN__INT,
328                   G_TYPE_BOOLEAN, 1,
329                   G_TYPE_INT);
330
331   binding_set = gtk_binding_set_by_class (klass);
332   gtk_binding_entry_add_signal (binding_set,
333                                 GDK_KEY_Escape, 0,
334                                 "cancel", 0);
335   gtk_binding_entry_add_signal (binding_set,
336                                 GDK_KEY_Return, 0,
337                                 "activate-current", 1,
338                                 G_TYPE_BOOLEAN,
339                                 TRUE);
340   gtk_binding_entry_add_signal (binding_set,
341                                 GDK_KEY_ISO_Enter, 0,
342                                 "activate-current", 1,
343                                 G_TYPE_BOOLEAN,
344                                 TRUE);
345   gtk_binding_entry_add_signal (binding_set,
346                                 GDK_KEY_KP_Enter, 0,
347                                 "activate-current", 1,
348                                 G_TYPE_BOOLEAN,
349                                 TRUE);
350   gtk_binding_entry_add_signal (binding_set,
351                                 GDK_KEY_space, 0,
352                                 "activate-current", 1,
353                                 G_TYPE_BOOLEAN,
354                                 FALSE);
355   gtk_binding_entry_add_signal (binding_set,
356                                 GDK_KEY_KP_Space, 0,
357                                 "activate-current", 1,
358                                 G_TYPE_BOOLEAN,
359                                 FALSE);
360   gtk_binding_entry_add_signal (binding_set,
361                                 GDK_KEY_F10, 0,
362                                 "cycle-focus", 1,
363                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
364   gtk_binding_entry_add_signal (binding_set,
365                                 GDK_KEY_F10, GDK_SHIFT_MASK,
366                                 "cycle-focus", 1,
367                                 GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
368
369   /**
370    * GtkMenuShell:take-focus:
371    *
372    * A boolean that determines whether the menu and its submenus grab the
373    * keyboard focus. See gtk_menu_shell_set_take_focus() and
374    * gtk_menu_shell_get_take_focus().
375    *
376    * Since: 2.8
377    **/
378   g_object_class_install_property (object_class,
379                                    PROP_TAKE_FOCUS,
380                                    g_param_spec_boolean ("take-focus",
381                                                          P_("Take Focus"),
382                                                          P_("A boolean that determines whether the menu grabs the keyboard focus"),
383                                                          TRUE,
384                                                          GTK_PARAM_READWRITE));
385
386   g_type_class_add_private (object_class, sizeof (GtkMenuShellPrivate));
387 }
388
389 static GType
390 gtk_menu_shell_child_type (GtkContainer     *container)
391 {
392   return GTK_TYPE_MENU_ITEM;
393 }
394
395 static void
396 gtk_menu_shell_init (GtkMenuShell *menu_shell)
397 {
398   GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
399
400   menu_shell->children = NULL;
401   menu_shell->active_menu_item = NULL;
402   menu_shell->parent_menu_shell = NULL;
403   menu_shell->active = FALSE;
404   menu_shell->have_grab = FALSE;
405   menu_shell->have_xgrab = FALSE;
406   menu_shell->button = 0;
407   menu_shell->activate_time = 0;
408
409   priv->mnemonic_hash = NULL;
410   priv->key_hash = NULL;
411   priv->take_focus = TRUE;
412   priv->activated_submenu = FALSE;
413 }
414
415 static void
416 gtk_menu_shell_set_property (GObject      *object,
417                              guint         prop_id,
418                              const GValue *value,
419                              GParamSpec   *pspec)
420 {
421   GtkMenuShell *menu_shell = GTK_MENU_SHELL (object);
422
423   switch (prop_id)
424     {
425     case PROP_TAKE_FOCUS:
426       gtk_menu_shell_set_take_focus (menu_shell, g_value_get_boolean (value));
427       break;
428     default:
429       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430       break;
431     }
432 }
433
434 static void
435 gtk_menu_shell_get_property (GObject     *object,
436                              guint        prop_id,
437                              GValue      *value,
438                              GParamSpec  *pspec)
439 {
440   GtkMenuShell *menu_shell = GTK_MENU_SHELL (object);
441
442   switch (prop_id)
443     {
444     case PROP_TAKE_FOCUS:
445       g_value_set_boolean (value, gtk_menu_shell_get_take_focus (menu_shell));
446       break;
447     default:
448       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
449       break;
450     }
451 }
452
453 static void
454 gtk_menu_shell_finalize (GObject *object)
455 {
456   GtkMenuShell *menu_shell = GTK_MENU_SHELL (object);
457   GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
458
459   if (priv->mnemonic_hash)
460     _gtk_mnemonic_hash_free (priv->mnemonic_hash);
461   if (priv->key_hash)
462     _gtk_key_hash_free (priv->key_hash);
463
464   G_OBJECT_CLASS (gtk_menu_shell_parent_class)->finalize (object);
465 }
466
467
468 static void 
469 gtk_menu_shell_dispose (GObject           *object)
470 {
471   GtkMenuShell *menu_shell = GTK_MENU_SHELL (object);
472
473   gtk_menu_shell_deactivate (menu_shell);
474
475   G_OBJECT_CLASS (gtk_menu_shell_parent_class)->dispose (object);
476 }
477
478 void
479 gtk_menu_shell_append (GtkMenuShell *menu_shell,
480                        GtkWidget    *child)
481 {
482   gtk_menu_shell_insert (menu_shell, child, -1);
483 }
484
485 void
486 gtk_menu_shell_prepend (GtkMenuShell *menu_shell,
487                         GtkWidget    *child)
488 {
489   gtk_menu_shell_insert (menu_shell, child, 0);
490 }
491
492 void
493 gtk_menu_shell_insert (GtkMenuShell *menu_shell,
494                        GtkWidget    *child,
495                        gint          position)
496 {
497   GtkMenuShellClass *class;
498
499   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
500   g_return_if_fail (GTK_IS_MENU_ITEM (child));
501
502   class = GTK_MENU_SHELL_GET_CLASS (menu_shell);
503
504   if (class->insert)
505     class->insert (menu_shell, child, position);
506 }
507
508 static void
509 gtk_menu_shell_real_insert (GtkMenuShell *menu_shell,
510                             GtkWidget    *child,
511                             gint          position)
512 {
513   menu_shell->children = g_list_insert (menu_shell->children, child, position);
514
515   gtk_widget_set_parent (child, GTK_WIDGET (menu_shell));
516 }
517
518 void
519 gtk_menu_shell_deactivate (GtkMenuShell *menu_shell)
520 {
521   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
522
523   g_signal_emit (menu_shell, menu_shell_signals[DEACTIVATE], 0);
524 }
525
526 static void
527 gtk_menu_shell_realize (GtkWidget *widget)
528 {
529   GtkAllocation allocation;
530   GdkWindow *window;
531   GdkWindowAttr attributes;
532   gint attributes_mask;
533
534   gtk_widget_set_realized (widget, TRUE);
535
536   gtk_widget_get_allocation (widget, &allocation);
537
538   attributes.x = allocation.x;
539   attributes.y = allocation.y;
540   attributes.width = allocation.width;
541   attributes.height = allocation.height;
542   attributes.window_type = GDK_WINDOW_CHILD;
543   attributes.wclass = GDK_INPUT_OUTPUT;
544   attributes.visual = gtk_widget_get_visual (widget);
545   attributes.event_mask = gtk_widget_get_events (widget);
546   attributes.event_mask |= (GDK_EXPOSURE_MASK |
547                             GDK_BUTTON_PRESS_MASK |
548                             GDK_BUTTON_RELEASE_MASK |
549                             GDK_KEY_PRESS_MASK |
550                             GDK_ENTER_NOTIFY_MASK |
551                             GDK_LEAVE_NOTIFY_MASK);
552
553   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
554
555   window = gdk_window_new (gtk_widget_get_parent_window (widget),
556                            &attributes, attributes_mask);
557   gtk_widget_set_window (widget, window);
558   gdk_window_set_user_data (window, widget);
559
560   gtk_widget_style_attach (widget);
561   gtk_style_set_background (gtk_widget_get_style (widget), window, GTK_STATE_NORMAL);
562 }
563
564 void
565 _gtk_menu_shell_activate (GtkMenuShell *menu_shell)
566 {
567   if (!menu_shell->active)
568     {
569       GdkDevice *device;
570
571       device = gtk_get_current_event_device ();
572
573       _gtk_menu_shell_set_grab_device (menu_shell, device);
574       gtk_device_grab_add (GTK_WIDGET (menu_shell), device, TRUE);
575
576       menu_shell->have_grab = TRUE;
577       menu_shell->active = TRUE;
578     }
579 }
580
581 static gint
582 gtk_menu_shell_button_press (GtkWidget      *widget,
583                              GdkEventButton *event)
584 {
585   GtkMenuShell *menu_shell;
586   GtkWidget *menu_item;
587   GtkWidget *parent;
588
589   if (event->type != GDK_BUTTON_PRESS)
590     return FALSE;
591
592   menu_shell = GTK_MENU_SHELL (widget);
593
594   if (menu_shell->parent_menu_shell)
595     return gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
596
597   menu_item = gtk_menu_shell_get_item (menu_shell, (GdkEvent *)event);
598
599   if (menu_item && _gtk_menu_item_is_selectable (menu_item))
600     {
601       parent = gtk_widget_get_parent (menu_item);
602
603       if (menu_item != GTK_MENU_SHELL (parent)->active_menu_item)
604         {
605           /*  select the menu item *before* activating the shell, so submenus
606            *  which might be open are closed the friendly way. If we activate
607            *  (and thus grab) this menu shell first, we might get grab_broken
608            *  events which will close the entire menu hierarchy. Selecting the
609            *  menu item also fixes up the state as if enter_notify() would
610            *  have run before (which normally selects the item).
611            */
612           if (GTK_MENU_SHELL_GET_CLASS (parent)->submenu_placement != GTK_TOP_BOTTOM)
613             gtk_menu_shell_select_item (GTK_MENU_SHELL (parent), menu_item);
614         }
615     }
616
617   if (!menu_shell->active || !menu_shell->button)
618     {
619       gboolean initially_active = menu_shell->active;
620
621       menu_shell->button = event->button;
622
623       if (menu_item)
624         {
625           if (_gtk_menu_item_is_selectable (menu_item) &&
626               gtk_widget_get_parent (menu_item) == widget &&
627               menu_item != menu_shell->active_menu_item)
628             {
629               _gtk_menu_shell_activate (menu_shell);
630               menu_shell->button = event->button;
631
632               if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement == GTK_TOP_BOTTOM)
633                 {
634                   menu_shell->activate_time = event->time;
635                   gtk_menu_shell_select_item (menu_shell, menu_item);
636                 }
637             }
638         }
639       else
640         {
641           if (!initially_active)
642             {
643               gboolean window_drag = FALSE;
644
645               gtk_widget_style_get (widget,
646                                     "window-dragging", &window_drag,
647                                     NULL);
648
649               if (window_drag)
650                 {
651                   gtk_menu_shell_deactivate (menu_shell);
652                   gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
653                                               event->button,
654                                               event->x_root,
655                                               event->y_root,
656                                               event->time);
657                 }
658             }
659         }
660     }
661   else
662     {
663       widget = gtk_get_event_widget ((GdkEvent*) event);
664       if (widget == GTK_WIDGET (menu_shell))
665         {
666           gtk_menu_shell_deactivate (menu_shell);
667           g_signal_emit (menu_shell, menu_shell_signals[SELECTION_DONE], 0);
668         }
669     }
670
671   if (menu_item && _gtk_menu_item_is_selectable (menu_item) &&
672       GTK_MENU_ITEM (menu_item)->submenu != NULL &&
673       !gtk_widget_get_visible (GTK_MENU_ITEM (menu_item)->submenu))
674     {
675       GtkMenuShellPrivate *priv;
676
677       _gtk_menu_item_popup_submenu (menu_item, FALSE);
678
679       priv = GTK_MENU_SHELL_GET_PRIVATE (gtk_widget_get_parent (menu_item));
680       priv->activated_submenu = TRUE;
681     }
682
683   return TRUE;
684 }
685
686 static gboolean
687 gtk_menu_shell_grab_broken (GtkWidget          *widget,
688                             GdkEventGrabBroken *event)
689 {
690   GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
691
692   if (menu_shell->have_xgrab && event->grab_window == NULL)
693     {
694       /* Unset the active menu item so gtk_menu_popdown() doesn't see it.
695        */
696       
697       gtk_menu_shell_deselect (menu_shell);
698       
699       gtk_menu_shell_deactivate (menu_shell);
700       g_signal_emit (menu_shell, menu_shell_signals[SELECTION_DONE], 0);
701     }
702
703   return TRUE;
704 }
705
706 static gint
707 gtk_menu_shell_button_release (GtkWidget      *widget,
708                                GdkEventButton *event)
709 {
710   GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
711   GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (widget);
712
713   if (menu_shell->active)
714     {
715       GtkWidget *menu_item;
716       gboolean   deactivate = TRUE;
717
718       if (menu_shell->button && (event->button != menu_shell->button))
719         {
720           menu_shell->button = 0;
721           if (menu_shell->parent_menu_shell)
722             return gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
723         }
724
725       menu_shell->button = 0;
726       menu_item = gtk_menu_shell_get_item (menu_shell, (GdkEvent*) event);
727
728       if ((event->time - menu_shell->activate_time) > MENU_SHELL_TIMEOUT)
729         {
730           if (menu_item && (menu_shell->active_menu_item == menu_item) &&
731               _gtk_menu_item_is_selectable (menu_item))
732             {
733               GtkWidget *submenu = GTK_MENU_ITEM (menu_item)->submenu;
734
735               if (submenu == NULL)
736                 {
737                   gtk_menu_shell_activate_item (menu_shell, menu_item, TRUE);
738
739                   deactivate = FALSE;
740                 }
741               else if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement != GTK_TOP_BOTTOM ||
742                        priv->activated_submenu)
743                 {
744                   gint popdown_delay;
745                   GTimeVal *popup_time;
746                   gint64 usec_since_popup = 0;
747
748                   g_object_get (gtk_widget_get_settings (widget),
749                                 "gtk-menu-popdown-delay", &popdown_delay,
750                                 NULL);
751
752                   popup_time = g_object_get_data (G_OBJECT (submenu),
753                                                   "gtk-menu-exact-popup-time");
754
755                   if (popup_time)
756                     {
757                       GTimeVal current_time;
758
759                       g_get_current_time (&current_time);
760
761                       usec_since_popup = ((gint64) current_time.tv_sec * 1000 * 1000 +
762                                           (gint64) current_time.tv_usec -
763                                           (gint64) popup_time->tv_sec * 1000 * 1000 -
764                                           (gint64) popup_time->tv_usec);
765
766                       g_object_set_data (G_OBJECT (submenu),
767                                          "gtk-menu-exact-popup-time", NULL);
768                     }
769
770                   /*  only close the submenu on click if we opened the
771                    *  menu explicitely (usec_since_popup == 0) or
772                    *  enough time has passed since it was opened by
773                    *  GtkMenuItem's timeout (usec_since_popup > delay).
774                    */
775                   if (!priv->activated_submenu &&
776                       (usec_since_popup == 0 ||
777                        usec_since_popup > popdown_delay * 1000))
778                     {
779                       _gtk_menu_item_popdown_submenu (menu_item);
780                     }
781                   else
782                     {
783                       gtk_menu_item_select (GTK_MENU_ITEM (menu_item));
784                     }
785
786                   deactivate = FALSE;
787                 }
788             }
789           else if (menu_item &&
790                    !_gtk_menu_item_is_selectable (menu_item) &&
791                    GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement != GTK_TOP_BOTTOM)
792             {
793               deactivate = FALSE;
794             }
795           else if (menu_shell->parent_menu_shell)
796             {
797               menu_shell->active = TRUE;
798               gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
799               deactivate = FALSE;
800             }
801
802           /* If we ended up on an item with a submenu, leave the menu up.
803            */
804           if (menu_item && (menu_shell->active_menu_item == menu_item) &&
805               GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement != GTK_TOP_BOTTOM)
806             {
807               deactivate = FALSE;
808             }
809         }
810       else /* a very fast press-release */
811         {
812           /* We only ever want to prevent deactivation on the first
813            * press/release. Setting the time to zero is a bit of a
814            * hack, since we could be being triggered in the first
815            * few fractions of a second after a server time wraparound.
816            * the chances of that happening are ~1/10^6, without
817            * serious harm if we lose.
818            */
819           menu_shell->activate_time = 0;
820           deactivate = FALSE;
821         }
822
823       if (deactivate)
824         {
825           gtk_menu_shell_deactivate (menu_shell);
826           g_signal_emit (menu_shell, menu_shell_signals[SELECTION_DONE], 0);
827         }
828
829       priv->activated_submenu = FALSE;
830     }
831
832   return TRUE;
833 }
834
835 void
836 _gtk_menu_shell_set_keyboard_mode (GtkMenuShell *menu_shell,
837                                    gboolean      keyboard_mode)
838 {
839   menu_shell->keyboard_mode = keyboard_mode;
840 }
841
842 gboolean
843 _gtk_menu_shell_get_keyboard_mode (GtkMenuShell *menu_shell)
844 {
845   return menu_shell->keyboard_mode;
846 }
847
848 void
849 _gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell)
850 {
851   GtkMenuShell *target;
852   gboolean auto_mnemonics;
853   gboolean found;
854   gboolean mnemonics_visible;
855
856   g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
857                 "gtk-auto-mnemonics", &auto_mnemonics, NULL);
858
859   if (!auto_mnemonics)
860     return;
861
862   target = menu_shell;
863   found = FALSE;
864   while (target)
865     {
866       GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (target);
867       GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (target));
868
869       /* The idea with keyboard mode is that once you start using
870        * the keyboard to navigate the menus, we show mnemonics
871        * until the menu navigation is over. To that end, we spread
872        * the keyboard mode upwards in the menu hierarchy here.
873        * Also see gtk_menu_popup, where we inherit it downwards.
874        */
875       if (menu_shell->keyboard_mode)
876         target->keyboard_mode = TRUE;
877
878       /* While navigating menus, the first parent menu with an active
879        * item is the one where mnemonics are effective, as can be seen
880        * in gtk_menu_shell_key_press below.
881        * We also show mnemonics in context menus. The grab condition is
882        * necessary to ensure we remove underlines from menu bars when
883        * dismissing menus.
884        */
885       mnemonics_visible = target->keyboard_mode &&
886                           (((target->active_menu_item || priv->in_unselectable_item) && !found) ||
887                            (target == menu_shell &&
888                             !target->parent_menu_shell &&
889                             gtk_widget_has_grab (GTK_WIDGET (target))));
890
891       /* While menus are up, only show underlines inside the menubar,
892        * not in the entire window.
893        */
894       if (GTK_IS_MENU_BAR (target))
895         {
896           gtk_window_set_mnemonics_visible (GTK_WINDOW (toplevel), FALSE);
897           _gtk_label_mnemonics_visible_apply_recursively (GTK_WIDGET (target),
898                                                           mnemonics_visible);
899         }
900       else
901         gtk_window_set_mnemonics_visible (GTK_WINDOW (toplevel), mnemonics_visible);
902
903       if (target->active_menu_item || priv->in_unselectable_item)
904         found = TRUE;
905
906       target = GTK_MENU_SHELL (target->parent_menu_shell);
907     }
908 }
909
910 static gint
911 gtk_menu_shell_key_press (GtkWidget   *widget,
912                           GdkEventKey *event)
913 {
914   GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
915   GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
916   gboolean enable_mnemonics;
917
918   menu_shell->keyboard_mode = TRUE;
919
920   if (!(menu_shell->active_menu_item || priv->in_unselectable_item) && menu_shell->parent_menu_shell)
921     return gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent *)event);
922
923   if (gtk_bindings_activate_event (G_OBJECT (widget), event))
924     return TRUE;
925
926   g_object_get (gtk_widget_get_settings (widget),
927                 "gtk-enable-mnemonics", &enable_mnemonics,
928                 NULL);
929
930   if (enable_mnemonics)
931     return gtk_menu_shell_activate_mnemonic (menu_shell, event);
932
933   return FALSE;
934 }
935
936 static gint
937 gtk_menu_shell_enter_notify (GtkWidget        *widget,
938                              GdkEventCrossing *event)
939 {
940   GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
941
942   if (event->mode == GDK_CROSSING_GTK_GRAB ||
943       event->mode == GDK_CROSSING_GTK_UNGRAB ||
944       event->mode == GDK_CROSSING_STATE_CHANGED)
945     return TRUE;
946
947   if (menu_shell->active)
948     {
949       GtkWidget *menu_item;
950       GtkWidget *parent;
951
952       menu_item = gtk_get_event_widget ((GdkEvent*) event);
953
954       if (!menu_item)
955         return TRUE;
956
957       if (GTK_IS_MENU_ITEM (menu_item) &&
958           !_gtk_menu_item_is_selectable (menu_item))
959         {
960           GtkMenuShellPrivate *priv;
961
962           priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
963           priv->in_unselectable_item = TRUE;
964
965           return TRUE;
966         }
967
968       parent = gtk_widget_get_parent (menu_item);
969       if (parent == widget &&
970           GTK_IS_MENU_ITEM (menu_item))
971         {
972           if (menu_shell->ignore_enter)
973             return TRUE;
974
975           if (event->detail != GDK_NOTIFY_INFERIOR)
976             {
977               if (gtk_widget_get_state (menu_item) != GTK_STATE_PRELIGHT)
978                 gtk_menu_shell_select_item (menu_shell, menu_item);
979
980               /* If any mouse button is down, and there is a submenu
981                * that is not yet visible, activate it. It's sufficient
982                * to check for any button's mask (not only the one
983                * matching menu_shell->button), because there is no
984                * situation a mouse button could be pressed while
985                * entering a menu item where we wouldn't want to show
986                * its submenu.
987                */
988               if ((event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) &&
989                   GTK_MENU_ITEM (menu_item)->submenu != NULL)
990                 {
991                   GtkMenuShellPrivate *priv;
992
993                   priv = GTK_MENU_SHELL_GET_PRIVATE (parent);
994                   priv->activated_submenu = TRUE;
995
996                   if (!gtk_widget_get_visible (GTK_MENU_ITEM (menu_item)->submenu))
997                     {
998                       gboolean touchscreen_mode;
999
1000                       g_object_get (gtk_widget_get_settings (widget),
1001                                     "gtk-touchscreen-mode", &touchscreen_mode,
1002                                     NULL);
1003
1004                       if (touchscreen_mode)
1005                         _gtk_menu_item_popup_submenu (menu_item, TRUE);
1006                     }
1007                 }
1008             }
1009         }
1010       else if (menu_shell->parent_menu_shell)
1011         {
1012           gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
1013         }
1014     }
1015
1016   return TRUE;
1017 }
1018
1019 static gint
1020 gtk_menu_shell_leave_notify (GtkWidget        *widget,
1021                              GdkEventCrossing *event)
1022 {
1023   if (event->mode == GDK_CROSSING_GTK_GRAB ||
1024       event->mode == GDK_CROSSING_GTK_GRAB ||
1025       event->mode == GDK_CROSSING_STATE_CHANGED)
1026     return TRUE;
1027
1028   if (gtk_widget_get_visible (widget))
1029     {
1030       GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
1031       GtkWidget *event_widget = gtk_get_event_widget ((GdkEvent*) event);
1032       GtkMenuItem *menu_item;
1033
1034       if (!event_widget || !GTK_IS_MENU_ITEM (event_widget))
1035         return TRUE;
1036
1037       menu_item = GTK_MENU_ITEM (event_widget);
1038
1039       if (!_gtk_menu_item_is_selectable (event_widget))
1040         {
1041           GtkMenuShellPrivate *priv;
1042
1043           priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1044           priv->in_unselectable_item = TRUE;
1045
1046           return TRUE;
1047         }
1048
1049       if ((menu_shell->active_menu_item == event_widget) &&
1050           (menu_item->submenu == NULL))
1051         {
1052           if ((event->detail != GDK_NOTIFY_INFERIOR) &&
1053               (gtk_widget_get_state (GTK_WIDGET (menu_item)) != GTK_STATE_NORMAL))
1054             {
1055               gtk_menu_shell_deselect (menu_shell);
1056             }
1057         }
1058       else if (menu_shell->parent_menu_shell)
1059         {
1060           gtk_widget_event (menu_shell->parent_menu_shell, (GdkEvent*) event);
1061         }
1062     }
1063
1064   return TRUE;
1065 }
1066
1067 static void
1068 gtk_menu_shell_screen_changed (GtkWidget *widget,
1069                                GdkScreen *previous_screen)
1070 {
1071   gtk_menu_shell_reset_key_hash (GTK_MENU_SHELL (widget));
1072 }
1073
1074 static void
1075 gtk_menu_shell_add (GtkContainer *container,
1076                     GtkWidget    *widget)
1077 {
1078   gtk_menu_shell_append (GTK_MENU_SHELL (container), widget);
1079 }
1080
1081 static void
1082 gtk_menu_shell_remove (GtkContainer *container,
1083                        GtkWidget    *widget)
1084 {
1085   GtkMenuShell *menu_shell = GTK_MENU_SHELL (container);
1086   gint was_visible;
1087
1088   was_visible = gtk_widget_get_visible (widget);
1089   menu_shell->children = g_list_remove (menu_shell->children, widget);
1090   
1091   if (widget == menu_shell->active_menu_item)
1092     {
1093       g_signal_emit_by_name (menu_shell->active_menu_item, "deselect");
1094       menu_shell->active_menu_item = NULL;
1095     }
1096
1097   gtk_widget_unparent (widget);
1098   
1099   /* queue resize regardless of gtk_widget_get_visible (container),
1100    * since that's what is needed by toplevels.
1101    */
1102   if (was_visible)
1103     gtk_widget_queue_resize (GTK_WIDGET (container));
1104 }
1105
1106 static void
1107 gtk_menu_shell_forall (GtkContainer *container,
1108                        gboolean      include_internals,
1109                        GtkCallback   callback,
1110                        gpointer      callback_data)
1111 {
1112   GtkMenuShell *menu_shell = GTK_MENU_SHELL (container);
1113   GtkWidget *child;
1114   GList *children;
1115
1116   children = menu_shell->children;
1117   while (children)
1118     {
1119       child = children->data;
1120       children = children->next;
1121
1122       (* callback) (child, callback_data);
1123     }
1124 }
1125
1126
1127 static void
1128 gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell)
1129 {
1130   if (menu_shell->active)
1131     {
1132       GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1133
1134       menu_shell->button = 0;
1135       menu_shell->active = FALSE;
1136       menu_shell->activate_time = 0;
1137
1138       if (menu_shell->active_menu_item)
1139         {
1140           gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
1141           menu_shell->active_menu_item = NULL;
1142         }
1143
1144       if (menu_shell->have_grab)
1145         {
1146           menu_shell->have_grab = FALSE;
1147           gtk_device_grab_remove (GTK_WIDGET (menu_shell), priv->grab_pointer);
1148         }
1149       if (menu_shell->have_xgrab)
1150         {
1151           GdkDevice *keyboard;
1152
1153           gdk_device_ungrab (priv->grab_pointer, GDK_CURRENT_TIME);
1154           keyboard = gdk_device_get_associated_device (priv->grab_pointer);
1155
1156           if (keyboard)
1157             gdk_device_ungrab (keyboard, GDK_CURRENT_TIME);
1158
1159           menu_shell->have_xgrab = FALSE;
1160         }
1161
1162       menu_shell->keyboard_mode = FALSE;
1163       _gtk_menu_shell_set_grab_device (menu_shell, NULL);
1164
1165       _gtk_menu_shell_update_mnemonics (menu_shell);
1166     }
1167 }
1168
1169 static gint
1170 gtk_menu_shell_is_item (GtkMenuShell *menu_shell,
1171                         GtkWidget    *child)
1172 {
1173   GtkWidget *parent;
1174
1175   g_return_val_if_fail (GTK_IS_MENU_SHELL (menu_shell), FALSE);
1176   g_return_val_if_fail (child != NULL, FALSE);
1177
1178   parent = gtk_widget_get_parent (child);
1179   while (GTK_IS_MENU_SHELL (parent))
1180     {
1181       if (parent == (GtkWidget*) menu_shell)
1182         return TRUE;
1183       parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
1184     }
1185
1186   return FALSE;
1187 }
1188
1189 static GtkWidget*
1190 gtk_menu_shell_get_item (GtkMenuShell *menu_shell,
1191                          GdkEvent     *event)
1192 {
1193   GtkWidget *menu_item;
1194
1195   menu_item = gtk_get_event_widget ((GdkEvent*) event);
1196   
1197   while (menu_item && !GTK_IS_MENU_ITEM (menu_item))
1198     menu_item = gtk_widget_get_parent (menu_item);
1199
1200   if (menu_item && gtk_menu_shell_is_item (menu_shell, menu_item))
1201     return menu_item;
1202   else
1203     return NULL;
1204 }
1205
1206 /* Handlers for action signals */
1207
1208 void
1209 gtk_menu_shell_select_item (GtkMenuShell *menu_shell,
1210                             GtkWidget    *menu_item)
1211 {
1212   GtkMenuShellClass *class;
1213
1214   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1215   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1216
1217   class = GTK_MENU_SHELL_GET_CLASS (menu_shell);
1218
1219   if (class->select_item &&
1220       !(menu_shell->active &&
1221         menu_shell->active_menu_item == menu_item))
1222     class->select_item (menu_shell, menu_item);
1223 }
1224
1225 void _gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
1226                                    GtkSubmenuPlacement  placement);
1227
1228 static void
1229 gtk_menu_shell_real_select_item (GtkMenuShell *menu_shell,
1230                                  GtkWidget    *menu_item)
1231 {
1232   GtkPackDirection pack_dir = PACK_DIRECTION (menu_shell);
1233
1234   if (menu_shell->active_menu_item)
1235     {
1236       gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
1237       menu_shell->active_menu_item = NULL;
1238     }
1239
1240   if (!_gtk_menu_item_is_selectable (menu_item))
1241     {
1242       GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1243
1244       priv->in_unselectable_item = TRUE;
1245       _gtk_menu_shell_update_mnemonics (menu_shell);
1246
1247       return;
1248     }
1249
1250   menu_shell->active_menu_item = menu_item;
1251   if (pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT)
1252     _gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item),
1253                                   GTK_LEFT_RIGHT);
1254   else
1255     _gtk_menu_item_set_placement (GTK_MENU_ITEM (menu_shell->active_menu_item),
1256                                   GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement);
1257   gtk_menu_item_select (GTK_MENU_ITEM (menu_shell->active_menu_item));
1258
1259   _gtk_menu_shell_update_mnemonics (menu_shell);
1260
1261   /* This allows the bizarre radio buttons-with-submenus-display-history
1262    * behavior
1263    */
1264   if (GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu)
1265     gtk_widget_activate (menu_shell->active_menu_item);
1266 }
1267
1268 void
1269 gtk_menu_shell_deselect (GtkMenuShell *menu_shell)
1270 {
1271   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1272
1273   if (menu_shell->active_menu_item)
1274     {
1275       gtk_menu_item_deselect (GTK_MENU_ITEM (menu_shell->active_menu_item));
1276       menu_shell->active_menu_item = NULL;
1277       _gtk_menu_shell_update_mnemonics (menu_shell);
1278     }
1279 }
1280
1281 void
1282 gtk_menu_shell_activate_item (GtkMenuShell      *menu_shell,
1283                               GtkWidget         *menu_item,
1284                               gboolean           force_deactivate)
1285 {
1286   GSList *slist, *shells = NULL;
1287   gboolean deactivate = force_deactivate;
1288
1289   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1290   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1291
1292   if (!deactivate)
1293     deactivate = GTK_MENU_ITEM_GET_CLASS (menu_item)->hide_on_activate;
1294
1295   g_object_ref (menu_shell);
1296   g_object_ref (menu_item);
1297
1298   if (deactivate)
1299     {
1300       GtkMenuShell *parent_menu_shell = menu_shell;
1301
1302       do
1303         {
1304           g_object_ref (parent_menu_shell);
1305           shells = g_slist_prepend (shells, parent_menu_shell);
1306           parent_menu_shell = (GtkMenuShell*) parent_menu_shell->parent_menu_shell;
1307         }
1308       while (parent_menu_shell);
1309       shells = g_slist_reverse (shells);
1310
1311       gtk_menu_shell_deactivate (menu_shell);
1312   
1313       /* flush the x-queue, so any grabs are removed and
1314        * the menu is actually taken down
1315        */
1316       gdk_display_sync (gtk_widget_get_display (menu_item));
1317     }
1318
1319   gtk_widget_activate (menu_item);
1320
1321   for (slist = shells; slist; slist = slist->next)
1322     {
1323       g_signal_emit (slist->data, menu_shell_signals[SELECTION_DONE], 0);
1324       g_object_unref (slist->data);
1325     }
1326   g_slist_free (shells);
1327
1328   g_object_unref (menu_shell);
1329   g_object_unref (menu_item);
1330 }
1331
1332 /* Distance should be +/- 1 */
1333 static gboolean
1334 gtk_menu_shell_real_move_selected (GtkMenuShell  *menu_shell, 
1335                                    gint           distance)
1336 {
1337   if (menu_shell->active_menu_item)
1338     {
1339       GList *node = g_list_find (menu_shell->children,
1340                                  menu_shell->active_menu_item);
1341       GList *start_node = node;
1342       gboolean wrap_around;
1343
1344       g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
1345                     "gtk-keynav-wrap-around", &wrap_around,
1346                     NULL);
1347
1348       if (distance > 0)
1349         {
1350           node = node->next;
1351           while (node != start_node && 
1352                  (!node || !_gtk_menu_item_is_selectable (node->data)))
1353             {
1354               if (node)
1355                 node = node->next;
1356               else if (wrap_around)
1357                 node = menu_shell->children;
1358               else
1359                 {
1360                   gtk_widget_error_bell (GTK_WIDGET (menu_shell));
1361                   break;
1362                 }
1363             }
1364         }
1365       else
1366         {
1367           node = node->prev;
1368           while (node != start_node &&
1369                  (!node || !_gtk_menu_item_is_selectable (node->data)))
1370             {
1371               if (node)
1372                 node = node->prev;
1373               else if (wrap_around)
1374                 node = g_list_last (menu_shell->children);
1375               else
1376                 {
1377                   gtk_widget_error_bell (GTK_WIDGET (menu_shell));
1378                   break;
1379                 }
1380             }
1381         }
1382       
1383       if (node)
1384         gtk_menu_shell_select_item (menu_shell, node->data);
1385     }
1386
1387   return TRUE;
1388 }
1389
1390 /* Distance should be +/- 1 */
1391 static void
1392 gtk_menu_shell_move_selected (GtkMenuShell  *menu_shell, 
1393                               gint           distance)
1394 {
1395   gboolean handled = FALSE;
1396
1397   g_signal_emit (menu_shell, menu_shell_signals[MOVE_SELECTED], 0,
1398                  distance, &handled);
1399 }
1400
1401 /**
1402  * gtk_menu_shell_select_first:
1403  * @menu_shell: a #GtkMenuShell
1404  * @search_sensitive: if %TRUE, search for the first selectable
1405  *                    menu item, otherwise select nothing if
1406  *                    the first item isn't sensitive. This
1407  *                    should be %FALSE if the menu is being
1408  *                    popped up initially.
1409  * 
1410  * Select the first visible or selectable child of the menu shell;
1411  * don't select tearoff items unless the only item is a tearoff
1412  * item.
1413  *
1414  * Since: 2.2
1415  **/
1416 void
1417 gtk_menu_shell_select_first (GtkMenuShell *menu_shell,
1418                              gboolean      search_sensitive)
1419 {
1420   GtkWidget *to_select = NULL;
1421   GList *tmp_list;
1422
1423   tmp_list = menu_shell->children;
1424   while (tmp_list)
1425     {
1426       GtkWidget *child = tmp_list->data;
1427       
1428       if ((!search_sensitive && gtk_widget_get_visible (child)) ||
1429           _gtk_menu_item_is_selectable (child))
1430         {
1431           to_select = child;
1432           if (!GTK_IS_TEAROFF_MENU_ITEM (child))
1433             break;
1434         }
1435       
1436       tmp_list = tmp_list->next;
1437     }
1438
1439   if (to_select)
1440     gtk_menu_shell_select_item (menu_shell, to_select);
1441 }
1442
1443 void
1444 _gtk_menu_shell_select_last (GtkMenuShell *menu_shell,
1445                              gboolean      search_sensitive)
1446 {
1447   GtkWidget *to_select = NULL;
1448   GList *tmp_list;
1449
1450   tmp_list = g_list_last (menu_shell->children);
1451   while (tmp_list)
1452     {
1453       GtkWidget *child = tmp_list->data;
1454       
1455       if ((!search_sensitive && gtk_widget_get_visible (child)) ||
1456           _gtk_menu_item_is_selectable (child))
1457         {
1458           to_select = child;
1459           if (!GTK_IS_TEAROFF_MENU_ITEM (child))
1460             break;
1461         }
1462       
1463       tmp_list = tmp_list->prev;
1464     }
1465
1466   if (to_select)
1467     gtk_menu_shell_select_item (menu_shell, to_select);
1468 }
1469
1470 static gboolean
1471 gtk_menu_shell_select_submenu_first (GtkMenuShell     *menu_shell)
1472 {
1473   GtkMenuItem *menu_item;
1474
1475   if (menu_shell->active_menu_item == NULL)
1476     return FALSE;
1477
1478   menu_item = GTK_MENU_ITEM (menu_shell->active_menu_item); 
1479   
1480   if (menu_item->submenu)
1481     {
1482       _gtk_menu_item_popup_submenu (GTK_WIDGET (menu_item), FALSE);
1483       gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
1484       if (GTK_MENU_SHELL (menu_item->submenu)->active_menu_item)
1485         return TRUE;
1486     }
1487
1488   return FALSE;
1489 }
1490
1491 static void
1492 gtk_real_menu_shell_move_current (GtkMenuShell         *menu_shell,
1493                                   GtkMenuDirectionType  direction)
1494 {
1495   GtkMenuShellPrivate *priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1496   GtkMenuShell *parent_menu_shell = NULL;
1497   gboolean had_selection;
1498   gboolean touchscreen_mode;
1499
1500   priv->in_unselectable_item = FALSE;
1501
1502   had_selection = menu_shell->active_menu_item != NULL;
1503
1504   g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
1505                 "gtk-touchscreen-mode", &touchscreen_mode,
1506                 NULL);
1507
1508   if (menu_shell->parent_menu_shell)
1509     parent_menu_shell = GTK_MENU_SHELL (menu_shell->parent_menu_shell);
1510
1511   switch (direction)
1512     {
1513     case GTK_MENU_DIR_PARENT:
1514       if (touchscreen_mode &&
1515           menu_shell->active_menu_item &&
1516           GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu &&
1517           gtk_widget_get_visible (GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu))
1518         {
1519           /* if we are on a menu item that has an open submenu but the
1520            * focus is not in that submenu (e.g. because it's empty or
1521            * has only insensitive items), close that submenu instead
1522            * of running into the code below which would close *this*
1523            * menu.
1524            */
1525           _gtk_menu_item_popdown_submenu (menu_shell->active_menu_item);
1526           _gtk_menu_shell_update_mnemonics (menu_shell);
1527         }
1528       else if (parent_menu_shell)
1529         {
1530           if (touchscreen_mode)
1531             {
1532               /* close menu when returning from submenu. */
1533               _gtk_menu_item_popdown_submenu (GTK_MENU (menu_shell)->parent_menu_item);
1534               _gtk_menu_shell_update_mnemonics (parent_menu_shell);
1535               break;
1536             }
1537
1538           if (GTK_MENU_SHELL_GET_CLASS (parent_menu_shell)->submenu_placement ==
1539               GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement)
1540             gtk_menu_shell_deselect (menu_shell);
1541           else
1542             {
1543               if (PACK_DIRECTION (parent_menu_shell) == GTK_PACK_DIRECTION_LTR)
1544                 gtk_menu_shell_move_selected (parent_menu_shell, -1);
1545               else
1546                 gtk_menu_shell_move_selected (parent_menu_shell, 1);
1547               gtk_menu_shell_select_submenu_first (parent_menu_shell);
1548             }
1549         }
1550       /* If there is no parent and the submenu is in the opposite direction
1551        * to the menu, then make the PARENT direction wrap around to
1552        * the bottom of the submenu.
1553        */
1554       else if (menu_shell->active_menu_item &&
1555                _gtk_menu_item_is_selectable (menu_shell->active_menu_item) &&
1556                GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu)
1557         {
1558           GtkMenuShell *submenu = GTK_MENU_SHELL (GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu);
1559
1560           if (GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement !=
1561               GTK_MENU_SHELL_GET_CLASS (submenu)->submenu_placement)
1562             _gtk_menu_shell_select_last (submenu, TRUE);
1563         }
1564       break;
1565
1566     case GTK_MENU_DIR_CHILD:
1567       if (menu_shell->active_menu_item &&
1568           _gtk_menu_item_is_selectable (menu_shell->active_menu_item) &&
1569           GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu)
1570         {
1571           if (gtk_menu_shell_select_submenu_first (menu_shell))
1572             break;
1573         }
1574
1575       /* Try to find a menu running the opposite direction */
1576       while (parent_menu_shell &&
1577              (GTK_MENU_SHELL_GET_CLASS (parent_menu_shell)->submenu_placement ==
1578               GTK_MENU_SHELL_GET_CLASS (menu_shell)->submenu_placement))
1579         {
1580           parent_menu_shell = GTK_MENU_SHELL (parent_menu_shell->parent_menu_shell);
1581         }
1582
1583       if (parent_menu_shell)
1584         {
1585           if (PACK_DIRECTION (parent_menu_shell) == GTK_PACK_DIRECTION_LTR)
1586             gtk_menu_shell_move_selected (parent_menu_shell, 1);
1587           else
1588             gtk_menu_shell_move_selected (parent_menu_shell, -1);
1589
1590           gtk_menu_shell_select_submenu_first (parent_menu_shell);
1591         }
1592       break;
1593
1594     case GTK_MENU_DIR_PREV:
1595       gtk_menu_shell_move_selected (menu_shell, -1);
1596       if (!had_selection &&
1597           !menu_shell->active_menu_item &&
1598           menu_shell->children)
1599         _gtk_menu_shell_select_last (menu_shell, TRUE);
1600       break;
1601
1602     case GTK_MENU_DIR_NEXT:
1603       gtk_menu_shell_move_selected (menu_shell, 1);
1604       if (!had_selection &&
1605           !menu_shell->active_menu_item &&
1606           menu_shell->children)
1607         gtk_menu_shell_select_first (menu_shell, TRUE);
1608       break;
1609     }
1610 }
1611
1612 static void
1613 gtk_real_menu_shell_activate_current (GtkMenuShell      *menu_shell,
1614                                       gboolean           force_hide)
1615 {
1616   if (menu_shell->active_menu_item &&
1617       _gtk_menu_item_is_selectable (menu_shell->active_menu_item))
1618   {
1619     if (GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL)
1620       gtk_menu_shell_activate_item (menu_shell,
1621                                     menu_shell->active_menu_item,
1622                                     force_hide);
1623     else
1624       _gtk_menu_item_popup_submenu (menu_shell->active_menu_item, FALSE);
1625   }
1626 }
1627
1628 static void
1629 gtk_real_menu_shell_cancel (GtkMenuShell      *menu_shell)
1630 {
1631   /* Unset the active menu item so gtk_menu_popdown() doesn't see it.
1632    */
1633   gtk_menu_shell_deselect (menu_shell);
1634   
1635   gtk_menu_shell_deactivate (menu_shell);
1636   g_signal_emit (menu_shell, menu_shell_signals[SELECTION_DONE], 0);
1637 }
1638
1639 static void
1640 gtk_real_menu_shell_cycle_focus (GtkMenuShell      *menu_shell,
1641                                  GtkDirectionType   dir)
1642 {
1643   while (menu_shell && !GTK_IS_MENU_BAR (menu_shell))
1644     {
1645       if (menu_shell->parent_menu_shell)
1646         menu_shell = GTK_MENU_SHELL (menu_shell->parent_menu_shell);
1647       else
1648         menu_shell = NULL;
1649     }
1650
1651   if (menu_shell)
1652     _gtk_menu_bar_cycle_focus (GTK_MENU_BAR (menu_shell), dir);
1653 }
1654
1655 gint
1656 _gtk_menu_shell_get_popup_delay (GtkMenuShell *menu_shell)
1657 {
1658   GtkMenuShellClass *klass = GTK_MENU_SHELL_GET_CLASS (menu_shell);
1659   
1660   if (klass->get_popup_delay)
1661     {
1662       return klass->get_popup_delay (menu_shell);
1663     }
1664   else
1665     {
1666       gint popup_delay;
1667       GtkWidget *widget = GTK_WIDGET (menu_shell);
1668       
1669       g_object_get (gtk_widget_get_settings (widget),
1670                     "gtk-menu-popup-delay", &popup_delay,
1671                     NULL);
1672       
1673       return popup_delay;
1674     }
1675 }
1676
1677 /**
1678  * gtk_menu_shell_cancel:
1679  * @menu_shell: a #GtkMenuShell
1680  * 
1681  * Cancels the selection within the menu shell.  
1682  * 
1683  * Since: 2.4
1684  */
1685 void
1686 gtk_menu_shell_cancel (GtkMenuShell *menu_shell)
1687 {
1688   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1689
1690   g_signal_emit (menu_shell, menu_shell_signals[CANCEL], 0);
1691 }
1692
1693 static GtkMnemonicHash *
1694 gtk_menu_shell_get_mnemonic_hash (GtkMenuShell *menu_shell,
1695                                   gboolean      create)
1696 {
1697   GtkMenuShellPrivate *private = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1698
1699   if (!private->mnemonic_hash && create)
1700     private->mnemonic_hash = _gtk_mnemonic_hash_new ();
1701   
1702   return private->mnemonic_hash;
1703 }
1704
1705 static void
1706 menu_shell_add_mnemonic_foreach (guint    keyval,
1707                                  GSList  *targets,
1708                                  gpointer data)
1709 {
1710   GtkKeyHash *key_hash = data;
1711
1712   _gtk_key_hash_add_entry (key_hash, keyval, 0, GUINT_TO_POINTER (keyval));
1713 }
1714
1715 static GtkKeyHash *
1716 gtk_menu_shell_get_key_hash (GtkMenuShell *menu_shell,
1717                              gboolean      create)
1718 {
1719   GtkMenuShellPrivate *private = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1720   GtkWidget *widget = GTK_WIDGET (menu_shell);
1721
1722   if (!private->key_hash && create && gtk_widget_has_screen (widget))
1723     {
1724       GtkMnemonicHash *mnemonic_hash = gtk_menu_shell_get_mnemonic_hash (menu_shell, FALSE);
1725       GdkScreen *screen = gtk_widget_get_screen (widget);
1726       GdkKeymap *keymap = gdk_keymap_get_for_display (gdk_screen_get_display (screen));
1727
1728       if (!mnemonic_hash)
1729         return NULL;
1730       
1731       private->key_hash = _gtk_key_hash_new (keymap, NULL);
1732
1733       _gtk_mnemonic_hash_foreach (mnemonic_hash,
1734                                   menu_shell_add_mnemonic_foreach,
1735                                   private->key_hash);
1736     }
1737   
1738   return private->key_hash;
1739 }
1740
1741 static void
1742 gtk_menu_shell_reset_key_hash (GtkMenuShell *menu_shell)
1743 {
1744   GtkMenuShellPrivate *private = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1745
1746   if (private->key_hash)
1747     {
1748       _gtk_key_hash_free (private->key_hash);
1749       private->key_hash = NULL;
1750     }
1751 }
1752
1753 static gboolean
1754 gtk_menu_shell_activate_mnemonic (GtkMenuShell *menu_shell,
1755                                   GdkEventKey  *event)
1756 {
1757   GtkMnemonicHash *mnemonic_hash;
1758   GtkKeyHash *key_hash;
1759   GSList *entries;
1760   gboolean result = FALSE;
1761
1762   mnemonic_hash = gtk_menu_shell_get_mnemonic_hash (menu_shell, FALSE);
1763   if (!mnemonic_hash)
1764     return FALSE;
1765
1766   key_hash = gtk_menu_shell_get_key_hash (menu_shell, TRUE);
1767   if (!key_hash)
1768     return FALSE;
1769   
1770   entries = _gtk_key_hash_lookup (key_hash,
1771                                   event->hardware_keycode,
1772                                   event->state,
1773                                   gtk_accelerator_get_default_mod_mask (),
1774                                   event->group);
1775
1776   if (entries)
1777     result = _gtk_mnemonic_hash_activate (mnemonic_hash,
1778                                           GPOINTER_TO_UINT (entries->data));
1779
1780   return result;
1781 }
1782
1783 void
1784 _gtk_menu_shell_add_mnemonic (GtkMenuShell *menu_shell,
1785                               guint      keyval,
1786                               GtkWidget *target)
1787 {
1788   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1789   g_return_if_fail (GTK_IS_WIDGET (target));
1790
1791   _gtk_mnemonic_hash_add (gtk_menu_shell_get_mnemonic_hash (menu_shell, TRUE),
1792                           keyval, target);
1793   gtk_menu_shell_reset_key_hash (menu_shell);
1794 }
1795
1796 void
1797 _gtk_menu_shell_remove_mnemonic (GtkMenuShell *menu_shell,
1798                                  guint      keyval,
1799                                  GtkWidget *target)
1800 {
1801   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1802   g_return_if_fail (GTK_IS_WIDGET (target));
1803   
1804   _gtk_mnemonic_hash_remove (gtk_menu_shell_get_mnemonic_hash (menu_shell, TRUE),
1805                              keyval, target);
1806   gtk_menu_shell_reset_key_hash (menu_shell);
1807 }
1808
1809 void
1810 _gtk_menu_shell_set_grab_device (GtkMenuShell *menu_shell,
1811                                  GdkDevice    *device)
1812 {
1813   GtkMenuShellPrivate *priv;
1814
1815   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1816   g_return_if_fail (!device || GDK_IS_DEVICE (device));
1817
1818   priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1819
1820   if (!device)
1821     priv->grab_pointer = NULL;
1822   else if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
1823     priv->grab_pointer = gdk_device_get_associated_device (device);
1824   else
1825     priv->grab_pointer = device;
1826 }
1827
1828 GdkDevice *
1829 _gtk_menu_shell_get_grab_device (GtkMenuShell  *menu_shell)
1830 {
1831   GtkMenuShellPrivate *priv;
1832
1833   g_return_val_if_fail (GTK_IS_MENU_SHELL (menu_shell), NULL);
1834
1835   priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1836
1837   return priv->grab_pointer;
1838 }
1839
1840 /**
1841  * gtk_menu_shell_get_take_focus:
1842  * @menu_shell: a #GtkMenuShell
1843  *
1844  * Returns %TRUE if the menu shell will take the keyboard focus on popup.
1845  *
1846  * Returns: %TRUE if the menu shell will take the keyboard focus on popup.
1847  *
1848  * Since: 2.8
1849  **/
1850 gboolean
1851 gtk_menu_shell_get_take_focus (GtkMenuShell *menu_shell)
1852 {
1853   GtkMenuShellPrivate *priv;
1854
1855   g_return_val_if_fail (GTK_IS_MENU_SHELL (menu_shell), FALSE);
1856
1857   priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1858
1859   return priv->take_focus;
1860 }
1861
1862 /**
1863  * gtk_menu_shell_set_take_focus:
1864  * @menu_shell: a #GtkMenuShell
1865  * @take_focus: %TRUE if the menu shell should take the keyboard focus on popup.
1866  *
1867  * If @take_focus is %TRUE (the default) the menu shell will take the keyboard 
1868  * focus so that it will receive all keyboard events which is needed to enable
1869  * keyboard navigation in menus.
1870  *
1871  * Setting @take_focus to %FALSE is useful only for special applications
1872  * like virtual keyboard implementations which should not take keyboard
1873  * focus.
1874  *
1875  * The @take_focus state of a menu or menu bar is automatically propagated
1876  * to submenus whenever a submenu is popped up, so you don't have to worry
1877  * about recursively setting it for your entire menu hierarchy. Only when
1878  * programmatically picking a submenu and popping it up manually, the
1879  * @take_focus property of the submenu needs to be set explicitely.
1880  *
1881  * Note that setting it to %FALSE has side-effects:
1882  *
1883  * If the focus is in some other app, it keeps the focus and keynav in
1884  * the menu doesn't work. Consequently, keynav on the menu will only
1885  * work if the focus is on some toplevel owned by the onscreen keyboard.
1886  *
1887  * To avoid confusing the user, menus with @take_focus set to %FALSE
1888  * should not display mnemonics or accelerators, since it cannot be
1889  * guaranteed that they will work.
1890  *
1891  * See also gdk_keyboard_grab()
1892  *
1893  * Since: 2.8
1894  **/
1895 void
1896 gtk_menu_shell_set_take_focus (GtkMenuShell *menu_shell,
1897                                gboolean      take_focus)
1898 {
1899   GtkMenuShellPrivate *priv;
1900
1901   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1902
1903   priv = GTK_MENU_SHELL_GET_PRIVATE (menu_shell);
1904
1905   if (priv->take_focus != take_focus)
1906     {
1907       priv->take_focus = take_focus;
1908       g_object_notify (G_OBJECT (menu_shell), "take-focus");
1909     }
1910 }