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_dialog (w
)
960 const char *fn
= xsettings_get_system_normal_font ();
963 XrmDatabase db
= XtDatabase (XtDisplay (w
));
965 XrmPutStringResource (&db
, "*dialog.faceName", fn
);
970 apply_systemfont_to_menu (w
)
973 const char *fn
= xsettings_get_system_normal_font ();
978 if (XtIsShell (w
)) /* popup menu */
980 Widget
*childs
= NULL
;
982 XtVaGetValues (w
, XtNchildren
, &childs
, NULL
);
983 if (*childs
) w
= *childs
;
986 /* Only use system font if the default is used for the menu. */
987 XtVaGetValues (w
, XtNdefaultFace
, &defflt
, NULL
);
989 XtVaSetValues (w
, XtNfaceName
, fn
, NULL
);
993 /* Set the contents of the menubar widgets of frame F.
994 The argument FIRST_TIME is currently ignored;
995 it is set the first time this is called, from initialize_frame_menubar. */
998 set_frame_menubar (f
, first_time
, deep_p
)
1003 xt_or_gtk_widget menubar_widget
;
1004 #ifdef USE_X_TOOLKIT
1008 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
1010 int *submenu_start
, *submenu_end
;
1011 int *submenu_top_level_items
, *submenu_n_panes
;
1013 if (! FRAME_X_P (f
))
1016 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1018 XSETFRAME (Vmenu_updating_frame
, f
);
1020 #ifdef USE_X_TOOLKIT
1021 if (f
->output_data
.x
->id
== 0)
1022 f
->output_data
.x
->id
= next_menubar_widget_id
++;
1023 id
= f
->output_data
.x
->id
;
1026 if (! menubar_widget
)
1028 else if (pending_menu_activation
&& !deep_p
)
1030 /* Make the first call for any given frame always go deep. */
1031 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
1034 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
1035 f
->output_data
.x
->saved_menu_event
->type
= 0;
1039 /* If we have detached menus, we must update deep so detached menus
1040 also gets updated. */
1041 deep_p
= deep_p
|| xg_have_tear_offs ();
1046 /* Make a widget-value tree representing the entire menu trees. */
1048 struct buffer
*prev
= current_buffer
;
1050 int specpdl_count
= SPECPDL_INDEX ();
1051 int previous_menu_items_used
= f
->menu_bar_items_used
;
1052 Lisp_Object
*previous_items
1053 = (Lisp_Object
*) alloca (previous_menu_items_used
1054 * sizeof (Lisp_Object
));
1056 /* If we are making a new widget, its contents are empty,
1057 do always reinitialize them. */
1058 if (! menubar_widget
)
1059 previous_menu_items_used
= 0;
1061 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1062 specbind (Qinhibit_quit
, Qt
);
1063 /* Don't let the debugger step into this code
1064 because it is not reentrant. */
1065 specbind (Qdebug_on_next_call
, Qnil
);
1067 record_unwind_save_match_data ();
1068 if (NILP (Voverriding_local_map_menu_flag
))
1070 specbind (Qoverriding_terminal_local_map
, Qnil
);
1071 specbind (Qoverriding_local_map
, Qnil
);
1074 set_buffer_internal_1 (XBUFFER (buffer
));
1076 /* Run the Lucid hook. */
1077 safe_run_hooks (Qactivate_menubar_hook
);
1079 /* If it has changed current-menubar from previous value,
1080 really recompute the menubar from the value. */
1081 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1082 call0 (Qrecompute_lucid_menubar
);
1083 safe_run_hooks (Qmenu_bar_update_hook
);
1084 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1086 items
= FRAME_MENU_BAR_ITEMS (f
);
1088 /* Save the frame's previous menu bar contents data. */
1089 if (previous_menu_items_used
)
1090 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
1091 previous_menu_items_used
* sizeof (Lisp_Object
));
1093 /* Fill in menu_items with the current menu bar contents.
1094 This can evaluate Lisp code. */
1097 menu_items
= f
->menu_bar_vector
;
1098 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1099 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1100 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1101 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
1102 submenu_top_level_items
1103 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1105 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1107 Lisp_Object key
, string
, maps
;
1111 key
= XVECTOR (items
)->contents
[i
];
1112 string
= XVECTOR (items
)->contents
[i
+ 1];
1113 maps
= XVECTOR (items
)->contents
[i
+ 2];
1117 submenu_start
[i
] = menu_items_used
;
1119 menu_items_n_panes
= 0;
1120 submenu_top_level_items
[i
]
1121 = parse_single_submenu (key
, string
, maps
);
1122 submenu_n_panes
[i
] = menu_items_n_panes
;
1124 submenu_end
[i
] = menu_items_used
;
1127 finish_menu_items ();
1129 /* Convert menu_items into widget_value trees
1130 to display the menu. This cannot evaluate Lisp code. */
1132 wv
= xmalloc_widget_value ();
1133 wv
->name
= "menubar";
1136 wv
->button_type
= BUTTON_TYPE_NONE
;
1140 for (i
= 0; i
< last_i
; i
+= 4)
1142 menu_items_n_panes
= submenu_n_panes
[i
];
1143 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
1144 submenu_top_level_items
[i
]);
1148 first_wv
->contents
= wv
;
1149 /* Don't set wv->name here; GC during the loop might relocate it. */
1151 wv
->button_type
= BUTTON_TYPE_NONE
;
1155 set_buffer_internal_1 (prev
);
1157 /* If there has been no change in the Lisp-level contents
1158 of the menu bar, skip redisplaying it. Just exit. */
1160 /* Compare the new menu items with the ones computed last time. */
1161 for (i
= 0; i
< previous_menu_items_used
; i
++)
1162 if (menu_items_used
== i
1163 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1165 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1167 /* The menu items have not changed. Don't bother updating
1168 the menus in any form, since it would be a no-op. */
1169 free_menubar_widget_value_tree (first_wv
);
1170 discard_menu_items ();
1171 unbind_to (specpdl_count
, Qnil
);
1175 /* The menu items are different, so store them in the frame. */
1176 f
->menu_bar_vector
= menu_items
;
1177 f
->menu_bar_items_used
= menu_items_used
;
1179 /* This undoes save_menu_items. */
1180 unbind_to (specpdl_count
, Qnil
);
1182 /* Now GC cannot happen during the lifetime of the widget_value,
1183 so it's safe to store data from a Lisp_String. */
1184 wv
= first_wv
->contents
;
1185 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1188 string
= XVECTOR (items
)->contents
[i
+ 1];
1191 wv
->name
= (char *) SDATA (string
);
1192 update_submenu_strings (wv
->contents
);
1199 /* Make a widget-value tree containing
1200 just the top level menu bar strings. */
1202 wv
= xmalloc_widget_value ();
1203 wv
->name
= "menubar";
1206 wv
->button_type
= BUTTON_TYPE_NONE
;
1210 items
= FRAME_MENU_BAR_ITEMS (f
);
1211 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1215 string
= XVECTOR (items
)->contents
[i
+ 1];
1219 wv
= xmalloc_widget_value ();
1220 wv
->name
= (char *) SDATA (string
);
1223 wv
->button_type
= BUTTON_TYPE_NONE
;
1225 /* This prevents lwlib from assuming this
1226 menu item is really supposed to be empty. */
1227 /* The EMACS_INT cast avoids a warning.
1228 This value just has to be different from small integers. */
1229 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1234 first_wv
->contents
= wv
;
1238 /* Forget what we thought we knew about what is in the
1239 detailed contents of the menu bar menus.
1240 Changing the top level always destroys the contents. */
1241 f
->menu_bar_items_used
= 0;
1244 /* Create or update the menu bar widget. */
1249 xg_crazy_callback_abort
= 1;
1252 /* The fourth arg is DEEP_P, which says to consider the entire
1253 menu trees we supply, rather than just the menu bar item names. */
1254 xg_modify_menubar_widgets (menubar_widget
,
1258 G_CALLBACK (menubar_selection_callback
),
1259 G_CALLBACK (popup_deactivate_callback
),
1260 G_CALLBACK (menu_highlight_callback
));
1264 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
1267 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
1268 G_CALLBACK (menubar_selection_callback
),
1269 G_CALLBACK (popup_deactivate_callback
),
1270 G_CALLBACK (menu_highlight_callback
));
1272 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1276 #else /* not USE_GTK */
1279 /* Disable resizing (done for Motif!) */
1280 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
1282 /* The third arg is DEEP_P, which says to consider the entire
1283 menu trees we supply, rather than just the menu bar item names. */
1284 lw_modify_all_widgets (id
, first_wv
, deep_p
);
1286 /* Re-enable the edit widget to resize. */
1287 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
1291 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1292 XtTranslations override
= XtParseTranslationTable (menuOverride
);
1294 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
1295 f
->output_data
.x
->column_widget
,
1297 popup_activate_callback
,
1298 menubar_selection_callback
,
1299 popup_deactivate_callback
,
1300 menu_highlight_callback
);
1301 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1303 /* Make menu pop down on C-g. */
1304 XtOverrideTranslations (menubar_widget
, override
);
1305 apply_systemfont_to_menu (menubar_widget
);
1310 = (f
->output_data
.x
->menubar_widget
1311 ? (f
->output_data
.x
->menubar_widget
->core
.height
1312 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
1315 #if 1 /* Experimentally, we now get the right results
1316 for -geometry -0-0 without this. 24 Aug 96, rms.
1317 Maybe so, but the menu bar size is missing the pixels so the
1318 WM size hints are off by theses pixel. Jan D, oct 2009. */
1320 if (FRAME_EXTERNAL_MENU_BAR (f
))
1323 XtVaGetValues (f
->output_data
.x
->column_widget
,
1324 XtNinternalBorderWidth
, &ibw
, NULL
);
1325 menubar_size
+= ibw
;
1327 #endif /* USE_LUCID */
1330 f
->output_data
.x
->menubar_height
= menubar_size
;
1332 #endif /* not USE_GTK */
1334 free_menubar_widget_value_tree (first_wv
);
1335 update_frame_menubar (f
);
1338 xg_crazy_callback_abort
= 0;
1344 /* Called from Fx_create_frame to create the initial menubar of a frame
1345 before it is mapped, so that the window is mapped with the menubar already
1346 there instead of us tacking it on later and thrashing the window after it
1350 initialize_frame_menubar (f
)
1353 /* This function is called before the first chance to redisplay
1354 the frame. It has to be, so the frame will have the right size. */
1355 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1356 set_frame_menubar (f
, 1, 1);
1360 /* Get rid of the menu bar of frame F, and free its storage.
1361 This is used when deleting a frame, and when turning off the menu bar.
1362 For GTK this function is in gtkutil.c. */
1366 free_frame_menubar (f
)
1369 Widget menubar_widget
;
1371 if (! FRAME_X_P (f
))
1374 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1376 f
->output_data
.x
->menubar_height
= 0;
1381 /* Removing the menu bar magically changes the shell widget's x
1382 and y position of (0, 0) which, when the menu bar is turned
1383 on again, leads to pull-down menuss appearing in strange
1384 positions near the upper-left corner of the display. This
1385 happens only with some window managers like twm and ctwm,
1386 but not with other like Motif's mwm or kwm, because the
1387 latter generate ConfigureNotify events when the menu bar
1388 is switched off, which fixes the shell position. */
1389 Position x0
, y0
, x1
, y1
;
1395 if (f
->output_data
.x
->widget
)
1396 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
1399 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
1400 f
->output_data
.x
->menubar_widget
= NULL
;
1403 if (f
->output_data
.x
->widget
)
1405 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
1406 if (x1
== 0 && y1
== 0)
1407 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
1414 #endif /* not USE_GTK */
1416 #endif /* USE_X_TOOLKIT || USE_GTK */
1418 /* xmenu_show actually displays a menu using the panes and items in menu_items
1419 and returns the value selected from it.
1420 There are two versions of xmenu_show, one for Xt and one for Xlib.
1421 Both assume input is blocked by the caller. */
1423 /* F is the frame the menu is for.
1424 X and Y are the frame-relative specified position,
1425 relative to the inside upper left corner of the frame F.
1426 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1427 KEYMAPS is 1 if this menu was specified with keymaps;
1428 in that case, we return a list containing the chosen item's value
1429 and perhaps also the pane's prefix.
1430 TITLE is the specified menu title.
1431 ERROR is a place to store an error message string in case of failure.
1432 (We return nil on failure, but the value doesn't actually matter.) */
1434 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1436 /* The item selected in the popup menu. */
1437 static Lisp_Object
*volatile menu_item_selection
;
1441 /* Used when position a popup menu. See menu_position_func and
1442 create_and_show_popup_menu below. */
1443 struct next_popup_x_y
1450 /* The menu position function to use if we are not putting a popup
1451 menu where the pointer is.
1452 MENU is the menu to pop up.
1453 X and Y shall on exit contain x/y where the menu shall pop up.
1454 PUSH_IN is not documented in the GTK manual.
1455 USER_DATA is any data passed in when calling gtk_menu_popup.
1456 Here it points to a struct next_popup_x_y where the coordinates
1457 to store in *X and *Y are as well as the frame for the popup.
1459 Here only X and Y are used. */
1461 menu_position_func (menu
, x
, y
, push_in
, user_data
)
1468 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
1470 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (data
->f
);
1471 int disp_width
= x_display_pixel_width (dpyinfo
);
1472 int disp_height
= x_display_pixel_height (dpyinfo
);
1477 /* Check if there is room for the menu. If not, adjust x/y so that
1478 the menu is fully visible. */
1479 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
1480 if (data
->x
+ req
.width
> disp_width
)
1481 *x
-= data
->x
+ req
.width
- disp_width
;
1482 if (data
->y
+ req
.height
> disp_height
)
1483 *y
-= data
->y
+ req
.height
- disp_height
;
1487 popup_selection_callback (widget
, client_data
)
1489 gpointer client_data
;
1491 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1493 if (xg_crazy_callback_abort
) return;
1494 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
1501 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1503 popup_activated_flag
= 0;
1505 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1510 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1512 menu_item_selection will be set to the selection. */
1514 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1516 widget_value
*first_wv
;
1520 EMACS_UINT timestamp
;
1524 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
1525 struct next_popup_x_y popup_x_y
;
1526 int specpdl_count
= SPECPDL_INDEX ();
1528 if (! FRAME_X_P (f
))
1531 xg_crazy_callback_abort
= 1;
1532 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
1533 G_CALLBACK (popup_selection_callback
),
1534 G_CALLBACK (popup_deactivate_callback
),
1535 G_CALLBACK (menu_highlight_callback
));
1536 xg_crazy_callback_abort
= 0;
1540 /* Not invoked by a click. pop up at x/y. */
1541 pos_func
= menu_position_func
;
1543 /* Adjust coordinates to be root-window-relative. */
1544 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1545 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1551 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1555 for (i
= 0; i
< 5; i
++)
1556 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1560 /* Display the menu. */
1561 gtk_widget_show_all (menu
);
1563 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
,
1564 timestamp
> 0 ? timestamp
: gtk_get_current_event_time());
1566 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1568 if (GTK_WIDGET_MAPPED (menu
))
1570 /* Set this to one. popup_widget_loop increases it by one, so it becomes
1571 two. show_help_echo uses this to detect popup menus. */
1572 popup_activated_flag
= 1;
1573 /* Process events that apply to the menu. */
1574 popup_widget_loop (1, menu
);
1577 unbind_to (specpdl_count
, Qnil
);
1579 /* Must reset this manually because the button release event is not passed
1580 to Emacs event loop. */
1581 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1584 #else /* not USE_GTK */
1586 /* We need a unique id for each widget handled by the Lucid Widget
1589 For the main windows, and popup menus, we use this counter,
1590 which we increment each time after use. This starts from 1<<16.
1592 For menu bars, we use numbers starting at 0, counted in
1593 next_menubar_widget_id. */
1594 LWLIB_ID widget_id_tick
;
1597 popup_selection_callback (widget
, id
, client_data
)
1600 XtPointer client_data
;
1602 menu_item_selection
= (Lisp_Object
*) client_data
;
1605 /* ARG is the LWLIB ID of the dialog box, represented
1606 as a Lisp object as (HIGHPART . LOWPART). */
1612 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
1613 | XINT (XCDR (arg
)));
1616 lw_destroy_all_widgets (id
);
1618 popup_activated_flag
= 0;
1623 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1625 menu_item_selection will be set to the selection. */
1627 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1629 widget_value
*first_wv
;
1633 EMACS_UINT timestamp
;
1638 XButtonPressedEvent dummy
;
1642 if (! FRAME_X_P (f
))
1645 menu_id
= widget_id_tick
++;
1646 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
1647 f
->output_data
.x
->widget
, 1, 0,
1648 popup_selection_callback
,
1649 popup_deactivate_callback
,
1650 menu_highlight_callback
);
1652 apply_systemfont_to_menu (menu
);
1654 dummy
.type
= ButtonPress
;
1656 dummy
.send_event
= 0;
1657 dummy
.display
= FRAME_X_DISPLAY (f
);
1658 dummy
.time
= CurrentTime
;
1659 dummy
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1660 dummy
.window
= dummy
.root
;
1661 dummy
.subwindow
= dummy
.root
;
1665 /* Adjust coordinates to be root-window-relative. */
1666 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1667 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1674 for (i
= 0; i
< 5; i
++)
1675 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1678 /* Don't allow any geometry request from the user. */
1679 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
1680 XtSetValues (menu
, av
, ac
);
1682 /* Display the menu. */
1683 lw_popup_menu (menu
, (XEvent
*) &dummy
);
1684 popup_activated_flag
= 1;
1685 x_activate_timeout_atimer ();
1688 int fact
= 4 * sizeof (LWLIB_ID
);
1689 int specpdl_count
= SPECPDL_INDEX ();
1690 record_unwind_protect (pop_down_menu
,
1691 Fcons (make_number (menu_id
>> (fact
)),
1692 make_number (menu_id
& ~(-1 << (fact
)))));
1694 /* Process events that apply to the menu. */
1695 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
1697 unbind_to (specpdl_count
, Qnil
);
1701 #endif /* not USE_GTK */
1704 xmenu_show (FRAME_PTR f
, int x
, int y
, int for_click
, int keymaps
,
1705 Lisp_Object title
, char **error
, EMACS_UINT timestamp
)
1708 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1709 widget_value
**submenu_stack
1710 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1711 Lisp_Object
*subprefix_stack
1712 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1713 int submenu_depth
= 0;
1717 if (! FRAME_X_P (f
))
1722 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1724 *error
= "Empty menu";
1728 /* Create a tree of widget_value objects
1729 representing the panes and their items. */
1730 wv
= xmalloc_widget_value ();
1734 wv
->button_type
= BUTTON_TYPE_NONE
;
1739 /* Loop over all panes and items, filling in the tree. */
1741 while (i
< menu_items_used
)
1743 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1745 submenu_stack
[submenu_depth
++] = save_wv
;
1751 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1754 save_wv
= submenu_stack
[--submenu_depth
];
1758 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1759 && submenu_depth
!= 0)
1760 i
+= MENU_ITEMS_PANE_LENGTH
;
1761 /* Ignore a nil in the item list.
1762 It's meaningful only for dialog boxes. */
1763 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1765 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1767 /* Create a new pane. */
1768 Lisp_Object pane_name
, prefix
;
1771 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1772 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1774 #ifndef HAVE_MULTILINGUAL_MENU
1775 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1777 pane_name
= ENCODE_MENU_STRING (pane_name
);
1778 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1781 pane_string
= (NILP (pane_name
)
1782 ? "" : (char *) SDATA (pane_name
));
1783 /* If there is just one top-level pane, put all its items directly
1784 under the top-level menu. */
1785 if (menu_items_n_panes
== 1)
1788 /* If the pane has a meaningful name,
1789 make the pane a top-level menu item
1790 with its items as a submenu beneath it. */
1791 if (!keymaps
&& strcmp (pane_string
, ""))
1793 wv
= xmalloc_widget_value ();
1797 first_wv
->contents
= wv
;
1798 wv
->name
= pane_string
;
1799 if (keymaps
&& !NILP (prefix
))
1803 wv
->button_type
= BUTTON_TYPE_NONE
;
1808 else if (first_pane
)
1814 i
+= MENU_ITEMS_PANE_LENGTH
;
1818 /* Create a new item within current pane. */
1819 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1820 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1821 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1822 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1823 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1824 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1825 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1826 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1828 #ifndef HAVE_MULTILINGUAL_MENU
1829 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
1831 item_name
= ENCODE_MENU_STRING (item_name
);
1832 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1835 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1837 descrip
= ENCODE_MENU_STRING (descrip
);
1838 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1840 #endif /* not HAVE_MULTILINGUAL_MENU */
1842 wv
= xmalloc_widget_value ();
1846 save_wv
->contents
= wv
;
1847 wv
->name
= (char *) SDATA (item_name
);
1848 if (!NILP (descrip
))
1849 wv
->key
= (char *) SDATA (descrip
);
1851 /* If this item has a null value,
1852 make the call_data null so that it won't display a box
1853 when the mouse is on it. */
1855 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
1856 wv
->enabled
= !NILP (enable
);
1859 wv
->button_type
= BUTTON_TYPE_NONE
;
1860 else if (EQ (type
, QCtoggle
))
1861 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1862 else if (EQ (type
, QCradio
))
1863 wv
->button_type
= BUTTON_TYPE_RADIO
;
1867 wv
->selected
= !NILP (selected
);
1869 if (! STRINGP (help
))
1876 i
+= MENU_ITEMS_ITEM_LENGTH
;
1880 /* Deal with the title, if it is non-nil. */
1883 widget_value
*wv_title
= xmalloc_widget_value ();
1884 widget_value
*wv_sep1
= xmalloc_widget_value ();
1885 widget_value
*wv_sep2
= xmalloc_widget_value ();
1887 wv_sep2
->name
= "--";
1888 wv_sep2
->next
= first_wv
->contents
;
1889 wv_sep2
->help
= Qnil
;
1891 wv_sep1
->name
= "--";
1892 wv_sep1
->next
= wv_sep2
;
1893 wv_sep1
->help
= Qnil
;
1895 #ifndef HAVE_MULTILINGUAL_MENU
1896 if (STRING_MULTIBYTE (title
))
1897 title
= ENCODE_MENU_STRING (title
);
1900 wv_title
->name
= (char *) SDATA (title
);
1901 wv_title
->enabled
= TRUE
;
1902 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1903 wv_title
->help
= Qnil
;
1904 wv_title
->next
= wv_sep1
;
1905 first_wv
->contents
= wv_title
;
1908 /* No selection has been chosen yet. */
1909 menu_item_selection
= 0;
1911 /* Actually create and show the menu until popped down. */
1912 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
);
1914 /* Free the widget_value objects we used to specify the contents. */
1915 free_menubar_widget_value_tree (first_wv
);
1917 /* Find the selected item, and its pane, to return
1918 the proper value. */
1919 if (menu_item_selection
!= 0)
1921 Lisp_Object prefix
, entry
;
1923 prefix
= entry
= Qnil
;
1925 while (i
< menu_items_used
)
1927 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1929 subprefix_stack
[submenu_depth
++] = prefix
;
1933 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1935 prefix
= subprefix_stack
[--submenu_depth
];
1938 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1941 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1942 i
+= MENU_ITEMS_PANE_LENGTH
;
1944 /* Ignore a nil in the item list.
1945 It's meaningful only for dialog boxes. */
1946 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1951 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1952 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
1958 entry
= Fcons (entry
, Qnil
);
1960 entry
= Fcons (prefix
, entry
);
1961 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1962 if (!NILP (subprefix_stack
[j
]))
1963 entry
= Fcons (subprefix_stack
[j
], entry
);
1967 i
+= MENU_ITEMS_ITEM_LENGTH
;
1971 else if (!for_click
)
1972 /* Make "Cancel" equivalent to C-g. */
1973 Fsignal (Qquit
, Qnil
);
1980 dialog_selection_callback (widget
, client_data
)
1982 gpointer client_data
;
1984 /* The EMACS_INT cast avoids a warning. There's no problem
1985 as long as pointers have enough bits to hold small integers. */
1986 if ((int) (EMACS_INT
) client_data
!= -1)
1987 menu_item_selection
= (Lisp_Object
*) client_data
;
1989 popup_activated_flag
= 0;
1992 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1994 menu_item_selection will be set to the selection. */
1996 create_and_show_dialog (f
, first_wv
)
1998 widget_value
*first_wv
;
2002 if (! FRAME_X_P (f
))
2005 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
2006 G_CALLBACK (dialog_selection_callback
),
2007 G_CALLBACK (popup_deactivate_callback
),
2012 int specpdl_count
= SPECPDL_INDEX ();
2013 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
2015 /* Display the menu. */
2016 gtk_widget_show_all (menu
);
2018 /* Process events that apply to the menu. */
2019 popup_widget_loop (1, menu
);
2021 unbind_to (specpdl_count
, Qnil
);
2025 #else /* not USE_GTK */
2027 dialog_selection_callback (widget
, id
, client_data
)
2030 XtPointer client_data
;
2032 /* The EMACS_INT cast avoids a warning. There's no problem
2033 as long as pointers have enough bits to hold small integers. */
2034 if ((int) (EMACS_INT
) client_data
!= -1)
2035 menu_item_selection
= (Lisp_Object
*) client_data
;
2038 lw_destroy_all_widgets (id
);
2040 popup_activated_flag
= 0;
2044 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2046 menu_item_selection will be set to the selection. */
2048 create_and_show_dialog (f
, first_wv
)
2050 widget_value
*first_wv
;
2057 dialog_id
= widget_id_tick
++;
2059 apply_systemfont_to_dialog (f
->output_data
.x
->widget
);
2061 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
2062 f
->output_data
.x
->widget
, 1, 0,
2063 dialog_selection_callback
, 0, 0);
2064 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
2065 /* Display the dialog box. */
2066 lw_pop_up_all_widgets (dialog_id
);
2067 popup_activated_flag
= 1;
2068 x_activate_timeout_atimer ();
2070 /* Process events that apply to the dialog box.
2071 Also handle timers. */
2073 int count
= SPECPDL_INDEX ();
2074 int fact
= 4 * sizeof (LWLIB_ID
);
2076 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2077 record_unwind_protect (pop_down_menu
,
2078 Fcons (make_number (dialog_id
>> (fact
)),
2079 make_number (dialog_id
& ~(-1 << (fact
)))));
2081 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
2084 unbind_to (count
, Qnil
);
2088 #endif /* not USE_GTK */
2090 static char * button_names
[] = {
2091 "button1", "button2", "button3", "button4", "button5",
2092 "button6", "button7", "button8", "button9", "button10" };
2095 xdialog_show (f
, keymaps
, title
, header
, error_name
)
2098 Lisp_Object title
, header
;
2101 int i
, nb_buttons
=0;
2102 char dialog_name
[6];
2104 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
2106 /* Number of elements seen so far, before boundary. */
2108 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2109 int boundary_seen
= 0;
2111 if (! FRAME_X_P (f
))
2116 if (menu_items_n_panes
> 1)
2118 *error_name
= "Multiple panes in dialog box";
2122 /* Create a tree of widget_value objects
2123 representing the text label and buttons. */
2125 Lisp_Object pane_name
, prefix
;
2127 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
2128 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
2129 pane_string
= (NILP (pane_name
)
2130 ? "" : (char *) SDATA (pane_name
));
2131 prev_wv
= xmalloc_widget_value ();
2132 prev_wv
->value
= pane_string
;
2133 if (keymaps
&& !NILP (prefix
))
2135 prev_wv
->enabled
= 1;
2136 prev_wv
->name
= "message";
2137 prev_wv
->help
= Qnil
;
2140 /* Loop over all panes and items, filling in the tree. */
2141 i
= MENU_ITEMS_PANE_LENGTH
;
2142 while (i
< menu_items_used
)
2145 /* Create a new item within current pane. */
2146 Lisp_Object item_name
, enable
, descrip
;
2147 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2148 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2150 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2152 if (NILP (item_name
))
2154 free_menubar_widget_value_tree (first_wv
);
2155 *error_name
= "Submenu in dialog items";
2158 if (EQ (item_name
, Qquote
))
2160 /* This is the boundary between left-side elts
2161 and right-side elts. Stop incrementing right_count. */
2166 if (nb_buttons
>= 9)
2168 free_menubar_widget_value_tree (first_wv
);
2169 *error_name
= "Too many dialog items";
2173 wv
= xmalloc_widget_value ();
2175 wv
->name
= (char *) button_names
[nb_buttons
];
2176 if (!NILP (descrip
))
2177 wv
->key
= (char *) SDATA (descrip
);
2178 wv
->value
= (char *) SDATA (item_name
);
2179 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
2180 wv
->enabled
= !NILP (enable
);
2184 if (! boundary_seen
)
2188 i
+= MENU_ITEMS_ITEM_LENGTH
;
2191 /* If the boundary was not specified,
2192 by default put half on the left and half on the right. */
2193 if (! boundary_seen
)
2194 left_count
= nb_buttons
- nb_buttons
/ 2;
2196 wv
= xmalloc_widget_value ();
2197 wv
->name
= dialog_name
;
2200 /* Frame title: 'Q' = Question, 'I' = Information.
2201 Can also have 'E' = Error if, one day, we want
2202 a popup for errors. */
2204 dialog_name
[0] = 'Q';
2206 dialog_name
[0] = 'I';
2208 /* Dialog boxes use a really stupid name encoding
2209 which specifies how many buttons to use
2210 and how many buttons are on the right. */
2211 dialog_name
[1] = '0' + nb_buttons
;
2212 dialog_name
[2] = 'B';
2213 dialog_name
[3] = 'R';
2214 /* Number of buttons to put on the right. */
2215 dialog_name
[4] = '0' + nb_buttons
- left_count
;
2217 wv
->contents
= first_wv
;
2221 /* No selection has been chosen yet. */
2222 menu_item_selection
= 0;
2224 /* Actually create and show the dialog. */
2225 create_and_show_dialog (f
, first_wv
);
2227 /* Free the widget_value objects we used to specify the contents. */
2228 free_menubar_widget_value_tree (first_wv
);
2230 /* Find the selected item, and its pane, to return
2231 the proper value. */
2232 if (menu_item_selection
!= 0)
2238 while (i
< menu_items_used
)
2242 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2245 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2246 i
+= MENU_ITEMS_PANE_LENGTH
;
2248 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2250 /* This is the boundary between left-side elts and
2257 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2258 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2262 entry
= Fcons (entry
, Qnil
);
2264 entry
= Fcons (prefix
, entry
);
2268 i
+= MENU_ITEMS_ITEM_LENGTH
;
2273 /* Make "Cancel" equivalent to C-g. */
2274 Fsignal (Qquit
, Qnil
);
2279 #else /* not USE_X_TOOLKIT && not USE_GTK */
2281 /* The frame of the last activated non-toolkit menu bar.
2282 Used to generate menu help events. */
2284 static struct frame
*menu_help_frame
;
2287 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2289 PANE is the pane number, and ITEM is the menu item number in
2290 the menu (currently not used).
2292 This cannot be done with generating a HELP_EVENT because
2293 XMenuActivate contains a loop that doesn't let Emacs process
2297 menu_help_callback (help_string
, pane
, item
)
2301 extern Lisp_Object Qmenu_item
;
2302 Lisp_Object
*first_item
;
2303 Lisp_Object pane_name
;
2304 Lisp_Object menu_object
;
2306 first_item
= XVECTOR (menu_items
)->contents
;
2307 if (EQ (first_item
[0], Qt
))
2308 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
2309 else if (EQ (first_item
[0], Qquote
))
2310 /* This shouldn't happen, see xmenu_show. */
2311 pane_name
= empty_unibyte_string
;
2313 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
2315 /* (menu-item MENU-NAME PANE-NUMBER) */
2316 menu_object
= Fcons (Qmenu_item
,
2318 Fcons (make_number (pane
), Qnil
)));
2319 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
2320 Qnil
, menu_object
, make_number (item
), 1);
2327 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
2328 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
2330 FRAME_PTR f
= p1
->pointer
;
2331 XMenu
*menu
= p2
->pointer
;
2335 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
2336 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
2338 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2340 #ifdef HAVE_X_WINDOWS
2341 /* Assume the mouse has moved out of the X window.
2342 If it has actually moved in, we will get an EnterNotify. */
2343 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
2345 /* State that no mouse buttons are now held.
2346 (The oldXMenu code doesn't track this info for us.)
2347 That is not necessarily true, but the fiction leads to reasonable
2348 results, and it is a pain to ask which are actually held now. */
2349 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2351 #endif /* HAVE_X_WINDOWS */
2360 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
, timestamp
)
2367 EMACS_UINT timestamp
;
2371 int pane
, selidx
, lpane
, status
;
2372 Lisp_Object entry
, pane_prefix
;
2374 int ulx
, uly
, width
, height
;
2375 int dispwidth
, dispheight
;
2376 int i
, j
, lines
, maxlines
;
2379 unsigned int dummy_uint
;
2380 int specpdl_count
= SPECPDL_INDEX ();
2382 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
2386 if (menu_items_n_panes
== 0)
2389 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2391 *error
= "Empty menu";
2395 /* Figure out which root window F is on. */
2396 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
2397 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
2398 &dummy_uint
, &dummy_uint
);
2400 /* Make the menu on that window. */
2401 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
2404 *error
= "Can't create menu";
2408 /* Don't GC while we prepare and show the menu,
2409 because we give the oldxmenu library pointers to the
2410 contents of strings. */
2411 inhibit_garbage_collection ();
2413 #ifdef HAVE_X_WINDOWS
2414 /* Adjust coordinates to relative to the outer (window manager) window. */
2415 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
2416 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2417 #endif /* HAVE_X_WINDOWS */
2419 /* Adjust coordinates to be root-window-relative. */
2423 /* Create all the necessary panes and their items. */
2424 maxlines
= lines
= i
= 0;
2425 while (i
< menu_items_used
)
2427 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2429 /* Create a new pane. */
2430 Lisp_Object pane_name
, prefix
;
2433 maxlines
= max (maxlines
, lines
);
2435 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
2436 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2437 pane_string
= (NILP (pane_name
)
2438 ? "" : (char *) SDATA (pane_name
));
2439 if (keymaps
&& !NILP (prefix
))
2442 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
2443 if (lpane
== XM_FAILURE
)
2445 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2446 *error
= "Can't create pane";
2449 i
+= MENU_ITEMS_PANE_LENGTH
;
2451 /* Find the width of the widest item in this pane. */
2454 while (j
< menu_items_used
)
2457 item
= XVECTOR (menu_items
)->contents
[j
];
2465 width
= SBYTES (item
);
2466 if (width
> maxwidth
)
2469 j
+= MENU_ITEMS_ITEM_LENGTH
;
2472 /* Ignore a nil in the item list.
2473 It's meaningful only for dialog boxes. */
2474 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2478 /* Create a new item within current pane. */
2479 Lisp_Object item_name
, enable
, descrip
, help
;
2480 unsigned char *item_data
;
2483 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2484 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2486 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2487 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
2488 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
2490 if (!NILP (descrip
))
2492 int gap
= maxwidth
- SBYTES (item_name
);
2493 /* if alloca is fast, use that to make the space,
2494 to reduce gc needs. */
2496 = (unsigned char *) alloca (maxwidth
2497 + SBYTES (descrip
) + 1);
2498 bcopy (SDATA (item_name
), item_data
,
2499 SBYTES (item_name
));
2500 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
2502 bcopy (SDATA (descrip
), item_data
+ j
,
2504 item_data
[j
+ SBYTES (descrip
)] = 0;
2507 item_data
= SDATA (item_name
);
2509 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
2510 menu
, lpane
, 0, item_data
,
2511 !NILP (enable
), help_string
)
2514 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2515 *error
= "Can't add selection to menu";
2518 i
+= MENU_ITEMS_ITEM_LENGTH
;
2523 maxlines
= max (maxlines
, lines
);
2525 /* All set and ready to fly. */
2526 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
2527 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2528 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2529 x
= min (x
, dispwidth
);
2530 y
= min (y
, dispheight
);
2533 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
2534 &ulx
, &uly
, &width
, &height
);
2535 if (ulx
+width
> dispwidth
)
2537 x
-= (ulx
+ width
) - dispwidth
;
2538 ulx
= dispwidth
- width
;
2540 if (uly
+height
> dispheight
)
2542 y
-= (uly
+ height
) - dispheight
;
2543 uly
= dispheight
- height
;
2545 #ifndef HAVE_X_WINDOWS
2546 if (FRAME_HAS_MINIBUF_P (f
) && uly
+height
> dispheight
- 1)
2548 /* Move the menu away of the echo area, to avoid overwriting the
2549 menu with help echo messages or vice versa. */
2550 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
2552 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2553 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2562 if (ulx
< 0) x
-= ulx
;
2563 if (uly
< 0) y
-= uly
;
2567 /* If position was not given by a mouse click, adjust so upper left
2568 corner of the menu as a whole ends up at given coordinates. This
2569 is what x-popup-menu says in its documentation. */
2571 y
+= 1.5*height
/(maxlines
+2);
2574 XMenuSetAEQ (menu
, TRUE
);
2575 XMenuSetFreeze (menu
, TRUE
);
2579 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
2582 record_unwind_protect (pop_down_menu
,
2583 Fcons (make_save_value (f
, 0),
2584 make_save_value (menu
, 0)));
2586 /* Help display under X won't work because XMenuActivate contains
2587 a loop that doesn't give Emacs a chance to process it. */
2588 menu_help_frame
= f
;
2589 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
2590 x
, y
, ButtonReleaseMask
, &datap
,
2591 menu_help_callback
);
2597 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
2600 /* Find the item number SELIDX in pane number PANE. */
2602 while (i
< menu_items_used
)
2604 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2608 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2610 i
+= MENU_ITEMS_PANE_LENGTH
;
2619 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2622 entry
= Fcons (entry
, Qnil
);
2623 if (!NILP (pane_prefix
))
2624 entry
= Fcons (pane_prefix
, entry
);
2630 i
+= MENU_ITEMS_ITEM_LENGTH
;
2636 *error
= "Can't activate menu";
2641 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2642 the menu was invoked with a mouse event as POSITION). */
2644 Fsignal (Qquit
, Qnil
);
2649 unbind_to (specpdl_count
, Qnil
);
2654 #endif /* not USE_X_TOOLKIT */
2656 #endif /* HAVE_MENUS */
2658 /* Detect if a dialog or menu has been posted. */
2663 return popup_activated_flag
;
2666 /* The following is used by delayed window autoselection. */
2668 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2669 doc
: /* Return t if a menu or popup dialog is active. */)
2673 return (popup_activated ()) ? Qt
: Qnil
;
2676 #endif /* HAVE_MENUS */
2682 Qdebug_on_next_call
= intern_c_string ("debug-on-next-call");
2683 staticpro (&Qdebug_on_next_call
);
2685 #ifdef USE_X_TOOLKIT
2686 widget_id_tick
= (1<<16);
2687 next_menubar_widget_id
= 1;
2690 defsubr (&Smenu_or_popup_active_p
);
2692 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2693 defsubr (&Sx_menu_bar_open_internal
);
2694 Ffset (intern_c_string ("accelerate-menu"),
2695 intern_c_string (Sx_menu_bar_open_internal
.symbol_name
));
2699 defsubr (&Sx_popup_dialog
);
2703 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2704 (do not change this comment) */