1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* X pop-up deck-of-cards menu facility for GNU Emacs.
22 * Written by Jon Arnold and Roman Budzianowski
23 * Mods and rewrite by Robert Krawitz
27 /* Modified by Fred Pierresteguy on December 93
28 to make the popup menus and menubar use the Xt. */
30 /* Rewritten for clarity and GC protection by rms in Feb 94. */
34 #if 0 /* Why was this included? And without syssignal.h? */
35 /* On 4.3 this loses if it comes after xterm.h. */
46 #include "termhooks.h"
48 #include "blockinput.h"
52 #include "sysselect.h"
59 /* This may include sys/types.h, and that somehow loses
60 if this is not done before the other system files. */
64 /* Load sys/types.h if not already loaded.
65 In some systems loading it twice is suicidal. */
67 #include <sys/types.h>
70 #include "dispextern.h"
73 /* Defining HAVE_MULTILINGUAL_MENU would mean that the toolkit menu
74 code accepts the Emacs internal encoding. */
75 #undef HAVE_MULTILINGUAL_MENU
79 #include <X11/IntrinsicP.h>
80 #include <X11/CoreP.h>
81 #include <X11/StringDefs.h>
82 #include <X11/Shell.h>
84 #include "xsettings.h"
85 #include "../lwlib/xlwmenu.h"
87 #include <X11/Xaw3d/Paned.h>
88 #else /* !HAVE_XAW3D */
89 #include <X11/Xaw/Paned.h>
90 #endif /* HAVE_XAW3D */
91 #endif /* USE_LUCID */
92 #include "../lwlib/lwlib.h"
93 #else /* not USE_X_TOOLKIT */
95 #include "../oldXMenu/XMenu.h"
97 #endif /* not USE_X_TOOLKIT */
98 #endif /* HAVE_X_WINDOWS */
111 Lisp_Object Qdebug_on_next_call
;
113 extern Lisp_Object Qmenu_bar
;
115 extern Lisp_Object QCtoggle
, QCradio
;
117 extern Lisp_Object Voverriding_local_map
;
118 extern Lisp_Object Voverriding_local_map_menu_flag
;
120 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
122 extern Lisp_Object Qmenu_bar_update_hook
;
125 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
126 extern XtAppContext Xt_app_con
;
128 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
130 static void popup_get_selection
P_ ((XEvent
*, struct x_display_info
*,
132 #endif /* USE_X_TOOLKIT */
135 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
136 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
140 static int update_frame_menubar
P_ ((struct frame
*));
142 /* Flag which when set indicates a dialog or menu has been posted by
143 Xt on behalf of one of the widget sets. */
144 static int popup_activated_flag
;
146 static int next_menubar_widget_id
;
148 /* For NS and NTGUI, these prototypes are defined in keyboard.h. */
149 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
150 extern widget_value
*xmalloc_widget_value
P_ ((void));
151 extern widget_value
*digest_single_submenu
P_ ((int, int, int));
154 /* This is set nonzero after the user activates the menu bar, and set
155 to zero again after the menu bars are redisplayed by prepare_menu_bar.
156 While it is nonzero, all calls to set_frame_menubar go deep.
158 I don't understand why this is needed, but it does seem to be
159 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
161 int pending_menu_activation
;
165 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
167 static struct frame
*
168 menubar_id_to_frame (id
)
171 Lisp_Object tail
, frame
;
174 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
180 if (!FRAME_WINDOW_P (f
))
182 if (f
->output_data
.x
->id
== id
)
190 #ifdef HAVE_X_WINDOWS
191 /* Return the mouse position in *X and *Y. The coordinates are window
192 relative for the edit window in frame F.
193 This is for Fx_popup_menu. The mouse_position_hook can not
194 be used for X, as it returns window relative coordinates
195 for the window where the mouse is in. This could be the menu bar,
196 the scroll bar or the edit window. Fx_popup_menu needs to be
197 sure it is the edit window. */
199 mouse_position_for_popup (f
, x
, y
)
204 Window root
, dummy_window
;
212 XQueryPointer (FRAME_X_DISPLAY (f
),
213 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
215 /* The root window which contains the pointer. */
218 /* Window pointer is on, not used */
221 /* The position on that root window. */
224 /* x/y in dummy_window coordinates, not used. */
227 /* Modifier keys and pointer buttons, about which
229 (unsigned int *) &dummy
);
233 /* xmenu_show expects window coordinates, not root window
234 coordinates. Translate. */
235 *x
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
236 *y
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
239 #endif /* HAVE_X_WINDOWS */
243 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
244 doc
: /* Pop up a dialog box and return user's selection.
245 POSITION specifies which frame to use.
246 This is normally a mouse button event or a window or frame.
247 If POSITION is t, it means to use the frame the mouse is on.
248 The dialog box appears in the middle of the specified frame.
250 CONTENTS specifies the alternatives to display in the dialog box.
251 It is a list of the form (DIALOG ITEM1 ITEM2...).
252 Each ITEM is a cons cell (STRING . VALUE).
253 The return value is VALUE from the chosen item.
255 An ITEM may also be just a string--that makes a nonselectable item.
256 An ITEM may also be nil--that means to put all preceding items
257 on the left of the dialog box and all following items on the right.
258 \(By default, approximately half appear on each side.)
260 If HEADER is non-nil, the frame title for the box is "Information",
261 otherwise it is "Question".
263 If the user gets rid of the dialog box without making a valid choice,
264 for instance using the window manager, then this produces a quit and
265 `x-popup-dialog' does not return. */)
266 (position
, contents
, header
)
267 Lisp_Object position
, contents
, header
;
274 /* Decode the first argument: find the window or frame to use. */
275 if (EQ (position
, Qt
)
276 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
277 || EQ (XCAR (position
), Qtool_bar
))))
279 #if 0 /* Using the frame the mouse is on may not be right. */
280 /* Use the mouse's current position. */
281 FRAME_PTR new_f
= SELECTED_FRAME ();
282 Lisp_Object bar_window
;
283 enum scroll_bar_part part
;
287 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
290 XSETFRAME (window
, new_f
);
292 window
= selected_window
;
294 window
= selected_window
;
296 else if (CONSP (position
))
299 tem
= Fcar (position
);
301 window
= Fcar (Fcdr (position
));
304 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
305 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
308 else if (WINDOWP (position
) || FRAMEP (position
))
313 /* Decode where to put the menu. */
317 else if (WINDOWP (window
))
319 CHECK_LIVE_WINDOW (window
);
320 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
323 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
324 but I don't want to make one now. */
325 CHECK_WINDOW (window
);
327 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
328 error ("Can not put X dialog on this terminal");
330 /* Force a redisplay before showing the dialog. If a frame is created
331 just before showing the dialog, its contents may not have been fully
332 drawn, as this depends on timing of events from the X server. Redisplay
333 is not done when a dialog is shown. If redisplay could be done in the
334 X event loop (i.e. the X event loop does not run in a signal handler)
335 this would not be needed.
337 Do this before creating the widget value that points to Lisp
338 string contents, because Fredisplay may GC and relocate them. */
341 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
342 /* Display a menu with these alternatives
343 in the middle of frame F. */
345 Lisp_Object x
, y
, frame
, newpos
;
346 XSETFRAME (frame
, f
);
347 XSETINT (x
, x_pixel_width (f
) / 2);
348 XSETINT (y
, x_pixel_height (f
) / 2);
349 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
351 return Fx_popup_menu (newpos
,
352 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
358 Lisp_Object selection
;
359 int specpdl_count
= SPECPDL_INDEX ();
361 /* Decode the dialog items from what was specified. */
362 title
= Fcar (contents
);
363 CHECK_STRING (title
);
364 record_unwind_protect (unuse_menu_items
, Qnil
);
366 if (NILP (Fcar (Fcdr (contents
))))
367 /* No buttons specified, add an "Ok" button so users can pop down
368 the dialog. Also, the lesstif/motif version crashes if there are
370 contents
= Fcons (title
, Fcons (Fcons (build_string ("Ok"), Qt
), Qnil
));
372 list_of_panes (Fcons (contents
, Qnil
));
374 /* Display them in a dialog box. */
376 selection
= xdialog_show (f
, 0, title
, header
, &error_name
);
379 unbind_to (specpdl_count
, Qnil
);
380 discard_menu_items ();
382 if (error_name
) error (error_name
);
391 /* Set menu_items_inuse so no other popup menu or dialog is created. */
394 x_menu_set_in_use (in_use
)
397 menu_items_inuse
= in_use
? Qt
: Qnil
;
398 popup_activated_flag
= in_use
;
400 if (popup_activated_flag
)
401 x_activate_timeout_atimer ();
405 /* Wait for an X event to arrive or for a timer to expire. */
408 x_menu_wait_for_event (void *data
)
410 /* Another way to do this is to register a timer callback, that can be
411 done in GTK and Xt. But we have to do it like this when using only X
412 anyway, and with callbacks we would have three variants for timer handling
413 instead of the small ifdefs below. */
417 ! XtAppPending (Xt_app_con
)
418 #elif defined USE_GTK
419 ! gtk_events_pending ()
421 ! XPending ((Display
*) data
)
425 EMACS_TIME next_time
= timer_check (1), *ntp
;
426 long secs
= EMACS_SECS (next_time
);
427 long usecs
= EMACS_USECS (next_time
);
428 SELECT_TYPE read_fds
;
429 struct x_display_info
*dpyinfo
;
433 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
435 int fd
= ConnectionNumber (dpyinfo
->display
);
436 FD_SET (fd
, &read_fds
);
438 XFlush (dpyinfo
->display
);
441 if (secs
< 0 && usecs
< 0)
446 select (n
+ 1, &read_fds
, (SELECT_TYPE
*)0, (SELECT_TYPE
*)0, ntp
);
452 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
456 /* Loop in Xt until the menu pulldown or dialog popup has been
457 popped down (deactivated). This is used for x-popup-menu
458 and x-popup-dialog; it is not used for the menu bar.
460 NOTE: All calls to popup_get_selection should be protected
461 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
464 popup_get_selection (initial_event
, dpyinfo
, id
, do_timers
)
465 XEvent
*initial_event
;
466 struct x_display_info
*dpyinfo
;
472 while (popup_activated_flag
)
476 event
= *initial_event
;
481 if (do_timers
) x_menu_wait_for_event (0);
482 XtAppNextEvent (Xt_app_con
, &event
);
485 /* Make sure we don't consider buttons grabbed after menu goes.
486 And make sure to deactivate for any ButtonRelease,
487 even if XtDispatchEvent doesn't do that. */
488 if (event
.type
== ButtonRelease
489 && dpyinfo
->display
== event
.xbutton
.display
)
491 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
492 #ifdef USE_MOTIF /* Pretending that the event came from a
493 Btn1Down seems the only way to convince Motif to
494 activate its callbacks; setting the XmNmenuPost
495 isn't working. --marcus@sysc.pdx.edu. */
496 event
.xbutton
.button
= 1;
497 /* Motif only pops down menus when no Ctrl, Alt or Mod
498 key is pressed and the button is released. So reset key state
499 so Motif thinks this is the case. */
500 event
.xbutton
.state
= 0;
503 /* Pop down on C-g and Escape. */
504 else if (event
.type
== KeyPress
505 && dpyinfo
->display
== event
.xbutton
.display
)
507 KeySym keysym
= XLookupKeysym (&event
.xkey
, 0);
509 if ((keysym
== XK_g
&& (event
.xkey
.state
& ControlMask
) != 0)
510 || keysym
== XK_Escape
) /* Any escape, ignore modifiers. */
511 popup_activated_flag
= 0;
514 x_dispatch_event (&event
, event
.xany
.display
);
518 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
519 doc
: /* Start key navigation of the menu bar in FRAME.
520 This initially opens the first menu bar item and you can then navigate with the
521 arrow keys, select a menu entry with the return key or cancel with the
522 escape key. If FRAME has no menu bar this function does nothing.
524 If FRAME is nil or not given, use the selected frame. */)
529 FRAME_PTR f
= check_x_frame (frame
);
533 if (FRAME_EXTERNAL_MENU_BAR (f
))
534 set_frame_menubar (f
, 0, 1);
536 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
542 x_catch_errors (FRAME_X_DISPLAY (f
));
543 memset (&ev
, 0, sizeof ev
);
544 ev
.xbutton
.display
= FRAME_X_DISPLAY (f
);
545 ev
.xbutton
.window
= XtWindow (menubar
);
546 ev
.xbutton
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
547 ev
.xbutton
.time
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
548 ev
.xbutton
.button
= Button1
;
549 ev
.xbutton
.x
= ev
.xbutton
.y
= FRAME_MENUBAR_HEIGHT (f
) / 2;
550 ev
.xbutton
.same_screen
= True
;
557 XtSetArg (al
[0], XtNchildren
, &list
);
558 XtSetArg (al
[1], XtNnumChildren
, &nr
);
559 XtGetValues (menubar
, al
, 2);
560 ev
.xbutton
.window
= XtWindow (list
[0]);
564 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
565 /* From-window, to-window. */
566 ev
.xbutton
.window
, ev
.xbutton
.root
,
568 /* From-position, to-position. */
569 ev
.xbutton
.x
, ev
.xbutton
.y
,
570 &ev
.xbutton
.x_root
, &ev
.xbutton
.y_root
,
574 error_p
= x_had_errors_p (FRAME_X_DISPLAY (f
));
579 ev
.type
= ButtonPress
;
580 ev
.xbutton
.state
= 0;
582 XtDispatchEvent (&ev
);
583 ev
.xbutton
.type
= ButtonRelease
;
584 ev
.xbutton
.state
= Button1Mask
;
585 XtDispatchEvent (&ev
);
593 #endif /* USE_X_TOOLKIT */
597 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
598 doc
: /* Start key navigation of the menu bar in FRAME.
599 This initially opens the first menu bar item and you can then navigate with the
600 arrow keys, select a menu entry with the return key or cancel with the
601 escape key. If FRAME has no menu bar this function does nothing.
603 If FRAME is nil or not given, use the selected frame. */)
610 /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
614 f
= check_x_frame (frame
);
616 if (FRAME_EXTERNAL_MENU_BAR (f
))
617 set_frame_menubar (f
, 0, 1);
619 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
622 /* Activate the first menu. */
623 GList
*children
= gtk_container_get_children (GTK_CONTAINER (menubar
));
627 g_signal_emit_by_name (children
->data
, "activate_item");
628 popup_activated_flag
= 1;
629 g_list_free (children
);
637 /* Loop util popup_activated_flag is set to zero in a callback.
638 Used for popup menus and dialogs. */
641 popup_widget_loop (do_timers
, widget
)
645 ++popup_activated_flag
;
647 /* Process events in the Gtk event loop until done. */
648 while (popup_activated_flag
)
650 if (do_timers
) x_menu_wait_for_event (0);
651 gtk_main_iteration ();
656 /* Activate the menu bar of frame F.
657 This is called from keyboard.c when it gets the
658 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
660 To activate the menu bar, we use the X button-press event
661 that was saved in saved_menu_event.
662 That makes the toolkit do its thing.
664 But first we recompute the menu bar contents (the whole tree).
666 The reason for saving the button event until here, instead of
667 passing it to the toolkit right away, is that we can safely
668 execute Lisp code. */
671 x_activate_menubar (f
)
677 if (!f
->output_data
.x
->saved_menu_event
->type
)
681 if (! xg_win_to_widget (FRAME_X_DISPLAY (f
),
682 f
->output_data
.x
->saved_menu_event
->xany
.window
))
686 set_frame_menubar (f
, 0, 1);
689 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
690 f
->output_data
.x
->saved_menu_event
);
691 popup_activated_flag
= 1;
693 XtDispatchEvent (f
->output_data
.x
->saved_menu_event
);
697 if (f
->output_data
.x
->saved_menu_event
->type
== ButtonRelease
)
698 pending_menu_activation
= 1;
701 /* Ignore this if we get it a second time. */
702 f
->output_data
.x
->saved_menu_event
->type
= 0;
705 /* This callback is invoked when the user selects a menubar cascade
706 pushbutton, but before the pulldown menu is posted. */
710 popup_activate_callback (widget
, id
, client_data
)
713 XtPointer client_data
;
715 popup_activated_flag
= 1;
717 x_activate_timeout_atimer ();
722 /* This callback is invoked when a dialog or menu is finished being
723 used and has been unposted. */
727 popup_deactivate_callback (widget
, client_data
)
729 gpointer client_data
;
731 popup_activated_flag
= 0;
735 popup_deactivate_callback (widget
, id
, client_data
)
738 XtPointer client_data
;
740 popup_activated_flag
= 0;
745 /* Function that finds the frame for WIDGET and shows the HELP text
747 F is the frame if known, or NULL if not known. */
749 show_help_event (f
, widget
, help
)
751 xt_or_gtk_widget widget
;
758 XSETFRAME (frame
, f
);
759 kbd_buffer_store_help_event (frame
, help
);
763 #if 0 /* This code doesn't do anything useful. ++kfs */
764 /* WIDGET is the popup menu. It's parent is the frame's
765 widget. See which frame that is. */
766 xt_or_gtk_widget frame_widget
= XtParent (widget
);
769 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
773 && (f
= XFRAME (frame
),
774 FRAME_X_P (f
) && f
->output_data
.x
->widget
== frame_widget
))
778 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
782 /* Callback called when menu items are highlighted/unhighlighted
783 while moving the mouse over them. WIDGET is the menu bar or menu
784 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
785 the data structure for the menu item, or null in case of
790 menu_highlight_callback (widget
, call_data
)
794 xg_menu_item_cb_data
*cb_data
;
797 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (widget
),
799 if (! cb_data
) return;
801 help
= call_data
? cb_data
->help
: Qnil
;
803 /* If popup_activated_flag is greater than 1 we are in a popup menu.
804 Don't show help for them, they won't appear before the
805 popup is popped down. */
806 if (popup_activated_flag
<= 1)
807 show_help_event (cb_data
->cl_data
->f
, widget
, help
);
811 menu_highlight_callback (widget
, id
, call_data
)
819 widget_value
*wv
= (widget_value
*) call_data
;
821 help
= wv
? wv
->help
: Qnil
;
823 /* Determine the frame for the help event. */
824 f
= menubar_id_to_frame (id
);
826 show_help_event (f
, widget
, help
);
831 /* Gtk calls callbacks just because we tell it what item should be
832 selected in a radio group. If this variable is set to a non-zero
833 value, we are creating menus and don't want callbacks right now.
835 static int xg_crazy_callback_abort
;
837 /* This callback is called from the menu bar pulldown menu
838 when the user makes a selection.
839 Figure out what the user chose
840 and put the appropriate events into the keyboard buffer. */
842 menubar_selection_callback (widget
, client_data
)
844 gpointer client_data
;
846 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
848 if (xg_crazy_callback_abort
)
851 if (! cb_data
|| ! cb_data
->cl_data
|| ! cb_data
->cl_data
->f
)
854 /* For a group of radio buttons, GTK calls the selection callback first
855 for the item that was active before the selection and then for the one that
856 is active after the selection. For C-h k this means we get the help on
857 the deselected item and then the selected item is executed. Prevent that
858 by ignoring the non-active item. */
859 if (GTK_IS_RADIO_MENU_ITEM (widget
)
860 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget
)))
863 /* When a menu is popped down, X generates a focus event (i.e. focus
864 goes back to the frame below the menu). Since GTK buffers events,
865 we force it out here before the menu selection event. Otherwise
866 sit-for will exit at once if the focus event follows the menu selection
870 while (gtk_events_pending ())
871 gtk_main_iteration ();
874 find_and_call_menu_selection (cb_data
->cl_data
->f
,
875 cb_data
->cl_data
->menu_bar_items_used
,
876 cb_data
->cl_data
->menu_bar_vector
,
880 #else /* not USE_GTK */
882 /* This callback is called from the menu bar pulldown menu
883 when the user makes a selection.
884 Figure out what the user chose
885 and put the appropriate events into the keyboard buffer. */
887 menubar_selection_callback (widget
, id
, client_data
)
890 XtPointer client_data
;
894 f
= menubar_id_to_frame (id
);
897 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
898 f
->menu_bar_vector
, client_data
);
900 #endif /* not USE_GTK */
902 /* Recompute all the widgets of frame F, when the menu bar has been
903 changed. Value is non-zero if widgets were updated. */
906 update_frame_menubar (f
)
910 return xg_update_frame_menubar (f
);
918 x
= f
->output_data
.x
;
920 if (!x
->menubar_widget
|| XtIsManaged (x
->menubar_widget
))
924 /* Save the size of the frame because the pane widget doesn't accept
925 to resize itself. So force it. */
926 columns
= FRAME_COLS (f
);
927 rows
= FRAME_LINES (f
);
929 /* Do the voodoo which means "I'm changing lots of things, don't try
930 to refigure sizes until I'm done." */
931 lw_refigure_widget (x
->column_widget
, False
);
933 /* The order in which children are managed is the top to bottom
934 order in which they are displayed in the paned window. First,
935 remove the text-area widget. */
936 XtUnmanageChild (x
->edit_widget
);
938 /* Remove the menubar that is there now, and put up the menubar that
940 XtManageChild (x
->menubar_widget
);
941 XtMapWidget (x
->menubar_widget
);
942 XtVaSetValues (x
->menubar_widget
, XtNmappedWhenManaged
, 1, NULL
);
944 /* Re-manage the text-area widget, and then thrash the sizes. */
945 XtManageChild (x
->edit_widget
);
946 lw_refigure_widget (x
->column_widget
, True
);
948 /* Force the pane widget to resize itself with the right values. */
949 EmacsFrameSetCharSize (x
->edit_widget
, columns
, rows
);
957 apply_systemfont_to_menu (w
)
960 const char *fn
= xsettings_get_system_normal_font ();
965 if (XtIsShell (w
)) /* popup menu */
970 XtVaGetValues (w
, XtNnumChildren
, &num
, NULL
);
971 if (num
!= 1) return; /* Should only be one. */
974 XtVaGetValues (w
, XtNchildren
, childs
, NULL
);
975 if (childs
[0] && *childs
[0]) w
= *childs
[0];
978 /* Only use system font if the default is used for the menu. */
979 XtVaGetValues (w
, XtNdefaultFace
, &defflt
, NULL
);
981 XtVaSetValues (w
, XtNfaceName
, fn
, NULL
);
985 /* Set the contents of the menubar widgets of frame F.
986 The argument FIRST_TIME is currently ignored;
987 it is set the first time this is called, from initialize_frame_menubar. */
990 set_frame_menubar (f
, first_time
, deep_p
)
995 xt_or_gtk_widget menubar_widget
;
1000 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
1002 int *submenu_start
, *submenu_end
;
1003 int *submenu_top_level_items
, *submenu_n_panes
;
1005 if (! FRAME_X_P (f
))
1008 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1010 XSETFRAME (Vmenu_updating_frame
, f
);
1012 #ifdef USE_X_TOOLKIT
1013 if (f
->output_data
.x
->id
== 0)
1014 f
->output_data
.x
->id
= next_menubar_widget_id
++;
1015 id
= f
->output_data
.x
->id
;
1018 if (! menubar_widget
)
1020 else if (pending_menu_activation
&& !deep_p
)
1022 /* Make the first call for any given frame always go deep. */
1023 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
1026 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
1027 f
->output_data
.x
->saved_menu_event
->type
= 0;
1031 /* If we have detached menus, we must update deep so detached menus
1032 also gets updated. */
1033 deep_p
= deep_p
|| xg_have_tear_offs ();
1038 /* Make a widget-value tree representing the entire menu trees. */
1040 struct buffer
*prev
= current_buffer
;
1042 int specpdl_count
= SPECPDL_INDEX ();
1043 int previous_menu_items_used
= f
->menu_bar_items_used
;
1044 Lisp_Object
*previous_items
1045 = (Lisp_Object
*) alloca (previous_menu_items_used
1046 * sizeof (Lisp_Object
));
1048 /* If we are making a new widget, its contents are empty,
1049 do always reinitialize them. */
1050 if (! menubar_widget
)
1051 previous_menu_items_used
= 0;
1053 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1054 specbind (Qinhibit_quit
, Qt
);
1055 /* Don't let the debugger step into this code
1056 because it is not reentrant. */
1057 specbind (Qdebug_on_next_call
, Qnil
);
1059 record_unwind_save_match_data ();
1060 if (NILP (Voverriding_local_map_menu_flag
))
1062 specbind (Qoverriding_terminal_local_map
, Qnil
);
1063 specbind (Qoverriding_local_map
, Qnil
);
1066 set_buffer_internal_1 (XBUFFER (buffer
));
1068 /* Run the Lucid hook. */
1069 safe_run_hooks (Qactivate_menubar_hook
);
1071 /* If it has changed current-menubar from previous value,
1072 really recompute the menubar from the value. */
1073 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1074 call0 (Qrecompute_lucid_menubar
);
1075 safe_run_hooks (Qmenu_bar_update_hook
);
1076 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1078 items
= FRAME_MENU_BAR_ITEMS (f
);
1080 /* Save the frame's previous menu bar contents data. */
1081 if (previous_menu_items_used
)
1082 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
1083 previous_menu_items_used
* sizeof (Lisp_Object
));
1085 /* Fill in menu_items with the current menu bar contents.
1086 This can evaluate Lisp code. */
1089 menu_items
= f
->menu_bar_vector
;
1090 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1091 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1092 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1093 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
1094 submenu_top_level_items
1095 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1097 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1099 Lisp_Object key
, string
, maps
;
1103 key
= XVECTOR (items
)->contents
[i
];
1104 string
= XVECTOR (items
)->contents
[i
+ 1];
1105 maps
= XVECTOR (items
)->contents
[i
+ 2];
1109 submenu_start
[i
] = menu_items_used
;
1111 menu_items_n_panes
= 0;
1112 submenu_top_level_items
[i
]
1113 = parse_single_submenu (key
, string
, maps
);
1114 submenu_n_panes
[i
] = menu_items_n_panes
;
1116 submenu_end
[i
] = menu_items_used
;
1119 finish_menu_items ();
1121 /* Convert menu_items into widget_value trees
1122 to display the menu. This cannot evaluate Lisp code. */
1124 wv
= xmalloc_widget_value ();
1125 wv
->name
= "menubar";
1128 wv
->button_type
= BUTTON_TYPE_NONE
;
1132 for (i
= 0; i
< last_i
; i
+= 4)
1134 menu_items_n_panes
= submenu_n_panes
[i
];
1135 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
1136 submenu_top_level_items
[i
]);
1140 first_wv
->contents
= wv
;
1141 /* Don't set wv->name here; GC during the loop might relocate it. */
1143 wv
->button_type
= BUTTON_TYPE_NONE
;
1147 set_buffer_internal_1 (prev
);
1149 /* If there has been no change in the Lisp-level contents
1150 of the menu bar, skip redisplaying it. Just exit. */
1152 /* Compare the new menu items with the ones computed last time. */
1153 for (i
= 0; i
< previous_menu_items_used
; i
++)
1154 if (menu_items_used
== i
1155 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1157 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1159 /* The menu items have not changed. Don't bother updating
1160 the menus in any form, since it would be a no-op. */
1161 free_menubar_widget_value_tree (first_wv
);
1162 discard_menu_items ();
1163 unbind_to (specpdl_count
, Qnil
);
1167 /* The menu items are different, so store them in the frame. */
1168 f
->menu_bar_vector
= menu_items
;
1169 f
->menu_bar_items_used
= menu_items_used
;
1171 /* This undoes save_menu_items. */
1172 unbind_to (specpdl_count
, Qnil
);
1174 /* Now GC cannot happen during the lifetime of the widget_value,
1175 so it's safe to store data from a Lisp_String. */
1176 wv
= first_wv
->contents
;
1177 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1180 string
= XVECTOR (items
)->contents
[i
+ 1];
1183 wv
->name
= (char *) SDATA (string
);
1184 update_submenu_strings (wv
->contents
);
1191 /* Make a widget-value tree containing
1192 just the top level menu bar strings. */
1194 wv
= xmalloc_widget_value ();
1195 wv
->name
= "menubar";
1198 wv
->button_type
= BUTTON_TYPE_NONE
;
1202 items
= FRAME_MENU_BAR_ITEMS (f
);
1203 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1207 string
= XVECTOR (items
)->contents
[i
+ 1];
1211 wv
= xmalloc_widget_value ();
1212 wv
->name
= (char *) SDATA (string
);
1215 wv
->button_type
= BUTTON_TYPE_NONE
;
1217 /* This prevents lwlib from assuming this
1218 menu item is really supposed to be empty. */
1219 /* The EMACS_INT cast avoids a warning.
1220 This value just has to be different from small integers. */
1221 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1226 first_wv
->contents
= wv
;
1230 /* Forget what we thought we knew about what is in the
1231 detailed contents of the menu bar menus.
1232 Changing the top level always destroys the contents. */
1233 f
->menu_bar_items_used
= 0;
1236 /* Create or update the menu bar widget. */
1241 xg_crazy_callback_abort
= 1;
1244 /* The fourth arg is DEEP_P, which says to consider the entire
1245 menu trees we supply, rather than just the menu bar item names. */
1246 xg_modify_menubar_widgets (menubar_widget
,
1250 G_CALLBACK (menubar_selection_callback
),
1251 G_CALLBACK (popup_deactivate_callback
),
1252 G_CALLBACK (menu_highlight_callback
));
1256 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
1259 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
1260 G_CALLBACK (menubar_selection_callback
),
1261 G_CALLBACK (popup_deactivate_callback
),
1262 G_CALLBACK (menu_highlight_callback
));
1264 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1268 #else /* not USE_GTK */
1271 /* Disable resizing (done for Motif!) */
1272 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
1274 /* The third arg is DEEP_P, which says to consider the entire
1275 menu trees we supply, rather than just the menu bar item names. */
1276 lw_modify_all_widgets (id
, first_wv
, deep_p
);
1278 /* Re-enable the edit widget to resize. */
1279 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
1283 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1284 XtTranslations override
= XtParseTranslationTable (menuOverride
);
1286 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
1287 f
->output_data
.x
->column_widget
,
1289 popup_activate_callback
,
1290 menubar_selection_callback
,
1291 popup_deactivate_callback
,
1292 menu_highlight_callback
);
1293 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1295 /* Make menu pop down on C-g. */
1296 XtOverrideTranslations (menubar_widget
, override
);
1297 apply_systemfont_to_menu (menubar_widget
);
1302 = (f
->output_data
.x
->menubar_widget
1303 ? (f
->output_data
.x
->menubar_widget
->core
.height
1304 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
1307 #if 1 /* Experimentally, we now get the right results
1308 for -geometry -0-0 without this. 24 Aug 96, rms.
1309 Maybe so, but the menu bar size is missing the pixels so the
1310 WM size hints are off by theses pixel. Jan D, oct 2009. */
1312 if (FRAME_EXTERNAL_MENU_BAR (f
))
1315 XtVaGetValues (f
->output_data
.x
->column_widget
,
1316 XtNinternalBorderWidth
, &ibw
, NULL
);
1317 menubar_size
+= ibw
;
1319 #endif /* USE_LUCID */
1322 f
->output_data
.x
->menubar_height
= menubar_size
;
1324 #endif /* not USE_GTK */
1326 free_menubar_widget_value_tree (first_wv
);
1327 update_frame_menubar (f
);
1330 xg_crazy_callback_abort
= 0;
1336 /* Called from Fx_create_frame to create the initial menubar of a frame
1337 before it is mapped, so that the window is mapped with the menubar already
1338 there instead of us tacking it on later and thrashing the window after it
1342 initialize_frame_menubar (f
)
1345 /* This function is called before the first chance to redisplay
1346 the frame. It has to be, so the frame will have the right size. */
1347 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1348 set_frame_menubar (f
, 1, 1);
1352 /* Get rid of the menu bar of frame F, and free its storage.
1353 This is used when deleting a frame, and when turning off the menu bar.
1354 For GTK this function is in gtkutil.c. */
1358 free_frame_menubar (f
)
1361 Widget menubar_widget
;
1363 if (! FRAME_X_P (f
))
1366 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1368 f
->output_data
.x
->menubar_height
= 0;
1373 /* Removing the menu bar magically changes the shell widget's x
1374 and y position of (0, 0) which, when the menu bar is turned
1375 on again, leads to pull-down menuss appearing in strange
1376 positions near the upper-left corner of the display. This
1377 happens only with some window managers like twm and ctwm,
1378 but not with other like Motif's mwm or kwm, because the
1379 latter generate ConfigureNotify events when the menu bar
1380 is switched off, which fixes the shell position. */
1381 Position x0
, y0
, x1
, y1
;
1387 if (f
->output_data
.x
->widget
)
1388 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
1391 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
1392 f
->output_data
.x
->menubar_widget
= NULL
;
1395 if (f
->output_data
.x
->widget
)
1397 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
1398 if (x1
== 0 && y1
== 0)
1399 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
1406 #endif /* not USE_GTK */
1408 #endif /* USE_X_TOOLKIT || USE_GTK */
1410 /* xmenu_show actually displays a menu using the panes and items in menu_items
1411 and returns the value selected from it.
1412 There are two versions of xmenu_show, one for Xt and one for Xlib.
1413 Both assume input is blocked by the caller. */
1415 /* F is the frame the menu is for.
1416 X and Y are the frame-relative specified position,
1417 relative to the inside upper left corner of the frame F.
1418 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1419 KEYMAPS is 1 if this menu was specified with keymaps;
1420 in that case, we return a list containing the chosen item's value
1421 and perhaps also the pane's prefix.
1422 TITLE is the specified menu title.
1423 ERROR is a place to store an error message string in case of failure.
1424 (We return nil on failure, but the value doesn't actually matter.) */
1426 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1428 /* The item selected in the popup menu. */
1429 static Lisp_Object
*volatile menu_item_selection
;
1433 /* Used when position a popup menu. See menu_position_func and
1434 create_and_show_popup_menu below. */
1435 struct next_popup_x_y
1442 /* The menu position function to use if we are not putting a popup
1443 menu where the pointer is.
1444 MENU is the menu to pop up.
1445 X and Y shall on exit contain x/y where the menu shall pop up.
1446 PUSH_IN is not documented in the GTK manual.
1447 USER_DATA is any data passed in when calling gtk_menu_popup.
1448 Here it points to a struct next_popup_x_y where the coordinates
1449 to store in *X and *Y are as well as the frame for the popup.
1451 Here only X and Y are used. */
1453 menu_position_func (menu
, x
, y
, push_in
, user_data
)
1460 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
1462 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (data
->f
);
1463 int disp_width
= x_display_pixel_width (dpyinfo
);
1464 int disp_height
= x_display_pixel_height (dpyinfo
);
1469 /* Check if there is room for the menu. If not, adjust x/y so that
1470 the menu is fully visible. */
1471 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
1472 if (data
->x
+ req
.width
> disp_width
)
1473 *x
-= data
->x
+ req
.width
- disp_width
;
1474 if (data
->y
+ req
.height
> disp_height
)
1475 *y
-= data
->y
+ req
.height
- disp_height
;
1479 popup_selection_callback (widget
, client_data
)
1481 gpointer client_data
;
1483 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1485 if (xg_crazy_callback_abort
) return;
1486 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
1493 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1495 popup_activated_flag
= 0;
1497 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1502 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1504 menu_item_selection will be set to the selection. */
1506 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1508 widget_value
*first_wv
;
1512 EMACS_UINT timestamp
;
1516 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
1517 struct next_popup_x_y popup_x_y
;
1518 int specpdl_count
= SPECPDL_INDEX ();
1520 if (! FRAME_X_P (f
))
1523 xg_crazy_callback_abort
= 1;
1524 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
1525 G_CALLBACK (popup_selection_callback
),
1526 G_CALLBACK (popup_deactivate_callback
),
1527 G_CALLBACK (menu_highlight_callback
));
1528 xg_crazy_callback_abort
= 0;
1532 /* Not invoked by a click. pop up at x/y. */
1533 pos_func
= menu_position_func
;
1535 /* Adjust coordinates to be root-window-relative. */
1536 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1537 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1543 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1547 for (i
= 0; i
< 5; i
++)
1548 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1552 /* Display the menu. */
1553 gtk_widget_show_all (menu
);
1555 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
,
1556 timestamp
> 0 ? timestamp
: gtk_get_current_event_time());
1558 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1560 if (GTK_WIDGET_MAPPED (menu
))
1562 /* Set this to one. popup_widget_loop increases it by one, so it becomes
1563 two. show_help_echo uses this to detect popup menus. */
1564 popup_activated_flag
= 1;
1565 /* Process events that apply to the menu. */
1566 popup_widget_loop (1, menu
);
1569 unbind_to (specpdl_count
, Qnil
);
1571 /* Must reset this manually because the button release event is not passed
1572 to Emacs event loop. */
1573 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1576 #else /* not USE_GTK */
1578 /* We need a unique id for each widget handled by the Lucid Widget
1581 For the main windows, and popup menus, we use this counter,
1582 which we increment each time after use. This starts from 1<<16.
1584 For menu bars, we use numbers starting at 0, counted in
1585 next_menubar_widget_id. */
1586 LWLIB_ID widget_id_tick
;
1589 popup_selection_callback (widget
, id
, client_data
)
1592 XtPointer client_data
;
1594 menu_item_selection
= (Lisp_Object
*) client_data
;
1597 /* ARG is the LWLIB ID of the dialog box, represented
1598 as a Lisp object as (HIGHPART . LOWPART). */
1604 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
1605 | XINT (XCDR (arg
)));
1608 lw_destroy_all_widgets (id
);
1610 popup_activated_flag
= 0;
1615 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1617 menu_item_selection will be set to the selection. */
1619 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1621 widget_value
*first_wv
;
1625 EMACS_UINT timestamp
;
1630 XButtonPressedEvent dummy
;
1634 if (! FRAME_X_P (f
))
1637 menu_id
= widget_id_tick
++;
1638 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
1639 f
->output_data
.x
->widget
, 1, 0,
1640 popup_selection_callback
,
1641 popup_deactivate_callback
,
1642 menu_highlight_callback
);
1644 apply_systemfont_to_menu (menu
);
1646 dummy
.type
= ButtonPress
;
1648 dummy
.send_event
= 0;
1649 dummy
.display
= FRAME_X_DISPLAY (f
);
1650 dummy
.time
= CurrentTime
;
1651 dummy
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1652 dummy
.window
= dummy
.root
;
1653 dummy
.subwindow
= dummy
.root
;
1657 /* Adjust coordinates to be root-window-relative. */
1658 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1659 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1666 for (i
= 0; i
< 5; i
++)
1667 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1670 /* Don't allow any geometry request from the user. */
1671 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
1672 XtSetValues (menu
, av
, ac
);
1674 /* Display the menu. */
1675 lw_popup_menu (menu
, (XEvent
*) &dummy
);
1676 popup_activated_flag
= 1;
1677 x_activate_timeout_atimer ();
1680 int fact
= 4 * sizeof (LWLIB_ID
);
1681 int specpdl_count
= SPECPDL_INDEX ();
1682 record_unwind_protect (pop_down_menu
,
1683 Fcons (make_number (menu_id
>> (fact
)),
1684 make_number (menu_id
& ~(-1 << (fact
)))));
1686 /* Process events that apply to the menu. */
1687 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
1689 unbind_to (specpdl_count
, Qnil
);
1693 #endif /* not USE_GTK */
1696 xmenu_show (FRAME_PTR f
, int x
, int y
, int for_click
, int keymaps
,
1697 Lisp_Object title
, char **error
, EMACS_UINT timestamp
)
1700 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1701 widget_value
**submenu_stack
1702 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1703 Lisp_Object
*subprefix_stack
1704 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1705 int submenu_depth
= 0;
1709 if (! FRAME_X_P (f
))
1714 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1716 *error
= "Empty menu";
1720 /* Create a tree of widget_value objects
1721 representing the panes and their items. */
1722 wv
= xmalloc_widget_value ();
1726 wv
->button_type
= BUTTON_TYPE_NONE
;
1731 /* Loop over all panes and items, filling in the tree. */
1733 while (i
< menu_items_used
)
1735 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1737 submenu_stack
[submenu_depth
++] = save_wv
;
1743 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1746 save_wv
= submenu_stack
[--submenu_depth
];
1750 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1751 && submenu_depth
!= 0)
1752 i
+= MENU_ITEMS_PANE_LENGTH
;
1753 /* Ignore a nil in the item list.
1754 It's meaningful only for dialog boxes. */
1755 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1757 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1759 /* Create a new pane. */
1760 Lisp_Object pane_name
, prefix
;
1763 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1764 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1766 #ifndef HAVE_MULTILINGUAL_MENU
1767 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1769 pane_name
= ENCODE_MENU_STRING (pane_name
);
1770 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1773 pane_string
= (NILP (pane_name
)
1774 ? "" : (char *) SDATA (pane_name
));
1775 /* If there is just one top-level pane, put all its items directly
1776 under the top-level menu. */
1777 if (menu_items_n_panes
== 1)
1780 /* If the pane has a meaningful name,
1781 make the pane a top-level menu item
1782 with its items as a submenu beneath it. */
1783 if (!keymaps
&& strcmp (pane_string
, ""))
1785 wv
= xmalloc_widget_value ();
1789 first_wv
->contents
= wv
;
1790 wv
->name
= pane_string
;
1791 if (keymaps
&& !NILP (prefix
))
1795 wv
->button_type
= BUTTON_TYPE_NONE
;
1800 else if (first_pane
)
1806 i
+= MENU_ITEMS_PANE_LENGTH
;
1810 /* Create a new item within current pane. */
1811 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1812 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1813 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1814 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1815 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1816 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1817 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1818 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1820 #ifndef HAVE_MULTILINGUAL_MENU
1821 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
1823 item_name
= ENCODE_MENU_STRING (item_name
);
1824 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1827 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1829 descrip
= ENCODE_MENU_STRING (descrip
);
1830 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1832 #endif /* not HAVE_MULTILINGUAL_MENU */
1834 wv
= xmalloc_widget_value ();
1838 save_wv
->contents
= wv
;
1839 wv
->name
= (char *) SDATA (item_name
);
1840 if (!NILP (descrip
))
1841 wv
->key
= (char *) SDATA (descrip
);
1843 /* If this item has a null value,
1844 make the call_data null so that it won't display a box
1845 when the mouse is on it. */
1847 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
1848 wv
->enabled
= !NILP (enable
);
1851 wv
->button_type
= BUTTON_TYPE_NONE
;
1852 else if (EQ (type
, QCtoggle
))
1853 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1854 else if (EQ (type
, QCradio
))
1855 wv
->button_type
= BUTTON_TYPE_RADIO
;
1859 wv
->selected
= !NILP (selected
);
1861 if (! STRINGP (help
))
1868 i
+= MENU_ITEMS_ITEM_LENGTH
;
1872 /* Deal with the title, if it is non-nil. */
1875 widget_value
*wv_title
= xmalloc_widget_value ();
1876 widget_value
*wv_sep1
= xmalloc_widget_value ();
1877 widget_value
*wv_sep2
= xmalloc_widget_value ();
1879 wv_sep2
->name
= "--";
1880 wv_sep2
->next
= first_wv
->contents
;
1881 wv_sep2
->help
= Qnil
;
1883 wv_sep1
->name
= "--";
1884 wv_sep1
->next
= wv_sep2
;
1885 wv_sep1
->help
= Qnil
;
1887 #ifndef HAVE_MULTILINGUAL_MENU
1888 if (STRING_MULTIBYTE (title
))
1889 title
= ENCODE_MENU_STRING (title
);
1892 wv_title
->name
= (char *) SDATA (title
);
1893 wv_title
->enabled
= TRUE
;
1894 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1895 wv_title
->help
= Qnil
;
1896 wv_title
->next
= wv_sep1
;
1897 first_wv
->contents
= wv_title
;
1900 /* No selection has been chosen yet. */
1901 menu_item_selection
= 0;
1903 /* Actually create and show the menu until popped down. */
1904 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
);
1906 /* Free the widget_value objects we used to specify the contents. */
1907 free_menubar_widget_value_tree (first_wv
);
1909 /* Find the selected item, and its pane, to return
1910 the proper value. */
1911 if (menu_item_selection
!= 0)
1913 Lisp_Object prefix
, entry
;
1915 prefix
= entry
= Qnil
;
1917 while (i
< menu_items_used
)
1919 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1921 subprefix_stack
[submenu_depth
++] = prefix
;
1925 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1927 prefix
= subprefix_stack
[--submenu_depth
];
1930 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1933 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1934 i
+= MENU_ITEMS_PANE_LENGTH
;
1936 /* Ignore a nil in the item list.
1937 It's meaningful only for dialog boxes. */
1938 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1943 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1944 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
1950 entry
= Fcons (entry
, Qnil
);
1952 entry
= Fcons (prefix
, entry
);
1953 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1954 if (!NILP (subprefix_stack
[j
]))
1955 entry
= Fcons (subprefix_stack
[j
], entry
);
1959 i
+= MENU_ITEMS_ITEM_LENGTH
;
1963 else if (!for_click
)
1964 /* Make "Cancel" equivalent to C-g. */
1965 Fsignal (Qquit
, Qnil
);
1972 dialog_selection_callback (widget
, client_data
)
1974 gpointer client_data
;
1976 /* The EMACS_INT cast avoids a warning. There's no problem
1977 as long as pointers have enough bits to hold small integers. */
1978 if ((int) (EMACS_INT
) client_data
!= -1)
1979 menu_item_selection
= (Lisp_Object
*) client_data
;
1981 popup_activated_flag
= 0;
1984 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1986 menu_item_selection will be set to the selection. */
1988 create_and_show_dialog (f
, first_wv
)
1990 widget_value
*first_wv
;
1994 if (! FRAME_X_P (f
))
1997 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
1998 G_CALLBACK (dialog_selection_callback
),
1999 G_CALLBACK (popup_deactivate_callback
),
2004 int specpdl_count
= SPECPDL_INDEX ();
2005 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
2007 /* Display the menu. */
2008 gtk_widget_show_all (menu
);
2010 /* Process events that apply to the menu. */
2011 popup_widget_loop (1, menu
);
2013 unbind_to (specpdl_count
, Qnil
);
2017 #else /* not USE_GTK */
2019 dialog_selection_callback (widget
, id
, client_data
)
2022 XtPointer client_data
;
2024 /* The EMACS_INT cast avoids a warning. There's no problem
2025 as long as pointers have enough bits to hold small integers. */
2026 if ((int) (EMACS_INT
) client_data
!= -1)
2027 menu_item_selection
= (Lisp_Object
*) client_data
;
2030 lw_destroy_all_widgets (id
);
2032 popup_activated_flag
= 0;
2036 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2038 menu_item_selection will be set to the selection. */
2040 create_and_show_dialog (f
, first_wv
)
2042 widget_value
*first_wv
;
2049 dialog_id
= widget_id_tick
++;
2050 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
2051 f
->output_data
.x
->widget
, 1, 0,
2052 dialog_selection_callback
, 0, 0);
2053 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
2055 /* Display the dialog box. */
2056 lw_pop_up_all_widgets (dialog_id
);
2057 popup_activated_flag
= 1;
2058 x_activate_timeout_atimer ();
2060 /* Process events that apply to the dialog box.
2061 Also handle timers. */
2063 int count
= SPECPDL_INDEX ();
2064 int fact
= 4 * sizeof (LWLIB_ID
);
2066 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2067 record_unwind_protect (pop_down_menu
,
2068 Fcons (make_number (dialog_id
>> (fact
)),
2069 make_number (dialog_id
& ~(-1 << (fact
)))));
2071 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
2074 unbind_to (count
, Qnil
);
2078 #endif /* not USE_GTK */
2080 static char * button_names
[] = {
2081 "button1", "button2", "button3", "button4", "button5",
2082 "button6", "button7", "button8", "button9", "button10" };
2085 xdialog_show (f
, keymaps
, title
, header
, error_name
)
2088 Lisp_Object title
, header
;
2091 int i
, nb_buttons
=0;
2092 char dialog_name
[6];
2094 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
2096 /* Number of elements seen so far, before boundary. */
2098 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2099 int boundary_seen
= 0;
2101 if (! FRAME_X_P (f
))
2106 if (menu_items_n_panes
> 1)
2108 *error_name
= "Multiple panes in dialog box";
2112 /* Create a tree of widget_value objects
2113 representing the text label and buttons. */
2115 Lisp_Object pane_name
, prefix
;
2117 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
2118 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
2119 pane_string
= (NILP (pane_name
)
2120 ? "" : (char *) SDATA (pane_name
));
2121 prev_wv
= xmalloc_widget_value ();
2122 prev_wv
->value
= pane_string
;
2123 if (keymaps
&& !NILP (prefix
))
2125 prev_wv
->enabled
= 1;
2126 prev_wv
->name
= "message";
2127 prev_wv
->help
= Qnil
;
2130 /* Loop over all panes and items, filling in the tree. */
2131 i
= MENU_ITEMS_PANE_LENGTH
;
2132 while (i
< menu_items_used
)
2135 /* Create a new item within current pane. */
2136 Lisp_Object item_name
, enable
, descrip
;
2137 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2138 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2140 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2142 if (NILP (item_name
))
2144 free_menubar_widget_value_tree (first_wv
);
2145 *error_name
= "Submenu in dialog items";
2148 if (EQ (item_name
, Qquote
))
2150 /* This is the boundary between left-side elts
2151 and right-side elts. Stop incrementing right_count. */
2156 if (nb_buttons
>= 9)
2158 free_menubar_widget_value_tree (first_wv
);
2159 *error_name
= "Too many dialog items";
2163 wv
= xmalloc_widget_value ();
2165 wv
->name
= (char *) button_names
[nb_buttons
];
2166 if (!NILP (descrip
))
2167 wv
->key
= (char *) SDATA (descrip
);
2168 wv
->value
= (char *) SDATA (item_name
);
2169 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
2170 wv
->enabled
= !NILP (enable
);
2174 if (! boundary_seen
)
2178 i
+= MENU_ITEMS_ITEM_LENGTH
;
2181 /* If the boundary was not specified,
2182 by default put half on the left and half on the right. */
2183 if (! boundary_seen
)
2184 left_count
= nb_buttons
- nb_buttons
/ 2;
2186 wv
= xmalloc_widget_value ();
2187 wv
->name
= dialog_name
;
2190 /* Frame title: 'Q' = Question, 'I' = Information.
2191 Can also have 'E' = Error if, one day, we want
2192 a popup for errors. */
2194 dialog_name
[0] = 'Q';
2196 dialog_name
[0] = 'I';
2198 /* Dialog boxes use a really stupid name encoding
2199 which specifies how many buttons to use
2200 and how many buttons are on the right. */
2201 dialog_name
[1] = '0' + nb_buttons
;
2202 dialog_name
[2] = 'B';
2203 dialog_name
[3] = 'R';
2204 /* Number of buttons to put on the right. */
2205 dialog_name
[4] = '0' + nb_buttons
- left_count
;
2207 wv
->contents
= first_wv
;
2211 /* No selection has been chosen yet. */
2212 menu_item_selection
= 0;
2214 /* Actually create and show the dialog. */
2215 create_and_show_dialog (f
, first_wv
);
2217 /* Free the widget_value objects we used to specify the contents. */
2218 free_menubar_widget_value_tree (first_wv
);
2220 /* Find the selected item, and its pane, to return
2221 the proper value. */
2222 if (menu_item_selection
!= 0)
2228 while (i
< menu_items_used
)
2232 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2235 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2236 i
+= MENU_ITEMS_PANE_LENGTH
;
2238 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2240 /* This is the boundary between left-side elts and
2247 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2248 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2252 entry
= Fcons (entry
, Qnil
);
2254 entry
= Fcons (prefix
, entry
);
2258 i
+= MENU_ITEMS_ITEM_LENGTH
;
2263 /* Make "Cancel" equivalent to C-g. */
2264 Fsignal (Qquit
, Qnil
);
2269 #else /* not USE_X_TOOLKIT && not USE_GTK */
2271 /* The frame of the last activated non-toolkit menu bar.
2272 Used to generate menu help events. */
2274 static struct frame
*menu_help_frame
;
2277 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2279 PANE is the pane number, and ITEM is the menu item number in
2280 the menu (currently not used).
2282 This cannot be done with generating a HELP_EVENT because
2283 XMenuActivate contains a loop that doesn't let Emacs process
2287 menu_help_callback (help_string
, pane
, item
)
2291 extern Lisp_Object Qmenu_item
;
2292 Lisp_Object
*first_item
;
2293 Lisp_Object pane_name
;
2294 Lisp_Object menu_object
;
2296 first_item
= XVECTOR (menu_items
)->contents
;
2297 if (EQ (first_item
[0], Qt
))
2298 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
2299 else if (EQ (first_item
[0], Qquote
))
2300 /* This shouldn't happen, see xmenu_show. */
2301 pane_name
= empty_unibyte_string
;
2303 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
2305 /* (menu-item MENU-NAME PANE-NUMBER) */
2306 menu_object
= Fcons (Qmenu_item
,
2308 Fcons (make_number (pane
), Qnil
)));
2309 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
2310 Qnil
, menu_object
, make_number (item
), 1);
2317 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
2318 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
2320 FRAME_PTR f
= p1
->pointer
;
2321 XMenu
*menu
= p2
->pointer
;
2325 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
2326 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
2328 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2330 #ifdef HAVE_X_WINDOWS
2331 /* Assume the mouse has moved out of the X window.
2332 If it has actually moved in, we will get an EnterNotify. */
2333 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
2335 /* State that no mouse buttons are now held.
2336 (The oldXMenu code doesn't track this info for us.)
2337 That is not necessarily true, but the fiction leads to reasonable
2338 results, and it is a pain to ask which are actually held now. */
2339 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2341 #endif /* HAVE_X_WINDOWS */
2350 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
, timestamp
)
2357 EMACS_UINT timestamp
;
2361 int pane
, selidx
, lpane
, status
;
2362 Lisp_Object entry
, pane_prefix
;
2364 int ulx
, uly
, width
, height
;
2365 int dispwidth
, dispheight
;
2366 int i
, j
, lines
, maxlines
;
2369 unsigned int dummy_uint
;
2370 int specpdl_count
= SPECPDL_INDEX ();
2372 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
2376 if (menu_items_n_panes
== 0)
2379 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2381 *error
= "Empty menu";
2385 /* Figure out which root window F is on. */
2386 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
2387 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
2388 &dummy_uint
, &dummy_uint
);
2390 /* Make the menu on that window. */
2391 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
2394 *error
= "Can't create menu";
2398 /* Don't GC while we prepare and show the menu,
2399 because we give the oldxmenu library pointers to the
2400 contents of strings. */
2401 inhibit_garbage_collection ();
2403 #ifdef HAVE_X_WINDOWS
2404 /* Adjust coordinates to relative to the outer (window manager) window. */
2405 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
2406 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2407 #endif /* HAVE_X_WINDOWS */
2409 /* Adjust coordinates to be root-window-relative. */
2413 /* Create all the necessary panes and their items. */
2414 maxlines
= lines
= i
= 0;
2415 while (i
< menu_items_used
)
2417 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2419 /* Create a new pane. */
2420 Lisp_Object pane_name
, prefix
;
2423 maxlines
= max (maxlines
, lines
);
2425 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
2426 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2427 pane_string
= (NILP (pane_name
)
2428 ? "" : (char *) SDATA (pane_name
));
2429 if (keymaps
&& !NILP (prefix
))
2432 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
2433 if (lpane
== XM_FAILURE
)
2435 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2436 *error
= "Can't create pane";
2439 i
+= MENU_ITEMS_PANE_LENGTH
;
2441 /* Find the width of the widest item in this pane. */
2444 while (j
< menu_items_used
)
2447 item
= XVECTOR (menu_items
)->contents
[j
];
2455 width
= SBYTES (item
);
2456 if (width
> maxwidth
)
2459 j
+= MENU_ITEMS_ITEM_LENGTH
;
2462 /* Ignore a nil in the item list.
2463 It's meaningful only for dialog boxes. */
2464 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2468 /* Create a new item within current pane. */
2469 Lisp_Object item_name
, enable
, descrip
, help
;
2470 unsigned char *item_data
;
2473 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2474 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2476 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2477 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
2478 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
2480 if (!NILP (descrip
))
2482 int gap
= maxwidth
- SBYTES (item_name
);
2483 /* if alloca is fast, use that to make the space,
2484 to reduce gc needs. */
2486 = (unsigned char *) alloca (maxwidth
2487 + SBYTES (descrip
) + 1);
2488 bcopy (SDATA (item_name
), item_data
,
2489 SBYTES (item_name
));
2490 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
2492 bcopy (SDATA (descrip
), item_data
+ j
,
2494 item_data
[j
+ SBYTES (descrip
)] = 0;
2497 item_data
= SDATA (item_name
);
2499 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
2500 menu
, lpane
, 0, item_data
,
2501 !NILP (enable
), help_string
)
2504 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2505 *error
= "Can't add selection to menu";
2508 i
+= MENU_ITEMS_ITEM_LENGTH
;
2513 maxlines
= max (maxlines
, lines
);
2515 /* All set and ready to fly. */
2516 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
2517 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2518 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2519 x
= min (x
, dispwidth
);
2520 y
= min (y
, dispheight
);
2523 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
2524 &ulx
, &uly
, &width
, &height
);
2525 if (ulx
+width
> dispwidth
)
2527 x
-= (ulx
+ width
) - dispwidth
;
2528 ulx
= dispwidth
- width
;
2530 if (uly
+height
> dispheight
)
2532 y
-= (uly
+ height
) - dispheight
;
2533 uly
= dispheight
- height
;
2535 #ifndef HAVE_X_WINDOWS
2536 if (FRAME_HAS_MINIBUF_P (f
) && uly
+height
> dispheight
- 1)
2538 /* Move the menu away of the echo area, to avoid overwriting the
2539 menu with help echo messages or vice versa. */
2540 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
2542 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2543 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2552 if (ulx
< 0) x
-= ulx
;
2553 if (uly
< 0) y
-= uly
;
2557 /* If position was not given by a mouse click, adjust so upper left
2558 corner of the menu as a whole ends up at given coordinates. This
2559 is what x-popup-menu says in its documentation. */
2561 y
+= 1.5*height
/(maxlines
+2);
2564 XMenuSetAEQ (menu
, TRUE
);
2565 XMenuSetFreeze (menu
, TRUE
);
2569 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
2572 record_unwind_protect (pop_down_menu
,
2573 Fcons (make_save_value (f
, 0),
2574 make_save_value (menu
, 0)));
2576 /* Help display under X won't work because XMenuActivate contains
2577 a loop that doesn't give Emacs a chance to process it. */
2578 menu_help_frame
= f
;
2579 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
2580 x
, y
, ButtonReleaseMask
, &datap
,
2581 menu_help_callback
);
2587 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
2590 /* Find the item number SELIDX in pane number PANE. */
2592 while (i
< menu_items_used
)
2594 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2598 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2600 i
+= MENU_ITEMS_PANE_LENGTH
;
2609 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2612 entry
= Fcons (entry
, Qnil
);
2613 if (!NILP (pane_prefix
))
2614 entry
= Fcons (pane_prefix
, entry
);
2620 i
+= MENU_ITEMS_ITEM_LENGTH
;
2626 *error
= "Can't activate menu";
2631 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2632 the menu was invoked with a mouse event as POSITION). */
2634 Fsignal (Qquit
, Qnil
);
2639 unbind_to (specpdl_count
, Qnil
);
2644 #endif /* not USE_X_TOOLKIT */
2646 #endif /* HAVE_MENUS */
2648 /* Detect if a dialog or menu has been posted. */
2653 return popup_activated_flag
;
2656 /* The following is used by delayed window autoselection. */
2658 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2659 doc
: /* Return t if a menu or popup dialog is active. */)
2663 return (popup_activated ()) ? Qt
: Qnil
;
2666 #endif /* HAVE_MENUS */
2672 Qdebug_on_next_call
= intern_c_string ("debug-on-next-call");
2673 staticpro (&Qdebug_on_next_call
);
2675 #ifdef USE_X_TOOLKIT
2676 widget_id_tick
= (1<<16);
2677 next_menubar_widget_id
= 1;
2680 defsubr (&Smenu_or_popup_active_p
);
2682 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2683 defsubr (&Sx_menu_bar_open_internal
);
2684 Ffset (intern_c_string ("accelerate-menu"),
2685 intern_c_string (Sx_menu_bar_open_internal
.symbol_name
));
2689 defsubr (&Sx_popup_dialog
);
2693 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2694 (do not change this comment) */