]> code.delx.au - gnu-emacs/blobdiff - src/xmenu.c
Merge from emacs--devo--0
[gnu-emacs] / src / xmenu.c
index 6de1dcb2bd15c40877994c6eafccd834ad0c4df3..bf9a9101ef043d0a0dd85bc2cfc21f43ed25fc5c 100644 (file)
@@ -1,12 +1,12 @@
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -41,10 +41,10 @@ Boston, MA 02110-1301, USA.  */
 #include <stdio.h>
 
 #include "lisp.h"
 #include <stdio.h>
 
 #include "lisp.h"
-#include "termhooks.h"
 #include "keyboard.h"
 #include "keymap.h"
 #include "frame.h"
 #include "keyboard.h"
 #include "keymap.h"
 #include "frame.h"
+#include "termhooks.h"
 #include "window.h"
 #include "blockinput.h"
 #include "buffer.h"
 #include "window.h"
 #include "blockinput.h"
 #include "buffer.h"
@@ -82,7 +82,11 @@ Boston, MA 02110-1301, USA.  */
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
 #ifdef USE_LUCID
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
 #ifdef USE_LUCID
+#ifdef HAVE_XAW3D
+#include <X11/Xaw3d/Paned.h>
+#else /* !HAVE_XAW3D */
 #include <X11/Xaw/Paned.h>
 #include <X11/Xaw/Paned.h>
+#endif /* HAVE_XAW3D */
 #endif /* USE_LUCID */
 #include "../lwlib/lwlib.h"
 #else /* not USE_X_TOOLKIT */
 #endif /* USE_LUCID */
 #include "../lwlib/lwlib.h"
 #else /* not USE_X_TOOLKIT */
@@ -97,10 +101,10 @@ Boston, MA 02110-1301, USA.  */
 #define FALSE 0
 #endif /* no TRUE */
 
 #define FALSE 0
 #endif /* no TRUE */
 
-Lisp_Object Vmenu_updating_frame;
-
 Lisp_Object Qdebug_on_next_call;
 
 Lisp_Object Qdebug_on_next_call;
 
+extern Lisp_Object Vmenu_updating_frame;
+
 extern Lisp_Object Qmenu_bar;
 
 extern Lisp_Object QCtoggle, QCradio;
 extern Lisp_Object Qmenu_bar;
 
 extern Lisp_Object QCtoggle, QCradio;
@@ -325,8 +329,9 @@ restore_menu_items (saved)
   menu_items_used = XINT (XCAR (saved));
   saved = XCDR (saved);
   menu_items_n_panes = XINT (XCAR (saved));
   menu_items_used = XINT (XCAR (saved));
   saved = XCDR (saved);
   menu_items_n_panes = XINT (XCAR (saved));
-  saved = XCDR (saved);  
+  saved = XCDR (saved);
   menu_items_submenu_depth = XINT (XCAR (saved));
   menu_items_submenu_depth = XINT (XCAR (saved));
+  return Qnil;
 }
 
 /* Push the whole state of menu_items processing onto the specpdl.
 }
 
 /* Push the whole state of menu_items processing onto the specpdl.
@@ -740,6 +745,9 @@ mouse_position_for_popup (f, x, y)
   Window root, dummy_window;
   int dummy;
 
   Window root, dummy_window;
   int dummy;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   BLOCK_INPUT;
 
   XQueryPointer (FRAME_X_DISPLAY (f),
   BLOCK_INPUT;
 
   XQueryPointer (FRAME_X_DISPLAY (f),
@@ -821,7 +829,7 @@ no quit occurs and `x-popup-menu' returns nil.  */)
   int xpos = 0, ypos = 0;
   Lisp_Object title;
   char *error_name = NULL;
   int xpos = 0, ypos = 0;
   Lisp_Object title;
   char *error_name = NULL;
-  Lisp_Object selection;
+  Lisp_Object selection = Qnil;
   FRAME_PTR f = NULL;
   Lisp_Object x, y, window;
   int keymaps = 0;
   FRAME_PTR f = NULL;
   Lisp_Object x, y, window;
   int keymaps = 0;
