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>
85 #include <X11/Xaw3d/Paned.h>
86 #else /* !HAVE_XAW3D */
87 #include <X11/Xaw/Paned.h>
88 #endif /* HAVE_XAW3D */
89 #endif /* USE_LUCID */
90 #include "../lwlib/lwlib.h"
91 #else /* not USE_X_TOOLKIT */
93 #include "../oldXMenu/XMenu.h"
95 #endif /* not USE_X_TOOLKIT */
96 #endif /* HAVE_X_WINDOWS */
109 Lisp_Object Qdebug_on_next_call
;
111 extern Lisp_Object Qmenu_bar
;
113 extern Lisp_Object QCtoggle
, QCradio
;
115 extern Lisp_Object Voverriding_local_map
;
116 extern Lisp_Object Voverriding_local_map_menu_flag
;
118 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
120 extern Lisp_Object Qmenu_bar_update_hook
;
123 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
124 extern XtAppContext Xt_app_con
;
126 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
128 static void popup_get_selection
P_ ((XEvent
*, struct x_display_info
*,
130 #endif /* USE_X_TOOLKIT */
133 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
134 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
138 static int update_frame_menubar
P_ ((struct frame
*));
140 /* Flag which when set indicates a dialog or menu has been posted by
141 Xt on behalf of one of the widget sets. */
142 static int popup_activated_flag
;
144 static int next_menubar_widget_id
;
146 /* For NS and NTGUI, these prototypes are defined in keyboard.h. */
147 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
148 extern widget_value
*xmalloc_widget_value
P_ ((void));
149 extern widget_value
*digest_single_submenu
P_ ((int, int, int));
152 /* This is set nonzero after the user activates the menu bar, and set
153 to zero again after the menu bars are redisplayed by prepare_menu_bar.
154 While it is nonzero, all calls to set_frame_menubar go deep.
156 I don't understand why this is needed, but it does seem to be
157 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
159 int pending_menu_activation
;
163 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
165 static struct frame
*
166 menubar_id_to_frame (id
)
169 Lisp_Object tail
, frame
;
172 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
178 if (!FRAME_WINDOW_P (f
))
180 if (f
->output_data
.x
->id
== id
)
188 #ifdef HAVE_X_WINDOWS
189 /* Return the mouse position in *X and *Y. The coordinates are window
190 relative for the edit window in frame F.
191 This is for Fx_popup_menu. The mouse_position_hook can not
192 be used for X, as it returns window relative coordinates
193 for the window where the mouse is in. This could be the menu bar,
194 the scroll bar or the edit window. Fx_popup_menu needs to be
195 sure it is the edit window. */
197 mouse_position_for_popup (f
, x
, y
)
202 Window root
, dummy_window
;
210 XQueryPointer (FRAME_X_DISPLAY (f
),
211 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
213 /* The root window which contains the pointer. */
216 /* Window pointer is on, not used */
219 /* The position on that root window. */
222 /* x/y in dummy_window coordinates, not used. */
225 /* Modifier keys and pointer buttons, about which
227 (unsigned int *) &dummy
);
231 /* xmenu_show expects window coordinates, not root window
232 coordinates. Translate. */
233 *x
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
234 *y
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
237 #endif /* HAVE_X_WINDOWS */
241 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
242 doc
: /* Pop up a dialog box and return user's selection.
243 POSITION specifies which frame to use.
244 This is normally a mouse button event or a window or frame.
245 If POSITION is t, it means to use the frame the mouse is on.
246 The dialog box appears in the middle of the specified frame.
248 CONTENTS specifies the alternatives to display in the dialog box.
249 It is a list of the form (DIALOG ITEM1 ITEM2...).
250 Each ITEM is a cons cell (STRING . VALUE).
251 The return value is VALUE from the chosen item.
253 An ITEM may also be just a string--that makes a nonselectable item.
254 An ITEM may also be nil--that means to put all preceding items
255 on the left of the dialog box and all following items on the right.
256 \(By default, approximately half appear on each side.)
258 If HEADER is non-nil, the frame title for the box is "Information",
259 otherwise it is "Question".
261 If the user gets rid of the dialog box without making a valid choice,
262 for instance using the window manager, then this produces a quit and
263 `x-popup-dialog' does not return. */)
264 (position
, contents
, header
)
265 Lisp_Object position
, contents
, header
;
272 /* Decode the first argument: find the window or frame to use. */
273 if (EQ (position
, Qt
)
274 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
275 || EQ (XCAR (position
), Qtool_bar
))))
277 #if 0 /* Using the frame the mouse is on may not be right. */
278 /* Use the mouse's current position. */
279 FRAME_PTR new_f
= SELECTED_FRAME ();
280 Lisp_Object bar_window
;
281 enum scroll_bar_part part
;
285 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
288 XSETFRAME (window
, new_f
);
290 window
= selected_window
;
292 window
= selected_window
;
294 else if (CONSP (position
))
297 tem
= Fcar (position
);
299 window
= Fcar (Fcdr (position
));
302 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
303 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
306 else if (WINDOWP (position
) || FRAMEP (position
))
311 /* Decode where to put the menu. */
315 else if (WINDOWP (window
))
317 CHECK_LIVE_WINDOW (window
);
318 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
321 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
322 but I don't want to make one now. */
323 CHECK_WINDOW (window
);
325 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
326 error ("Can not put X dialog on this terminal");
328 /* Force a redisplay before showing the dialog. If a frame is created
329 just before showing the dialog, its contents may not have been fully
330 drawn, as this depends on timing of events from the X server. Redisplay
331 is not done when a dialog is shown. If redisplay could be done in the
332 X event loop (i.e. the X event loop does not run in a signal handler)
333 this would not be needed.
335 Do this before creating the widget value that points to Lisp
336 string contents, because Fredisplay may GC and relocate them. */
339 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
340 /* Display a menu with these alternatives
341 in the middle of frame F. */
343 Lisp_Object x
, y
, frame
, newpos
;
344 XSETFRAME (frame
, f
);
345 XSETINT (x
, x_pixel_width (f
) / 2);
346 XSETINT (y
, x_pixel_height (f
) / 2);
347 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
349 return Fx_popup_menu (newpos
,
350 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
356 Lisp_Object selection
;
357 int specpdl_count
= SPECPDL_INDEX ();
359 /* Decode the dialog items from what was specified. */
360 title
= Fcar (contents
);
361 CHECK_STRING (title
);
362 record_unwind_protect (unuse_menu_items
, Qnil
);
364 if (NILP (Fcar (Fcdr (contents
))))
365 /* No buttons specified, add an "Ok" button so users can pop down
366 the dialog. Also, the lesstif/motif version crashes if there are
368 contents
= Fcons (title
, Fcons (Fcons (build_string ("Ok"), Qt
), Qnil
));
370 list_of_panes (Fcons (contents
, Qnil
));
372 /* Display them in a dialog box. */
374 selection
= xdialog_show (f
, 0, title
, header
, &error_name
);
377 unbind_to (specpdl_count
, Qnil
);
378 discard_menu_items ();
380 if (error_name
) error (error_name
);
389 /* Set menu_items_inuse so no other popup menu or dialog is created. */
392 x_menu_set_in_use (in_use
)
395 menu_items_inuse
= in_use
? Qt
: Qnil
;
396 popup_activated_flag
= in_use
;
398 if (popup_activated_flag
)
399 x_activate_timeout_atimer ();
403 /* Wait for an X event to arrive or for a timer to expire. */
406 x_menu_wait_for_event (void *data
)
408 /* Another way to do this is to register a timer callback, that can be
409 done in GTK and Xt. But we have to do it like this when using only X
410 anyway, and with callbacks we would have three variants for timer handling
411 instead of the small ifdefs below. */
415 ! XtAppPending (Xt_app_con
)
416 #elif defined USE_GTK
417 ! gtk_events_pending ()
419 ! XPending ((Display
*) data
)
423 EMACS_TIME next_time
= timer_check (1), *ntp
;
424 long secs
= EMACS_SECS (next_time
);
425 long usecs
= EMACS_USECS (next_time
);
426 SELECT_TYPE read_fds
;
427 struct x_display_info
*dpyinfo
;
431 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
433 int fd
= ConnectionNumber (dpyinfo
->display
);
434 FD_SET (fd
, &read_fds
);
436 XFlush (dpyinfo
->display
);
439 if (secs
< 0 && usecs
< 0)
444 select (n
+ 1, &read_fds
, (SELECT_TYPE
*)0, (SELECT_TYPE
*)0, ntp
);
450 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
454 /* Loop in Xt until the menu pulldown or dialog popup has been
455 popped down (deactivated). This is used for x-popup-menu
456 and x-popup-dialog; it is not used for the menu bar.
458 NOTE: All calls to popup_get_selection should be protected
459 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
462 popup_get_selection (initial_event
, dpyinfo
, id
, do_timers
)
463 XEvent
*initial_event
;
464 struct x_display_info
*dpyinfo
;
470 while (popup_activated_flag
)
474 event
= *initial_event
;
479 if (do_timers
) x_menu_wait_for_event (0);
480 XtAppNextEvent (Xt_app_con
, &event
);
483 /* Make sure we don't consider buttons grabbed after menu goes.
484 And make sure to deactivate for any ButtonRelease,
485 even if XtDispatchEvent doesn't do that. */
486 if (event
.type
== ButtonRelease
487 && dpyinfo
->display
== event
.xbutton
.display
)
489 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
490 #ifdef USE_MOTIF /* Pretending that the event came from a
491 Btn1Down seems the only way to convince Motif to
492 activate its callbacks; setting the XmNmenuPost
493 isn't working. --marcus@sysc.pdx.edu. */
494 event
.xbutton
.button
= 1;
495 /* Motif only pops down menus when no Ctrl, Alt or Mod
496 key is pressed and the button is released. So reset key state
497 so Motif thinks this is the case. */
498 event
.xbutton
.state
= 0;
501 /* Pop down on C-g and Escape. */
502 else if (event
.type
== KeyPress
503 && dpyinfo
->display
== event
.xbutton
.display
)
505 KeySym keysym
= XLookupKeysym (&event
.xkey
, 0);
507 if ((keysym
== XK_g
&& (event
.xkey
.state
& ControlMask
) != 0)
508 || keysym
== XK_Escape
) /* Any escape, ignore modifiers. */
509 popup_activated_flag
= 0;
512 x_dispatch_event (&event
, event
.xany
.display
);
516 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
517 doc
: /* Start key navigation of the menu bar in FRAME.
518 This initially opens the first menu bar item and you can then navigate with the
519 arrow keys, select a menu entry with the return key or cancel with the
520 escape key. If FRAME has no menu bar this function does nothing.
522 If FRAME is nil or not given, use the selected frame. */)
527 FRAME_PTR f
= check_x_frame (frame
);
531 if (FRAME_EXTERNAL_MENU_BAR (f
))
532 set_frame_menubar (f
, 0, 1);
534 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
540 x_catch_errors (FRAME_X_DISPLAY (f
));
541 memset (&ev
, 0, sizeof ev
);
542 ev
.xbutton
.display
= FRAME_X_DISPLAY (f
);
543 ev
.xbutton
.window
= XtWindow (menubar
);
544 ev
.xbutton
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
545 ev
.xbutton
.time
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
546 ev
.xbutton
.button
= Button1
;
547 ev
.xbutton
.x
= ev
.xbutton
.y
= FRAME_MENUBAR_HEIGHT (f
) / 2;
548 ev
.xbutton
.same_screen
= True
;
555 XtSetArg (al
[0], XtNchildren
, &list
);
556 XtSetArg (al
[1], XtNnumChildren
, &nr
);
557 XtGetValues (menubar
, al
, 2);
558 ev
.xbutton
.window
= XtWindow (list
[0]);
562 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
563 /* From-window, to-window. */
564 ev
.xbutton
.window
, ev
.xbutton
.root
,
566 /* From-position, to-position. */
567 ev
.xbutton
.x
, ev
.xbutton
.y
,
568 &ev
.xbutton
.x_root
, &ev
.xbutton
.y_root
,
572 error_p
= x_had_errors_p (FRAME_X_DISPLAY (f
));
577 ev
.type
= ButtonPress
;
578 ev
.xbutton
.state
= 0;
580 XtDispatchEvent (&ev
);
581 ev
.xbutton
.type
= ButtonRelease
;
582 ev
.xbutton
.state
= Button1Mask
;
583 XtDispatchEvent (&ev
);
591 #endif /* USE_X_TOOLKIT */
595 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
596 doc
: /* Start key navigation of the menu bar in FRAME.
597 This initially opens the first menu bar item and you can then navigate with the
598 arrow keys, select a menu entry with the return key or cancel with the
599 escape key. If FRAME has no menu bar this function does nothing.
601 If FRAME is nil or not given, use the selected frame. */)
608 /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
612 f
= check_x_frame (frame
);
614 if (FRAME_EXTERNAL_MENU_BAR (f
))
615 set_frame_menubar (f
, 0, 1);
617 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
620 /* Activate the first menu. */
621 GList
*children
= gtk_container_get_children (GTK_CONTAINER (menubar
));
625 g_signal_emit_by_name (children
->data
, "activate_item");
626 popup_activated_flag
= 1;
627 g_list_free (children
);
635 /* Loop util popup_activated_flag is set to zero in a callback.
636 Used for popup menus and dialogs. */
639 popup_widget_loop (do_timers
, widget
)
643 ++popup_activated_flag
;
645 /* Process events in the Gtk event loop until done. */
646 while (popup_activated_flag
)
648 if (do_timers
) x_menu_wait_for_event (0);
649 gtk_main_iteration ();
654 /* Activate the menu bar of frame F.
655 This is called from keyboard.c when it gets the
656 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
658 To activate the menu bar, we use the X button-press event
659 that was saved in saved_menu_event.
660 That makes the toolkit do its thing.
662 But first we recompute the menu bar contents (the whole tree).
664 The reason for saving the button event until here, instead of
665 passing it to the toolkit right away, is that we can safely
666 execute Lisp code. */
669 x_activate_menubar (f
)
675 if (!f
->output_data
.x
->saved_menu_event
->type
)
679 if (! xg_win_to_widget (FRAME_X_DISPLAY (f
),
680 f
->output_data
.x
->saved_menu_event
->xany
.window
))
684 set_frame_menubar (f
, 0, 1);
687 /* If we click outside any menu item, the menu bar still grabs.
688 So we send Press and the Release. If outside, grab is released.
689 If on a menu item, it is popped up normally.
690 PutBack is like a stack, so we put back in reverse order. */
691 f
->output_data
.x
->saved_menu_event
->type
= ButtonRelease
;
692 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
693 f
->output_data
.x
->saved_menu_event
);
694 f
->output_data
.x
->saved_menu_event
->type
= ButtonPress
;
695 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
696 f
->output_data
.x
->saved_menu_event
);
697 popup_activated_flag
= 1;
699 XtDispatchEvent (f
->output_data
.x
->saved_menu_event
);
703 if (f
->output_data
.x
->saved_menu_event
->type
== ButtonRelease
)
704 pending_menu_activation
= 1;
707 /* Ignore this if we get it a second time. */
708 f
->output_data
.x
->saved_menu_event
->type
= 0;
711 /* This callback is invoked when the user selects a menubar cascade
712 pushbutton, but before the pulldown menu is posted. */
716 popup_activate_callback (widget
, id
, client_data
)
719 XtPointer client_data
;
721 popup_activated_flag
= 1;
723 x_activate_timeout_atimer ();
728 /* This callback is invoked when a dialog or menu is finished being
729 used and has been unposted. */
733 popup_deactivate_callback (widget
, client_data
)
735 gpointer client_data
;
737 popup_activated_flag
= 0;
741 popup_deactivate_callback (widget
, id
, client_data
)
744 XtPointer client_data
;
746 popup_activated_flag
= 0;
751 /* Function that finds the frame for WIDGET and shows the HELP text
753 F is the frame if known, or NULL if not known. */
755 show_help_event (f
, widget
, help
)
757 xt_or_gtk_widget widget
;
764 XSETFRAME (frame
, f
);
765 kbd_buffer_store_help_event (frame
, help
);
769 #if 0 /* This code doesn't do anything useful. ++kfs */
770 /* WIDGET is the popup menu. It's parent is the frame's
771 widget. See which frame that is. */
772 xt_or_gtk_widget frame_widget
= XtParent (widget
);
775 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
779 && (f
= XFRAME (frame
),
780 FRAME_X_P (f
) && f
->output_data
.x
->widget
== frame_widget
))
784 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
788 /* Callback called when menu items are highlighted/unhighlighted
789 while moving the mouse over them. WIDGET is the menu bar or menu
790 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
791 the data structure for the menu item, or null in case of
796 menu_highlight_callback (widget
, call_data
)
800 xg_menu_item_cb_data
*cb_data
;
803 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (widget
),
805 if (! cb_data
) return;
807 help
= call_data
? cb_data
->help
: Qnil
;
809 /* If popup_activated_flag is greater than 1 we are in a popup menu.
810 Don't show help for them, they won't appear before the
811 popup is popped down. */
812 if (popup_activated_flag
<= 1)
813 show_help_event (cb_data
->cl_data
->f
, widget
, help
);
817 menu_highlight_callback (widget
, id
, call_data
)
825 widget_value
*wv
= (widget_value
*) call_data
;
827 help
= wv
? wv
->help
: Qnil
;
829 /* Determine the frame for the help event. */
830 f
= menubar_id_to_frame (id
);
832 show_help_event (f
, widget
, help
);
837 /* Gtk calls callbacks just because we tell it what item should be
838 selected in a radio group. If this variable is set to a non-zero
839 value, we are creating menus and don't want callbacks right now.
841 static int xg_crazy_callback_abort
;
843 /* This callback is called from the menu bar pulldown menu
844 when the user makes a selection.
845 Figure out what the user chose
846 and put the appropriate events into the keyboard buffer. */
848 menubar_selection_callback (widget
, client_data
)
850 gpointer client_data
;
852 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
854 if (xg_crazy_callback_abort
)
857 if (! cb_data
|| ! cb_data
->cl_data
|| ! cb_data
->cl_data
->f
)
860 /* For a group of radio buttons, GTK calls the selection callback first
861 for the item that was active before the selection and then for the one that
862 is active after the selection. For C-h k this means we get the help on
863 the deselected item and then the selected item is executed. Prevent that
864 by ignoring the non-active item. */
865 if (GTK_IS_RADIO_MENU_ITEM (widget
)
866 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget
)))
869 /* When a menu is popped down, X generates a focus event (i.e. focus
870 goes back to the frame below the menu). Since GTK buffers events,
871 we force it out here before the menu selection event. Otherwise
872 sit-for will exit at once if the focus event follows the menu selection
876 while (gtk_events_pending ())
877 gtk_main_iteration ();
880 find_and_call_menu_selection (cb_data
->cl_data
->f
,
881 cb_data
->cl_data
->menu_bar_items_used
,
882 cb_data
->cl_data
->menu_bar_vector
,
886 #else /* not USE_GTK */
888 /* This callback is called from the menu bar pulldown menu
889 when the user makes a selection.
890 Figure out what the user chose
891 and put the appropriate events into the keyboard buffer. */
893 menubar_selection_callback (widget
, id
, client_data
)
896 XtPointer client_data
;
900 f
= menubar_id_to_frame (id
);
903 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
904 f
->menu_bar_vector
, client_data
);
906 #endif /* not USE_GTK */
908 /* Recompute all the widgets of frame F, when the menu bar has been
909 changed. Value is non-zero if widgets were updated. */
912 update_frame_menubar (f
)
916 return xg_update_frame_menubar (f
);
924 x
= f
->output_data
.x
;
926 if (!x
->menubar_widget
|| XtIsManaged (x
->menubar_widget
))
930 /* Save the size of the frame because the pane widget doesn't accept
931 to resize itself. So force it. */
932 columns
= FRAME_COLS (f
);
933 rows
= FRAME_LINES (f
);
935 /* Do the voodoo which means "I'm changing lots of things, don't try
936 to refigure sizes until I'm done." */
937 lw_refigure_widget (x
->column_widget
, False
);
939 /* The order in which children are managed is the top to bottom
940 order in which they are displayed in the paned window. First,
941 remove the text-area widget. */
942 XtUnmanageChild (x
->edit_widget
);
944 /* Remove the menubar that is there now, and put up the menubar that
946 XtManageChild (x
->menubar_widget
);
947 XtMapWidget (x
->menubar_widget
);
948 XtVaSetValues (x
->menubar_widget
, XtNmappedWhenManaged
, 1, NULL
);
950 /* Re-manage the text-area widget, and then thrash the sizes. */
951 XtManageChild (x
->edit_widget
);
952 lw_refigure_widget (x
->column_widget
, True
);
954 /* Force the pane widget to resize itself with the right values. */
955 EmacsFrameSetCharSize (x
->edit_widget
, columns
, rows
);
961 /* Set the contents of the menubar widgets of frame F.
962 The argument FIRST_TIME is currently ignored;
963 it is set the first time this is called, from initialize_frame_menubar. */
966 set_frame_menubar (f
, first_time
, deep_p
)
971 xt_or_gtk_widget menubar_widget
;
976 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
978 int *submenu_start
, *submenu_end
;
979 int *submenu_top_level_items
, *submenu_n_panes
;
984 menubar_widget
= f
->output_data
.x
->menubar_widget
;
986 XSETFRAME (Vmenu_updating_frame
, f
);
989 if (f
->output_data
.x
->id
== 0)
990 f
->output_data
.x
->id
= next_menubar_widget_id
++;
991 id
= f
->output_data
.x
->id
;
994 if (! menubar_widget
)
996 else if (pending_menu_activation
&& !deep_p
)
998 /* Make the first call for any given frame always go deep. */
999 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
1002 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
1003 f
->output_data
.x
->saved_menu_event
->type
= 0;
1007 /* If we have detached menus, we must update deep so detached menus
1008 also gets updated. */
1009 deep_p
= deep_p
|| xg_have_tear_offs ();
1014 /* Make a widget-value tree representing the entire menu trees. */
1016 struct buffer
*prev
= current_buffer
;
1018 int specpdl_count
= SPECPDL_INDEX ();
1019 int previous_menu_items_used
= f
->menu_bar_items_used
;
1020 Lisp_Object
*previous_items
1021 = (Lisp_Object
*) alloca (previous_menu_items_used
1022 * sizeof (Lisp_Object
));
1024 /* If we are making a new widget, its contents are empty,
1025 do always reinitialize them. */
1026 if (! menubar_widget
)
1027 previous_menu_items_used
= 0;
1029 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1030 specbind (Qinhibit_quit
, Qt
);
1031 /* Don't let the debugger step into this code
1032 because it is not reentrant. */
1033 specbind (Qdebug_on_next_call
, Qnil
);
1035 record_unwind_save_match_data ();
1036 if (NILP (Voverriding_local_map_menu_flag
))
1038 specbind (Qoverriding_terminal_local_map
, Qnil
);
1039 specbind (Qoverriding_local_map
, Qnil
);
1042 set_buffer_internal_1 (XBUFFER (buffer
));
1044 /* Run the Lucid hook. */
1045 safe_run_hooks (Qactivate_menubar_hook
);
1047 /* If it has changed current-menubar from previous value,
1048 really recompute the menubar from the value. */
1049 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1050 call0 (Qrecompute_lucid_menubar
);
1051 safe_run_hooks (Qmenu_bar_update_hook
);
1052 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1054 items
= FRAME_MENU_BAR_ITEMS (f
);
1056 /* Save the frame's previous menu bar contents data. */
1057 if (previous_menu_items_used
)
1058 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
1059 previous_menu_items_used
* sizeof (Lisp_Object
));
1061 /* Fill in menu_items with the current menu bar contents.
1062 This can evaluate Lisp code. */
1065 menu_items
= f
->menu_bar_vector
;
1066 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1067 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1068 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1069 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
1070 submenu_top_level_items
1071 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1073 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1075 Lisp_Object key
, string
, maps
;
1079 key
= XVECTOR (items
)->contents
[i
];
1080 string
= XVECTOR (items
)->contents
[i
+ 1];
1081 maps
= XVECTOR (items
)->contents
[i
+ 2];
1085 submenu_start
[i
] = menu_items_used
;
1087 menu_items_n_panes
= 0;
1088 submenu_top_level_items
[i
]
1089 = parse_single_submenu (key
, string
, maps
);
1090 submenu_n_panes
[i
] = menu_items_n_panes
;
1092 submenu_end
[i
] = menu_items_used
;
1095 finish_menu_items ();
1097 /* Convert menu_items into widget_value trees
1098 to display the menu. This cannot evaluate Lisp code. */
1100 wv
= xmalloc_widget_value ();
1101 wv
->name
= "menubar";
1104 wv
->button_type
= BUTTON_TYPE_NONE
;
1108 for (i
= 0; i
< last_i
; i
+= 4)
1110 menu_items_n_panes
= submenu_n_panes
[i
];
1111 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
1112 submenu_top_level_items
[i
]);
1116 first_wv
->contents
= wv
;
1117 /* Don't set wv->name here; GC during the loop might relocate it. */
1119 wv
->button_type
= BUTTON_TYPE_NONE
;
1123 set_buffer_internal_1 (prev
);
1125 /* If there has been no change in the Lisp-level contents
1126 of the menu bar, skip redisplaying it. Just exit. */
1128 /* Compare the new menu items with the ones computed last time. */
1129 for (i
= 0; i
< previous_menu_items_used
; i
++)
1130 if (menu_items_used
== i
1131 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1133 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1135 /* The menu items have not changed. Don't bother updating
1136 the menus in any form, since it would be a no-op. */
1137 free_menubar_widget_value_tree (first_wv
);
1138 discard_menu_items ();
1139 unbind_to (specpdl_count
, Qnil
);
1143 /* The menu items are different, so store them in the frame. */
1144 f
->menu_bar_vector
= menu_items
;
1145 f
->menu_bar_items_used
= menu_items_used
;
1147 /* This undoes save_menu_items. */
1148 unbind_to (specpdl_count
, Qnil
);
1150 /* Now GC cannot happen during the lifetime of the widget_value,
1151 so it's safe to store data from a Lisp_String. */
1152 wv
= first_wv
->contents
;
1153 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1156 string
= XVECTOR (items
)->contents
[i
+ 1];
1159 wv
->name
= (char *) SDATA (string
);
1160 update_submenu_strings (wv
->contents
);
1167 /* Make a widget-value tree containing
1168 just the top level menu bar strings. */
1170 wv
= xmalloc_widget_value ();
1171 wv
->name
= "menubar";
1174 wv
->button_type
= BUTTON_TYPE_NONE
;
1178 items
= FRAME_MENU_BAR_ITEMS (f
);
1179 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1183 string
= XVECTOR (items
)->contents
[i
+ 1];
1187 wv
= xmalloc_widget_value ();
1188 wv
->name
= (char *) SDATA (string
);
1191 wv
->button_type
= BUTTON_TYPE_NONE
;
1193 /* This prevents lwlib from assuming this
1194 menu item is really supposed to be empty. */
1195 /* The EMACS_INT cast avoids a warning.
1196 This value just has to be different from small integers. */
1197 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1202 first_wv
->contents
= wv
;
1206 /* Forget what we thought we knew about what is in the
1207 detailed contents of the menu bar menus.
1208 Changing the top level always destroys the contents. */
1209 f
->menu_bar_items_used
= 0;
1212 /* Create or update the menu bar widget. */
1217 xg_crazy_callback_abort
= 1;
1220 /* The fourth arg is DEEP_P, which says to consider the entire
1221 menu trees we supply, rather than just the menu bar item names. */
1222 xg_modify_menubar_widgets (menubar_widget
,
1226 G_CALLBACK (menubar_selection_callback
),
1227 G_CALLBACK (popup_deactivate_callback
),
1228 G_CALLBACK (menu_highlight_callback
));
1232 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
1235 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
1236 G_CALLBACK (menubar_selection_callback
),
1237 G_CALLBACK (popup_deactivate_callback
),
1238 G_CALLBACK (menu_highlight_callback
));
1240 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1244 #else /* not USE_GTK */
1247 /* Disable resizing (done for Motif!) */
1248 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
1250 /* The third arg is DEEP_P, which says to consider the entire
1251 menu trees we supply, rather than just the menu bar item names. */
1252 lw_modify_all_widgets (id
, first_wv
, deep_p
);
1254 /* Re-enable the edit widget to resize. */
1255 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
1259 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1260 XtTranslations override
= XtParseTranslationTable (menuOverride
);
1262 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
1263 f
->output_data
.x
->column_widget
,
1265 popup_activate_callback
,
1266 menubar_selection_callback
,
1267 popup_deactivate_callback
,
1268 menu_highlight_callback
);
1269 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1271 /* Make menu pop down on C-g. */
1272 XtOverrideTranslations (menubar_widget
, override
);
1277 = (f
->output_data
.x
->menubar_widget
1278 ? (f
->output_data
.x
->menubar_widget
->core
.height
1279 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
1282 #if 1 /* Experimentally, we now get the right results
1283 for -geometry -0-0 without this. 24 Aug 96, rms.
1284 Maybe so, but the menu bar size is missing the pixels so the
1285 WM size hints are off by theses pixel. Jan D, oct 2009. */
1287 if (FRAME_EXTERNAL_MENU_BAR (f
))
1290 XtVaGetValues (f
->output_data
.x
->column_widget
,
1291 XtNinternalBorderWidth
, &ibw
, NULL
);
1292 menubar_size
+= ibw
;
1294 #endif /* USE_LUCID */
1297 f
->output_data
.x
->menubar_height
= menubar_size
;
1299 #endif /* not USE_GTK */
1301 free_menubar_widget_value_tree (first_wv
);
1302 update_frame_menubar (f
);
1305 xg_crazy_callback_abort
= 0;
1311 /* Called from Fx_create_frame to create the initial menubar of a frame
1312 before it is mapped, so that the window is mapped with the menubar already
1313 there instead of us tacking it on later and thrashing the window after it
1317 initialize_frame_menubar (f
)
1320 /* This function is called before the first chance to redisplay
1321 the frame. It has to be, so the frame will have the right size. */
1322 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1323 set_frame_menubar (f
, 1, 1);
1327 /* Get rid of the menu bar of frame F, and free its storage.
1328 This is used when deleting a frame, and when turning off the menu bar.
1329 For GTK this function is in gtkutil.c. */
1333 free_frame_menubar (f
)
1336 Widget menubar_widget
;
1338 if (! FRAME_X_P (f
))
1341 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1343 f
->output_data
.x
->menubar_height
= 0;
1348 /* Removing the menu bar magically changes the shell widget's x
1349 and y position of (0, 0) which, when the menu bar is turned
1350 on again, leads to pull-down menuss appearing in strange
1351 positions near the upper-left corner of the display. This
1352 happens only with some window managers like twm and ctwm,
1353 but not with other like Motif's mwm or kwm, because the
1354 latter generate ConfigureNotify events when the menu bar
1355 is switched off, which fixes the shell position. */
1356 Position x0
, y0
, x1
, y1
;
1362 if (f
->output_data
.x
->widget
)
1363 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
1366 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
1367 f
->output_data
.x
->menubar_widget
= NULL
;
1370 if (f
->output_data
.x
->widget
)
1372 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
1373 if (x1
== 0 && y1
== 0)
1374 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
1381 #endif /* not USE_GTK */
1383 #endif /* USE_X_TOOLKIT || USE_GTK */
1385 /* xmenu_show actually displays a menu using the panes and items in menu_items
1386 and returns the value selected from it.
1387 There are two versions of xmenu_show, one for Xt and one for Xlib.
1388 Both assume input is blocked by the caller. */
1390 /* F is the frame the menu is for.
1391 X and Y are the frame-relative specified position,
1392 relative to the inside upper left corner of the frame F.
1393 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1394 KEYMAPS is 1 if this menu was specified with keymaps;
1395 in that case, we return a list containing the chosen item's value
1396 and perhaps also the pane's prefix.
1397 TITLE is the specified menu title.
1398 ERROR is a place to store an error message string in case of failure.
1399 (We return nil on failure, but the value doesn't actually matter.) */
1401 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1403 /* The item selected in the popup menu. */
1404 static Lisp_Object
*volatile menu_item_selection
;
1408 /* Used when position a popup menu. See menu_position_func and
1409 create_and_show_popup_menu below. */
1410 struct next_popup_x_y
1417 /* The menu position function to use if we are not putting a popup
1418 menu where the pointer is.
1419 MENU is the menu to pop up.
1420 X and Y shall on exit contain x/y where the menu shall pop up.
1421 PUSH_IN is not documented in the GTK manual.
1422 USER_DATA is any data passed in when calling gtk_menu_popup.
1423 Here it points to a struct next_popup_x_y where the coordinates
1424 to store in *X and *Y are as well as the frame for the popup.
1426 Here only X and Y are used. */
1428 menu_position_func (menu
, x
, y
, push_in
, user_data
)
1435 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
1437 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (data
->f
);
1438 int disp_width
= x_display_pixel_width (dpyinfo
);
1439 int disp_height
= x_display_pixel_height (dpyinfo
);
1444 /* Check if there is room for the menu. If not, adjust x/y so that
1445 the menu is fully visible. */
1446 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
1447 if (data
->x
+ req
.width
> disp_width
)
1448 *x
-= data
->x
+ req
.width
- disp_width
;
1449 if (data
->y
+ req
.height
> disp_height
)
1450 *y
-= data
->y
+ req
.height
- disp_height
;
1454 popup_selection_callback (widget
, client_data
)
1456 gpointer client_data
;
1458 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1460 if (xg_crazy_callback_abort
) return;
1461 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
1468 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1470 popup_activated_flag
= 0;
1472 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1477 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1479 menu_item_selection will be set to the selection. */
1481 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1483 widget_value
*first_wv
;
1487 EMACS_UINT timestamp
;
1491 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
1492 struct next_popup_x_y popup_x_y
;
1493 int specpdl_count
= SPECPDL_INDEX ();
1495 if (! FRAME_X_P (f
))
1498 xg_crazy_callback_abort
= 1;
1499 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
1500 G_CALLBACK (popup_selection_callback
),
1501 G_CALLBACK (popup_deactivate_callback
),
1502 G_CALLBACK (menu_highlight_callback
));
1503 xg_crazy_callback_abort
= 0;
1507 /* Not invoked by a click. pop up at x/y. */
1508 pos_func
= menu_position_func
;
1510 /* Adjust coordinates to be root-window-relative. */
1511 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1512 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1518 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1522 for (i
= 0; i
< 5; i
++)
1523 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1527 /* Display the menu. */
1528 gtk_widget_show_all (menu
);
1530 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
,
1531 timestamp
> 0 ? timestamp
: gtk_get_current_event_time());
1533 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1535 if (GTK_WIDGET_MAPPED (menu
))
1537 /* Set this to one. popup_widget_loop increases it by one, so it becomes
1538 two. show_help_echo uses this to detect popup menus. */
1539 popup_activated_flag
= 1;
1540 /* Process events that apply to the menu. */
1541 popup_widget_loop (1, menu
);
1544 unbind_to (specpdl_count
, Qnil
);
1546 /* Must reset this manually because the button release event is not passed
1547 to Emacs event loop. */
1548 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1551 #else /* not USE_GTK */
1553 /* We need a unique id for each widget handled by the Lucid Widget
1556 For the main windows, and popup menus, we use this counter,
1557 which we increment each time after use. This starts from 1<<16.
1559 For menu bars, we use numbers starting at 0, counted in
1560 next_menubar_widget_id. */
1561 LWLIB_ID widget_id_tick
;
1564 popup_selection_callback (widget
, id
, client_data
)
1567 XtPointer client_data
;
1569 menu_item_selection
= (Lisp_Object
*) client_data
;
1572 /* ARG is the LWLIB ID of the dialog box, represented
1573 as a Lisp object as (HIGHPART . LOWPART). */
1579 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
1580 | XINT (XCDR (arg
)));
1583 lw_destroy_all_widgets (id
);
1585 popup_activated_flag
= 0;
1590 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1592 menu_item_selection will be set to the selection. */
1594 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1596 widget_value
*first_wv
;
1600 EMACS_UINT timestamp
;
1605 XButtonPressedEvent dummy
;
1609 if (! FRAME_X_P (f
))
1612 menu_id
= widget_id_tick
++;
1613 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
1614 f
->output_data
.x
->widget
, 1, 0,
1615 popup_selection_callback
,
1616 popup_deactivate_callback
,
1617 menu_highlight_callback
);
1619 dummy
.type
= ButtonPress
;
1621 dummy
.send_event
= 0;
1622 dummy
.display
= FRAME_X_DISPLAY (f
);
1623 dummy
.time
= CurrentTime
;
1624 dummy
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1625 dummy
.window
= dummy
.root
;
1626 dummy
.subwindow
= dummy
.root
;
1630 /* Adjust coordinates to be root-window-relative. */
1631 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1632 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1639 for (i
= 0; i
< 5; i
++)
1640 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1643 /* Don't allow any geometry request from the user. */
1644 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
1645 XtSetValues (menu
, av
, ac
);
1647 /* Display the menu. */
1648 lw_popup_menu (menu
, (XEvent
*) &dummy
);
1649 popup_activated_flag
= 1;
1650 x_activate_timeout_atimer ();
1653 int fact
= 4 * sizeof (LWLIB_ID
);
1654 int specpdl_count
= SPECPDL_INDEX ();
1655 record_unwind_protect (pop_down_menu
,
1656 Fcons (make_number (menu_id
>> (fact
)),
1657 make_number (menu_id
& ~(-1 << (fact
)))));
1659 /* Process events that apply to the menu. */
1660 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
1662 unbind_to (specpdl_count
, Qnil
);
1666 #endif /* not USE_GTK */
1669 xmenu_show (FRAME_PTR f
, int x
, int y
, int for_click
, int keymaps
,
1670 Lisp_Object title
, char **error
, EMACS_UINT timestamp
)
1673 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1674 widget_value
**submenu_stack
1675 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1676 Lisp_Object
*subprefix_stack
1677 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1678 int submenu_depth
= 0;
1682 if (! FRAME_X_P (f
))
1687 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1689 *error
= "Empty menu";
1693 /* Create a tree of widget_value objects
1694 representing the panes and their items. */
1695 wv
= xmalloc_widget_value ();
1699 wv
->button_type
= BUTTON_TYPE_NONE
;
1704 /* Loop over all panes and items, filling in the tree. */
1706 while (i
< menu_items_used
)
1708 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1710 submenu_stack
[submenu_depth
++] = save_wv
;
1716 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1719 save_wv
= submenu_stack
[--submenu_depth
];
1723 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1724 && submenu_depth
!= 0)
1725 i
+= MENU_ITEMS_PANE_LENGTH
;
1726 /* Ignore a nil in the item list.
1727 It's meaningful only for dialog boxes. */
1728 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1730 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1732 /* Create a new pane. */
1733 Lisp_Object pane_name
, prefix
;
1736 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1737 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1739 #ifndef HAVE_MULTILINGUAL_MENU
1740 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1742 pane_name
= ENCODE_MENU_STRING (pane_name
);
1743 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1746 pane_string
= (NILP (pane_name
)
1747 ? "" : (char *) SDATA (pane_name
));
1748 /* If there is just one top-level pane, put all its items directly
1749 under the top-level menu. */
1750 if (menu_items_n_panes
== 1)
1753 /* If the pane has a meaningful name,
1754 make the pane a top-level menu item
1755 with its items as a submenu beneath it. */
1756 if (!keymaps
&& strcmp (pane_string
, ""))
1758 wv
= xmalloc_widget_value ();
1762 first_wv
->contents
= wv
;
1763 wv
->name
= pane_string
;
1764 if (keymaps
&& !NILP (prefix
))
1768 wv
->button_type
= BUTTON_TYPE_NONE
;
1773 else if (first_pane
)
1779 i
+= MENU_ITEMS_PANE_LENGTH
;
1783 /* Create a new item within current pane. */
1784 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1785 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1786 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1787 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1788 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1789 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1790 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1791 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1793 #ifndef HAVE_MULTILINGUAL_MENU
1794 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
1796 item_name
= ENCODE_MENU_STRING (item_name
);
1797 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1800 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1802 descrip
= ENCODE_MENU_STRING (descrip
);
1803 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1805 #endif /* not HAVE_MULTILINGUAL_MENU */
1807 wv
= xmalloc_widget_value ();
1811 save_wv
->contents
= wv
;
1812 wv
->name
= (char *) SDATA (item_name
);
1813 if (!NILP (descrip
))
1814 wv
->key
= (char *) SDATA (descrip
);
1816 /* If this item has a null value,
1817 make the call_data null so that it won't display a box
1818 when the mouse is on it. */
1820 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
1821 wv
->enabled
= !NILP (enable
);
1824 wv
->button_type
= BUTTON_TYPE_NONE
;
1825 else if (EQ (type
, QCtoggle
))
1826 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1827 else if (EQ (type
, QCradio
))
1828 wv
->button_type
= BUTTON_TYPE_RADIO
;
1832 wv
->selected
= !NILP (selected
);
1834 if (! STRINGP (help
))
1841 i
+= MENU_ITEMS_ITEM_LENGTH
;
1845 /* Deal with the title, if it is non-nil. */
1848 widget_value
*wv_title
= xmalloc_widget_value ();
1849 widget_value
*wv_sep1
= xmalloc_widget_value ();
1850 widget_value
*wv_sep2
= xmalloc_widget_value ();
1852 wv_sep2
->name
= "--";
1853 wv_sep2
->next
= first_wv
->contents
;
1854 wv_sep2
->help
= Qnil
;
1856 wv_sep1
->name
= "--";
1857 wv_sep1
->next
= wv_sep2
;
1858 wv_sep1
->help
= Qnil
;
1860 #ifndef HAVE_MULTILINGUAL_MENU
1861 if (STRING_MULTIBYTE (title
))
1862 title
= ENCODE_MENU_STRING (title
);
1865 wv_title
->name
= (char *) SDATA (title
);
1866 wv_title
->enabled
= TRUE
;
1867 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1868 wv_title
->help
= Qnil
;
1869 wv_title
->next
= wv_sep1
;
1870 first_wv
->contents
= wv_title
;
1873 /* No selection has been chosen yet. */
1874 menu_item_selection
= 0;
1876 /* Actually create and show the menu until popped down. */
1877 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
);
1879 /* Free the widget_value objects we used to specify the contents. */
1880 free_menubar_widget_value_tree (first_wv
);
1882 /* Find the selected item, and its pane, to return
1883 the proper value. */
1884 if (menu_item_selection
!= 0)
1886 Lisp_Object prefix
, entry
;
1888 prefix
= entry
= Qnil
;
1890 while (i
< menu_items_used
)
1892 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1894 subprefix_stack
[submenu_depth
++] = prefix
;
1898 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1900 prefix
= subprefix_stack
[--submenu_depth
];
1903 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1906 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1907 i
+= MENU_ITEMS_PANE_LENGTH
;
1909 /* Ignore a nil in the item list.
1910 It's meaningful only for dialog boxes. */
1911 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1916 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1917 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
1923 entry
= Fcons (entry
, Qnil
);
1925 entry
= Fcons (prefix
, entry
);
1926 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1927 if (!NILP (subprefix_stack
[j
]))
1928 entry
= Fcons (subprefix_stack
[j
], entry
);
1932 i
+= MENU_ITEMS_ITEM_LENGTH
;
1936 else if (!for_click
)
1937 /* Make "Cancel" equivalent to C-g. */
1938 Fsignal (Qquit
, Qnil
);
1945 dialog_selection_callback (widget
, client_data
)
1947 gpointer client_data
;
1949 /* The EMACS_INT cast avoids a warning. There's no problem
1950 as long as pointers have enough bits to hold small integers. */
1951 if ((int) (EMACS_INT
) client_data
!= -1)
1952 menu_item_selection
= (Lisp_Object
*) client_data
;
1954 popup_activated_flag
= 0;
1957 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1959 menu_item_selection will be set to the selection. */
1961 create_and_show_dialog (f
, first_wv
)
1963 widget_value
*first_wv
;
1967 if (! FRAME_X_P (f
))
1970 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
1971 G_CALLBACK (dialog_selection_callback
),
1972 G_CALLBACK (popup_deactivate_callback
),
1977 int specpdl_count
= SPECPDL_INDEX ();
1978 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1980 /* Display the menu. */
1981 gtk_widget_show_all (menu
);
1983 /* Process events that apply to the menu. */
1984 popup_widget_loop (1, menu
);
1986 unbind_to (specpdl_count
, Qnil
);
1990 #else /* not USE_GTK */
1992 dialog_selection_callback (widget
, id
, client_data
)
1995 XtPointer client_data
;
1997 /* The EMACS_INT cast avoids a warning. There's no problem
1998 as long as pointers have enough bits to hold small integers. */
1999 if ((int) (EMACS_INT
) client_data
!= -1)
2000 menu_item_selection
= (Lisp_Object
*) client_data
;
2003 lw_destroy_all_widgets (id
);
2005 popup_activated_flag
= 0;
2009 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2011 menu_item_selection will be set to the selection. */
2013 create_and_show_dialog (f
, first_wv
)
2015 widget_value
*first_wv
;
2022 dialog_id
= widget_id_tick
++;
2023 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
2024 f
->output_data
.x
->widget
, 1, 0,
2025 dialog_selection_callback
, 0, 0);
2026 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
2028 /* Display the dialog box. */
2029 lw_pop_up_all_widgets (dialog_id
);
2030 popup_activated_flag
= 1;
2031 x_activate_timeout_atimer ();
2033 /* Process events that apply to the dialog box.
2034 Also handle timers. */
2036 int count
= SPECPDL_INDEX ();
2037 int fact
= 4 * sizeof (LWLIB_ID
);
2039 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2040 record_unwind_protect (pop_down_menu
,
2041 Fcons (make_number (dialog_id
>> (fact
)),
2042 make_number (dialog_id
& ~(-1 << (fact
)))));
2044 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
2047 unbind_to (count
, Qnil
);
2051 #endif /* not USE_GTK */
2053 static char * button_names
[] = {
2054 "button1", "button2", "button3", "button4", "button5",
2055 "button6", "button7", "button8", "button9", "button10" };
2058 xdialog_show (f
, keymaps
, title
, header
, error_name
)
2061 Lisp_Object title
, header
;
2064 int i
, nb_buttons
=0;
2065 char dialog_name
[6];
2067 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
2069 /* Number of elements seen so far, before boundary. */
2071 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2072 int boundary_seen
= 0;
2074 if (! FRAME_X_P (f
))
2079 if (menu_items_n_panes
> 1)
2081 *error_name
= "Multiple panes in dialog box";
2085 /* Create a tree of widget_value objects
2086 representing the text label and buttons. */
2088 Lisp_Object pane_name
, prefix
;
2090 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
2091 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
2092 pane_string
= (NILP (pane_name
)
2093 ? "" : (char *) SDATA (pane_name
));
2094 prev_wv
= xmalloc_widget_value ();
2095 prev_wv
->value
= pane_string
;
2096 if (keymaps
&& !NILP (prefix
))
2098 prev_wv
->enabled
= 1;
2099 prev_wv
->name
= "message";
2100 prev_wv
->help
= Qnil
;
2103 /* Loop over all panes and items, filling in the tree. */
2104 i
= MENU_ITEMS_PANE_LENGTH
;
2105 while (i
< menu_items_used
)
2108 /* Create a new item within current pane. */
2109 Lisp_Object item_name
, enable
, descrip
;
2110 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2111 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2113 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2115 if (NILP (item_name
))
2117 free_menubar_widget_value_tree (first_wv
);
2118 *error_name
= "Submenu in dialog items";
2121 if (EQ (item_name
, Qquote
))
2123 /* This is the boundary between left-side elts
2124 and right-side elts. Stop incrementing right_count. */
2129 if (nb_buttons
>= 9)
2131 free_menubar_widget_value_tree (first_wv
);
2132 *error_name
= "Too many dialog items";
2136 wv
= xmalloc_widget_value ();
2138 wv
->name
= (char *) button_names
[nb_buttons
];
2139 if (!NILP (descrip
))
2140 wv
->key
= (char *) SDATA (descrip
);
2141 wv
->value
= (char *) SDATA (item_name
);
2142 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
2143 wv
->enabled
= !NILP (enable
);
2147 if (! boundary_seen
)
2151 i
+= MENU_ITEMS_ITEM_LENGTH
;
2154 /* If the boundary was not specified,
2155 by default put half on the left and half on the right. */
2156 if (! boundary_seen
)
2157 left_count
= nb_buttons
- nb_buttons
/ 2;
2159 wv
= xmalloc_widget_value ();
2160 wv
->name
= dialog_name
;
2163 /* Frame title: 'Q' = Question, 'I' = Information.
2164 Can also have 'E' = Error if, one day, we want
2165 a popup for errors. */
2167 dialog_name
[0] = 'Q';
2169 dialog_name
[0] = 'I';
2171 /* Dialog boxes use a really stupid name encoding
2172 which specifies how many buttons to use
2173 and how many buttons are on the right. */
2174 dialog_name
[1] = '0' + nb_buttons
;
2175 dialog_name
[2] = 'B';
2176 dialog_name
[3] = 'R';
2177 /* Number of buttons to put on the right. */
2178 dialog_name
[4] = '0' + nb_buttons
- left_count
;
2180 wv
->contents
= first_wv
;
2184 /* No selection has been chosen yet. */
2185 menu_item_selection
= 0;
2187 /* Actually create and show the dialog. */
2188 create_and_show_dialog (f
, first_wv
);
2190 /* Free the widget_value objects we used to specify the contents. */
2191 free_menubar_widget_value_tree (first_wv
);
2193 /* Find the selected item, and its pane, to return
2194 the proper value. */
2195 if (menu_item_selection
!= 0)
2201 while (i
< menu_items_used
)
2205 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2208 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2209 i
+= MENU_ITEMS_PANE_LENGTH
;
2211 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2213 /* This is the boundary between left-side elts and
2220 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2221 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2225 entry
= Fcons (entry
, Qnil
);
2227 entry
= Fcons (prefix
, entry
);
2231 i
+= MENU_ITEMS_ITEM_LENGTH
;
2236 /* Make "Cancel" equivalent to C-g. */
2237 Fsignal (Qquit
, Qnil
);
2242 #else /* not USE_X_TOOLKIT && not USE_GTK */
2244 /* The frame of the last activated non-toolkit menu bar.
2245 Used to generate menu help events. */
2247 static struct frame
*menu_help_frame
;
2250 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2252 PANE is the pane number, and ITEM is the menu item number in
2253 the menu (currently not used).
2255 This cannot be done with generating a HELP_EVENT because
2256 XMenuActivate contains a loop that doesn't let Emacs process
2260 menu_help_callback (help_string
, pane
, item
)
2264 extern Lisp_Object Qmenu_item
;
2265 Lisp_Object
*first_item
;
2266 Lisp_Object pane_name
;
2267 Lisp_Object menu_object
;
2269 first_item
= XVECTOR (menu_items
)->contents
;
2270 if (EQ (first_item
[0], Qt
))
2271 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
2272 else if (EQ (first_item
[0], Qquote
))
2273 /* This shouldn't happen, see xmenu_show. */
2274 pane_name
= empty_unibyte_string
;
2276 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
2278 /* (menu-item MENU-NAME PANE-NUMBER) */
2279 menu_object
= Fcons (Qmenu_item
,
2281 Fcons (make_number (pane
), Qnil
)));
2282 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
2283 Qnil
, menu_object
, make_number (item
), 1);
2290 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
2291 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
2293 FRAME_PTR f
= p1
->pointer
;
2294 XMenu
*menu
= p2
->pointer
;
2298 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
2299 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
2301 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2303 #ifdef HAVE_X_WINDOWS
2304 /* Assume the mouse has moved out of the X window.
2305 If it has actually moved in, we will get an EnterNotify. */
2306 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
2308 /* State that no mouse buttons are now held.
2309 (The oldXMenu code doesn't track this info for us.)
2310 That is not necessarily true, but the fiction leads to reasonable
2311 results, and it is a pain to ask which are actually held now. */
2312 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2314 #endif /* HAVE_X_WINDOWS */
2323 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
, timestamp
)
2330 EMACS_UINT timestamp
;
2334 int pane
, selidx
, lpane
, status
;
2335 Lisp_Object entry
, pane_prefix
;
2337 int ulx
, uly
, width
, height
;
2338 int dispwidth
, dispheight
;
2339 int i
, j
, lines
, maxlines
;
2342 unsigned int dummy_uint
;
2343 int specpdl_count
= SPECPDL_INDEX ();
2345 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
2349 if (menu_items_n_panes
== 0)
2352 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2354 *error
= "Empty menu";
2358 /* Figure out which root window F is on. */
2359 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
2360 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
2361 &dummy_uint
, &dummy_uint
);
2363 /* Make the menu on that window. */
2364 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
2367 *error
= "Can't create menu";
2371 /* Don't GC while we prepare and show the menu,
2372 because we give the oldxmenu library pointers to the
2373 contents of strings. */
2374 inhibit_garbage_collection ();
2376 #ifdef HAVE_X_WINDOWS
2377 /* Adjust coordinates to relative to the outer (window manager) window. */
2378 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
2379 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2380 #endif /* HAVE_X_WINDOWS */
2382 /* Adjust coordinates to be root-window-relative. */
2386 /* Create all the necessary panes and their items. */
2387 maxlines
= lines
= i
= 0;
2388 while (i
< menu_items_used
)
2390 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2392 /* Create a new pane. */
2393 Lisp_Object pane_name
, prefix
;
2396 maxlines
= max (maxlines
, lines
);
2398 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
2399 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2400 pane_string
= (NILP (pane_name
)
2401 ? "" : (char *) SDATA (pane_name
));
2402 if (keymaps
&& !NILP (prefix
))
2405 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
2406 if (lpane
== XM_FAILURE
)
2408 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2409 *error
= "Can't create pane";
2412 i
+= MENU_ITEMS_PANE_LENGTH
;
2414 /* Find the width of the widest item in this pane. */
2417 while (j
< menu_items_used
)
2420 item
= XVECTOR (menu_items
)->contents
[j
];
2428 width
= SBYTES (item
);
2429 if (width
> maxwidth
)
2432 j
+= MENU_ITEMS_ITEM_LENGTH
;
2435 /* Ignore a nil in the item list.
2436 It's meaningful only for dialog boxes. */
2437 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2441 /* Create a new item within current pane. */
2442 Lisp_Object item_name
, enable
, descrip
, help
;
2443 unsigned char *item_data
;
2446 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2447 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2449 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2450 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
2451 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
2453 if (!NILP (descrip
))
2455 int gap
= maxwidth
- SBYTES (item_name
);
2456 /* if alloca is fast, use that to make the space,
2457 to reduce gc needs. */
2459 = (unsigned char *) alloca (maxwidth
2460 + SBYTES (descrip
) + 1);
2461 bcopy (SDATA (item_name
), item_data
,
2462 SBYTES (item_name
));
2463 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
2465 bcopy (SDATA (descrip
), item_data
+ j
,
2467 item_data
[j
+ SBYTES (descrip
)] = 0;
2470 item_data
= SDATA (item_name
);
2472 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
2473 menu
, lpane
, 0, item_data
,
2474 !NILP (enable
), help_string
)
2477 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2478 *error
= "Can't add selection to menu";
2481 i
+= MENU_ITEMS_ITEM_LENGTH
;
2486 maxlines
= max (maxlines
, lines
);
2488 /* All set and ready to fly. */
2489 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
2490 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2491 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2492 x
= min (x
, dispwidth
);
2493 y
= min (y
, dispheight
);
2496 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
2497 &ulx
, &uly
, &width
, &height
);
2498 if (ulx
+width
> dispwidth
)
2500 x
-= (ulx
+ width
) - dispwidth
;
2501 ulx
= dispwidth
- width
;
2503 if (uly
+height
> dispheight
)
2505 y
-= (uly
+ height
) - dispheight
;
2506 uly
= dispheight
- height
;
2508 #ifndef HAVE_X_WINDOWS
2509 if (FRAME_HAS_MINIBUF_P (f
) && uly
+height
> dispheight
- 1)
2511 /* Move the menu away of the echo area, to avoid overwriting the
2512 menu with help echo messages or vice versa. */
2513 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
2515 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2516 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2525 if (ulx
< 0) x
-= ulx
;
2526 if (uly
< 0) y
-= uly
;
2530 /* If position was not given by a mouse click, adjust so upper left
2531 corner of the menu as a whole ends up at given coordinates. This
2532 is what x-popup-menu says in its documentation. */
2534 y
+= 1.5*height
/(maxlines
+2);
2537 XMenuSetAEQ (menu
, TRUE
);
2538 XMenuSetFreeze (menu
, TRUE
);
2542 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
2545 record_unwind_protect (pop_down_menu
,
2546 Fcons (make_save_value (f
, 0),
2547 make_save_value (menu
, 0)));
2549 /* Help display under X won't work because XMenuActivate contains
2550 a loop that doesn't give Emacs a chance to process it. */
2551 menu_help_frame
= f
;
2552 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
2553 x
, y
, ButtonReleaseMask
, &datap
,
2554 menu_help_callback
);
2560 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
2563 /* Find the item number SELIDX in pane number PANE. */
2565 while (i
< menu_items_used
)
2567 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2571 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2573 i
+= MENU_ITEMS_PANE_LENGTH
;
2582 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2585 entry
= Fcons (entry
, Qnil
);
2586 if (!NILP (pane_prefix
))
2587 entry
= Fcons (pane_prefix
, entry
);
2593 i
+= MENU_ITEMS_ITEM_LENGTH
;
2599 *error
= "Can't activate menu";
2604 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2605 the menu was invoked with a mouse event as POSITION). */
2607 Fsignal (Qquit
, Qnil
);
2612 unbind_to (specpdl_count
, Qnil
);
2617 #endif /* not USE_X_TOOLKIT */
2619 #endif /* HAVE_MENUS */
2621 /* Detect if a dialog or menu has been posted. */
2626 return popup_activated_flag
;
2629 /* The following is used by delayed window autoselection. */
2631 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2632 doc
: /* Return t if a menu or popup dialog is active. */)
2636 return (popup_activated ()) ? Qt
: Qnil
;
2639 #endif /* HAVE_MENUS */
2645 Qdebug_on_next_call
= intern_c_string ("debug-on-next-call");
2646 staticpro (&Qdebug_on_next_call
);
2648 #ifdef USE_X_TOOLKIT
2649 widget_id_tick
= (1<<16);
2650 next_menubar_widget_id
= 1;
2653 defsubr (&Smenu_or_popup_active_p
);
2655 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2656 defsubr (&Sx_menu_bar_open_internal
);
2657 Ffset (intern_c_string ("accelerate-menu"),
2658 intern_c_string (Sx_menu_bar_open_internal
.symbol_name
));
2662 defsubr (&Sx_popup_dialog
);
2666 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2667 (do not change this comment) */