1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 /* X pop-up deck-of-cards menu facility for GNU Emacs.
22 * Written by Jon Arnold and Roman Budzianowski
23 * Mods and rewrite by Robert Krawitz
27 /* Modified by Fred Pierresteguy on December 93
28 to make the popup menus and menubar use the Xt. */
30 /* Rewritten for clarity and GC protection by rms in Feb 94. */
34 #if 0 /* Why was this included? And without syssignal.h? */
35 /* On 4.3 this loses if it comes after xterm.h. */
46 #include "termhooks.h"
48 #include "blockinput.h"
52 #include "sysselect.h"
59 /* This may include sys/types.h, and that somehow loses
60 if this is not done before the other system files. */
64 /* Load sys/types.h if not already loaded.
65 In some systems loading it twice is suicidal. */
67 #include <sys/types.h>
70 #include "dispextern.h"
73 /* Defining HAVE_MULTILINGUAL_MENU would mean that the toolkit menu
74 code accepts the Emacs internal encoding. */
75 #undef HAVE_MULTILINGUAL_MENU
79 #include <X11/IntrinsicP.h>
80 #include <X11/CoreP.h>
81 #include <X11/StringDefs.h>
82 #include <X11/Shell.h>
84 #include "xsettings.h"
85 #include "../lwlib/xlwmenu.h"
87 #include <X11/Xaw3d/Paned.h>
88 #else /* !HAVE_XAW3D */
89 #include <X11/Xaw/Paned.h>
90 #endif /* HAVE_XAW3D */
91 #endif /* USE_LUCID */
92 #else /* not USE_X_TOOLKIT */
94 #include "../oldXMenu/XMenu.h"
96 #endif /* not USE_X_TOOLKIT */
97 #endif /* HAVE_X_WINDOWS */
110 Lisp_Object Qdebug_on_next_call
;
112 extern Lisp_Object Qmenu_bar
;
114 extern Lisp_Object QCtoggle
, QCradio
;
116 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
118 extern Lisp_Object Qmenu_bar_update_hook
;
121 extern void set_frame_menubar (FRAME_PTR
, int, int);
122 extern XtAppContext Xt_app_con
;
124 static Lisp_Object
xdialog_show (FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
126 static void popup_get_selection (XEvent
*, struct x_display_info
*,
128 #endif /* USE_X_TOOLKIT */
131 extern void set_frame_menubar (FRAME_PTR
, int, int);
132 static Lisp_Object
xdialog_show (FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
136 static int update_frame_menubar (struct frame
*);
138 /* Flag which when set indicates a dialog or menu has been posted by
139 Xt on behalf of one of the widget sets. */
140 static int popup_activated_flag
;
142 static int next_menubar_widget_id
;
144 /* For NS and NTGUI, these prototypes are defined in keyboard.h. */
145 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
146 extern widget_value
*xmalloc_widget_value (void);
147 extern widget_value
*digest_single_submenu (int, int, int);
153 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
155 static struct frame
*
156 menubar_id_to_frame (LWLIB_ID id
)
158 Lisp_Object tail
, frame
;
161 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
167 if (!FRAME_WINDOW_P (f
))
169 if (f
->output_data
.x
->id
== id
)
177 #ifdef HAVE_X_WINDOWS
178 /* Return the mouse position in *X and *Y. The coordinates are window
179 relative for the edit window in frame F.
180 This is for Fx_popup_menu. The mouse_position_hook can not
181 be used for X, as it returns window relative coordinates
182 for the window where the mouse is in. This could be the menu bar,
183 the scroll bar or the edit window. Fx_popup_menu needs to be
184 sure it is the edit window. */
186 mouse_position_for_popup (FRAME_PTR f
, int *x
, int *y
)
188 Window root
, dummy_window
;
196 XQueryPointer (FRAME_X_DISPLAY (f
),
197 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
199 /* The root window which contains the pointer. */
202 /* Window pointer is on, not used */
205 /* The position on that root window. */
208 /* x/y in dummy_window coordinates, not used. */
211 /* Modifier keys and pointer buttons, about which
213 (unsigned int *) &dummy
);
217 /* xmenu_show expects window coordinates, not root window
218 coordinates. Translate. */
219 *x
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
220 *y
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
223 #endif /* HAVE_X_WINDOWS */
227 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
228 doc
: /* Pop up a dialog box and return user's selection.
229 POSITION specifies which frame to use.
230 This is normally a mouse button event or a window or frame.
231 If POSITION is t, it means to use the frame the mouse is on.
232 The dialog box appears in the middle of the specified frame.
234 CONTENTS specifies the alternatives to display in the dialog box.
235 It is a list of the form (DIALOG ITEM1 ITEM2...).
236 Each ITEM is a cons cell (STRING . VALUE).
237 The return value is VALUE from the chosen item.
239 An ITEM may also be just a string--that makes a nonselectable item.
240 An ITEM may also be nil--that means to put all preceding items
241 on the left of the dialog box and all following items on the right.
242 \(By default, approximately half appear on each side.)
244 If HEADER is non-nil, the frame title for the box is "Information",
245 otherwise it is "Question".
247 If the user gets rid of the dialog box without making a valid choice,
248 for instance using the window manager, then this produces a quit and
249 `x-popup-dialog' does not return. */)
250 (Lisp_Object position
, Lisp_Object contents
, Lisp_Object header
)
257 /* Decode the first argument: find the window or frame to use. */
258 if (EQ (position
, Qt
)
259 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
260 || EQ (XCAR (position
), Qtool_bar
))))
262 #if 0 /* Using the frame the mouse is on may not be right. */
263 /* Use the mouse's current position. */
264 FRAME_PTR new_f
= SELECTED_FRAME ();
265 Lisp_Object bar_window
;
266 enum scroll_bar_part part
;
270 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
273 XSETFRAME (window
, new_f
);
275 window
= selected_window
;
277 window
= selected_window
;
279 else if (CONSP (position
))
282 tem
= Fcar (position
);
284 window
= Fcar (Fcdr (position
));
287 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
288 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
291 else if (WINDOWP (position
) || FRAMEP (position
))
296 /* Decode where to put the menu. */
300 else if (WINDOWP (window
))
302 CHECK_LIVE_WINDOW (window
);
303 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
306 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
307 but I don't want to make one now. */
308 CHECK_WINDOW (window
);
310 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
311 error ("Can not put X dialog on this terminal");
313 /* Force a redisplay before showing the dialog. If a frame is created
314 just before showing the dialog, its contents may not have been fully
315 drawn, as this depends on timing of events from the X server. Redisplay
316 is not done when a dialog is shown. If redisplay could be done in the
317 X event loop (i.e. the X event loop does not run in a signal handler)
318 this would not be needed.
320 Do this before creating the widget value that points to Lisp
321 string contents, because Fredisplay may GC and relocate them. */
324 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
325 /* Display a menu with these alternatives
326 in the middle of frame F. */
328 Lisp_Object x
, y
, frame
, newpos
;
329 XSETFRAME (frame
, f
);
330 XSETINT (x
, x_pixel_width (f
) / 2);
331 XSETINT (y
, x_pixel_height (f
) / 2);
332 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
334 return Fx_popup_menu (newpos
,
335 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
341 Lisp_Object selection
;
342 int specpdl_count
= SPECPDL_INDEX ();
344 /* Decode the dialog items from what was specified. */
345 title
= Fcar (contents
);
346 CHECK_STRING (title
);
347 record_unwind_protect (unuse_menu_items
, Qnil
);
349 if (NILP (Fcar (Fcdr (contents
))))
350 /* No buttons specified, add an "Ok" button so users can pop down
351 the dialog. Also, the lesstif/motif version crashes if there are
353 contents
= Fcons (title
, Fcons (Fcons (build_string ("Ok"), Qt
), Qnil
));
355 list_of_panes (Fcons (contents
, Qnil
));
357 /* Display them in a dialog box. */
359 selection
= xdialog_show (f
, 0, title
, header
, &error_name
);
362 unbind_to (specpdl_count
, Qnil
);
363 discard_menu_items ();
365 if (error_name
) error (error_name
);
374 /* Set menu_items_inuse so no other popup menu or dialog is created. */
377 x_menu_set_in_use (int in_use
)
379 menu_items_inuse
= in_use
? Qt
: Qnil
;
380 popup_activated_flag
= in_use
;
382 if (popup_activated_flag
)
383 x_activate_timeout_atimer ();
387 /* Wait for an X event to arrive or for a timer to expire. */
390 x_menu_wait_for_event (void *data
)
392 /* Another way to do this is to register a timer callback, that can be
393 done in GTK and Xt. But we have to do it like this when using only X
394 anyway, and with callbacks we would have three variants for timer handling
395 instead of the small ifdefs below. */
399 ! XtAppPending (Xt_app_con
)
400 #elif defined USE_GTK
401 ! gtk_events_pending ()
403 ! XPending ((Display
*) data
)
407 EMACS_TIME next_time
= timer_check (1), *ntp
;
408 long secs
= EMACS_SECS (next_time
);
409 long usecs
= EMACS_USECS (next_time
);
410 SELECT_TYPE read_fds
;
411 struct x_display_info
*dpyinfo
;
415 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
417 int fd
= ConnectionNumber (dpyinfo
->display
);
418 FD_SET (fd
, &read_fds
);
420 XFlush (dpyinfo
->display
);
423 if (secs
< 0 && usecs
< 0)
428 select (n
+ 1, &read_fds
, (SELECT_TYPE
*)0, (SELECT_TYPE
*)0, ntp
);
434 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
438 /* Loop in Xt until the menu pulldown or dialog popup has been
439 popped down (deactivated). This is used for x-popup-menu
440 and x-popup-dialog; it is not used for the menu bar.
442 NOTE: All calls to popup_get_selection should be protected
443 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
446 popup_get_selection (XEvent
*initial_event
, struct x_display_info
*dpyinfo
, LWLIB_ID id
, int do_timers
)
450 while (popup_activated_flag
)
454 event
= *initial_event
;
459 if (do_timers
) x_menu_wait_for_event (0);
460 XtAppNextEvent (Xt_app_con
, &event
);
463 /* Make sure we don't consider buttons grabbed after menu goes.
464 And make sure to deactivate for any ButtonRelease,
465 even if XtDispatchEvent doesn't do that. */
466 if (event
.type
== ButtonRelease
467 && dpyinfo
->display
== event
.xbutton
.display
)
469 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
470 #ifdef USE_MOTIF /* Pretending that the event came from a
471 Btn1Down seems the only way to convince Motif to
472 activate its callbacks; setting the XmNmenuPost
473 isn't working. --marcus@sysc.pdx.edu. */
474 event
.xbutton
.button
= 1;
475 /* Motif only pops down menus when no Ctrl, Alt or Mod
476 key is pressed and the button is released. So reset key state
477 so Motif thinks this is the case. */
478 event
.xbutton
.state
= 0;
481 /* Pop down on C-g and Escape. */
482 else if (event
.type
== KeyPress
483 && dpyinfo
->display
== event
.xbutton
.display
)
485 KeySym keysym
= XLookupKeysym (&event
.xkey
, 0);
487 if ((keysym
== XK_g
&& (event
.xkey
.state
& ControlMask
) != 0)
488 || keysym
== XK_Escape
) /* Any escape, ignore modifiers. */
489 popup_activated_flag
= 0;
492 x_dispatch_event (&event
, event
.xany
.display
);
496 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
497 doc
: /* Start key navigation of the menu bar in FRAME.
498 This initially opens the first menu bar item and you can then navigate with the
499 arrow keys, select a menu entry with the return key or cancel with the
500 escape key. If FRAME has no menu bar this function does nothing.
502 If FRAME is nil or not given, use the selected frame. */)
506 FRAME_PTR f
= check_x_frame (frame
);
510 if (FRAME_EXTERNAL_MENU_BAR (f
))
511 set_frame_menubar (f
, 0, 1);
513 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
519 x_catch_errors (FRAME_X_DISPLAY (f
));
520 memset (&ev
, 0, sizeof ev
);
521 ev
.xbutton
.display
= FRAME_X_DISPLAY (f
);
522 ev
.xbutton
.window
= XtWindow (menubar
);
523 ev
.xbutton
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
524 ev
.xbutton
.time
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
525 ev
.xbutton
.button
= Button1
;
526 ev
.xbutton
.x
= ev
.xbutton
.y
= FRAME_MENUBAR_HEIGHT (f
) / 2;
527 ev
.xbutton
.same_screen
= True
;
534 XtSetArg (al
[0], XtNchildren
, &list
);
535 XtSetArg (al
[1], XtNnumChildren
, &nr
);
536 XtGetValues (menubar
, al
, 2);
537 ev
.xbutton
.window
= XtWindow (list
[0]);
541 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
542 /* From-window, to-window. */
543 ev
.xbutton
.window
, ev
.xbutton
.root
,
545 /* From-position, to-position. */
546 ev
.xbutton
.x
, ev
.xbutton
.y
,
547 &ev
.xbutton
.x_root
, &ev
.xbutton
.y_root
,
551 error_p
= x_had_errors_p (FRAME_X_DISPLAY (f
));
556 ev
.type
= ButtonPress
;
557 ev
.xbutton
.state
= 0;
559 XtDispatchEvent (&ev
);
560 ev
.xbutton
.type
= ButtonRelease
;
561 ev
.xbutton
.state
= Button1Mask
;
562 XtDispatchEvent (&ev
);
570 #endif /* USE_X_TOOLKIT */
574 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
575 doc
: /* Start key navigation of the menu bar in FRAME.
576 This initially opens the first menu bar item and you can then navigate with the
577 arrow keys, select a menu entry with the return key or cancel with the
578 escape key. If FRAME has no menu bar this function does nothing.
580 If FRAME is nil or not given, use the selected frame. */)
586 /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
590 f
= check_x_frame (frame
);
592 if (FRAME_EXTERNAL_MENU_BAR (f
))
593 set_frame_menubar (f
, 0, 1);
595 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
598 /* Activate the first menu. */
599 GList
*children
= gtk_container_get_children (GTK_CONTAINER (menubar
));
603 g_signal_emit_by_name (children
->data
, "activate_item");
604 popup_activated_flag
= 1;
605 g_list_free (children
);
613 /* Loop util popup_activated_flag is set to zero in a callback.
614 Used for popup menus and dialogs. */
617 popup_widget_loop (int do_timers
, GtkWidget
*widget
)
619 ++popup_activated_flag
;
621 /* Process events in the Gtk event loop until done. */
622 while (popup_activated_flag
)
624 if (do_timers
) x_menu_wait_for_event (0);
625 gtk_main_iteration ();
630 /* Activate the menu bar of frame F.
631 This is called from keyboard.c when it gets the
632 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
634 To activate the menu bar, we use the X button-press event
635 that was saved in saved_menu_event.
636 That makes the toolkit do its thing.
638 But first we recompute the menu bar contents (the whole tree).
640 The reason for saving the button event until here, instead of
641 passing it to the toolkit right away, is that we can safely
642 execute Lisp code. */
645 x_activate_menubar (FRAME_PTR f
)
650 if (!f
->output_data
.x
->saved_menu_event
->type
)
654 if (! xg_win_to_widget (FRAME_X_DISPLAY (f
),
655 f
->output_data
.x
->saved_menu_event
->xany
.window
))
659 set_frame_menubar (f
, 0, 1);
661 popup_activated_flag
= 1;
663 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
664 f
->output_data
.x
->saved_menu_event
);
666 XtDispatchEvent (f
->output_data
.x
->saved_menu_event
);
670 /* Ignore this if we get it a second time. */
671 f
->output_data
.x
->saved_menu_event
->type
= 0;
674 /* This callback is invoked when the user selects a menubar cascade
675 pushbutton, but before the pulldown menu is posted. */
679 popup_activate_callback (Widget widget
, LWLIB_ID id
, XtPointer client_data
)
681 popup_activated_flag
= 1;
683 x_activate_timeout_atimer ();
688 /* This callback is invoked when a dialog or menu is finished being
689 used and has been unposted. */
693 popup_deactivate_callback (GtkWidget
*widget
, gpointer client_data
)
695 popup_activated_flag
= 0;
699 popup_deactivate_callback (Widget widget
, LWLIB_ID id
, XtPointer client_data
)
701 popup_activated_flag
= 0;
706 /* Function that finds the frame for WIDGET and shows the HELP text
708 F is the frame if known, or NULL if not known. */
710 show_help_event (FRAME_PTR f
, xt_or_gtk_widget widget
, Lisp_Object help
)
716 XSETFRAME (frame
, f
);
717 kbd_buffer_store_help_event (frame
, help
);
721 #if 0 /* This code doesn't do anything useful. ++kfs */
722 /* WIDGET is the popup menu. It's parent is the frame's
723 widget. See which frame that is. */
724 xt_or_gtk_widget frame_widget
= XtParent (widget
);
727 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
731 && (f
= XFRAME (frame
),
732 FRAME_X_P (f
) && f
->output_data
.x
->widget
== frame_widget
))
736 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
740 /* Callback called when menu items are highlighted/unhighlighted
741 while moving the mouse over them. WIDGET is the menu bar or menu
742 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
743 the data structure for the menu item, or null in case of
748 menu_highlight_callback (GtkWidget
*widget
, gpointer call_data
)
750 xg_menu_item_cb_data
*cb_data
;
753 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (widget
),
755 if (! cb_data
) return;
757 help
= call_data
? cb_data
->help
: Qnil
;
759 /* If popup_activated_flag is greater than 1 we are in a popup menu.
760 Don't show help for them, they won't appear before the
761 popup is popped down. */
762 if (popup_activated_flag
<= 1)
763 show_help_event (cb_data
->cl_data
->f
, widget
, help
);
767 menu_highlight_callback (Widget widget
, LWLIB_ID id
, void *call_data
)
772 widget_value
*wv
= (widget_value
*) call_data
;
774 help
= wv
? wv
->help
: Qnil
;
776 /* Determine the frame for the help event. */
777 f
= menubar_id_to_frame (id
);
779 show_help_event (f
, widget
, help
);
784 /* Gtk calls callbacks just because we tell it what item should be
785 selected in a radio group. If this variable is set to a non-zero
786 value, we are creating menus and don't want callbacks right now.
788 static int xg_crazy_callback_abort
;
790 /* This callback is called from the menu bar pulldown menu
791 when the user makes a selection.
792 Figure out what the user chose
793 and put the appropriate events into the keyboard buffer. */
795 menubar_selection_callback (GtkWidget
*widget
, gpointer client_data
)
797 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
799 if (xg_crazy_callback_abort
)
802 if (! cb_data
|| ! cb_data
->cl_data
|| ! cb_data
->cl_data
->f
)
805 /* For a group of radio buttons, GTK calls the selection callback first
806 for the item that was active before the selection and then for the one that
807 is active after the selection. For C-h k this means we get the help on
808 the deselected item and then the selected item is executed. Prevent that
809 by ignoring the non-active item. */
810 if (GTK_IS_RADIO_MENU_ITEM (widget
)
811 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget
)))
814 /* When a menu is popped down, X generates a focus event (i.e. focus
815 goes back to the frame below the menu). Since GTK buffers events,
816 we force it out here before the menu selection event. Otherwise
817 sit-for will exit at once if the focus event follows the menu selection
821 while (gtk_events_pending ())
822 gtk_main_iteration ();
825 find_and_call_menu_selection (cb_data
->cl_data
->f
,
826 cb_data
->cl_data
->menu_bar_items_used
,
827 cb_data
->cl_data
->menu_bar_vector
,
831 #else /* not USE_GTK */
833 /* This callback is called from the menu bar pulldown menu
834 when the user makes a selection.
835 Figure out what the user chose
836 and put the appropriate events into the keyboard buffer. */
838 menubar_selection_callback (Widget widget
, LWLIB_ID id
, XtPointer client_data
)
842 f
= menubar_id_to_frame (id
);
845 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
846 f
->menu_bar_vector
, client_data
);
848 #endif /* not USE_GTK */
850 /* Recompute all the widgets of frame F, when the menu bar has been
851 changed. Value is non-zero if widgets were updated. */
854 update_frame_menubar (FRAME_PTR f
)
857 return xg_update_frame_menubar (f
);
865 x
= f
->output_data
.x
;
867 if (!x
->menubar_widget
|| XtIsManaged (x
->menubar_widget
))
871 /* Save the size of the frame because the pane widget doesn't accept
872 to resize itself. So force it. */
873 columns
= FRAME_COLS (f
);
874 rows
= FRAME_LINES (f
);
876 /* Do the voodoo which means "I'm changing lots of things, don't try
877 to refigure sizes until I'm done." */
878 lw_refigure_widget (x
->column_widget
, False
);
880 /* The order in which children are managed is the top to bottom
881 order in which they are displayed in the paned window. First,
882 remove the text-area widget. */
883 XtUnmanageChild (x
->edit_widget
);
885 /* Remove the menubar that is there now, and put up the menubar that
887 XtManageChild (x
->menubar_widget
);
888 XtMapWidget (x
->menubar_widget
);
889 XtVaSetValues (x
->menubar_widget
, XtNmappedWhenManaged
, 1, NULL
);
891 /* Re-manage the text-area widget, and then thrash the sizes. */
892 XtManageChild (x
->edit_widget
);
893 lw_refigure_widget (x
->column_widget
, True
);
895 /* Force the pane widget to resize itself with the right values. */
896 EmacsFrameSetCharSize (x
->edit_widget
, columns
, rows
);
904 apply_systemfont_to_dialog (Widget w
)
906 const char *fn
= xsettings_get_system_normal_font ();
909 XrmDatabase db
= XtDatabase (XtDisplay (w
));
911 XrmPutStringResource (&db
, "*dialog.faceName", fn
);
916 apply_systemfont_to_menu (Widget w
)
918 const char *fn
= xsettings_get_system_normal_font ();
923 if (XtIsShell (w
)) /* popup menu */
925 Widget
*childs
= NULL
;
927 XtVaGetValues (w
, XtNchildren
, &childs
, NULL
);
928 if (*childs
) w
= *childs
;
931 /* Only use system font if the default is used for the menu. */
932 XtVaGetValues (w
, XtNdefaultFace
, &defflt
, NULL
);
934 XtVaSetValues (w
, XtNfaceName
, fn
, NULL
);
938 /* Set the contents of the menubar widgets of frame F.
939 The argument FIRST_TIME is currently ignored;
940 it is set the first time this is called, from initialize_frame_menubar. */
943 set_frame_menubar (FRAME_PTR f
, int first_time
, int deep_p
)
945 xt_or_gtk_widget menubar_widget
;
950 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
952 int *submenu_start
, *submenu_end
;
953 int *submenu_top_level_items
, *submenu_n_panes
;
958 menubar_widget
= f
->output_data
.x
->menubar_widget
;
960 XSETFRAME (Vmenu_updating_frame
, f
);
963 if (f
->output_data
.x
->id
== 0)
964 f
->output_data
.x
->id
= next_menubar_widget_id
++;
965 id
= f
->output_data
.x
->id
;
968 if (! menubar_widget
)
970 /* Make the first call for any given frame always go deep. */
971 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
974 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
975 f
->output_data
.x
->saved_menu_event
->type
= 0;
979 /* If we have detached menus, we must update deep so detached menus
980 also gets updated. */
981 deep_p
= deep_p
|| xg_have_tear_offs ();
986 /* Make a widget-value tree representing the entire menu trees. */
988 struct buffer
*prev
= current_buffer
;
990 int specpdl_count
= SPECPDL_INDEX ();
991 int previous_menu_items_used
= f
->menu_bar_items_used
;
992 Lisp_Object
*previous_items
993 = (Lisp_Object
*) alloca (previous_menu_items_used
994 * sizeof (Lisp_Object
));
996 /* If we are making a new widget, its contents are empty,
997 do always reinitialize them. */
998 if (! menubar_widget
)
999 previous_menu_items_used
= 0;
1001 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1002 specbind (Qinhibit_quit
, Qt
);
1003 /* Don't let the debugger step into this code
1004 because it is not reentrant. */
1005 specbind (Qdebug_on_next_call
, Qnil
);
1007 record_unwind_save_match_data ();
1008 if (NILP (Voverriding_local_map_menu_flag
))
1010 specbind (Qoverriding_terminal_local_map
, Qnil
);
1011 specbind (Qoverriding_local_map
, Qnil
);
1014 set_buffer_internal_1 (XBUFFER (buffer
));
1016 /* Run the Lucid hook. */
1017 safe_run_hooks (Qactivate_menubar_hook
);
1019 /* If it has changed current-menubar from previous value,
1020 really recompute the menubar from the value. */
1021 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1022 call0 (Qrecompute_lucid_menubar
);
1023 safe_run_hooks (Qmenu_bar_update_hook
);
1024 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1026 items
= FRAME_MENU_BAR_ITEMS (f
);
1028 /* Save the frame's previous menu bar contents data. */
1029 if (previous_menu_items_used
)
1030 memcpy (previous_items
, XVECTOR (f
->menu_bar_vector
)->contents
,
1031 previous_menu_items_used
* sizeof (Lisp_Object
));
1033 /* Fill in menu_items with the current menu bar contents.
1034 This can evaluate Lisp code. */
1037 menu_items
= f
->menu_bar_vector
;
1038 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1039 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1040 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1041 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
1042 submenu_top_level_items
1043 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1045 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1047 Lisp_Object key
, string
, maps
;
1051 key
= XVECTOR (items
)->contents
[i
];
1052 string
= XVECTOR (items
)->contents
[i
+ 1];
1053 maps
= XVECTOR (items
)->contents
[i
+ 2];
1057 submenu_start
[i
] = menu_items_used
;
1059 menu_items_n_panes
= 0;
1060 submenu_top_level_items
[i
]
1061 = parse_single_submenu (key
, string
, maps
);
1062 submenu_n_panes
[i
] = menu_items_n_panes
;
1064 submenu_end
[i
] = menu_items_used
;
1067 finish_menu_items ();
1069 /* Convert menu_items into widget_value trees
1070 to display the menu. This cannot evaluate Lisp code. */
1072 wv
= xmalloc_widget_value ();
1073 wv
->name
= "menubar";
1076 wv
->button_type
= BUTTON_TYPE_NONE
;
1080 for (i
= 0; i
< last_i
; i
+= 4)
1082 menu_items_n_panes
= submenu_n_panes
[i
];
1083 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
1084 submenu_top_level_items
[i
]);
1088 first_wv
->contents
= wv
;
1089 /* Don't set wv->name here; GC during the loop might relocate it. */
1091 wv
->button_type
= BUTTON_TYPE_NONE
;
1095 set_buffer_internal_1 (prev
);
1097 /* If there has been no change in the Lisp-level contents
1098 of the menu bar, skip redisplaying it. Just exit. */
1100 /* Compare the new menu items with the ones computed last time. */
1101 for (i
= 0; i
< previous_menu_items_used
; i
++)
1102 if (menu_items_used
== i
1103 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1105 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1107 /* The menu items have not changed. Don't bother updating
1108 the menus in any form, since it would be a no-op. */
1109 free_menubar_widget_value_tree (first_wv
);
1110 discard_menu_items ();
1111 unbind_to (specpdl_count
, Qnil
);
1115 /* The menu items are different, so store them in the frame. */
1116 f
->menu_bar_vector
= menu_items
;
1117 f
->menu_bar_items_used
= menu_items_used
;
1119 /* This undoes save_menu_items. */
1120 unbind_to (specpdl_count
, Qnil
);
1122 /* Now GC cannot happen during the lifetime of the widget_value,
1123 so it's safe to store data from a Lisp_String. */
1124 wv
= first_wv
->contents
;
1125 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1128 string
= XVECTOR (items
)->contents
[i
+ 1];
1131 wv
->name
= (char *) SDATA (string
);
1132 update_submenu_strings (wv
->contents
);
1139 /* Make a widget-value tree containing
1140 just the top level menu bar strings. */
1142 wv
= xmalloc_widget_value ();
1143 wv
->name
= "menubar";
1146 wv
->button_type
= BUTTON_TYPE_NONE
;
1150 items
= FRAME_MENU_BAR_ITEMS (f
);
1151 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1155 string
= XVECTOR (items
)->contents
[i
+ 1];
1159 wv
= xmalloc_widget_value ();
1160 wv
->name
= (char *) SDATA (string
);
1163 wv
->button_type
= BUTTON_TYPE_NONE
;
1165 /* This prevents lwlib from assuming this
1166 menu item is really supposed to be empty. */
1167 /* The EMACS_INT cast avoids a warning.
1168 This value just has to be different from small integers. */
1169 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1174 first_wv
->contents
= wv
;
1178 /* Forget what we thought we knew about what is in the
1179 detailed contents of the menu bar menus.
1180 Changing the top level always destroys the contents. */
1181 f
->menu_bar_items_used
= 0;
1184 /* Create or update the menu bar widget. */
1189 xg_crazy_callback_abort
= 1;
1192 /* The fourth arg is DEEP_P, which says to consider the entire
1193 menu trees we supply, rather than just the menu bar item names. */
1194 xg_modify_menubar_widgets (menubar_widget
,
1198 G_CALLBACK (menubar_selection_callback
),
1199 G_CALLBACK (popup_deactivate_callback
),
1200 G_CALLBACK (menu_highlight_callback
));
1204 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
1207 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
1208 G_CALLBACK (menubar_selection_callback
),
1209 G_CALLBACK (popup_deactivate_callback
),
1210 G_CALLBACK (menu_highlight_callback
));
1212 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1216 #else /* not USE_GTK */
1219 /* Disable resizing (done for Motif!) */
1220 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
1222 /* The third arg is DEEP_P, which says to consider the entire
1223 menu trees we supply, rather than just the menu bar item names. */
1224 lw_modify_all_widgets (id
, first_wv
, deep_p
);
1226 /* Re-enable the edit widget to resize. */
1227 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
1231 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1232 XtTranslations override
= XtParseTranslationTable (menuOverride
);
1234 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
1235 f
->output_data
.x
->column_widget
,
1237 popup_activate_callback
,
1238 menubar_selection_callback
,
1239 popup_deactivate_callback
,
1240 menu_highlight_callback
);
1241 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1243 /* Make menu pop down on C-g. */
1244 XtOverrideTranslations (menubar_widget
, override
);
1246 apply_systemfont_to_menu (menubar_widget
);
1252 if (f
->output_data
.x
->menubar_widget
)
1253 XtRealizeWidget (f
->output_data
.x
->menubar_widget
);
1256 = (f
->output_data
.x
->menubar_widget
1257 ? (f
->output_data
.x
->menubar_widget
->core
.height
1258 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
1261 #if 1 /* Experimentally, we now get the right results
1262 for -geometry -0-0 without this. 24 Aug 96, rms.
1263 Maybe so, but the menu bar size is missing the pixels so the
1264 WM size hints are off by these pixels. Jan D, oct 2009. */
1266 if (FRAME_EXTERNAL_MENU_BAR (f
))
1269 XtVaGetValues (f
->output_data
.x
->column_widget
,
1270 XtNinternalBorderWidth
, &ibw
, NULL
);
1271 menubar_size
+= ibw
;
1273 #endif /* USE_LUCID */
1276 f
->output_data
.x
->menubar_height
= menubar_size
;
1278 #endif /* not USE_GTK */
1280 free_menubar_widget_value_tree (first_wv
);
1281 update_frame_menubar (f
);
1284 xg_crazy_callback_abort
= 0;
1290 /* Called from Fx_create_frame to create the initial menubar of a frame
1291 before it is mapped, so that the window is mapped with the menubar already
1292 there instead of us tacking it on later and thrashing the window after it
1296 initialize_frame_menubar (FRAME_PTR f
)
1298 /* This function is called before the first chance to redisplay
1299 the frame. It has to be, so the frame will have the right size. */
1300 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1301 set_frame_menubar (f
, 1, 1);
1305 /* Get rid of the menu bar of frame F, and free its storage.
1306 This is used when deleting a frame, and when turning off the menu bar.
1307 For GTK this function is in gtkutil.c. */
1311 free_frame_menubar (FRAME_PTR f
)
1313 Widget menubar_widget
;
1315 if (! FRAME_X_P (f
))
1318 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1320 f
->output_data
.x
->menubar_height
= 0;
1325 /* Removing the menu bar magically changes the shell widget's x
1326 and y position of (0, 0) which, when the menu bar is turned
1327 on again, leads to pull-down menuss appearing in strange
1328 positions near the upper-left corner of the display. This
1329 happens only with some window managers like twm and ctwm,
1330 but not with other like Motif's mwm or kwm, because the
1331 latter generate ConfigureNotify events when the menu bar
1332 is switched off, which fixes the shell position. */
1333 Position x0
, y0
, x1
, y1
;
1339 if (f
->output_data
.x
->widget
)
1340 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
1343 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
1344 f
->output_data
.x
->menubar_widget
= NULL
;
1346 if (f
->output_data
.x
->widget
)
1349 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
1350 if (x1
== 0 && y1
== 0)
1351 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
1353 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
1358 #endif /* not USE_GTK */
1360 #endif /* USE_X_TOOLKIT || USE_GTK */
1362 /* xmenu_show actually displays a menu using the panes and items in menu_items
1363 and returns the value selected from it.
1364 There are two versions of xmenu_show, one for Xt and one for Xlib.
1365 Both assume input is blocked by the caller. */
1367 /* F is the frame the menu is for.
1368 X and Y are the frame-relative specified position,
1369 relative to the inside upper left corner of the frame F.
1370 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1371 KEYMAPS is 1 if this menu was specified with keymaps;
1372 in that case, we return a list containing the chosen item's value
1373 and perhaps also the pane's prefix.
1374 TITLE is the specified menu title.
1375 ERROR is a place to store an error message string in case of failure.
1376 (We return nil on failure, but the value doesn't actually matter.) */
1378 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1380 /* The item selected in the popup menu. */
1381 static Lisp_Object
*volatile menu_item_selection
;
1385 /* Used when position a popup menu. See menu_position_func and
1386 create_and_show_popup_menu below. */
1387 struct next_popup_x_y
1394 /* The menu position function to use if we are not putting a popup
1395 menu where the pointer is.
1396 MENU is the menu to pop up.
1397 X and Y shall on exit contain x/y where the menu shall pop up.
1398 PUSH_IN is not documented in the GTK manual.
1399 USER_DATA is any data passed in when calling gtk_menu_popup.
1400 Here it points to a struct next_popup_x_y where the coordinates
1401 to store in *X and *Y are as well as the frame for the popup.
1403 Here only X and Y are used. */
1405 menu_position_func (GtkMenu
*menu
, gint
*x
, gint
*y
, gboolean
*push_in
, gpointer user_data
)
1407 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
1409 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (data
->f
);
1410 int disp_width
= x_display_pixel_width (dpyinfo
);
1411 int disp_height
= x_display_pixel_height (dpyinfo
);
1416 /* Check if there is room for the menu. If not, adjust x/y so that
1417 the menu is fully visible. */
1418 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
1419 if (data
->x
+ req
.width
> disp_width
)
1420 *x
-= data
->x
+ req
.width
- disp_width
;
1421 if (data
->y
+ req
.height
> disp_height
)
1422 *y
-= data
->y
+ req
.height
- disp_height
;
1426 popup_selection_callback (GtkWidget
*widget
, gpointer client_data
)
1428 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1430 if (xg_crazy_callback_abort
) return;
1431 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
1435 pop_down_menu (Lisp_Object arg
)
1437 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1439 popup_activated_flag
= 0;
1441 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1446 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1448 menu_item_selection will be set to the selection. */
1450 create_and_show_popup_menu (FRAME_PTR f
, widget_value
*first_wv
, int x
, int y
, int for_click
, EMACS_UINT timestamp
)
1454 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
1455 struct next_popup_x_y popup_x_y
;
1456 int specpdl_count
= SPECPDL_INDEX ();
1458 if (! FRAME_X_P (f
))
1461 xg_crazy_callback_abort
= 1;
1462 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
1463 G_CALLBACK (popup_selection_callback
),
1464 G_CALLBACK (popup_deactivate_callback
),
1465 G_CALLBACK (menu_highlight_callback
));
1466 xg_crazy_callback_abort
= 0;
1470 /* Not invoked by a click. pop up at x/y. */
1471 pos_func
= menu_position_func
;
1473 /* Adjust coordinates to be root-window-relative. */
1474 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1475 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1481 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1485 for (i
= 0; i
< 5; i
++)
1486 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1490 /* Display the menu. */
1491 gtk_widget_show_all (menu
);
1493 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
,
1494 timestamp
> 0 ? timestamp
: gtk_get_current_event_time());
1496 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1498 if (gtk_widget_get_mapped (menu
))
1500 /* Set this to one. popup_widget_loop increases it by one, so it becomes
1501 two. show_help_echo uses this to detect popup menus. */
1502 popup_activated_flag
= 1;
1503 /* Process events that apply to the menu. */
1504 popup_widget_loop (1, menu
);
1507 unbind_to (specpdl_count
, Qnil
);
1509 /* Must reset this manually because the button release event is not passed
1510 to Emacs event loop. */
1511 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1514 #else /* not USE_GTK */
1516 /* We need a unique id for each widget handled by the Lucid Widget
1519 For the main windows, and popup menus, we use this counter,
1520 which we increment each time after use. This starts from 1<<16.
1522 For menu bars, we use numbers starting at 0, counted in
1523 next_menubar_widget_id. */
1524 LWLIB_ID widget_id_tick
;
1527 popup_selection_callback (Widget widget
, LWLIB_ID id
, XtPointer client_data
)
1529 menu_item_selection
= (Lisp_Object
*) client_data
;
1532 /* ARG is the LWLIB ID of the dialog box, represented
1533 as a Lisp object as (HIGHPART . LOWPART). */
1536 pop_down_menu (Lisp_Object arg
)
1538 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
1539 | XINT (XCDR (arg
)));
1542 lw_destroy_all_widgets (id
);
1544 popup_activated_flag
= 0;
1549 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1551 menu_item_selection will be set to the selection. */
1553 create_and_show_popup_menu (FRAME_PTR f
, widget_value
*first_wv
,
1554 int x
, int y
, int for_click
, EMACS_UINT timestamp
)
1559 XButtonPressedEvent dummy
;
1563 if (! FRAME_X_P (f
))
1566 menu_id
= widget_id_tick
++;
1567 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
1568 f
->output_data
.x
->widget
, 1, 0,
1569 popup_selection_callback
,
1570 popup_deactivate_callback
,
1571 menu_highlight_callback
);
1574 apply_systemfont_to_menu (menu
);
1577 dummy
.type
= ButtonPress
;
1579 dummy
.send_event
= 0;
1580 dummy
.display
= FRAME_X_DISPLAY (f
);
1581 dummy
.time
= CurrentTime
;
1582 dummy
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1583 dummy
.window
= dummy
.root
;
1584 dummy
.subwindow
= dummy
.root
;
1588 /* Adjust coordinates to be root-window-relative. */
1589 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1590 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1597 for (i
= 0; i
< 5; i
++)
1598 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1601 /* Don't allow any geometry request from the user. */
1602 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
1603 XtSetValues (menu
, av
, ac
);
1605 /* Display the menu. */
1606 lw_popup_menu (menu
, (XEvent
*) &dummy
);
1607 popup_activated_flag
= 1;
1608 x_activate_timeout_atimer ();
1611 int fact
= 4 * sizeof (LWLIB_ID
);
1612 int specpdl_count
= SPECPDL_INDEX ();
1613 record_unwind_protect (pop_down_menu
,
1614 Fcons (make_number (menu_id
>> (fact
)),
1615 make_number (menu_id
& ~(-1 << (fact
)))));
1617 /* Process events that apply to the menu. */
1618 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
1620 unbind_to (specpdl_count
, Qnil
);
1624 #endif /* not USE_GTK */
1627 xmenu_show (FRAME_PTR f
, int x
, int y
, int for_click
, int keymaps
,
1628 Lisp_Object title
, char **error
, EMACS_UINT timestamp
)
1631 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1632 widget_value
**submenu_stack
1633 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1634 Lisp_Object
*subprefix_stack
1635 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1636 int submenu_depth
= 0;
1640 if (! FRAME_X_P (f
))
1645 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1647 *error
= "Empty menu";
1651 /* Create a tree of widget_value objects
1652 representing the panes and their items. */
1653 wv
= xmalloc_widget_value ();
1657 wv
->button_type
= BUTTON_TYPE_NONE
;
1662 /* Loop over all panes and items, filling in the tree. */
1664 while (i
< menu_items_used
)
1666 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1668 submenu_stack
[submenu_depth
++] = save_wv
;
1674 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1677 save_wv
= submenu_stack
[--submenu_depth
];
1681 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1682 && submenu_depth
!= 0)
1683 i
+= MENU_ITEMS_PANE_LENGTH
;
1684 /* Ignore a nil in the item list.
1685 It's meaningful only for dialog boxes. */
1686 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1688 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1690 /* Create a new pane. */
1691 Lisp_Object pane_name
, prefix
;
1694 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1695 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1697 #ifndef HAVE_MULTILINGUAL_MENU
1698 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1700 pane_name
= ENCODE_MENU_STRING (pane_name
);
1701 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1704 pane_string
= (NILP (pane_name
)
1705 ? "" : (char *) SDATA (pane_name
));
1706 /* If there is just one top-level pane, put all its items directly
1707 under the top-level menu. */
1708 if (menu_items_n_panes
== 1)
1711 /* If the pane has a meaningful name,
1712 make the pane a top-level menu item
1713 with its items as a submenu beneath it. */
1714 if (!keymaps
&& strcmp (pane_string
, ""))
1716 wv
= xmalloc_widget_value ();
1720 first_wv
->contents
= wv
;
1721 wv
->name
= pane_string
;
1722 if (keymaps
&& !NILP (prefix
))
1726 wv
->button_type
= BUTTON_TYPE_NONE
;
1731 else if (first_pane
)
1737 i
+= MENU_ITEMS_PANE_LENGTH
;
1741 /* Create a new item within current pane. */
1742 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1743 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1744 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1745 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1746 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1747 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1748 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1749 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1751 #ifndef HAVE_MULTILINGUAL_MENU
1752 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
1754 item_name
= ENCODE_MENU_STRING (item_name
);
1755 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1758 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1760 descrip
= ENCODE_MENU_STRING (descrip
);
1761 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1763 #endif /* not HAVE_MULTILINGUAL_MENU */
1765 wv
= xmalloc_widget_value ();
1769 save_wv
->contents
= wv
;
1770 wv
->name
= (char *) SDATA (item_name
);
1771 if (!NILP (descrip
))
1772 wv
->key
= (char *) SDATA (descrip
);
1774 /* If this item has a null value,
1775 make the call_data null so that it won't display a box
1776 when the mouse is on it. */
1778 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
1779 wv
->enabled
= !NILP (enable
);
1782 wv
->button_type
= BUTTON_TYPE_NONE
;
1783 else if (EQ (type
, QCtoggle
))
1784 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1785 else if (EQ (type
, QCradio
))
1786 wv
->button_type
= BUTTON_TYPE_RADIO
;
1790 wv
->selected
= !NILP (selected
);
1792 if (! STRINGP (help
))
1799 i
+= MENU_ITEMS_ITEM_LENGTH
;
1803 /* Deal with the title, if it is non-nil. */
1806 widget_value
*wv_title
= xmalloc_widget_value ();
1807 widget_value
*wv_sep1
= xmalloc_widget_value ();
1808 widget_value
*wv_sep2
= xmalloc_widget_value ();
1810 wv_sep2
->name
= "--";
1811 wv_sep2
->next
= first_wv
->contents
;
1812 wv_sep2
->help
= Qnil
;
1814 wv_sep1
->name
= "--";
1815 wv_sep1
->next
= wv_sep2
;
1816 wv_sep1
->help
= Qnil
;
1818 #ifndef HAVE_MULTILINGUAL_MENU
1819 if (STRING_MULTIBYTE (title
))
1820 title
= ENCODE_MENU_STRING (title
);
1823 wv_title
->name
= (char *) SDATA (title
);
1824 wv_title
->enabled
= TRUE
;
1825 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1826 wv_title
->help
= Qnil
;
1827 wv_title
->next
= wv_sep1
;
1828 first_wv
->contents
= wv_title
;
1831 /* No selection has been chosen yet. */
1832 menu_item_selection
= 0;
1834 /* Actually create and show the menu until popped down. */
1835 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
, timestamp
);
1837 /* Free the widget_value objects we used to specify the contents. */
1838 free_menubar_widget_value_tree (first_wv
);
1840 /* Find the selected item, and its pane, to return
1841 the proper value. */
1842 if (menu_item_selection
!= 0)
1844 Lisp_Object prefix
, entry
;
1846 prefix
= entry
= Qnil
;
1848 while (i
< menu_items_used
)
1850 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1852 subprefix_stack
[submenu_depth
++] = prefix
;
1856 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1858 prefix
= subprefix_stack
[--submenu_depth
];
1861 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1864 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1865 i
+= MENU_ITEMS_PANE_LENGTH
;
1867 /* Ignore a nil in the item list.
1868 It's meaningful only for dialog boxes. */
1869 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1874 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1875 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
1881 entry
= Fcons (entry
, Qnil
);
1883 entry
= Fcons (prefix
, entry
);
1884 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1885 if (!NILP (subprefix_stack
[j
]))
1886 entry
= Fcons (subprefix_stack
[j
], entry
);
1890 i
+= MENU_ITEMS_ITEM_LENGTH
;
1894 else if (!for_click
)
1895 /* Make "Cancel" equivalent to C-g. */
1896 Fsignal (Qquit
, Qnil
);
1903 dialog_selection_callback (GtkWidget
*widget
, gpointer client_data
)
1905 /* The EMACS_INT cast avoids a warning. There's no problem
1906 as long as pointers have enough bits to hold small integers. */
1907 if ((int) (EMACS_INT
) client_data
!= -1)
1908 menu_item_selection
= (Lisp_Object
*) client_data
;
1910 popup_activated_flag
= 0;
1913 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1915 menu_item_selection will be set to the selection. */
1917 create_and_show_dialog (FRAME_PTR f
, widget_value
*first_wv
)
1921 if (! FRAME_X_P (f
))
1924 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
1925 G_CALLBACK (dialog_selection_callback
),
1926 G_CALLBACK (popup_deactivate_callback
),
1931 int specpdl_count
= SPECPDL_INDEX ();
1932 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1934 /* Display the menu. */
1935 gtk_widget_show_all (menu
);
1937 /* Process events that apply to the menu. */
1938 popup_widget_loop (1, menu
);
1940 unbind_to (specpdl_count
, Qnil
);
1944 #else /* not USE_GTK */
1946 dialog_selection_callback (Widget widget
, LWLIB_ID id
, XtPointer client_data
)
1948 /* The EMACS_INT cast avoids a warning. There's no problem
1949 as long as pointers have enough bits to hold small integers. */
1950 if ((int) (EMACS_INT
) client_data
!= -1)
1951 menu_item_selection
= (Lisp_Object
*) client_data
;
1954 lw_destroy_all_widgets (id
);
1956 popup_activated_flag
= 0;
1960 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1962 menu_item_selection will be set to the selection. */
1964 create_and_show_dialog (FRAME_PTR f
, widget_value
*first_wv
)
1971 dialog_id
= widget_id_tick
++;
1973 apply_systemfont_to_dialog (f
->output_data
.x
->widget
);
1975 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
1976 f
->output_data
.x
->widget
, 1, 0,
1977 dialog_selection_callback
, 0, 0);
1978 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
1979 /* Display the dialog box. */
1980 lw_pop_up_all_widgets (dialog_id
);
1981 popup_activated_flag
= 1;
1982 x_activate_timeout_atimer ();
1984 /* Process events that apply to the dialog box.
1985 Also handle timers. */
1987 int count
= SPECPDL_INDEX ();
1988 int fact
= 4 * sizeof (LWLIB_ID
);
1990 /* xdialog_show_unwind is responsible for popping the dialog box down. */
1991 record_unwind_protect (pop_down_menu
,
1992 Fcons (make_number (dialog_id
>> (fact
)),
1993 make_number (dialog_id
& ~(-1 << (fact
)))));
1995 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
1998 unbind_to (count
, Qnil
);
2002 #endif /* not USE_GTK */
2004 static char * button_names
[] = {
2005 "button1", "button2", "button3", "button4", "button5",
2006 "button6", "button7", "button8", "button9", "button10" };
2009 xdialog_show (FRAME_PTR f
, int keymaps
, Lisp_Object title
, Lisp_Object header
, char **error_name
)
2011 int i
, nb_buttons
=0;
2012 char dialog_name
[6];
2014 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
2016 /* Number of elements seen so far, before boundary. */
2018 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2019 int boundary_seen
= 0;
2021 if (! FRAME_X_P (f
))
2026 if (menu_items_n_panes
> 1)
2028 *error_name
= "Multiple panes in dialog box";
2032 /* Create a tree of widget_value objects
2033 representing the text label and buttons. */
2035 Lisp_Object pane_name
, prefix
;
2037 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
2038 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
2039 pane_string
= (NILP (pane_name
)
2040 ? "" : (char *) SDATA (pane_name
));
2041 prev_wv
= xmalloc_widget_value ();
2042 prev_wv
->value
= pane_string
;
2043 if (keymaps
&& !NILP (prefix
))
2045 prev_wv
->enabled
= 1;
2046 prev_wv
->name
= "message";
2047 prev_wv
->help
= Qnil
;
2050 /* Loop over all panes and items, filling in the tree. */
2051 i
= MENU_ITEMS_PANE_LENGTH
;
2052 while (i
< menu_items_used
)
2055 /* Create a new item within current pane. */
2056 Lisp_Object item_name
, enable
, descrip
;
2057 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2058 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2060 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2062 if (NILP (item_name
))
2064 free_menubar_widget_value_tree (first_wv
);
2065 *error_name
= "Submenu in dialog items";
2068 if (EQ (item_name
, Qquote
))
2070 /* This is the boundary between left-side elts
2071 and right-side elts. Stop incrementing right_count. */
2076 if (nb_buttons
>= 9)
2078 free_menubar_widget_value_tree (first_wv
);
2079 *error_name
= "Too many dialog items";
2083 wv
= xmalloc_widget_value ();
2085 wv
->name
= (char *) button_names
[nb_buttons
];
2086 if (!NILP (descrip
))
2087 wv
->key
= (char *) SDATA (descrip
);
2088 wv
->value
= (char *) SDATA (item_name
);
2089 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
2090 wv
->enabled
= !NILP (enable
);
2094 if (! boundary_seen
)
2098 i
+= MENU_ITEMS_ITEM_LENGTH
;
2101 /* If the boundary was not specified,
2102 by default put half on the left and half on the right. */
2103 if (! boundary_seen
)
2104 left_count
= nb_buttons
- nb_buttons
/ 2;
2106 wv
= xmalloc_widget_value ();
2107 wv
->name
= dialog_name
;
2110 /* Frame title: 'Q' = Question, 'I' = Information.
2111 Can also have 'E' = Error if, one day, we want
2112 a popup for errors. */
2114 dialog_name
[0] = 'Q';
2116 dialog_name
[0] = 'I';
2118 /* Dialog boxes use a really stupid name encoding
2119 which specifies how many buttons to use
2120 and how many buttons are on the right. */
2121 dialog_name
[1] = '0' + nb_buttons
;
2122 dialog_name
[2] = 'B';
2123 dialog_name
[3] = 'R';
2124 /* Number of buttons to put on the right. */
2125 dialog_name
[4] = '0' + nb_buttons
- left_count
;
2127 wv
->contents
= first_wv
;
2131 /* No selection has been chosen yet. */
2132 menu_item_selection
= 0;
2134 /* Actually create and show the dialog. */
2135 create_and_show_dialog (f
, first_wv
);
2137 /* Free the widget_value objects we used to specify the contents. */
2138 free_menubar_widget_value_tree (first_wv
);
2140 /* Find the selected item, and its pane, to return
2141 the proper value. */
2142 if (menu_item_selection
!= 0)
2148 while (i
< menu_items_used
)
2152 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2155 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2156 i
+= MENU_ITEMS_PANE_LENGTH
;
2158 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2160 /* This is the boundary between left-side elts and
2167 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2168 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2172 entry
= Fcons (entry
, Qnil
);
2174 entry
= Fcons (prefix
, entry
);
2178 i
+= MENU_ITEMS_ITEM_LENGTH
;
2183 /* Make "Cancel" equivalent to C-g. */
2184 Fsignal (Qquit
, Qnil
);
2189 #else /* not USE_X_TOOLKIT && not USE_GTK */
2191 /* The frame of the last activated non-toolkit menu bar.
2192 Used to generate menu help events. */
2194 static struct frame
*menu_help_frame
;
2197 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2199 PANE is the pane number, and ITEM is the menu item number in
2200 the menu (currently not used).
2202 This cannot be done with generating a HELP_EVENT because
2203 XMenuActivate contains a loop that doesn't let Emacs process
2207 menu_help_callback (char *help_string
, int pane
, int item
)
2209 Lisp_Object
*first_item
;
2210 Lisp_Object pane_name
;
2211 Lisp_Object menu_object
;
2213 first_item
= XVECTOR (menu_items
)->contents
;
2214 if (EQ (first_item
[0], Qt
))
2215 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
2216 else if (EQ (first_item
[0], Qquote
))
2217 /* This shouldn't happen, see xmenu_show. */
2218 pane_name
= empty_unibyte_string
;
2220 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
2222 /* (menu-item MENU-NAME PANE-NUMBER) */
2223 menu_object
= Fcons (Qmenu_item
,
2225 Fcons (make_number (pane
), Qnil
)));
2226 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
2227 Qnil
, menu_object
, make_number (item
), 1);
2231 pop_down_menu (Lisp_Object arg
)
2233 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
2234 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
2236 FRAME_PTR f
= p1
->pointer
;
2237 XMenu
*menu
= p2
->pointer
;
2241 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
2242 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
2244 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2246 #ifdef HAVE_X_WINDOWS
2247 /* Assume the mouse has moved out of the X window.
2248 If it has actually moved in, we will get an EnterNotify. */
2249 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
2251 /* State that no mouse buttons are now held.
2252 (The oldXMenu code doesn't track this info for us.)
2253 That is not necessarily true, but the fiction leads to reasonable
2254 results, and it is a pain to ask which are actually held now. */
2255 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2257 #endif /* HAVE_X_WINDOWS */
2266 xmenu_show (FRAME_PTR f
, int x
, int y
, int for_click
, int keymaps
,
2267 Lisp_Object title
, char **error
, EMACS_UINT timestamp
)
2271 int pane
, selidx
, lpane
, status
;
2272 Lisp_Object entry
, pane_prefix
;
2274 int ulx
, uly
, width
, height
;
2275 int dispwidth
, dispheight
;
2276 int i
, j
, lines
, maxlines
;
2279 unsigned int dummy_uint
;
2280 int specpdl_count
= SPECPDL_INDEX ();
2282 if (! FRAME_X_P (f
) && ! FRAME_MSDOS_P (f
))
2286 if (menu_items_n_panes
== 0)
2289 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2291 *error
= "Empty menu";
2295 /* Figure out which root window F is on. */
2296 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
2297 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
2298 &dummy_uint
, &dummy_uint
);
2300 /* Make the menu on that window. */
2301 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
2304 *error
= "Can't create menu";
2308 /* Don't GC while we prepare and show the menu,
2309 because we give the oldxmenu library pointers to the
2310 contents of strings. */
2311 inhibit_garbage_collection ();
2313 #ifdef HAVE_X_WINDOWS
2314 /* Adjust coordinates to relative to the outer (window manager) window. */
2315 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
2316 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2317 #endif /* HAVE_X_WINDOWS */
2319 /* Adjust coordinates to be root-window-relative. */
2323 /* Create all the necessary panes and their items. */
2324 maxlines
= lines
= i
= 0;
2325 while (i
< menu_items_used
)
2327 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2329 /* Create a new pane. */
2330 Lisp_Object pane_name
, prefix
;
2333 maxlines
= max (maxlines
, lines
);
2335 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
2336 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2337 pane_string
= (NILP (pane_name
)
2338 ? "" : (char *) SDATA (pane_name
));
2339 if (keymaps
&& !NILP (prefix
))
2342 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
2343 if (lpane
== XM_FAILURE
)
2345 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2346 *error
= "Can't create pane";
2349 i
+= MENU_ITEMS_PANE_LENGTH
;
2351 /* Find the width of the widest item in this pane. */
2354 while (j
< menu_items_used
)
2357 item
= XVECTOR (menu_items
)->contents
[j
];
2365 width
= SBYTES (item
);
2366 if (width
> maxwidth
)
2369 j
+= MENU_ITEMS_ITEM_LENGTH
;
2372 /* Ignore a nil in the item list.
2373 It's meaningful only for dialog boxes. */
2374 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2378 /* Create a new item within current pane. */
2379 Lisp_Object item_name
, enable
, descrip
, help
;
2380 unsigned char *item_data
;
2383 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2384 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2386 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2387 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
2388 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
2390 if (!NILP (descrip
))
2392 int gap
= maxwidth
- SBYTES (item_name
);
2393 /* if alloca is fast, use that to make the space,
2394 to reduce gc needs. */
2396 = (unsigned char *) alloca (maxwidth
2397 + SBYTES (descrip
) + 1);
2398 memcpy (item_data
, SDATA (item_name
), SBYTES (item_name
));
2399 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
2401 memcpy (item_data
+ j
, SDATA (descrip
), SBYTES (descrip
));
2402 item_data
[j
+ SBYTES (descrip
)] = 0;
2405 item_data
= SDATA (item_name
);
2407 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
2408 menu
, lpane
, 0, item_data
,
2409 !NILP (enable
), help_string
)
2412 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2413 *error
= "Can't add selection to menu";
2416 i
+= MENU_ITEMS_ITEM_LENGTH
;
2421 maxlines
= max (maxlines
, lines
);
2423 /* All set and ready to fly. */
2424 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
2425 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2426 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2427 x
= min (x
, dispwidth
);
2428 y
= min (y
, dispheight
);
2431 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
2432 &ulx
, &uly
, &width
, &height
);
2433 if (ulx
+width
> dispwidth
)
2435 x
-= (ulx
+ width
) - dispwidth
;
2436 ulx
= dispwidth
- width
;
2438 if (uly
+height
> dispheight
)
2440 y
-= (uly
+ height
) - dispheight
;
2441 uly
= dispheight
- height
;
2443 #ifndef HAVE_X_WINDOWS
2444 if (FRAME_HAS_MINIBUF_P (f
) && uly
+height
> dispheight
- 1)
2446 /* Move the menu away of the echo area, to avoid overwriting the
2447 menu with help echo messages or vice versa. */
2448 if (BUFFERP (echo_area_buffer
[0]) && WINDOWP (echo_area_window
))
2450 y
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2451 uly
-= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window
));
2460 if (ulx
< 0) x
-= ulx
;
2461 if (uly
< 0) y
-= uly
;
2465 /* If position was not given by a mouse click, adjust so upper left
2466 corner of the menu as a whole ends up at given coordinates. This
2467 is what x-popup-menu says in its documentation. */
2469 y
+= 1.5*height
/(maxlines
+2);
2472 XMenuSetAEQ (menu
, TRUE
);
2473 XMenuSetFreeze (menu
, TRUE
);
2477 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
2480 record_unwind_protect (pop_down_menu
,
2481 Fcons (make_save_value (f
, 0),
2482 make_save_value (menu
, 0)));
2484 /* Help display under X won't work because XMenuActivate contains
2485 a loop that doesn't give Emacs a chance to process it. */
2486 menu_help_frame
= f
;
2487 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
2488 x
, y
, ButtonReleaseMask
, &datap
,
2489 menu_help_callback
);
2495 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
2498 /* Find the item number SELIDX in pane number PANE. */
2500 while (i
< menu_items_used
)
2502 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2506 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2508 i
+= MENU_ITEMS_PANE_LENGTH
;
2517 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2520 entry
= Fcons (entry
, Qnil
);
2521 if (!NILP (pane_prefix
))
2522 entry
= Fcons (pane_prefix
, entry
);
2528 i
+= MENU_ITEMS_ITEM_LENGTH
;
2534 *error
= "Can't activate menu";
2539 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2540 the menu was invoked with a mouse event as POSITION). */
2542 Fsignal (Qquit
, Qnil
);
2547 unbind_to (specpdl_count
, Qnil
);
2552 #endif /* not USE_X_TOOLKIT */
2554 #endif /* HAVE_MENUS */
2556 /* Detect if a dialog or menu has been posted. */
2559 popup_activated (void)
2561 return popup_activated_flag
;
2564 /* The following is used by delayed window autoselection. */
2566 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2567 doc
: /* Return t if a menu or popup dialog is active. */)
2571 return (popup_activated ()) ? Qt
: Qnil
;
2574 #endif /* HAVE_MENUS */
2578 syms_of_xmenu (void)
2580 Qdebug_on_next_call
= intern_c_string ("debug-on-next-call");
2581 staticpro (&Qdebug_on_next_call
);
2583 #ifdef USE_X_TOOLKIT
2584 widget_id_tick
= (1<<16);
2585 next_menubar_widget_id
= 1;
2588 defsubr (&Smenu_or_popup_active_p
);
2590 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2591 defsubr (&Sx_menu_bar_open_internal
);
2592 Ffset (intern_c_string ("accelerate-menu"),
2593 intern_c_string (Sx_menu_bar_open_internal
.symbol_name
));
2597 defsubr (&Sx_popup_dialog
);
2601 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2602 (do not change this comment) */