@@ -935,6 +943,9 @@ no quit occurs and `x-popup-menu' returns nil.  */)
       xpos += XINT (x);
       ypos += XINT (y);
 
       xpos += XINT (x);
       ypos += XINT (y);
 
+      if (! FRAME_X_P (f))
+        error ("Can not put X menu on non-X terminal");
+
       XSETFRAME (Vmenu_updating_frame, f);
     }
   else
       XSETFRAME (Vmenu_updating_frame, f);
     }
   else
@@ -1123,6 +1134,9 @@ for instance using the window manager, then this produces a quit and
        but I don't want to make one now.  */
     CHECK_WINDOW (window);
 
        but I don't want to make one now.  */
     CHECK_WINDOW (window);
 
+  if (! FRAME_X_P (f))
+    error ("Can not put X dialog on non-X terminal");
+
 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   /* Display a menu with these alternatives
      in the middle of frame F.  */
 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   /* Display a menu with these alternatives
      in the middle of frame F.  */
@@ -1181,6 +1195,10 @@ x_menu_set_in_use (in_use)
 {
   menu_items_inuse = in_use ? Qt : Qnil;
   popup_activated_flag = in_use;
 {
   menu_items_inuse = in_use ? Qt : Qnil;
   popup_activated_flag = in_use;
+#ifdef USE_X_TOOLKIT
+  if (popup_activated_flag)
+    x_activate_timeout_atimer ();
+#endif
 }
 
 /* Wait for an X event to arrive or for a timer to expire.  */
 }
 
 /* Wait for an X event to arrive or for a timer to expire.  */
@@ -1300,9 +1318,124 @@ popup_get_selection (initial_event, dpyinfo, id, do_timers)
     }
 }
 
     }
 }
 
+DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
+       doc: /* Start key navigation of the menu bar in FRAME.
+This initially opens the first menu bar item and you can then navigate with the
+arrow keys, select a menu entry with the return key or cancel with the
+escape key.  If FRAME has no menu bar this function does nothing.
+
+If FRAME is nil or not given, use the selected frame.  */)
+     (frame)
+     Lisp_Object frame;
+{
+  XEvent ev;
+  FRAME_PTR f = check_x_frame (frame);
+  Widget menubar;
+  BLOCK_INPUT;
+
+  if (FRAME_EXTERNAL_MENU_BAR (f))
+    set_frame_menubar (f, 0, 1);
+
+  menubar = FRAME_X_OUTPUT (f)->menubar_widget;
+  if (menubar)
+    {
+      Window child;
+      int error_p = 0;
+
+      x_catch_errors (FRAME_X_DISPLAY (f));
+      memset (&ev, 0, sizeof ev);
+      ev.xbutton.display = FRAME_X_DISPLAY (f);
+      ev.xbutton.window = XtWindow (menubar);
+      ev.xbutton.root = FRAME_X_DISPLAY_INFO (f)->root_window;
+      ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
+      ev.xbutton.button = Button1;
+      ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
+      ev.xbutton.same_screen = True;
+
+#ifdef USE_MOTIF
+      {
+        Arg al[2];
+        WidgetList list;
+        Cardinal nr;
+        XtSetArg (al[0], XtNchildren, &list);
+        XtSetArg (al[1], XtNnumChildren, &nr);
+        XtGetValues (menubar, al, 2);
+        ev.xbutton.window = XtWindow (list[0]);
+      }
+#endif
+
+      XTranslateCoordinates (FRAME_X_DISPLAY (f),
+                             /* From-window, to-window.  */
+                             ev.xbutton.window, ev.xbutton.root,
+
+                             /* From-position, to-position.  */
+                             ev.xbutton.x, ev.xbutton.y,
+                             &ev.xbutton.x_root, &ev.xbutton.y_root,
+
+                             /* Child of win.  */
+                             &child);
+      error_p = x_had_errors_p (FRAME_X_DISPLAY (f));
+      x_uncatch_errors ();
+
+      if (! error_p)
+        {
+          ev.type = ButtonPress;
+          ev.xbutton.state = 0;
+
+          XtDispatchEvent (&ev);
+          ev.xbutton.type = ButtonRelease;
+          ev.xbutton.state = Button1Mask;
+          XtDispatchEvent (&ev);
+        }
+    }
+
+  UNBLOCK_INPUT;
+
+  return Qnil;
+}
 #endif /* USE_X_TOOLKIT */
 
 #endif /* USE_X_TOOLKIT */
 
+
 #ifdef USE_GTK
 #ifdef USE_GTK
+DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
+       doc: /* Start key navigation of the menu bar in FRAME.
+This initially opens the first menu bar item and you can then navigate with the
+arrow keys, select a menu entry with the return key or cancel with the
+escape key.  If FRAME has no menu bar this function does nothing.
+
+If FRAME is nil or not given, use the selected frame.  */)
+     (frame)
+     Lisp_Object frame;
+{
+  GtkWidget *menubar;
+  FRAME_PTR f;
+
+  /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
+     BLOCK_INPUT.  */
+
+  BLOCK_INPUT;
+  f = check_x_frame (frame);
+
+  if (FRAME_EXTERNAL_MENU_BAR (f))
+    set_frame_menubar (f, 0, 1);
+
+  menubar = FRAME_X_OUTPUT (f)->menubar_widget;
+  if (menubar)
+    {
+      /* Activate the first menu.  */
+      GList *children = gtk_container_get_children (GTK_CONTAINER (menubar));
+
+      gtk_menu_shell_select_item (GTK_MENU_SHELL (menubar),
+                                  GTK_WIDGET (children->data));
+
+      popup_activated_flag = 1;
+      g_list_free (children);
+    }
+  UNBLOCK_INPUT;
+
+  return Qnil;
+}
+
 /* Loop util popup_activated_flag is set to zero in a callback.
    Used for popup menus and dialogs. */
 
 /* Loop util popup_activated_flag is set to zero in a callback.
    Used for popup menus and dialogs. */
 
@@ -1340,6 +1473,9 @@ void
 x_activate_menubar (f)
      FRAME_PTR f;
 {
 x_activate_menubar (f)
      FRAME_PTR f;
 {
+  if (! FRAME_X_P (f))
+    abort ();
+
   if (!f->output_data.x->saved_menu_event->type)
     return;
 
   if (!f->output_data.x->saved_menu_event->type)
     return;
 
@@ -1368,14 +1504,6 @@ x_activate_menubar (f)
   f->output_data.x->saved_menu_event->type = 0;
 }
 
   f->output_data.x->saved_menu_event->type = 0;
 }
 
-/* Detect if a dialog or menu has been posted.  */
-
-int
-popup_activated ()
-{
-  return popup_activated_flag;
-}
-
 /* This callback is invoked when the user selects a menubar cascade
    pushbutton, but before the pulldown menu is posted.  */
 
 /* This callback is invoked when the user selects a menubar cascade
    pushbutton, but before the pulldown menu is posted.  */
 
@@ -1387,6 +1515,9 @@ popup_activate_callback (widget, id, client_data)
      XtPointer client_data;
 {
   popup_activated_flag = 1;
      XtPointer client_data;
 {
   popup_activated_flag = 1;
+#ifdef USE_X_TOOLKIT
+  x_activate_timeout_atimer ();
+#endif
 }
 #endif
 
 }
 #endif
 
@@ -1979,9 +2110,14 @@ update_frame_menubar (f)
 #ifdef USE_GTK
   return xg_update_frame_menubar (f);
 #else
 #ifdef USE_GTK
   return xg_update_frame_menubar (f);
 #else
-  struct x_output *x = f->output_data.x;
+  struct x_output *x;
   int columns, rows;
 
   int columns, rows;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
+  x = f->output_data.x;
+
   if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
     return 0;
 
   if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
     return 0;
 
@@ -2027,7 +2163,7 @@ set_frame_menubar (f, first_time, deep_p)
      int first_time;
      int deep_p;
 {
      int first_time;
      int deep_p;
 {
-  xt_or_gtk_widget menubar_widget = f->output_data.x->menubar_widget;
+  xt_or_gtk_widget menubar_widget;
 #ifdef USE_X_TOOLKIT
   LWLIB_ID id;
 #endif
 #ifdef USE_X_TOOLKIT
   LWLIB_ID id;
 #endif
@@ -2037,6 +2173,10 @@ set_frame_menubar (f, first_time, deep_p)
   int *submenu_start, *submenu_end;
   int *submenu_top_level_items, *submenu_n_panes;
 
   int *submenu_start, *submenu_end;
   int *submenu_top_level_items, *submenu_n_panes;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
+  menubar_widget = f->output_data.x->menubar_widget;
 
   XSETFRAME (Vmenu_updating_frame, f);
 
 
   XSETFRAME (Vmenu_updating_frame, f);
 
@@ -2180,21 +2320,27 @@ set_frame_menubar (f, first_time, deep_p)
       /* If there has been no change in the Lisp-level contents
         of the menu bar, skip redisplaying it.  Just exit.  */
 
       /* If there has been no change in the Lisp-level contents
         of the menu bar, skip redisplaying it.  Just exit.  */
 
+      /* Compare the new menu items with the ones computed last time.  */
       for (i = 0; i < previous_menu_items_used; i++)
        if (menu_items_used == i
            || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
          break;
       if (i == menu_items_used && i == previous_menu_items_used && i != 0)
        {
       for (i = 0; i < previous_menu_items_used; i++)
        if (menu_items_used == i
            || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
          break;
       if (i == menu_items_used && i == previous_menu_items_used && i != 0)
        {
+         /* The menu items have not changed.  Don't bother updating
+            the menus in any form, since it would be a no-op.  */
          free_menubar_widget_value_tree (first_wv);
          discard_menu_items ();
          unbind_to (specpdl_count, Qnil);
          return;
        }
 
          free_menubar_widget_value_tree (first_wv);
          discard_menu_items ();
          unbind_to (specpdl_count, Qnil);
          return;
        }
 
+      /* The menu items are different, so store them in the frame.  */
       f->menu_bar_vector = menu_items;
       f->menu_bar_items_used = menu_items_used;
 
       f->menu_bar_vector = menu_items;
       f->menu_bar_items_used = menu_items_used;
 
+      /* This calls restore_menu_items to restore menu_items, etc.,
+        as they were outside.  */
       unbind_to (specpdl_count, Qnil);
 
       /* Now GC cannot happen during the lifetime of the widget_value,
       unbind_to (specpdl_count, Qnil);
 
       /* Now GC cannot happen during the lifetime of the widget_value,
@@ -2383,6 +2529,9 @@ free_frame_menubar (f)
 {
   Widget menubar_widget;
 
 {
   Widget menubar_widget;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   menubar_widget = f->output_data.x->menubar_widget;
 
   f->output_data.x->menubar_height = 0;
   menubar_widget = f->output_data.x->menubar_widget;
 
   f->output_data.x->menubar_height = 0;
@@ -2535,6 +2684,9 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
   struct next_popup_x_y popup_x_y;
   int specpdl_count = SPECPDL_INDEX ();
 
   struct next_popup_x_y popup_x_y;
   int specpdl_count = SPECPDL_INDEX ();
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   xg_crazy_callback_abort = 1;
   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
                            G_CALLBACK (popup_selection_callback),
   xg_crazy_callback_abort = 1;
   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
                            G_CALLBACK (popup_selection_callback),
@@ -2643,6 +2795,9 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
   LWLIB_ID menu_id;
   Widget menu;
 
   LWLIB_ID menu_id;
   Widget menu;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   menu_id = widget_id_tick++;
   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
                            f->output_data.x->widget, 1, 0,
   menu_id = widget_id_tick++;
   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
                            f->output_data.x->widget, 1, 0,
@@ -2681,6 +2836,7 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
   /* Display the menu.  */
   lw_popup_menu (menu, (XEvent *) &dummy);
   popup_activated_flag = 1;
   /* Display the menu.  */
   lw_popup_menu (menu, (XEvent *) &dummy);
   popup_activated_flag = 1;
+  x_activate_timeout_atimer ();
 
   {
     int fact = 4 * sizeof (LWLIB_ID);
 
   {
     int fact = 4 * sizeof (LWLIB_ID);
@@ -2718,6 +2874,9 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
 
   int first_pane;
 
 
   int first_pane;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   *error = NULL;
 
   if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
   *error = NULL;
 
   if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
@@ -3000,6 +3159,9 @@ create_and_show_dialog (f, first_wv)
 {
   GtkWidget *menu;
 
 {
   GtkWidget *menu;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
                            G_CALLBACK (dialog_selection_callback),
                            G_CALLBACK (popup_deactivate_callback),
   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
                            G_CALLBACK (dialog_selection_callback),
                            G_CALLBACK (popup_deactivate_callback),
@@ -3049,6 +3211,9 @@ create_and_show_dialog (f, first_wv)
 {
   LWLIB_ID dialog_id;
 
 {
   LWLIB_ID dialog_id;
 
+  if (!FRAME_X_P (f))
+    abort();
+
   dialog_id = widget_id_tick++;
   lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
                     f->output_data.x->widget, 1, 0,
   dialog_id = widget_id_tick++;
   lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
                     f->output_data.x->widget, 1, 0,
@@ -3058,6 +3223,7 @@ create_and_show_dialog (f, first_wv)
   /* Display the dialog box.  */
   lw_pop_up_all_widgets (dialog_id);
   popup_activated_flag = 1;
   /* Display the dialog box.  */
   lw_pop_up_all_widgets (dialog_id);
   popup_activated_flag = 1;
+  x_activate_timeout_atimer ();
 
   /* Process events that apply to the dialog box.
      Also handle timers.  */
 
   /* Process events that apply to the dialog box.
      Also handle timers.  */
@@ -3100,6 +3266,9 @@ xdialog_show (f, keymaps, title, header, error_name)
   /* 1 means we've seen the boundary between left-hand elts and right-hand.  */
   int boundary_seen = 0;
 
   /* 1 means we've seen the boundary between left-hand elts and right-hand.  */
   int boundary_seen = 0;
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   *error_name = NULL;
 
   if (menu_items_n_panes > 1)
   *error_name = NULL;
 
   if (menu_items_n_panes > 1)
@@ -3210,6 +3379,14 @@ xdialog_show (f, keymaps, title, header, error_name)
   /* No selection has been chosen yet.  */
   menu_item_selection = 0;
 
   /* No selection has been chosen yet.  */
   menu_item_selection = 0;
 
+  /* Force a redisplay before showing the dialog.  If a frame is created
+     just before showing the dialog, its contents may not have been fully
+     drawn, as this depends on timing of events from the X server.  Redisplay
+     is not done when a dialog is shown.  If redisplay could be done in the
+     X event loop (i.e. the X event loop does not run in a signal handler)
+     this would not be needed.  */
+  Fredisplay (Qt);
+
   /* Actually create and show the dialog.  */
   create_and_show_dialog (f, first_wv);
 
   /* Actually create and show the dialog.  */
   create_and_show_dialog (f, first_wv);
 
@@ -3297,7 +3474,7 @@ menu_help_callback (help_string, pane, item)
     pane_name = first_item[MENU_ITEMS_PANE_NAME];
   else if (EQ (first_item[0], Qquote))
     /* This shouldn't happen, see xmenu_show.  */
     pane_name = first_item[MENU_ITEMS_PANE_NAME];
   else if (EQ (first_item[0], Qquote))
     /* This shouldn't happen, see xmenu_show.  */
-    pane_name = empty_string;
+    pane_name = empty_unibyte_string;
   else
     pane_name = first_item[MENU_ITEMS_ITEM_NAME];
 
   else
     pane_name = first_item[MENU_ITEMS_ITEM_NAME];
 
@@ -3367,6 +3544,9 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
   unsigned int dummy_uint;
   int specpdl_count = SPECPDL_INDEX ();
 
   unsigned int dummy_uint;
   int specpdl_count = SPECPDL_INDEX ();
 
+  if (! FRAME_X_P (f))
+    abort ();
+
   *error = 0;
   if (menu_items_n_panes == 0)
     return Qnil;
   *error = 0;
   if (menu_items_n_panes == 0)
     return Qnil;
@@ -3630,6 +3810,27 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
 #endif /* not USE_X_TOOLKIT */
 
 #endif /* HAVE_MENUS */
 #endif /* not USE_X_TOOLKIT */
 
 #endif /* HAVE_MENUS */
+
+/* Detect if a dialog or menu has been posted.  */
+
+int
+popup_activated ()
+{
+  return popup_activated_flag;
+}
+
+/* The following is used by delayed window autoselection.  */
+
+DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
+       doc: /* Return t if a menu or popup dialog is active.  */)
+     ()
+{
+#ifdef HAVE_MENUS
+  return (popup_activated ()) ? Qt : Qnil;
+#else
+  return Qnil;
+#endif /* HAVE_MENUS */
+}
 \f
 void
 syms_of_xmenu ()
 \f
 void
 syms_of_xmenu ()
@@ -3641,17 +3842,20 @@ syms_of_xmenu ()
   Qdebug_on_next_call = intern ("debug-on-next-call");
   staticpro (&Qdebug_on_next_call);
 
   Qdebug_on_next_call = intern ("debug-on-next-call");
   staticpro (&Qdebug_on_next_call);
 
-  DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
-              doc: /* Frame for which we are updating a menu.
-The enable predicate for a menu command should check this variable.  */);
-  Vmenu_updating_frame = Qnil;
-
 #ifdef USE_X_TOOLKIT
   widget_id_tick = (1<<16);
   next_menubar_widget_id = 1;
 #endif
 
   defsubr (&Sx_popup_menu);
 #ifdef USE_X_TOOLKIT
   widget_id_tick = (1<<16);
   next_menubar_widget_id = 1;
 #endif
 
   defsubr (&Sx_popup_menu);
+  defsubr (&Smenu_or_popup_active_p);
+
+#if defined (USE_GTK) || defined (USE_X_TOOLKIT)
+  defsubr (&Sx_menu_bar_open_internal);
+  Ffset (intern ("accelerate-menu"),
+        intern (Sx_menu_bar_open_internal.symbol_name));
+#endif
+
 #ifdef HAVE_MENUS
   defsubr (&Sx_popup_dialog);
 #endif
 #ifdef HAVE_MENUS
   defsubr (&Sx_popup_dialog);
 #endif