/* 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, 2008 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
-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,
#define FALSE 0
#endif /* no TRUE */
-Lisp_Object Vmenu_updating_frame;
-
Lisp_Object Qdebug_on_next_call;
+extern Lisp_Object Vmenu_updating_frame;
+
extern Lisp_Object Qmenu_bar;
extern Lisp_Object QCtoggle, QCradio;
menu_items_n_panes = XINT (XCAR (saved));
saved = XCDR (saved);
menu_items_submenu_depth = XINT (XCAR (saved));
+ return Qnil;
}
/* Push the whole state of menu_items processing onto the specpdl.
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;
{
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. */
}
}
+DEFUN ("menu-bar-open", Fmenu_bar_open, Smenu_bar_open, 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 */
+
#ifdef USE_GTK
+DEFUN ("menu-bar-open", Fmenu_bar_open, Smenu_bar_open, 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. */
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. */
XtPointer client_data;
{
popup_activated_flag = 1;
+#ifdef USE_X_TOOLKIT
+ x_activate_timeout_atimer ();
+#endif
}
#endif
/* 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)
{
+ /* 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;
}
+ /* 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;
+ /* 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,
/* Display the menu. */
lw_popup_menu (menu, (XEvent *) &dummy);
popup_activated_flag = 1;
+ x_activate_timeout_atimer ();
{
int fact = 4 * sizeof (LWLIB_ID);
/* 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. */
/* 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);
#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 ()
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);
+ defsubr (&Smenu_or_popup_active_p);
+
+#if defined (USE_GTK) || defined (USE_X_TOOLKIT)
+ defsubr (&Smenu_bar_open);
+ Ffset (intern ("accelerate-menu"), intern (Smenu_bar_open.symbol_name));
+#endif
+
#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
#endif