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, 2011 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 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
688 f
->output_data
.x
->saved_menu_event
);
689 popup_activated_flag
= 1;
691 XtDispatchEvent (f
->output_data
.x
->saved_menu_event
);
695 if (f
->output_data
.x
->saved_menu_event
->type
== ButtonRelease
)
696 pending_menu_activation
= 1;
699 /* Ignore this if we get it a second time. */
700 f
->output_data
.x
->saved_menu_event
->type
= 0;
703 /* This callback is invoked when the user selects a menubar cascade
704 pushbutton, but before the pulldown menu is posted. */
708 popup_activate_callback (widget
, id
, client_data
)
711 XtPointer client_data
;
713 popup_activated_flag
= 1;
715 x_activate_timeout_atimer ();
720 /* This callback is invoked when a dialog or menu is finished being
721 used and has been unposted. */
725 popup_deactivate_callback (widget
, client_data
)
727 gpointer client_data
;
729 popup_activated_flag
= 0;
733 popup_deactivate_callback (widget
, id
, client_data
)
736 XtPointer client_data
;
738 popup_activated_flag
= 0;
743 /* Function that finds the frame for WIDGET and shows the HELP text
745 F is the frame if known, or NULL if not known. */
747 show_help_event (f
, widget
, help
)
749 xt_or_gtk_widget widget
;
756 XSETFRAME (frame
, f
);
757 kbd_buffer_store_help_event (frame
, help
);
761 #if 0 /* This code doesn't do anything useful. ++kfs */
762 /* WIDGET is the popup menu. It's parent is the frame's
763 widget. See which frame that is. */
764 xt_or_gtk_widget frame_widget
= XtParent (widget
);
767 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
771 && (f
= XFRAME (frame
),
772 FRAME_X_P (f
) && f
->output_data
.x
->widget
== frame_widget
))
776 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
780 /* Callback called when menu items are highlighted/unhighlighted
781 while moving the mouse over them. WIDGET is the menu bar or menu
782 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
783 the data structure for the menu item, or null in case of
788 menu_highlight_callback (widget
, call_data
)
792 xg_menu_item_cb_data
*cb_data
;
795 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (widget
),
797 if (! cb_data
) return;
799 help
= call_data
? cb_data
->help
: Qnil
;
801 /* If popup_activated_flag is greater than 1 we are in a popup menu.
802 Don't show help for them, they won't appear before the
803 popup is popped down. */
804 if (popup_activated_flag
<= 1)
805 show_help_event (cb_data
->cl_data
->f
, widget
, help
);
809 menu_highlight_callback (widget
, id
, call_data
)
817 widget_value
*wv
= (widget_value
*) call_data
;
819 help
= wv
? wv
->help
: Qnil
;
821 /* Determine the frame for the help event. */
822 f
= menubar_id_to_frame (id
);
824 show_help_event (f
, widget
, help
);
829 /* Gtk calls callbacks just because we tell it what item should be
830 selected in a radio group. If this variable is set to a non-zero
831 value, we are creating menus and don't want callbacks right now.
833 static int xg_crazy_callback_abort
;
835 /* This callback is called from the menu bar pulldown menu
836 when the user makes a selection.
837 Figure out what the user chose
838 and put the appropriate events into the keyboard buffer. */
840 menubar_selection_callback (widget
, client_data
)
842 gpointer client_data
;
844 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
846 if (xg_crazy_callback_abort
)
849 if (! cb_data
|| ! cb_data
->cl_data
|| ! cb_data
->cl_data
->f
)
852 /* For a group of radio buttons, GTK calls the selection callback first
853 for the item that was active before the selection and then for the one that
854 is active after the selection. For C-h k this means we get the help on
855 the deselected item and then the selected item is executed. Prevent that
856 by ignoring the non-active item. */
857 if (GTK_IS_RADIO_MENU_ITEM (widget
)
858 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget
)))
861 /* When a menu is popped down, X generates a focus event (i.e. focus
862 goes back to the frame below the menu). Since GTK buffers events,
863 we force it out here before the menu selection event. Otherwise
864 sit-for will exit at once if the focus event follows the menu selection
868 while (gtk_events_pending ())
869 gtk_main_iteration ();
872 find_and_call_menu_selection (cb_data
->cl_data
->f
,
873 cb_data
->cl_data
->menu_bar_items_used
,
874 cb_data
->cl_data
->menu_bar_vector
,
878 #else /* not USE_GTK */
880 /* This callback is called from the menu bar pulldown menu
881 when the user makes a selection.
882 Figure out what the user chose
883 and put the appropriate events into the keyboard buffer. */
885 menubar_selection_callback (widget
, id
, client_data
)
888 XtPointer client_data
;
892 f
= menubar_id_to_frame (id
);
895 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
896 f
->menu_bar_vector
, client_data
);
898 #endif /* not USE_GTK */
900 /* Recompute all the widgets of frame F, when the menu bar has been
901 changed. Value is non-zero if widgets were updated. */
904 update_frame_menubar (f
)
908 return xg_update_frame_menubar (f
);
916 x
= f
->output_data
.x
;
918 if (!x
->menubar_widget
|| XtIsManaged (x
->menubar_widget
))
922 /* Save the size of the frame because the pane widget doesn't accept
923 to resize itself. So force it. */
924 columns
= FRAME_COLS (f
);
925 rows
= FRAME_LINES (f
);
927 /* Do the voodoo which means "I'm changing lots of things, don't try
928 to refigure sizes until I'm done." */
929 lw_refigure_widget (x
->column_widget
, False
);
931 /* The order in which children are managed is the top to bottom
932 order in which they are displayed in the paned window. First,
933 remove the text-area widget. */
934 XtUnmanageChild (x
->edit_widget
);
936 /* Remove the menubar that is there now, and put up the menubar that
938 XtManageChild (x
->menubar_widget
);
939 XtMapWidget (x
->menubar_widget
);
940 XtVaSetValues (x
->menubar_widget
, XtNmappedWhenManaged
, 1, NULL
);
942 /* Re-manage the text-area widget, and then thrash the sizes. */
943 XtManageChild (x
->edit_widget
);
944 lw_refigure_widget (x
->column_widget
, True
);
946 /* Force the pane widget to resize itself with the right values. */
947 EmacsFrameSetCharSize (x
->edit_widget
, columns
, rows
);
953 /* Set the contents of the menubar widgets of frame F.
954 The argument FIRST_TIME is currently ignored;
955 it is set the first time this is called, from initialize_frame_menubar. */
958 set_frame_menubar (f
, first_time
, deep_p
)
963 xt_or_gtk_widget menubar_widget
;
968 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
970 int *submenu_start
, *submenu_end
;
971 int *submenu_top_level_items
, *submenu_n_panes
;
976 menubar_widget
= f
->output_data
.x
->menubar_widget
;
978 XSETFRAME (Vmenu_updating_frame
, f
);
981 if (f
->output_data
.x
->id
== 0)
982 f
->output_data
.x
->id
= next_menubar_widget_id
++;
983 id
= f
->output_data
.x
->id
;
986 if (! menubar_widget
)
988 else if (pending_menu_activation
&& !deep_p
)
990 /* Make the first call for any given frame always go deep. */
991 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
994 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
995 f
->output_data
.x
->saved_menu_event
->type
= 0;
999 /* If we have detached menus, we must update deep so detached menus
1000 also gets updated. */
1001 deep_p
= deep_p
|| xg_have_tear_offs ();
1006 /* Make a widget-value tree representing the entire menu trees. */
1008 struct buffer
*prev
= current_buffer
;
1010 int specpdl_count
= SPECPDL_INDEX ();
1011 int previous_menu_items_used
= f
->menu_bar_items_used
;
1012 Lisp_Object
*previous_items
1013 = (Lisp_Object
*) alloca (previous_menu_items_used
1014 * sizeof (Lisp_Object
));
1015 EMACS_UINT subitems
;
1017 /* If we are making a new widget, its contents are empty,
1018 do always reinitialize them. */
1019 if (! menubar_widget
)
1020 previous_menu_items_used
= 0;
1022 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1023 specbind (Qinhibit_quit
, Qt
);
1024 /* Don't let the debugger step into this code
1025 because it is not reentrant. */
1026 specbind (Qdebug_on_next_call
, Qnil
);
1028 record_unwind_save_match_data ();
1029 if (NILP (Voverriding_local_map_menu_flag
))
1031 specbind (Qoverriding_terminal_local_map
, Qnil
);
1032 specbind (Qoverriding_local_map
, Qnil
);
1035 set_buffer_internal_1 (XBUFFER (buffer
));
1037 /* Run the Lucid hook. */
1038 safe_run_hooks (Qactivate_menubar_hook
);
1040 /* If it has changed current-menubar from previous value,
1041 really recompute the menubar from the value. */
1042 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1043 call0 (Qrecompute_lucid_menubar
);
1044 safe_run_hooks (Qmenu_bar_update_hook
);
1045 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1047 items
= FRAME_MENU_BAR_ITEMS (f
);
1049 /* Save the frame's previous menu bar contents data. */
1050 if (previous_menu_items_used
)
1051 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
1052 previous_menu_items_used
* sizeof (Lisp_Object
));
1054 /* Fill in menu_items with the current menu bar contents.
1055 This can evaluate Lisp code. */
1058 menu_items
= f
->menu_bar_vector
;
1059 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1060 subitems
= XVECTOR_SIZE (items
) / 4;
1061 submenu_start
= (int *) alloca (subitems
* sizeof (int));
1062 submenu_end
= (int *) alloca (subitems
* sizeof (int));
1063 submenu_n_panes
= (int *) alloca (subitems
* sizeof (int));
1064 submenu_top_level_items
= (int *) alloca (subitems
* sizeof (int));
1066 for (i
= 0; i
< subitems
; i
++)
1068 Lisp_Object key
, string
, maps
;
1072 key
= XVECTOR (items
)->contents
[i
* 4];
1073 string
= XVECTOR (items
)->contents
[i
* 4 + 1];
1074 maps
= XVECTOR (items
)->contents
[i
* 4 + 2];
1078 submenu_start
[i
] = menu_items_used
;
1080 menu_items_n_panes
= 0;
1081 submenu_top_level_items
[i
]
1082 = parse_single_submenu (key
, string
, maps
);
1083 submenu_n_panes
[i
] = menu_items_n_panes
;
1085 submenu_end
[i
] = menu_items_used
;
1088 finish_menu_items ();
1090 /* Convert menu_items into widget_value trees
1091 to display the menu. This cannot evaluate Lisp code. */
1093 wv
= xmalloc_widget_value ();
1094 wv
->name
= "menubar";
1097 wv
->button_type
= BUTTON_TYPE_NONE
;
1101 for (i
= 0; i
< last_i
; i
++)
1103 menu_items_n_panes
= submenu_n_panes
[i
];
1104 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
1105 submenu_top_level_items
[i
]);
1109 first_wv
->contents
= wv
;
1110 /* Don't set wv->name here; GC during the loop might relocate it. */
1112 wv
->button_type
= BUTTON_TYPE_NONE
;
1116 set_buffer_internal_1 (prev
);
1118 /* If there has been no change in the Lisp-level contents
1119 of the menu bar, skip redisplaying it. Just exit. */
1121 /* Compare the new menu items with the ones computed last time. */
1122 for (i
= 0; i
< previous_menu_items_used
; i
++)
1123 if (menu_items_used
== i
1124 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1126 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1128 /* The menu items have not changed. Don't bother updating
1129 the menus in any form, since it would be a no-op. */
1130 free_menubar_widget_value_tree (first_wv
);
1131 discard_menu_items ();
1132 unbind_to (specpdl_count
, Qnil
);
1136 /* The menu items are different, so store them in the frame. */
1137 f
->menu_bar_vector
= menu_items
;
1138 f
->menu_bar_items_used
= menu_items_used
;
1140 /* This undoes save_menu_items. */
1141 unbind_to (specpdl_count
, Qnil
);
1143 /* Now GC cannot happen during the lifetime of the widget_value,
1144 so it's safe to store data from a Lisp_String. */
1145 wv
= first_wv
->contents
;
1146 for (i
= 0; i
< XVECTOR_SIZE (items
); i
+= 4)
1149 string
= XVECTOR (items
)->contents
[i
+ 1];
1152 wv
->name
= (char *) SDATA (string
);
1153 update_submenu_strings (wv
->contents
);
1160 /* Make a widget-value tree containing
1161 just the top level menu bar strings. */
1163 wv
= xmalloc_widget_value ();
1164 wv
->name
= "menubar";
1167 wv
->button_type
= BUTTON_TYPE_NONE
;
1171 items
= FRAME_MENU_BAR_ITEMS (f
);
1172 for (i
= 0; i
< XVECTOR_SIZE (items
); i
+= 4)
1176 string
= XVECTOR (items
)->contents
[i
+ 1];
1180 wv
= xmalloc_widget_value ();
1181 wv
->name
= (char *) SDATA (string
);
1184 wv
->button_type
= BUTTON_TYPE_NONE
;
1186 /* This prevents lwlib from assuming this
1187 menu item is really supposed to be empty. */
1188 /* The EMACS_INT cast avoids a warning.
1189 This value just has to be different from small integers. */
1190 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1195 first_wv
->contents
= wv
;
1199 /* Forget what we thought we knew about what is in the
1200 detailed contents of the menu bar menus.
1201 Changing the top level always destroys the contents. */
1202 f
->menu_bar_items_used
= 0;
1205 /* Create or update the menu bar widget. */
1210 xg_crazy_callback_abort
= 1;
1213 /* The fourth arg is DEEP_P, which says to consider the entire
1214 menu trees we supply, rather than just the menu bar item names. */
1215 xg_modify_menubar_widgets (menubar_widget
,
1219 G_CALLBACK (menubar_selection_callback
),
1220 G_CALLBACK (popup_deactivate_callback
),
1221 G_CALLBACK (menu_highlight_callback
));
1225 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
1228 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
1229 G_CALLBACK (menubar_selection_callback
),
1230 G_CALLBACK (popup_deactivate_callback
),
1231 G_CALLBACK (menu_highlight_callback
));
1233 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1237 #else /* not USE_GTK */
1240 /* Disable resizing (done for Motif!) */
1241 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
1243 /* The third arg is DEEP_P, which says to consider the entire
1244 menu trees we supply, rather than just the menu bar item names. */
1245 lw_modify_all_widgets (id
, first_wv
, deep_p
);
1247 /* Re-enable the edit widget to resize. */
1248 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
1252 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1253 XtTranslations override
= XtParseTranslationTable (menuOverride
);
1255 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
1256 f
->output_data
.x
->column_widget
,
1258 popup_activate_callback
,
1259 menubar_selection_callback
,
1260 popup_deactivate_callback
,
1261 menu_highlight_callback
);
1262 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1264 /* Make menu pop down on C-g. */
1265 XtOverrideTranslations (menubar_widget
, override
);
1270 = (f
->output_data
.x
->menubar_widget
1271 ? (f
->output_data
.x
->menubar_widget
->core
.height
1272 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
1275 #if 1 /* Experimentally, we now get the right results
1276 for -geometry -0-0 without this. 24 Aug 96, rms.
1277 Maybe so, but the menu bar size is missing the pixels so the
1278 WM size hints are off by theses pixel. Jan D, oct 2009. */
1280 if (FRAME_EXTERNAL_MENU_BAR (f
))
1283 XtVaGetValues (f
->output_data
.x
->column_widget
,
1284 XtNinternalBorderWidth
, &ibw
, NULL
);
1285 menubar_size
+= ibw
;
1287 #endif /* USE_LUCID */
1290 f
->output_data
.x
->menubar_height
= menubar_size
;
1292 #endif /* not USE_GTK */
1294 free_menubar_widget_value_tree (first_wv
);
1295 update_frame_menubar (f
);
1298 xg_crazy_callback_abort
= 0;
1304 /* Called from Fx_create_frame to create the initial menubar of a frame
1305 before it is mapped, so that the window is mapped with the menubar already
1306 there instead of us tacking it on later and thrashing the window after it
1310 initialize_frame_menubar (f
)
1313 /* This function is called before the first chance to redisplay
1314 the frame. It has to be, so the frame will have the right size. */
1315 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1316 set_frame_menubar (f
, 1, 1);
1320 /* Get rid of the menu bar of frame F, and free its storage.
1321 This is used when deleting a frame, and when turning off the menu bar.
1322 For GTK this function is in gtkutil.c. */
1326 free_frame_menubar (f
)
1329 Widget menubar_widget
;
1331 if (! FRAME_X_P (f
))
1334 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1336 f
->output_data
.x
->menubar_height
= 0;
1341 /* Removing the menu bar magically changes the shell widget's x
1342 and y position of (0, 0) which, when the menu bar is turned
1343 on again, leads to pull-down menuss appearing in strange
1344 positions near the upper-left corner of the display. This
1345 happens only with some window managers like twm and ctwm,
1346 but not with other like Motif's mwm or kwm, because the
1347 latter generate ConfigureNotify events when the menu bar
1348 is switched off, which fixes the shell position. */
1349 Position x0
, y0
, x1
, y1
;
1355 if (f
->output_data
.x
->widget
)
1356 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
1359 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
1360 f
->output_data
.x
->menubar_widget
= NULL
;
1363 if (f
->output_data
.x
->widget
)
1365 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
1366 if (x1
== 0 && y1
== 0)
1367 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
1374 #endif /* not USE_GTK */
1376 #endif /* USE_X_TOOLKIT || USE_GTK */
1378 /* xmenu_show actually displays a menu using the panes and items in menu_items
1379 and returns the value selected from it.
1380 There are two versions of xmenu_show, one for Xt and one for Xlib.
1381 Both assume input is blocked by the caller. */
1383 /* F is the frame the menu is for.
1384 X and Y are the frame-relative specified position,
1385 relative to the inside upper left corner of the frame F.
1386 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1387 KEYMAPS is 1 if this menu was specified with keymaps;
1388 in that case, we return a list containing the chosen item's value
1389 and perhaps also the pane's prefix.
1390 TITLE is the specified menu title.
1391 ERROR is a place to store an error message string in case of failure.
1392 (We return nil on failure, but the value doesn't actually matter.) */
1394 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1396 /* The item selected in the popup menu. */
1397 static Lisp_Object
*volatile menu_item_selection
;
1401 /* Used when position a popup menu. See menu_position_func and
1402 create_and_show_popup_menu below. */
1403 struct next_popup_x_y
1410 /* The menu position function to use if we are not putting a popup
1411 menu where the pointer is.
1412 MENU is the menu to pop up.
1413 X and Y shall on exit contain x/y where the menu shall pop up.
1414 PUSH_IN is not documented in the GTK manual.
1415 USER_DATA is any data passed in when calling gtk_menu_popup.
1416 Here it points to a struct next_popup_x_y where the coordinates
1417 to store in *X and *Y are as well as the frame for the popup.
1419 Here only X and Y are used. */
1421 menu_position_func (menu
, x
, y
, push_in
, user_data
)
1428 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
1430 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (data
->f
);
1431 int disp_width
= x_display_pixel_width (dpyinfo
);
1432 int disp_height
= x_display_pixel_height (dpyinfo
);
1437 /* Check if there is room for the menu. If not, adjust x/y so that
1438 the menu is fully visible. */
1439 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
1440 if (data
->x
+ req
.width
> disp_width
)
1441 *x
-= data
->x
+ req
.width
- disp_width
;
1442 if (data
->y
+ req
.height
> disp_height
)
1443 *y
-= data
->y
+ req
.height
- disp_height
;
1447 popup_selection_callback (widget
, client_data
)
1449 gpointer client_data
;
1451 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1453 if (xg_crazy_callback_abort
) return;
1454 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
1461 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1463 popup_activated_flag
= 0;
1465 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1470 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1472 menu_item_selection will be set to the selection. */
1474 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1476 widget_value
*first_wv
;
1480 EMACS_UINT timestamp
;
1484 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
1485 struct next_popup_x_y popup_x_y
;
1486 int specpdl_count
= SPECPDL_INDEX ();
1488 if (! FRAME_X_P (f
))
1491 xg_crazy_callback_abort
= 1;
1492 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
1493 G_CALLBACK (popup_selection_callback
),
1494 G_CALLBACK (popup_deactivate_callback
),
1495 G_CALLBACK (menu_highlight_callback
));
1496 xg_crazy_callback_abort
= 0;
1500 /* Not invoked by a click. pop up at x/y. */
1501 pos_func
= menu_position_func
;
1503 /* Adjust coordinates to be root-window-relative. */
1504 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1505 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1511 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1515 for (i
= 0; i
< 5; i
++)
1516 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1520 /* Display the menu. */
1521 gtk_widget_show_all (menu
);
1523 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
,
1524 timestamp
> 0 ? timestamp
: gtk_get_current_event_time());
1526 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1528 if (GTK_WIDGET_MAPPED (menu
))
1530 /* Set this to one. popup_widget_loop increases it by one, so it becomes
1531 two. show_help_echo uses this to detect popup menus. */
1532 popup_activated_flag
= 1;
1533 /* Process events that apply to the menu. */
1534 popup_widget_loop (1, menu
);
1537 unbind_to (specpdl_count
, Qnil
);
1539 /* Must reset this manually because the button release event is not passed
1540 to Emacs event loop. */
1541 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1544 #else /* not USE_GTK */
1546 /* We need a unique id for each widget handled by the Lucid Widget
1549 For the main windows, and popup menus, we use this counter,
1550 which we increment each time after use. This starts from 1<<16.
1552 For menu bars, we use numbers starting at 0, counted in
1553 next_menubar_widget_id. */
1554 LWLIB_ID widget_id_tick
;
1557 popup_selection_callback (widget
, id
, client_data
)
1560 XtPointer client_data
;
1562 menu_item_selection
= (Lisp_Object
*) client_data
;
1565 /* ARG is the LWLIB ID of the dialog box, represented
1566 as a Lisp object as (HIGHPART . LOWPART). */
1572 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
1573 | XINT (XCDR (arg
)));
1576 lw_destroy_all_widgets (id
);
1578 popup_activated_flag
= 0;
1583 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1585 menu_item_selection will be set to the selection. */
1587 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
)
1589 widget_value
*first_wv
;
1593 EMACS_UINT timestamp
;
1599 XButtonPressedEvent
*event
= &(dummy
.xbutton
);
1603 if (! FRAME_X_P (f
))
1606 menu_id
= widget_id_tick
++;
1607 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
1608 f
->output_data
.x
->widget
, 1, 0,
1609 popup_selection_callback
,
1610 popup_deactivate_callback
,
1611 menu_highlight_callback
);
1613 event
->type
= ButtonPress
;
1615 event
->send_event
= 0;
1616 event
->display
= FRAME_X_DISPLAY (f
);
1617 event
->time
= CurrentTime
;
1618 event
->root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1619 event
->window
= event
->subwindow
= event
->root
;
1623 /* Adjust coordinates to be root-window-relative. */
1624 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1625 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1632 for (i
= 0; i
< 5; i
++)
1633 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1636 /* Don't allow any geometry request from the user. */
1637 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
1638 XtSetValues (menu
, av
, ac
);
1640 /* Display the menu. */
1641 lw_popup_menu (menu
, &dummy
);
1642 popup_activated_flag
= 1;
1643 x_activate_timeout_atimer ();
1646 int fact
= 4 * sizeof (LWLIB_ID
);
1647 int specpdl_count
= SPECPDL_INDEX ();
1648 record_unwind_protect (pop_down_menu
,
1649 Fcons (make_number (menu_id
>> (fact
)),
1650 make_number (menu_id
& ~(-1 << (fact
)))));
1652 /* Process events that apply to the menu. */
1653 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
1655 unbind_to (specpdl_count
, Qnil
);
1659 #endif /* not USE_GTK */
1662 xmenu_show (FRAME_PTR f
, int x
, int y
, int for_click
, int keymaps
,
1663 Lisp_Object title
, char **error
, EMACS_UINT timestamp
)
1666 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1667 widget_value
**submenu_stack
1668 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1669 Lisp_Object
*subprefix_stack
1670 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1671 int submenu_depth
= 0;
1675 if (! FRAME_X_P (f
))
1680 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1682 *error
= "Empty menu";
1686 /* Create a tree of widget_value objects
1687 representing the panes and their items. */
1688 wv
= xmalloc_widget_value ();
1692 wv
->button_type
= BUTTON_TYPE_NONE
;
1697 /* Loop over all panes and items, filling in the tree. */
1699 while (i
< menu_items_used
)
1701 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1703 submenu_stack
[submenu_depth
++] = save_wv
;
1709 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1712 save_wv
= submenu_stack
[--submenu_depth
];
1716 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1717 && submenu_depth
!= 0)
1718 i
+= MENU_ITEMS_PANE_LENGTH
;
1719 /* Ignore a nil in the item list.
1720 It's meaningful only for dialog boxes. */
1721 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1723 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1725 /* Create a new pane. */
1726 Lisp_Object pane_name
, prefix
;
1729 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1730 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1732 #ifndef HAVE_MULTILINGUAL_MENU
1733 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1735 pane_name
= ENCODE_MENU_STRING (pane_name
);
1736 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1739 pane_string
= (NILP (pane_name
)
1740 ? "" : (char *) SDATA (pane_name
));
1741 /* If there is just one top-level pane, put all its items directly
1742 under the top-level menu. */
1743 if (menu_items_n_panes
== 1)
1746 /* If the pane has a meaningful name,
1747 make the pane a top-level menu item
1748 with its items as a submenu beneath it. */
1749 if (!keymaps
&& strcmp (pane_string
, ""))
1751 wv
= xmalloc_widget_value ();
1755 first_wv
->contents
= wv
;
1756 wv
->name
= pane_string
;
1757 if (keymaps
&& !NILP (prefix
))
1761 wv
->button_type
= BUTTON_TYPE_NONE
;
1766 else if (first_pane
)
1772 i
+= MENU_ITEMS_PANE_LENGTH
;
1776 /* Create a new item within current pane. */
1777 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1778 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1779 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1780 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1781 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1782 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1783 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1784 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1786 #ifndef HAVE_MULTILINGUAL_MENU
1787 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
1789 item_name
= ENCODE_MENU_STRING (item_name
);
1790 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1793 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1795 descrip
= ENCODE_MENU_STRING (descrip
);
1796 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1798 #endif /* not HAVE_MULTILINGUAL_MENU */
1800 wv
= xmalloc_widget_value ();
1804 save_wv
->contents
= wv
;
1805 wv
->name
= (char *) SDATA (item_name
);
1806 if (!NILP (descrip
))
1807 wv
->key
= (char *) SDATA (descrip
);
1809 /* If this item has a null value,
1810 make the call_data null so that it won't display a box
1811 when the mouse is on it. */
1813 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
1814 wv
->enabled
= !NILP (enable
);
1817 wv
->button_type
= BUTTON_TYPE_NONE
;
1818 else if (EQ (type
, QCtoggle
))
1819 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1820 else if (EQ (type
, QCradio
))
1821 wv
->button_type
= BUTTON_TYPE_RADIO
;
1825 wv
->selected
= !NILP (selected
);
1827 if (! STRINGP (help
))
1834 i
+= MENU_ITEMS_ITEM_LENGTH
;
1838 /* Deal with the title, if it is non-nil. */
1841 widget_value
*wv_title
= xmalloc_widget_value ();
1842 widget_value
*wv_sep1
= xmalloc_widget_value ();
1843 widget_value
*wv_sep2
= xmalloc_widget_value ();
1845 wv_sep2
->name
= "--";
1846 wv_sep2
->next
= first_wv
->contents
;
1847 wv_sep2
->help
= Qnil
;
1849 wv_sep1
->name
= "--";
1850 wv_sep1
->next
= wv_sep2
;
1851 wv_sep1
->help
= Qnil
;
1853 #ifndef HAVE_MULTILINGUAL_MENU
1854 if (STRING_MULTIBYTE (title
))
1855 title
= ENCODE_MENU_STRING (title
);
1858 wv_title
->name
= (char *) SDATA (title
);
1859 wv_title
->enabled
= TRUE
;
1860 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1861 wv_title
->help
= Qnil
;
1862 wv_title
->next
= wv_sep1
;
1863 first_wv
->contents
= wv_title
;
1866 /* No selection has been chosen yet. */
1867 menu_item_selection
= 0;
1869 /* Actually create and show the menu until popped down. */
1870 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
);
1872 /* Free the widget_value objects we used to specify the contents. */
1873 free_menubar_widget_value_tree (first_wv
);
1875 /* Find the selected item, and its pane, to return
1876 the proper value. */
1877 if (menu_item_selection
!= 0)
1879 Lisp_Object prefix
, entry
;
1881 prefix
= entry
= Qnil
;
1883 while (i
< menu_items_used
)
1885 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1887 subprefix_stack
[submenu_depth
++] = prefix
;
1891 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1893 prefix
= subprefix_stack
[--submenu_depth
];
1896 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1899 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1900 i
+= MENU_ITEMS_PANE_LENGTH
;
1902 /* Ignore a nil in the item list.
1903 It's meaningful only for dialog boxes. */
1904 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1909 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1910 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
1916 entry
= Fcons (entry
, Qnil
);
1918 entry
= Fcons (prefix
, entry
);
1919 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1920 if (!NILP (subprefix_stack
[j
]))
1921 entry
= Fcons (subprefix_stack
[j
], entry
);
1925 i
+= MENU_ITEMS_ITEM_LENGTH
;
1929 else if (!for_click
)
1930 /* Make "Cancel" equivalent to C-g. */
1931 Fsignal (Qquit
, Qnil
);
1938 dialog_selection_callback (widget
, client_data
)
1940 gpointer client_data
;
1942 /* The EMACS_INT cast avoids a warning. There's no problem
1943 as long as pointers have enough bits to hold small integers. */
1944 if ((int) (EMACS_INT
) client_data
!= -1)
1945 menu_item_selection
= (Lisp_Object
*) client_data
;
1947 popup_activated_flag
= 0;
1950 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1952 menu_item_selection will be set to the selection. */
1954 create_and_show_dialog (f
, first_wv
)
1956 widget_value
*first_wv
;
1960 if (! FRAME_X_P (f
))
1963 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
1964 G_CALLBACK (dialog_selection_callback
),
1965 G_CALLBACK (popup_deactivate_callback
),
1970 int specpdl_count
= SPECPDL_INDEX ();
1971 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1973 /* Display the menu. */
1974 gtk_widget_show_all (menu
);
1976 /* Process events that apply to the menu. */
1977 popup_widget_loop (1, menu
);
1979 unbind_to (specpdl_count
, Qnil
);
1983 #else /* not USE_GTK */
1985 dialog_selection_callback (widget
, id
, client_data
)
1988 XtPointer client_data
;
1990 /* The EMACS_INT cast avoids a warning. There's no problem
1991 as long as pointers have enough bits to hold small integers. */
1992 if ((int) (EMACS_INT
) client_data
!= -1)
1993 menu_item_selection
= (Lisp_Object
*) client_data
;
1996 lw_destroy_all_widgets (id
);
1998 popup_activated_flag
= 0;
2002 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2004 menu_item_selection will be set to the selection. */
2006 create_and_show_dialog (f
, first_wv
)
2008 widget_value
*first_wv
;
2015 dialog_id
= widget_id_tick
++;
2016 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
2017 f
->output_data
.x
->widget
, 1, 0,
2018 dialog_selection_callback
, 0, 0);
2019 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
2021 /* Display the dialog box. */
2022 lw_pop_up_all_widgets (dialog_id
);
2023 popup_activated_flag
= 1;
2024 x_activate_timeout_atimer ();
2026 /* Process events that apply to the dialog box.
2027 Also handle timers. */
2029 int count
= SPECPDL_INDEX ();
2030 int fact
= 4 * sizeof (LWLIB_ID
);
2032 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2033 record_unwind_protect (pop_down_menu
,
2034 Fcons (make_number (dialog_id
>> (fact
)),
2035 make_number (dialog_id
& ~(-1 << (fact
)))));
2037 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
2040 unbind_to (count
, Qnil
);
2044 #endif /* not USE_GTK */
2046 static char * button_names
[] = {
2047 "button1", "button2", "button3", "button4", "button5",
2048 "button6", "button7", "button8", "button9", "button10" };
2051 xdialog_show (f
, keymaps
, title
, header
, error_name
)
2054 Lisp_Object title
, header
;
2057 int i
, nb_buttons
=0;
2058 char dialog_name
[6];
2060 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
2062 /* Number of elements seen so far, before boundary. */
2064 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2065 int boundary_seen
= 0;
2067 if (! FRAME_X_P (f
))
2072 if (menu_items_n_panes
> 1)
2074 *error_name
= "Multiple panes in dialog box";
2078 /* Create a tree of widget_value objects
2079 representing the text label and buttons. */
2081 Lisp_Object pane_name
, prefix
;
2083 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
2084 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
2085 pane_string
= (NILP (pane_name
)
2086 ? "" : (char *) SDATA (pane_name
));
2087 prev_wv
= xmalloc_widget_value ();
2088 prev_wv
->value
= pane_string
;
2089 if (keymaps
&& !NILP (prefix
))
2091 prev_wv
->enabled
= 1;
2092 prev_wv
->name
= "message";
2093 prev_wv
->help
= Qnil
;
2096 /* Loop over all panes and items, filling in the tree. */
2097 i
= MENU_ITEMS_PANE_LENGTH
;
2098 while (i
< menu_items_used
)
2101 /* Create a new item within current pane. */
2102 Lisp_Object item_name
, enable
, descrip
;
2103 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2104 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2106 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2108 if (NILP (item_name
))
2110 free_menubar_widget_value_tree (first_wv
);
2111 *error_name
= "Submenu in dialog items";
2114 if (EQ (item_name
, Qquote
))
2116 /* This is the boundary between left-side elts
2117 and right-side elts. Stop incrementing right_count. */
2122 if (nb_buttons
>= 9)
2124 free_menubar_widget_value_tree (first_wv
);
2125 *error_name
= "Too many dialog items";
2129 wv
= xmalloc_widget_value ();
2131 wv
->name
= (char *) button_names
[nb_buttons
];
2132 if (!NILP (descrip
))
2133 wv
->key
= (char *) SDATA (descrip
);
2134 wv
->value
= (char *) SDATA (item_name
);
2135 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
2136 wv
->enabled
= !NILP (enable
);
2140 if (! boundary_seen
)
2144 i
+= MENU_ITEMS_ITEM_LENGTH
;
2147 /* If the boundary was not specified,
2148 by default put half on the left and half on the right. */
2149 if (! boundary_seen
)
2150 left_count
= nb_buttons
- nb_buttons
/ 2;
2152 wv
= xmalloc_widget_value ();
2153 wv
->name
= dialog_name
;
2156 /* Frame title: 'Q' = Question, 'I' = Information.
2157 Can also have 'E' = Error if, one day, we want
2158 a popup for errors. */
2160 dialog_name
[0] = 'Q';
2162 dialog_name
[0] = 'I';
2164 /* Dialog boxes use a really stupid name encoding
2165 which specifies how many buttons to use
2166 and how many buttons are on the right. */
2167 dialog_name
[1] = '0' + nb_buttons
;
2168 dialog_name
[2] = 'B';
2169 dialog_name
[3] = 'R';
2170 /* Number of buttons to put on the right. */
2171 dialog_name
[4] = '0' + nb_buttons
- left_count
;
2173 wv
->contents
= first_wv
;
2177 /* No selection has been chosen yet. */
2178 menu_item_selection
= 0;
2180 /* Actually create and show the dialog. */
2181 create_and_show_dialog (f
, first_wv
);
2183 /* Free the widget_value objects we used to specify the contents. */
2184 free_menubar_widget_value_tree (first_wv
);
2186 /* Find the selected item, and its pane, to return
2187 the proper value. */
2188 if (menu_item_selection
!= 0)
2194 while (i
< menu_items_used
)
2198 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2201 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2202 i
+= MENU_ITEMS_PANE_LENGTH
;
2204 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2206 /* This is the boundary between left-side elts and
2213 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2214 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2218 entry
= Fcons (entry
, Qnil
);
2220 entry
= Fcons (prefix
, entry
);
2224 i
+= MENU_ITEMS_ITEM_LENGTH
;
2229 /* Make "Cancel" equivalent to C-g. */
2230 Fsignal (Qquit
, Qnil
);
2235 #else /* not USE_X_TOOLKIT && not USE_GTK */
2237 /* The frame of the last activated non-toolkit menu bar.
2238 Used to generate menu help events. */
2240 static struct frame
*menu_help_frame
;
2243 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2245 PANE is the pane number, and ITEM is the menu item number in
2246 the menu (currently not used).
2248 This cannot be done with generating a HELP_EVENT because
2249 XMenuActivate contains a loop that doesn't let Emacs process
2253 menu_help_callback (help_string
, pane
, item
)
2257 extern Lisp_Object Qmenu_item
;
2258 Lisp_Object
*first_item
;
2259 Lisp_Object pane_name
;
2260 Lisp_Object menu_object
;
2262 first_item
= XVECTOR (menu_items
)->contents
;
2263 if (EQ (first_item
[0], Qt
))
2264 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
2265 else if (EQ (first_item
[0], Qquote
))
2266 /* This shouldn't happen, see xmenu_show. */
2267 pane_name
= empty_unibyte_string
;
2269 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
2271 /* (menu-item MENU-NAME PANE-NUMBER) */
2272 menu_object
= Fcons (Qmenu_item
,
2274 Fcons (make_number (pane
), Qnil
)));
2275 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
2276 Qnil
, menu_object
, make_number (item
), 1);
2283 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
2284 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
2286 FRAME_PTR f
= p1
->pointer
;
2287 XMenu
*menu
= p2
->pointer
;
2291 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
2292 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
2294 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2296 #ifdef HAVE_X_WINDOWS
2297 /* Assume the mouse has moved out of the X window.
2298 If it has actually moved in, we will get an EnterNotify. */
2299 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
2301 /* State that no mouse buttons are now held.
2302 (The oldXMenu code doesn't track this info for us.)
2303 That is not necessarily true, but the fiction leads to reasonable
2304 results, and it is a pain to ask which are actually held now. */
2305 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2307 #endif /* HAVE_X_WINDOWS */
2316 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
, timestamp
)
2323 EMACS_UINT timestamp
;
2327 int pane
, selidx
, lpane
, status
;
2328 Lisp_Object entry
, pane_prefix
;
2330 int ulx
, uly
, width
, height
;
2331 int dispwidth
, dispheight
;
2332 int i
, j
, lines
, maxlines
;
2335 unsigned int dummy_uint
;
2336 int specpdl_count
= SPECPDL_INDEX ();
2338 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
2342 if (menu_items_n_panes
== 0)
2345 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2347 *error
= "Empty menu";
2351 /* Figure out which root window F is on. */
2352 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
2353 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
2354 &dummy_uint
, &dummy_uint
);
2356 /* Make the menu on that window. */
2357 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
2360 *error
= "Can't create menu";
2364 /* Don't GC while we prepare and show the menu,
2365 because we give the oldxmenu library pointers to the
2366 contents of strings. */
2367 inhibit_garbage_collection ();
2369 #ifdef HAVE_X_WINDOWS
2370 /* Adjust coordinates to relative to the outer (window manager) window. */
2371 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
2372 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2373 #endif /* HAVE_X_WINDOWS */
2375 /* Adjust coordinates to be root-window-relative. */
2379 /* Create all the necessary panes and their items. */
2380 maxlines
= lines
= i
= 0;
2381 while (i
< menu_items_used
)
2383 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2385 /* Create a new pane. */
2386 Lisp_Object pane_name
, prefix
;
2389 maxlines
= max (maxlines
, lines
);
2391 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
2392 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2393 pane_string
= (NILP (pane_name
)
2394 ? "" : (char *) SDATA (pane_name
));
2395 if (keymaps
&& !NILP (prefix
))
2398 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
2399 if (lpane
== XM_FAILURE
)
2401 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2402 *error
= "Can't create pane";
2405 i
+= MENU_ITEMS_PANE_LENGTH
;
2407 /* Find the width of the widest item in this pane. */
2410 while (j
< menu_items_used
)
2413 item
= XVECTOR (menu_items
)->contents
[j
];
2421 width
= SBYTES (item
);
2422 if (width
> maxwidth
)
2425 j
+= MENU_ITEMS_ITEM_LENGTH
;
2428 /* Ignore a nil in the item list.
2429 It's meaningful only for dialog boxes. */
2430 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2434 /* Create a new item within current pane. */
2435 Lisp_Object item_name
, enable
, descrip
, help
;
2436 unsigned char *item_data
;
2439 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2440 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2442 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2443 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
2444 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
2446 if (!NILP (descrip
))
2448 int gap
= maxwidth
- SBYTES (item_name
);
2449 /* if alloca is fast, use that to make the space,
2450 to reduce gc needs. */
2452 = (unsigned char *) alloca (maxwidth
2453 + SBYTES (descrip
) + 1);
2454 bcopy (SDATA (item_name
), item_data
,
2455 SBYTES (item_name
));
2456 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
2458 bcopy (SDATA (descrip
), item_data
+ j
,
2460 item_data
[j
+ SBYTES (descrip
)] = 0;
2463 item_data
= SDATA (item_name
);
2465 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
2466 menu
, lpane
, 0, item_data
,
2467 !NILP (enable
), help_string
)
2470 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2471 *error
= "Can't add selection to menu";
2474 i
+= MENU_ITEMS_ITEM_LENGTH
;
2479 maxlines
= max (maxlines
, lines
);
2481 /* All set and ready to fly. */
2482 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
2483 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2484 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2485 x
= min (x
, dispwidth
);
2486 y
= min (y
, dispheight
);
2489 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
2490 &ulx
, &uly
, &width
, &height
);
2491 if (ulx
+width
> dispwidth
)
2493 x
-= (ulx
+ width
) - dispwidth
;
2494 ulx
= dispwidth
- width
;
2496 if (uly
+height
> dispheight
)
2498 y
-= (uly
+ height
) - dispheight
;
2499 uly
= dispheight
- height
;
2501 #ifndef HAVE_X_WINDOWS
2502 if (FRAME_HAS_MINIBUF_P (f
) && uly
+height
> dispheight
- 1)
2504 /* Move the menu away of the echo area, to avoid overwriting the
2505 menu with help echo messages or vice versa. */
2506 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
2508 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2509 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2518 if (ulx
< 0) x
-= ulx
;
2519 if (uly
< 0) y
-= uly
;
2523 /* If position was not given by a mouse click, adjust so upper left
2524 corner of the menu as a whole ends up at given coordinates. This
2525 is what x-popup-menu says in its documentation. */
2527 y
+= 1.5*height
/(maxlines
+2);
2530 XMenuSetAEQ (menu
, TRUE
);
2531 XMenuSetFreeze (menu
, TRUE
);
2535 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
2538 record_unwind_protect (pop_down_menu
,
2539 Fcons (make_save_value (f
, 0),
2540 make_save_value (menu
, 0)));
2542 /* Help display under X won't work because XMenuActivate contains
2543 a loop that doesn't give Emacs a chance to process it. */
2544 menu_help_frame
= f
;
2545 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
2546 x
, y
, ButtonReleaseMask
, &datap
,
2547 menu_help_callback
);
2553 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
2556 /* Find the item number SELIDX in pane number PANE. */
2558 while (i
< menu_items_used
)
2560 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2564 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2566 i
+= MENU_ITEMS_PANE_LENGTH
;
2575 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2578 entry
= Fcons (entry
, Qnil
);
2579 if (!NILP (pane_prefix
))
2580 entry
= Fcons (pane_prefix
, entry
);
2586 i
+= MENU_ITEMS_ITEM_LENGTH
;
2592 *error
= "Can't activate menu";
2597 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2598 the menu was invoked with a mouse event as POSITION). */
2600 Fsignal (Qquit
, Qnil
);
2605 unbind_to (specpdl_count
, Qnil
);
2610 #endif /* not USE_X_TOOLKIT */
2612 #endif /* HAVE_MENUS */
2614 /* Detect if a dialog or menu has been posted. */
2619 return popup_activated_flag
;
2622 /* The following is used by delayed window autoselection. */
2624 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2625 doc
: /* Return t if a menu or popup dialog is active. */)
2629 return (popup_activated ()) ? Qt
: Qnil
;
2632 #endif /* HAVE_MENUS */
2638 Qdebug_on_next_call
= intern_c_string ("debug-on-next-call");
2639 staticpro (&Qdebug_on_next_call
);
2641 #ifdef USE_X_TOOLKIT
2642 widget_id_tick
= (1<<16);
2643 next_menubar_widget_id
= 1;
2646 defsubr (&Smenu_or_popup_active_p
);
2648 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2649 defsubr (&Sx_menu_bar_open_internal
);
2650 Ffset (intern_c_string ("accelerate-menu"),
2651 intern_c_string (Sx_menu_bar_open_internal
.symbol_name
));
2655 defsubr (&Sx_popup_dialog
);
2659 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2660 (do not change this comment) */