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 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. */
45 #include "termhooks.h"
47 #include "blockinput.h"
51 #include "sysselect.h"
58 /* This may include sys/types.h, and that somehow loses
59 if this is not done before the other system files. */
63 /* Load sys/types.h if not already loaded.
64 In some systems loading it twice is suicidal. */
66 #include <sys/types.h>
69 #include "dispextern.h"
72 /* Defining HAVE_MULTILINGUAL_MENU would mean that the toolkit menu
73 code accepts the Emacs internal encoding. */
74 #undef HAVE_MULTILINGUAL_MENU
78 #include <X11/IntrinsicP.h>
79 #include <X11/CoreP.h>
80 #include <X11/StringDefs.h>
81 #include <X11/Shell.h>
84 #include <X11/Xaw3d/Paned.h>
85 #else /* !HAVE_XAW3D */
86 #include <X11/Xaw/Paned.h>
87 #endif /* HAVE_XAW3D */
88 #endif /* USE_LUCID */
89 #include "../lwlib/lwlib.h"
90 #else /* not USE_X_TOOLKIT */
92 #include "../oldXMenu/XMenu.h"
94 #endif /* not USE_X_TOOLKIT */
95 #endif /* HAVE_X_WINDOWS */
108 Lisp_Object Qdebug_on_next_call
;
110 extern Lisp_Object Vmenu_updating_frame
;
112 extern Lisp_Object Qmenu_bar
;
114 extern Lisp_Object QCtoggle
, QCradio
;
116 extern Lisp_Object Voverriding_local_map
;
117 extern Lisp_Object Voverriding_local_map_menu_flag
;
119 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
121 extern Lisp_Object Qmenu_bar_update_hook
;
124 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
125 extern XtAppContext Xt_app_con
;
127 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
129 static void popup_get_selection
P_ ((XEvent
*, struct x_display_info
*,
131 #endif /* USE_X_TOOLKIT */
134 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
135 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
139 static int update_frame_menubar
P_ ((struct frame
*));
140 static Lisp_Object xmenu_show
P_ ((struct frame
*, int, int, int, int,
141 Lisp_Object
, char **));
143 /* Flag which when set indicates a dialog or menu has been posted by
144 Xt on behalf of one of the widget sets. */
145 static int popup_activated_flag
;
147 static int next_menubar_widget_id
;
149 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
150 extern widget_value
*xmalloc_widget_value
P_ ((void));
151 extern widget_value
*digest_single_submenu
P_ ((int, int, int));
154 /* This is set nonzero after the user activates the menu bar, and set
155 to zero again after the menu bars are redisplayed by prepare_menu_bar.
156 While it is nonzero, all calls to set_frame_menubar go deep.
158 I don't understand why this is needed, but it does seem to be
159 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
161 int pending_menu_activation
;
165 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
167 static struct frame
*
168 menubar_id_to_frame (id
)
171 Lisp_Object tail
, frame
;
174 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
180 if (!FRAME_WINDOW_P (f
))
182 if (f
->output_data
.x
->id
== id
)
190 #ifdef HAVE_X_WINDOWS
191 /* Return the mouse position in *X and *Y. The coordinates are window
192 relative for the edit window in frame F.
193 This is for Fx_popup_menu. The mouse_position_hook can not
194 be used for X, as it returns window relative coordinates
195 for the window where the mouse is in. This could be the menu bar,
196 the scroll bar or the edit window. Fx_popup_menu needs to be
197 sure it is the edit window. */
199 mouse_position_for_popup (f
, x
, y
)
204 Window root
, dummy_window
;
212 XQueryPointer (FRAME_X_DISPLAY (f
),
213 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
215 /* The root window which contains the pointer. */
218 /* Window pointer is on, not used */
221 /* The position on that root window. */
224 /* x/y in dummy_window coordinates, not used. */
227 /* Modifier keys and pointer buttons, about which
229 (unsigned int *) &dummy
);
233 /* xmenu_show expects window coordinates, not root window
234 coordinates. Translate. */
235 *x
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
236 *y
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
239 #endif /* HAVE_X_WINDOWS */
241 DEFUN ("x-popup-menu", Fx_popup_menu
, Sx_popup_menu
, 2, 2, 0,
242 doc
: /* Pop up a deck-of-cards menu and return user's selection.
243 POSITION is a position specification. This is either a mouse button event
244 or a list ((XOFFSET YOFFSET) WINDOW)
245 where XOFFSET and YOFFSET are positions in pixels from the top left
246 corner of WINDOW. (WINDOW may be a window or a frame object.)
247 This controls the position of the top left of the menu as a whole.
248 If POSITION is t, it means to use the current mouse position.
250 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
251 The menu items come from key bindings that have a menu string as well as
252 a definition; actually, the "definition" in such a key binding looks like
253 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into
254 the keymap as a top-level element.
256 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
257 Otherwise, REAL-DEFINITION should be a valid key binding definition.
259 You can also use a list of keymaps as MENU.
260 Then each keymap makes a separate pane.
262 When MENU is a keymap or a list of keymaps, the return value is the
263 list of events corresponding to the user's choice. Note that
264 `x-popup-menu' does not actually execute the command bound to that
267 Alternatively, you can specify a menu of multiple panes
268 with a list of the form (TITLE PANE1 PANE2...),
269 where each pane is a list of form (TITLE ITEM1 ITEM2...).
270 Each ITEM is normally a cons cell (STRING . VALUE);
271 but a string can appear as an item--that makes a nonselectable line
273 With this form of menu, the return value is VALUE from the chosen item.
275 If POSITION is nil, don't display the menu at all, just precalculate the
276 cached information about equivalent key sequences.
278 If the user gets rid of the menu without making a valid choice, for
279 instance by clicking the mouse away from a valid choice or by typing
280 keyboard input, then this normally results in a quit and
281 `x-popup-menu' does not return. But if POSITION is a mouse button
282 event (indicating that the user invoked the menu with the mouse) then
283 no quit occurs and `x-popup-menu' returns nil. */)
285 Lisp_Object position
, menu
;
287 Lisp_Object keymap
, tem
;
288 int xpos
= 0, ypos
= 0;
290 char *error_name
= NULL
;
291 Lisp_Object selection
= Qnil
;
293 Lisp_Object x
, y
, window
;
296 int specpdl_count
= SPECPDL_INDEX ();
300 if (! NILP (position
))
302 int get_current_pos_p
= 0;
305 /* Decode the first argument: find the window and the coordinates. */
306 if (EQ (position
, Qt
)
307 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
308 || EQ (XCAR (position
), Qtool_bar
))))
310 get_current_pos_p
= 1;
314 tem
= Fcar (position
);
317 window
= Fcar (Fcdr (position
));
319 y
= Fcar (XCDR (tem
));
324 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
325 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
326 tem
= Fcar (Fcdr (Fcdr (tem
))); /* POSN_WINDOW_POSN (tem) */
331 /* If a click happens in an external tool bar or a detached
332 tool bar, x and y is NIL. In that case, use the current
333 mouse position. This happens for the help button in the
334 tool bar. Ideally popup-menu should pass NIL to
335 this function, but it doesn't. */
336 if (NILP (x
) && NILP (y
))
337 get_current_pos_p
= 1;
340 if (get_current_pos_p
)
342 /* Use the mouse's current position. */
343 FRAME_PTR new_f
= SELECTED_FRAME ();
344 #ifdef HAVE_X_WINDOWS
345 /* Can't use mouse_position_hook for X since it returns
346 coordinates relative to the window the mouse is in,
347 we need coordinates relative to the edit widget always. */
352 mouse_position_for_popup (new_f
, &cur_x
, &cur_y
);
353 /* cur_x/y may be negative, so use make_number. */
354 x
= make_number (cur_x
);
355 y
= make_number (cur_y
);
358 #else /* not HAVE_X_WINDOWS */
359 Lisp_Object bar_window
;
360 enum scroll_bar_part part
;
363 if (mouse_position_hook
)
364 (*mouse_position_hook
) (&new_f
, 1, &bar_window
,
365 &part
, &x
, &y
, &time
);
366 #endif /* not HAVE_X_WINDOWS */
369 XSETFRAME (window
, new_f
);
372 window
= selected_window
;
381 /* Decode where to put the menu. */
389 else if (WINDOWP (window
))
391 CHECK_LIVE_WINDOW (window
);
392 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
394 xpos
= WINDOW_LEFT_EDGE_X (XWINDOW (window
));
395 ypos
= WINDOW_TOP_EDGE_Y (XWINDOW (window
));
398 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
399 but I don't want to make one now. */
400 CHECK_WINDOW (window
);
406 error ("Can not put X menu on non-X terminal");
408 XSETFRAME (Vmenu_updating_frame
, f
);
411 Vmenu_updating_frame
= Qnil
;
412 #endif /* HAVE_MENUS */
414 record_unwind_protect (unuse_menu_items
, Qnil
);
418 /* Decode the menu items from what was specified. */
420 keymap
= get_keymap (menu
, 0, 0);
423 /* We were given a keymap. Extract menu info from the keymap. */
426 /* Extract the detailed info to make one pane. */
427 keymap_panes (&menu
, 1, NILP (position
));
429 /* Search for a string appearing directly as an element of the keymap.
430 That string is the title of the menu. */
431 prompt
= Fkeymap_prompt (keymap
);
432 if (NILP (title
) && !NILP (prompt
))
435 /* Make that be the pane title of the first pane. */
436 if (!NILP (prompt
) && menu_items_n_panes
>= 0)
437 XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
] = prompt
;
441 else if (CONSP (menu
) && KEYMAPP (XCAR (menu
)))
443 /* We were given a list of keymaps. */
444 int nmaps
= XFASTINT (Flength (menu
));
446 = (Lisp_Object
*) alloca (nmaps
* sizeof (Lisp_Object
));
451 /* The first keymap that has a prompt string
452 supplies the menu title. */
453 for (tem
= menu
, i
= 0; CONSP (tem
); tem
= XCDR (tem
))
457 maps
[i
++] = keymap
= get_keymap (XCAR (tem
), 1, 0);
459 prompt
= Fkeymap_prompt (keymap
);
460 if (NILP (title
) && !NILP (prompt
))
464 /* Extract the detailed info to make one pane. */
465 keymap_panes (maps
, nmaps
, NILP (position
));
467 /* Make the title be the pane title of the first pane. */
468 if (!NILP (title
) && menu_items_n_panes
>= 0)
469 XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
] = title
;
475 /* We were given an old-fashioned menu. */
477 CHECK_STRING (title
);
479 list_of_panes (Fcdr (menu
));
484 unbind_to (specpdl_count
, Qnil
);
488 discard_menu_items ();
494 /* Display them in a menu. */
497 selection
= xmenu_show (f
, xpos
, ypos
, for_click
,
498 keymaps
, title
, &error_name
);
501 discard_menu_items ();
504 #endif /* HAVE_MENUS */
506 if (error_name
) error (error_name
);
512 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
513 doc
: /* Pop up a dialog box and return user's selection.
514 POSITION specifies which frame to use.
515 This is normally a mouse button event or a window or frame.
516 If POSITION is t, it means to use the frame the mouse is on.
517 The dialog box appears in the middle of the specified frame.
519 CONTENTS specifies the alternatives to display in the dialog box.
520 It is a list of the form (DIALOG ITEM1 ITEM2...).
521 Each ITEM is a cons cell (STRING . VALUE).
522 The return value is VALUE from the chosen item.
524 An ITEM may also be just a string--that makes a nonselectable item.
525 An ITEM may also be nil--that means to put all preceding items
526 on the left of the dialog box and all following items on the right.
527 \(By default, approximately half appear on each side.)
529 If HEADER is non-nil, the frame title for the box is "Information",
530 otherwise it is "Question".
532 If the user gets rid of the dialog box without making a valid choice,
533 for instance using the window manager, then this produces a quit and
534 `x-popup-dialog' does not return. */)
535 (position
, contents
, header
)
536 Lisp_Object position
, contents
, header
;
543 /* Decode the first argument: find the window or frame to use. */
544 if (EQ (position
, Qt
)
545 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
546 || EQ (XCAR (position
), Qtool_bar
))))
548 #if 0 /* Using the frame the mouse is on may not be right. */
549 /* Use the mouse's current position. */
550 FRAME_PTR new_f
= SELECTED_FRAME ();
551 Lisp_Object bar_window
;
552 enum scroll_bar_part part
;
556 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
559 XSETFRAME (window
, new_f
);
561 window
= selected_window
;
563 window
= selected_window
;
565 else if (CONSP (position
))
568 tem
= Fcar (position
);
570 window
= Fcar (Fcdr (position
));
573 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
574 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
577 else if (WINDOWP (position
) || FRAMEP (position
))
582 /* Decode where to put the menu. */
586 else if (WINDOWP (window
))
588 CHECK_LIVE_WINDOW (window
);
589 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
592 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
593 but I don't want to make one now. */
594 CHECK_WINDOW (window
);
597 error ("Can not put X dialog on non-X terminal");
599 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
600 /* Display a menu with these alternatives
601 in the middle of frame F. */
603 Lisp_Object x
, y
, frame
, newpos
;
604 XSETFRAME (frame
, f
);
605 XSETINT (x
, x_pixel_width (f
) / 2);
606 XSETINT (y
, x_pixel_height (f
) / 2);
607 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
609 return Fx_popup_menu (newpos
,
610 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
616 Lisp_Object selection
;
617 int specpdl_count
= SPECPDL_INDEX ();
619 /* Decode the dialog items from what was specified. */
620 title
= Fcar (contents
);
621 CHECK_STRING (title
);
622 record_unwind_protect (unuse_menu_items
, Qnil
);
624 if (NILP (Fcar (Fcdr (contents
))))
625 /* No buttons specified, add an "Ok" button so users can pop down
626 the dialog. Also, the lesstif/motif version crashes if there are
628 contents
= Fcons (title
, Fcons (Fcons (build_string ("Ok"), Qt
), Qnil
));
630 list_of_panes (Fcons (contents
, Qnil
));
632 /* Display them in a dialog box. */
634 selection
= xdialog_show (f
, 0, title
, header
, &error_name
);
637 unbind_to (specpdl_count
, Qnil
);
638 discard_menu_items ();
640 if (error_name
) error (error_name
);
649 /* Set menu_items_inuse so no other popup menu or dialog is created. */
652 x_menu_set_in_use (in_use
)
655 menu_items_inuse
= in_use
? Qt
: Qnil
;
656 popup_activated_flag
= in_use
;
658 if (popup_activated_flag
)
659 x_activate_timeout_atimer ();
663 /* Wait for an X event to arrive or for a timer to expire. */
666 x_menu_wait_for_event (void *data
)
668 extern EMACS_TIME timer_check
P_ ((int));
670 /* Another way to do this is to register a timer callback, that can be
671 done in GTK and Xt. But we have to do it like this when using only X
672 anyway, and with callbacks we would have three variants for timer handling
673 instead of the small ifdefs below. */
677 ! XtAppPending (Xt_app_con
)
678 #elif defined USE_GTK
679 ! gtk_events_pending ()
681 ! XPending ((Display
*) data
)
685 EMACS_TIME next_time
= timer_check (1);
686 long secs
= EMACS_SECS (next_time
);
687 long usecs
= EMACS_USECS (next_time
);
688 SELECT_TYPE read_fds
;
689 struct x_display_info
*dpyinfo
;
693 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
695 int fd
= ConnectionNumber (dpyinfo
->display
);
696 FD_SET (fd
, &read_fds
);
700 if (secs
< 0 || (secs
== 0 && usecs
== 0))
702 /* Sometimes timer_check returns -1 (no timers) even if there are
703 timers. So do a timeout anyway. */
704 EMACS_SET_SECS (next_time
, 1);
705 EMACS_SET_USECS (next_time
, 0);
708 select (n
+ 1, &read_fds
, (SELECT_TYPE
*)0, (SELECT_TYPE
*)0, &next_time
);
714 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
718 /* Loop in Xt until the menu pulldown or dialog popup has been
719 popped down (deactivated). This is used for x-popup-menu
720 and x-popup-dialog; it is not used for the menu bar.
722 NOTE: All calls to popup_get_selection should be protected
723 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
726 popup_get_selection (initial_event
, dpyinfo
, id
, do_timers
)
727 XEvent
*initial_event
;
728 struct x_display_info
*dpyinfo
;
734 while (popup_activated_flag
)
738 event
= *initial_event
;
743 if (do_timers
) x_menu_wait_for_event (0);
744 XtAppNextEvent (Xt_app_con
, &event
);
747 /* Make sure we don't consider buttons grabbed after menu goes.
748 And make sure to deactivate for any ButtonRelease,
749 even if XtDispatchEvent doesn't do that. */
750 if (event
.type
== ButtonRelease
751 && dpyinfo
->display
== event
.xbutton
.display
)
753 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
754 #ifdef USE_MOTIF /* Pretending that the event came from a
755 Btn1Down seems the only way to convince Motif to
756 activate its callbacks; setting the XmNmenuPost
757 isn't working. --marcus@sysc.pdx.edu. */
758 event
.xbutton
.button
= 1;
759 /* Motif only pops down menus when no Ctrl, Alt or Mod
760 key is pressed and the button is released. So reset key state
761 so Motif thinks this is the case. */
762 event
.xbutton
.state
= 0;
765 /* Pop down on C-g and Escape. */
766 else if (event
.type
== KeyPress
767 && dpyinfo
->display
== event
.xbutton
.display
)
769 KeySym keysym
= XLookupKeysym (&event
.xkey
, 0);
771 if ((keysym
== XK_g
&& (event
.xkey
.state
& ControlMask
) != 0)
772 || keysym
== XK_Escape
) /* Any escape, ignore modifiers. */
773 popup_activated_flag
= 0;
776 x_dispatch_event (&event
, event
.xany
.display
);
780 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
781 doc
: /* Start key navigation of the menu bar in FRAME.
782 This initially opens the first menu bar item and you can then navigate with the
783 arrow keys, select a menu entry with the return key or cancel with the
784 escape key. If FRAME has no menu bar this function does nothing.
786 If FRAME is nil or not given, use the selected frame. */)
791 FRAME_PTR f
= check_x_frame (frame
);
795 if (FRAME_EXTERNAL_MENU_BAR (f
))
796 set_frame_menubar (f
, 0, 1);
798 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
804 x_catch_errors (FRAME_X_DISPLAY (f
));
805 memset (&ev
, 0, sizeof ev
);
806 ev
.xbutton
.display
= FRAME_X_DISPLAY (f
);
807 ev
.xbutton
.window
= XtWindow (menubar
);
808 ev
.xbutton
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
809 ev
.xbutton
.time
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
810 ev
.xbutton
.button
= Button1
;
811 ev
.xbutton
.x
= ev
.xbutton
.y
= FRAME_MENUBAR_HEIGHT (f
) / 2;
812 ev
.xbutton
.same_screen
= True
;
819 XtSetArg (al
[0], XtNchildren
, &list
);
820 XtSetArg (al
[1], XtNnumChildren
, &nr
);
821 XtGetValues (menubar
, al
, 2);
822 ev
.xbutton
.window
= XtWindow (list
[0]);
826 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
827 /* From-window, to-window. */
828 ev
.xbutton
.window
, ev
.xbutton
.root
,
830 /* From-position, to-position. */
831 ev
.xbutton
.x
, ev
.xbutton
.y
,
832 &ev
.xbutton
.x_root
, &ev
.xbutton
.y_root
,
836 error_p
= x_had_errors_p (FRAME_X_DISPLAY (f
));
841 ev
.type
= ButtonPress
;
842 ev
.xbutton
.state
= 0;
844 XtDispatchEvent (&ev
);
845 ev
.xbutton
.type
= ButtonRelease
;
846 ev
.xbutton
.state
= Button1Mask
;
847 XtDispatchEvent (&ev
);
855 #endif /* USE_X_TOOLKIT */
859 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
860 doc
: /* Start key navigation of the menu bar in FRAME.
861 This initially opens the first menu bar item and you can then navigate with the
862 arrow keys, select a menu entry with the return key or cancel with the
863 escape key. If FRAME has no menu bar this function does nothing.
865 If FRAME is nil or not given, use the selected frame. */)
872 /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
876 f
= check_x_frame (frame
);
878 if (FRAME_EXTERNAL_MENU_BAR (f
))
879 set_frame_menubar (f
, 0, 1);
881 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
884 /* Activate the first menu. */
885 GList
*children
= gtk_container_get_children (GTK_CONTAINER (menubar
));
887 gtk_menu_shell_select_item (GTK_MENU_SHELL (menubar
),
888 GTK_WIDGET (children
->data
));
890 popup_activated_flag
= 1;
891 g_list_free (children
);
898 /* Loop util popup_activated_flag is set to zero in a callback.
899 Used for popup menus and dialogs. */
902 popup_widget_loop (do_timers
, widget
)
906 ++popup_activated_flag
;
908 /* Process events in the Gtk event loop until done. */
909 while (popup_activated_flag
)
911 if (do_timers
) x_menu_wait_for_event (0);
912 gtk_main_iteration ();
917 /* Activate the menu bar of frame F.
918 This is called from keyboard.c when it gets the
919 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
921 To activate the menu bar, we use the X button-press event
922 that was saved in saved_menu_event.
923 That makes the toolkit do its thing.
925 But first we recompute the menu bar contents (the whole tree).
927 The reason for saving the button event until here, instead of
928 passing it to the toolkit right away, is that we can safely
929 execute Lisp code. */
932 x_activate_menubar (f
)
938 if (!f
->output_data
.x
->saved_menu_event
->type
)
942 if (! xg_win_to_widget (FRAME_X_DISPLAY (f
),
943 f
->output_data
.x
->saved_menu_event
->xany
.window
))
947 set_frame_menubar (f
, 0, 1);
950 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
951 f
->output_data
.x
->saved_menu_event
);
952 popup_activated_flag
= 1;
954 XtDispatchEvent (f
->output_data
.x
->saved_menu_event
);
958 if (f
->output_data
.x
->saved_menu_event
->type
== ButtonRelease
)
959 pending_menu_activation
= 1;
962 /* Ignore this if we get it a second time. */
963 f
->output_data
.x
->saved_menu_event
->type
= 0;
966 /* This callback is invoked when the user selects a menubar cascade
967 pushbutton, but before the pulldown menu is posted. */
971 popup_activate_callback (widget
, id
, client_data
)
974 XtPointer client_data
;
976 popup_activated_flag
= 1;
978 x_activate_timeout_atimer ();
983 /* This callback is invoked when a dialog or menu is finished being
984 used and has been unposted. */
988 popup_deactivate_callback (widget
, client_data
)
990 gpointer client_data
;
992 popup_activated_flag
= 0;
996 popup_deactivate_callback (widget
, id
, client_data
)
999 XtPointer client_data
;
1001 popup_activated_flag
= 0;
1006 /* Function that finds the frame for WIDGET and shows the HELP text
1008 F is the frame if known, or NULL if not known. */
1010 show_help_event (f
, widget
, help
)
1012 xt_or_gtk_widget widget
;
1019 XSETFRAME (frame
, f
);
1020 kbd_buffer_store_help_event (frame
, help
);
1024 #if 0 /* This code doesn't do anything useful. ++kfs */
1025 /* WIDGET is the popup menu. It's parent is the frame's
1026 widget. See which frame that is. */
1027 xt_or_gtk_widget frame_widget
= XtParent (widget
);
1030 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1032 frame
= XCAR (tail
);
1034 && (f
= XFRAME (frame
),
1035 FRAME_X_P (f
) && f
->output_data
.x
->widget
== frame_widget
))
1039 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
1043 /* Callback called when menu items are highlighted/unhighlighted
1044 while moving the mouse over them. WIDGET is the menu bar or menu
1045 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
1046 the data structure for the menu item, or null in case of
1051 menu_highlight_callback (widget
, call_data
)
1055 xg_menu_item_cb_data
*cb_data
;
1058 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (widget
),
1060 if (! cb_data
) return;
1062 help
= call_data
? cb_data
->help
: Qnil
;
1064 /* If popup_activated_flag is greater than 1 we are in a popup menu.
1065 Don't show help for them, they won't appear before the
1066 popup is popped down. */
1067 if (popup_activated_flag
<= 1)
1068 show_help_event (cb_data
->cl_data
->f
, widget
, help
);
1072 menu_highlight_callback (widget
, id
, call_data
)
1080 widget_value
*wv
= (widget_value
*) call_data
;
1082 help
= wv
? wv
->help
: Qnil
;
1084 /* Determine the frame for the help event. */
1085 f
= menubar_id_to_frame (id
);
1087 show_help_event (f
, widget
, help
);
1092 /* Gtk calls callbacks just because we tell it what item should be
1093 selected in a radio group. If this variable is set to a non-zero
1094 value, we are creating menus and don't want callbacks right now.
1096 static int xg_crazy_callback_abort
;
1098 /* This callback is called from the menu bar pulldown menu
1099 when the user makes a selection.
1100 Figure out what the user chose
1101 and put the appropriate events into the keyboard buffer. */
1103 menubar_selection_callback (widget
, client_data
)
1105 gpointer client_data
;
1107 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1109 if (xg_crazy_callback_abort
)
1112 if (! cb_data
|| ! cb_data
->cl_data
|| ! cb_data
->cl_data
->f
)
1115 /* For a group of radio buttons, GTK calls the selection callback first
1116 for the item that was active before the selection and then for the one that
1117 is active after the selection. For C-h k this means we get the help on
1118 the deselected item and then the selected item is executed. Prevent that
1119 by ignoring the non-active item. */
1120 if (GTK_IS_RADIO_MENU_ITEM (widget
)
1121 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget
)))
1124 /* When a menu is popped down, X generates a focus event (i.e. focus
1125 goes back to the frame below the menu). Since GTK buffers events,
1126 we force it out here before the menu selection event. Otherwise
1127 sit-for will exit at once if the focus event follows the menu selection
1131 while (gtk_events_pending ())
1132 gtk_main_iteration ();
1135 find_and_call_menu_selection (cb_data
->cl_data
->f
,
1136 cb_data
->cl_data
->menu_bar_items_used
,
1137 cb_data
->cl_data
->menu_bar_vector
,
1138 cb_data
->call_data
);
1141 #else /* not USE_GTK */
1143 /* This callback is called from the menu bar pulldown menu
1144 when the user makes a selection.
1145 Figure out what the user chose
1146 and put the appropriate events into the keyboard buffer. */
1148 menubar_selection_callback (widget
, id
, client_data
)
1151 XtPointer client_data
;
1155 f
= menubar_id_to_frame (id
);
1158 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
1159 f
->menu_bar_vector
, client_data
);
1161 #endif /* not USE_GTK */
1163 /* Recompute all the widgets of frame F, when the menu bar has been
1164 changed. Value is non-zero if widgets were updated. */
1167 update_frame_menubar (f
)
1171 return xg_update_frame_menubar (f
);
1176 if (! FRAME_X_P (f
))
1179 x
= f
->output_data
.x
;
1181 if (!x
->menubar_widget
|| XtIsManaged (x
->menubar_widget
))
1185 /* Save the size of the frame because the pane widget doesn't accept
1186 to resize itself. So force it. */
1187 columns
= FRAME_COLS (f
);
1188 rows
= FRAME_LINES (f
);
1190 /* Do the voodoo which means "I'm changing lots of things, don't try
1191 to refigure sizes until I'm done." */
1192 lw_refigure_widget (x
->column_widget
, False
);
1194 /* The order in which children are managed is the top to bottom
1195 order in which they are displayed in the paned window. First,
1196 remove the text-area widget. */
1197 XtUnmanageChild (x
->edit_widget
);
1199 /* Remove the menubar that is there now, and put up the menubar that
1201 XtManageChild (x
->menubar_widget
);
1202 XtMapWidget (x
->menubar_widget
);
1203 XtVaSetValues (x
->menubar_widget
, XtNmappedWhenManaged
, 1, NULL
);
1205 /* Re-manage the text-area widget, and then thrash the sizes. */
1206 XtManageChild (x
->edit_widget
);
1207 lw_refigure_widget (x
->column_widget
, True
);
1209 /* Force the pane widget to resize itself with the right values. */
1210 EmacsFrameSetCharSize (x
->edit_widget
, columns
, rows
);
1216 /* Set the contents of the menubar widgets of frame F.
1217 The argument FIRST_TIME is currently ignored;
1218 it is set the first time this is called, from initialize_frame_menubar. */
1221 set_frame_menubar (f
, first_time
, deep_p
)
1226 xt_or_gtk_widget menubar_widget
;
1227 #ifdef USE_X_TOOLKIT
1231 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
1233 int *submenu_start
, *submenu_end
;
1234 int *submenu_top_level_items
, *submenu_n_panes
;
1236 if (! FRAME_X_P (f
))
1239 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1241 XSETFRAME (Vmenu_updating_frame
, f
);
1243 #ifdef USE_X_TOOLKIT
1244 if (f
->output_data
.x
->id
== 0)
1245 f
->output_data
.x
->id
= next_menubar_widget_id
++;
1246 id
= f
->output_data
.x
->id
;
1249 if (! menubar_widget
)
1251 else if (pending_menu_activation
&& !deep_p
)
1253 /* Make the first call for any given frame always go deep. */
1254 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
1257 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
1258 f
->output_data
.x
->saved_menu_event
->type
= 0;
1262 /* If we have detached menus, we must update deep so detached menus
1263 also gets updated. */
1264 deep_p
= deep_p
|| xg_have_tear_offs ();
1269 /* Make a widget-value tree representing the entire menu trees. */
1271 struct buffer
*prev
= current_buffer
;
1273 int specpdl_count
= SPECPDL_INDEX ();
1274 int previous_menu_items_used
= f
->menu_bar_items_used
;
1275 Lisp_Object
*previous_items
1276 = (Lisp_Object
*) alloca (previous_menu_items_used
1277 * sizeof (Lisp_Object
));
1279 /* If we are making a new widget, its contents are empty,
1280 do always reinitialize them. */
1281 if (! menubar_widget
)
1282 previous_menu_items_used
= 0;
1284 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1285 specbind (Qinhibit_quit
, Qt
);
1286 /* Don't let the debugger step into this code
1287 because it is not reentrant. */
1288 specbind (Qdebug_on_next_call
, Qnil
);
1290 record_unwind_save_match_data ();
1291 if (NILP (Voverriding_local_map_menu_flag
))
1293 specbind (Qoverriding_terminal_local_map
, Qnil
);
1294 specbind (Qoverriding_local_map
, Qnil
);
1297 set_buffer_internal_1 (XBUFFER (buffer
));
1299 /* Run the Lucid hook. */
1300 safe_run_hooks (Qactivate_menubar_hook
);
1302 /* If it has changed current-menubar from previous value,
1303 really recompute the menubar from the value. */
1304 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1305 call0 (Qrecompute_lucid_menubar
);
1306 safe_run_hooks (Qmenu_bar_update_hook
);
1307 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1309 items
= FRAME_MENU_BAR_ITEMS (f
);
1311 /* Save the frame's previous menu bar contents data. */
1312 if (previous_menu_items_used
)
1313 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
1314 previous_menu_items_used
* sizeof (Lisp_Object
));
1316 /* Fill in menu_items with the current menu bar contents.
1317 This can evaluate Lisp code. */
1320 menu_items
= f
->menu_bar_vector
;
1321 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1322 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1323 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1324 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
1325 submenu_top_level_items
1326 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
1328 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1330 Lisp_Object key
, string
, maps
;
1334 key
= XVECTOR (items
)->contents
[i
];
1335 string
= XVECTOR (items
)->contents
[i
+ 1];
1336 maps
= XVECTOR (items
)->contents
[i
+ 2];
1340 submenu_start
[i
] = menu_items_used
;
1342 menu_items_n_panes
= 0;
1343 submenu_top_level_items
[i
]
1344 = parse_single_submenu (key
, string
, maps
);
1345 submenu_n_panes
[i
] = menu_items_n_panes
;
1347 submenu_end
[i
] = menu_items_used
;
1350 finish_menu_items ();
1352 /* Convert menu_items into widget_value trees
1353 to display the menu. This cannot evaluate Lisp code. */
1355 wv
= xmalloc_widget_value ();
1356 wv
->name
= "menubar";
1359 wv
->button_type
= BUTTON_TYPE_NONE
;
1363 for (i
= 0; i
< last_i
; i
+= 4)
1365 menu_items_n_panes
= submenu_n_panes
[i
];
1366 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
1367 submenu_top_level_items
[i
]);
1371 first_wv
->contents
= wv
;
1372 /* Don't set wv->name here; GC during the loop might relocate it. */
1374 wv
->button_type
= BUTTON_TYPE_NONE
;
1378 set_buffer_internal_1 (prev
);
1380 /* If there has been no change in the Lisp-level contents
1381 of the menu bar, skip redisplaying it. Just exit. */
1383 /* Compare the new menu items with the ones computed last time. */
1384 for (i
= 0; i
< previous_menu_items_used
; i
++)
1385 if (menu_items_used
== i
1386 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1388 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1390 /* The menu items have not changed. Don't bother updating
1391 the menus in any form, since it would be a no-op. */
1392 free_menubar_widget_value_tree (first_wv
);
1393 discard_menu_items ();
1394 unbind_to (specpdl_count
, Qnil
);
1398 /* The menu items are different, so store them in the frame. */
1399 f
->menu_bar_vector
= menu_items
;
1400 f
->menu_bar_items_used
= menu_items_used
;
1402 /* This undoes save_menu_items. */
1403 unbind_to (specpdl_count
, Qnil
);
1405 /* Now GC cannot happen during the lifetime of the widget_value,
1406 so it's safe to store data from a Lisp_String. */
1407 wv
= first_wv
->contents
;
1408 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1411 string
= XVECTOR (items
)->contents
[i
+ 1];
1414 wv
->name
= (char *) SDATA (string
);
1415 update_submenu_strings (wv
->contents
);
1422 /* Make a widget-value tree containing
1423 just the top level menu bar strings. */
1425 wv
= xmalloc_widget_value ();
1426 wv
->name
= "menubar";
1429 wv
->button_type
= BUTTON_TYPE_NONE
;
1433 items
= FRAME_MENU_BAR_ITEMS (f
);
1434 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1438 string
= XVECTOR (items
)->contents
[i
+ 1];
1442 wv
= xmalloc_widget_value ();
1443 wv
->name
= (char *) SDATA (string
);
1446 wv
->button_type
= BUTTON_TYPE_NONE
;
1448 /* This prevents lwlib from assuming this
1449 menu item is really supposed to be empty. */
1450 /* The EMACS_INT cast avoids a warning.
1451 This value just has to be different from small integers. */
1452 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1457 first_wv
->contents
= wv
;
1461 /* Forget what we thought we knew about what is in the
1462 detailed contents of the menu bar menus.
1463 Changing the top level always destroys the contents. */
1464 f
->menu_bar_items_used
= 0;
1467 /* Create or update the menu bar widget. */
1472 xg_crazy_callback_abort
= 1;
1475 /* The fourth arg is DEEP_P, which says to consider the entire
1476 menu trees we supply, rather than just the menu bar item names. */
1477 xg_modify_menubar_widgets (menubar_widget
,
1481 G_CALLBACK (menubar_selection_callback
),
1482 G_CALLBACK (popup_deactivate_callback
),
1483 G_CALLBACK (menu_highlight_callback
));
1487 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
1490 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
1491 G_CALLBACK (menubar_selection_callback
),
1492 G_CALLBACK (popup_deactivate_callback
),
1493 G_CALLBACK (menu_highlight_callback
));
1495 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1499 #else /* not USE_GTK */
1502 /* Disable resizing (done for Motif!) */
1503 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
1505 /* The third arg is DEEP_P, which says to consider the entire
1506 menu trees we supply, rather than just the menu bar item names. */
1507 lw_modify_all_widgets (id
, first_wv
, deep_p
);
1509 /* Re-enable the edit widget to resize. */
1510 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
1514 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1515 XtTranslations override
= XtParseTranslationTable (menuOverride
);
1517 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
1518 f
->output_data
.x
->column_widget
,
1520 popup_activate_callback
,
1521 menubar_selection_callback
,
1522 popup_deactivate_callback
,
1523 menu_highlight_callback
);
1524 f
->output_data
.x
->menubar_widget
= menubar_widget
;
1526 /* Make menu pop down on C-g. */
1527 XtOverrideTranslations (menubar_widget
, override
);
1532 = (f
->output_data
.x
->menubar_widget
1533 ? (f
->output_data
.x
->menubar_widget
->core
.height
1534 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
1537 #if 0 /* Experimentally, we now get the right results
1538 for -geometry -0-0 without this. 24 Aug 96, rms. */
1540 if (FRAME_EXTERNAL_MENU_BAR (f
))
1543 XtVaGetValues (f
->output_data
.x
->column_widget
,
1544 XtNinternalBorderWidth
, &ibw
, NULL
);
1545 menubar_size
+= ibw
;
1547 #endif /* USE_LUCID */
1550 f
->output_data
.x
->menubar_height
= menubar_size
;
1552 #endif /* not USE_GTK */
1554 free_menubar_widget_value_tree (first_wv
);
1555 update_frame_menubar (f
);
1558 xg_crazy_callback_abort
= 0;
1564 /* Called from Fx_create_frame to create the initial menubar of a frame
1565 before it is mapped, so that the window is mapped with the menubar already
1566 there instead of us tacking it on later and thrashing the window after it
1570 initialize_frame_menubar (f
)
1573 /* This function is called before the first chance to redisplay
1574 the frame. It has to be, so the frame will have the right size. */
1575 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1576 set_frame_menubar (f
, 1, 1);
1580 /* Get rid of the menu bar of frame F, and free its storage.
1581 This is used when deleting a frame, and when turning off the menu bar.
1582 For GTK this function is in gtkutil.c. */
1586 free_frame_menubar (f
)
1589 Widget menubar_widget
;
1591 if (! FRAME_X_P (f
))
1594 menubar_widget
= f
->output_data
.x
->menubar_widget
;
1596 f
->output_data
.x
->menubar_height
= 0;
1601 /* Removing the menu bar magically changes the shell widget's x
1602 and y position of (0, 0) which, when the menu bar is turned
1603 on again, leads to pull-down menuss appearing in strange
1604 positions near the upper-left corner of the display. This
1605 happens only with some window managers like twm and ctwm,
1606 but not with other like Motif's mwm or kwm, because the
1607 latter generate ConfigureNotify events when the menu bar
1608 is switched off, which fixes the shell position. */
1609 Position x0
, y0
, x1
, y1
;
1615 if (f
->output_data
.x
->widget
)
1616 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
1619 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
1620 f
->output_data
.x
->menubar_widget
= NULL
;
1623 if (f
->output_data
.x
->widget
)
1625 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
1626 if (x1
== 0 && y1
== 0)
1627 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
1634 #endif /* not USE_GTK */
1636 #endif /* USE_X_TOOLKIT || USE_GTK */
1638 /* xmenu_show actually displays a menu using the panes and items in menu_items
1639 and returns the value selected from it.
1640 There are two versions of xmenu_show, one for Xt and one for Xlib.
1641 Both assume input is blocked by the caller. */
1643 /* F is the frame the menu is for.
1644 X and Y are the frame-relative specified position,
1645 relative to the inside upper left corner of the frame F.
1646 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1647 KEYMAPS is 1 if this menu was specified with keymaps;
1648 in that case, we return a list containing the chosen item's value
1649 and perhaps also the pane's prefix.
1650 TITLE is the specified menu title.
1651 ERROR is a place to store an error message string in case of failure.
1652 (We return nil on failure, but the value doesn't actually matter.) */
1654 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1656 /* The item selected in the popup menu. */
1657 static Lisp_Object
*volatile menu_item_selection
;
1661 /* Used when position a popup menu. See menu_position_func and
1662 create_and_show_popup_menu below. */
1663 struct next_popup_x_y
1670 /* The menu position function to use if we are not putting a popup
1671 menu where the pointer is.
1672 MENU is the menu to pop up.
1673 X and Y shall on exit contain x/y where the menu shall pop up.
1674 PUSH_IN is not documented in the GTK manual.
1675 USER_DATA is any data passed in when calling gtk_menu_popup.
1676 Here it points to a struct next_popup_x_y where the coordinates
1677 to store in *X and *Y are as well as the frame for the popup.
1679 Here only X and Y are used. */
1681 menu_position_func (menu
, x
, y
, push_in
, user_data
)
1688 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
1690 int disp_width
= FRAME_X_DISPLAY_INFO (data
->f
)->width
;
1691 int disp_height
= FRAME_X_DISPLAY_INFO (data
->f
)->height
;
1696 /* Check if there is room for the menu. If not, adjust x/y so that
1697 the menu is fully visible. */
1698 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
1699 if (data
->x
+ req
.width
> disp_width
)
1700 *x
-= data
->x
+ req
.width
- disp_width
;
1701 if (data
->y
+ req
.height
> disp_height
)
1702 *y
-= data
->y
+ req
.height
- disp_height
;
1706 popup_selection_callback (widget
, client_data
)
1708 gpointer client_data
;
1710 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1712 if (xg_crazy_callback_abort
) return;
1713 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
1720 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
1722 popup_activated_flag
= 0;
1724 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
1729 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1731 menu_item_selection will be set to the selection. */
1733 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
)
1735 widget_value
*first_wv
;
1742 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
1743 struct next_popup_x_y popup_x_y
;
1744 int specpdl_count
= SPECPDL_INDEX ();
1746 if (! FRAME_X_P (f
))
1749 xg_crazy_callback_abort
= 1;
1750 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
1751 G_CALLBACK (popup_selection_callback
),
1752 G_CALLBACK (popup_deactivate_callback
),
1753 G_CALLBACK (menu_highlight_callback
));
1754 xg_crazy_callback_abort
= 0;
1758 /* Not invoked by a click. pop up at x/y. */
1759 pos_func
= menu_position_func
;
1761 /* Adjust coordinates to be root-window-relative. */
1762 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1763 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1769 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
1773 for (i
= 0; i
< 5; i
++)
1774 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1778 /* Display the menu. */
1779 gtk_widget_show_all (menu
);
1780 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
, 0);
1782 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
1784 if (GTK_WIDGET_MAPPED (menu
))
1786 /* Set this to one. popup_widget_loop increases it by one, so it becomes
1787 two. show_help_echo uses this to detect popup menus. */
1788 popup_activated_flag
= 1;
1789 /* Process events that apply to the menu. */
1790 popup_widget_loop (1, menu
);
1793 unbind_to (specpdl_count
, Qnil
);
1795 /* Must reset this manually because the button release event is not passed
1796 to Emacs event loop. */
1797 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1800 #else /* not USE_GTK */
1802 /* We need a unique id for each widget handled by the Lucid Widget
1805 For the main windows, and popup menus, we use this counter,
1806 which we increment each time after use. This starts from 1<<16.
1808 For menu bars, we use numbers starting at 0, counted in
1809 next_menubar_widget_id. */
1810 LWLIB_ID widget_id_tick
;
1813 popup_selection_callback (widget
, id
, client_data
)
1816 XtPointer client_data
;
1818 menu_item_selection
= (Lisp_Object
*) client_data
;
1821 /* ARG is the LWLIB ID of the dialog box, represented
1822 as a Lisp object as (HIGHPART . LOWPART). */
1828 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
1829 | XINT (XCDR (arg
)));
1832 lw_destroy_all_widgets (id
);
1834 popup_activated_flag
= 0;
1839 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1841 menu_item_selection will be set to the selection. */
1843 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
)
1845 widget_value
*first_wv
;
1853 XButtonPressedEvent dummy
;
1857 if (! FRAME_X_P (f
))
1860 menu_id
= widget_id_tick
++;
1861 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
1862 f
->output_data
.x
->widget
, 1, 0,
1863 popup_selection_callback
,
1864 popup_deactivate_callback
,
1865 menu_highlight_callback
);
1867 dummy
.type
= ButtonPress
;
1869 dummy
.send_event
= 0;
1870 dummy
.display
= FRAME_X_DISPLAY (f
);
1871 dummy
.time
= CurrentTime
;
1872 dummy
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1873 dummy
.window
= dummy
.root
;
1874 dummy
.subwindow
= dummy
.root
;
1878 /* Adjust coordinates to be root-window-relative. */
1879 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1880 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1887 for (i
= 0; i
< 5; i
++)
1888 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
1891 /* Don't allow any geometry request from the user. */
1892 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
1893 XtSetValues (menu
, av
, ac
);
1895 /* Display the menu. */
1896 lw_popup_menu (menu
, (XEvent
*) &dummy
);
1897 popup_activated_flag
= 1;
1898 x_activate_timeout_atimer ();
1901 int fact
= 4 * sizeof (LWLIB_ID
);
1902 int specpdl_count
= SPECPDL_INDEX ();
1903 record_unwind_protect (pop_down_menu
,
1904 Fcons (make_number (menu_id
>> (fact
)),
1905 make_number (menu_id
& ~(-1 << (fact
)))));
1907 /* Process events that apply to the menu. */
1908 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
1910 unbind_to (specpdl_count
, Qnil
);
1914 #endif /* not USE_GTK */
1917 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
1927 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1928 widget_value
**submenu_stack
1929 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1930 Lisp_Object
*subprefix_stack
1931 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1932 int submenu_depth
= 0;
1936 if (! FRAME_X_P (f
))
1941 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1943 *error
= "Empty menu";
1947 /* Create a tree of widget_value objects
1948 representing the panes and their items. */
1949 wv
= xmalloc_widget_value ();
1953 wv
->button_type
= BUTTON_TYPE_NONE
;
1958 /* Loop over all panes and items, filling in the tree. */
1960 while (i
< menu_items_used
)
1962 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1964 submenu_stack
[submenu_depth
++] = save_wv
;
1970 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1973 save_wv
= submenu_stack
[--submenu_depth
];
1977 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1978 && submenu_depth
!= 0)
1979 i
+= MENU_ITEMS_PANE_LENGTH
;
1980 /* Ignore a nil in the item list.
1981 It's meaningful only for dialog boxes. */
1982 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1984 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1986 /* Create a new pane. */
1987 Lisp_Object pane_name
, prefix
;
1990 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1991 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1993 #ifndef HAVE_MULTILINGUAL_MENU
1994 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1996 pane_name
= ENCODE_MENU_STRING (pane_name
);
1997 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
2000 pane_string
= (NILP (pane_name
)
2001 ? "" : (char *) SDATA (pane_name
));
2002 /* If there is just one top-level pane, put all its items directly
2003 under the top-level menu. */
2004 if (menu_items_n_panes
== 1)
2007 /* If the pane has a meaningful name,
2008 make the pane a top-level menu item
2009 with its items as a submenu beneath it. */
2010 if (!keymaps
&& strcmp (pane_string
, ""))
2012 wv
= xmalloc_widget_value ();
2016 first_wv
->contents
= wv
;
2017 wv
->name
= pane_string
;
2018 if (keymaps
&& !NILP (prefix
))
2022 wv
->button_type
= BUTTON_TYPE_NONE
;
2027 else if (first_pane
)
2033 i
+= MENU_ITEMS_PANE_LENGTH
;
2037 /* Create a new item within current pane. */
2038 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
2039 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
2040 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
2041 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
2042 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
2043 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
2044 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
2045 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
2047 #ifndef HAVE_MULTILINGUAL_MENU
2048 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
2050 item_name
= ENCODE_MENU_STRING (item_name
);
2051 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
2054 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
2056 descrip
= ENCODE_MENU_STRING (descrip
);
2057 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
2059 #endif /* not HAVE_MULTILINGUAL_MENU */
2061 wv
= xmalloc_widget_value ();
2065 save_wv
->contents
= wv
;
2066 wv
->name
= (char *) SDATA (item_name
);
2067 if (!NILP (descrip
))
2068 wv
->key
= (char *) SDATA (descrip
);
2070 /* If this item has a null value,
2071 make the call_data null so that it won't display a box
2072 when the mouse is on it. */
2074 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
2075 wv
->enabled
= !NILP (enable
);
2078 wv
->button_type
= BUTTON_TYPE_NONE
;
2079 else if (EQ (type
, QCtoggle
))
2080 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
2081 else if (EQ (type
, QCradio
))
2082 wv
->button_type
= BUTTON_TYPE_RADIO
;
2086 wv
->selected
= !NILP (selected
);
2088 if (! STRINGP (help
))
2095 i
+= MENU_ITEMS_ITEM_LENGTH
;
2099 /* Deal with the title, if it is non-nil. */
2102 widget_value
*wv_title
= xmalloc_widget_value ();
2103 widget_value
*wv_sep1
= xmalloc_widget_value ();
2104 widget_value
*wv_sep2
= xmalloc_widget_value ();
2106 wv_sep2
->name
= "--";
2107 wv_sep2
->next
= first_wv
->contents
;
2108 wv_sep2
->help
= Qnil
;
2110 wv_sep1
->name
= "--";
2111 wv_sep1
->next
= wv_sep2
;
2112 wv_sep1
->help
= Qnil
;
2114 #ifndef HAVE_MULTILINGUAL_MENU
2115 if (STRING_MULTIBYTE (title
))
2116 title
= ENCODE_MENU_STRING (title
);
2119 wv_title
->name
= (char *) SDATA (title
);
2120 wv_title
->enabled
= TRUE
;
2121 wv_title
->button_type
= BUTTON_TYPE_NONE
;
2122 wv_title
->help
= Qnil
;
2123 wv_title
->next
= wv_sep1
;
2124 first_wv
->contents
= wv_title
;
2127 /* No selection has been chosen yet. */
2128 menu_item_selection
= 0;
2130 /* Actually create and show the menu until popped down. */
2131 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
);
2133 /* Free the widget_value objects we used to specify the contents. */
2134 free_menubar_widget_value_tree (first_wv
);
2136 /* Find the selected item, and its pane, to return
2137 the proper value. */
2138 if (menu_item_selection
!= 0)
2140 Lisp_Object prefix
, entry
;
2142 prefix
= entry
= Qnil
;
2144 while (i
< menu_items_used
)
2146 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
2148 subprefix_stack
[submenu_depth
++] = prefix
;
2152 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
2154 prefix
= subprefix_stack
[--submenu_depth
];
2157 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2160 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2161 i
+= MENU_ITEMS_PANE_LENGTH
;
2163 /* Ignore a nil in the item list.
2164 It's meaningful only for dialog boxes. */
2165 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2170 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2171 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2177 entry
= Fcons (entry
, Qnil
);
2179 entry
= Fcons (prefix
, entry
);
2180 for (j
= submenu_depth
- 1; j
>= 0; j
--)
2181 if (!NILP (subprefix_stack
[j
]))
2182 entry
= Fcons (subprefix_stack
[j
], entry
);
2186 i
+= MENU_ITEMS_ITEM_LENGTH
;
2190 else if (!for_click
)
2191 /* Make "Cancel" equivalent to C-g. */
2192 Fsignal (Qquit
, Qnil
);
2199 dialog_selection_callback (widget
, client_data
)
2201 gpointer client_data
;
2203 /* The EMACS_INT cast avoids a warning. There's no problem
2204 as long as pointers have enough bits to hold small integers. */
2205 if ((int) (EMACS_INT
) client_data
!= -1)
2206 menu_item_selection
= (Lisp_Object
*) client_data
;
2208 popup_activated_flag
= 0;
2211 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2213 menu_item_selection will be set to the selection. */
2215 create_and_show_dialog (f
, first_wv
)
2217 widget_value
*first_wv
;
2221 if (! FRAME_X_P (f
))
2224 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
2225 G_CALLBACK (dialog_selection_callback
),
2226 G_CALLBACK (popup_deactivate_callback
),
2231 int specpdl_count
= SPECPDL_INDEX ();
2232 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
2234 /* Display the menu. */
2235 gtk_widget_show_all (menu
);
2237 /* Process events that apply to the menu. */
2238 popup_widget_loop (1, menu
);
2240 unbind_to (specpdl_count
, Qnil
);
2244 #else /* not USE_GTK */
2246 dialog_selection_callback (widget
, id
, client_data
)
2249 XtPointer client_data
;
2251 /* The EMACS_INT cast avoids a warning. There's no problem
2252 as long as pointers have enough bits to hold small integers. */
2253 if ((int) (EMACS_INT
) client_data
!= -1)
2254 menu_item_selection
= (Lisp_Object
*) client_data
;
2257 lw_destroy_all_widgets (id
);
2259 popup_activated_flag
= 0;
2263 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2265 menu_item_selection will be set to the selection. */
2267 create_and_show_dialog (f
, first_wv
)
2269 widget_value
*first_wv
;
2276 dialog_id
= widget_id_tick
++;
2277 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
2278 f
->output_data
.x
->widget
, 1, 0,
2279 dialog_selection_callback
, 0, 0);
2280 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
2282 /* Display the dialog box. */
2283 lw_pop_up_all_widgets (dialog_id
);
2284 popup_activated_flag
= 1;
2285 x_activate_timeout_atimer ();
2287 /* Process events that apply to the dialog box.
2288 Also handle timers. */
2290 int count
= SPECPDL_INDEX ();
2291 int fact
= 4 * sizeof (LWLIB_ID
);
2293 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2294 record_unwind_protect (pop_down_menu
,
2295 Fcons (make_number (dialog_id
>> (fact
)),
2296 make_number (dialog_id
& ~(-1 << (fact
)))));
2298 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
2301 unbind_to (count
, Qnil
);
2305 #endif /* not USE_GTK */
2307 static char * button_names
[] = {
2308 "button1", "button2", "button3", "button4", "button5",
2309 "button6", "button7", "button8", "button9", "button10" };
2312 xdialog_show (f
, keymaps
, title
, header
, error_name
)
2315 Lisp_Object title
, header
;
2318 int i
, nb_buttons
=0;
2319 char dialog_name
[6];
2321 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
2323 /* Number of elements seen so far, before boundary. */
2325 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2326 int boundary_seen
= 0;
2328 if (! FRAME_X_P (f
))
2333 if (menu_items_n_panes
> 1)
2335 *error_name
= "Multiple panes in dialog box";
2339 /* Create a tree of widget_value objects
2340 representing the text label and buttons. */
2342 Lisp_Object pane_name
, prefix
;
2344 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
2345 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
2346 pane_string
= (NILP (pane_name
)
2347 ? "" : (char *) SDATA (pane_name
));
2348 prev_wv
= xmalloc_widget_value ();
2349 prev_wv
->value
= pane_string
;
2350 if (keymaps
&& !NILP (prefix
))
2352 prev_wv
->enabled
= 1;
2353 prev_wv
->name
= "message";
2354 prev_wv
->help
= Qnil
;
2357 /* Loop over all panes and items, filling in the tree. */
2358 i
= MENU_ITEMS_PANE_LENGTH
;
2359 while (i
< menu_items_used
)
2362 /* Create a new item within current pane. */
2363 Lisp_Object item_name
, enable
, descrip
;
2364 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2365 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2367 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2369 if (NILP (item_name
))
2371 free_menubar_widget_value_tree (first_wv
);
2372 *error_name
= "Submenu in dialog items";
2375 if (EQ (item_name
, Qquote
))
2377 /* This is the boundary between left-side elts
2378 and right-side elts. Stop incrementing right_count. */
2383 if (nb_buttons
>= 9)
2385 free_menubar_widget_value_tree (first_wv
);
2386 *error_name
= "Too many dialog items";
2390 wv
= xmalloc_widget_value ();
2392 wv
->name
= (char *) button_names
[nb_buttons
];
2393 if (!NILP (descrip
))
2394 wv
->key
= (char *) SDATA (descrip
);
2395 wv
->value
= (char *) SDATA (item_name
);
2396 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
2397 wv
->enabled
= !NILP (enable
);
2401 if (! boundary_seen
)
2405 i
+= MENU_ITEMS_ITEM_LENGTH
;
2408 /* If the boundary was not specified,
2409 by default put half on the left and half on the right. */
2410 if (! boundary_seen
)
2411 left_count
= nb_buttons
- nb_buttons
/ 2;
2413 wv
= xmalloc_widget_value ();
2414 wv
->name
= dialog_name
;
2417 /* Frame title: 'Q' = Question, 'I' = Information.
2418 Can also have 'E' = Error if, one day, we want
2419 a popup for errors. */
2421 dialog_name
[0] = 'Q';
2423 dialog_name
[0] = 'I';
2425 /* Dialog boxes use a really stupid name encoding
2426 which specifies how many buttons to use
2427 and how many buttons are on the right. */
2428 dialog_name
[1] = '0' + nb_buttons
;
2429 dialog_name
[2] = 'B';
2430 dialog_name
[3] = 'R';
2431 /* Number of buttons to put on the right. */
2432 dialog_name
[4] = '0' + nb_buttons
- left_count
;
2434 wv
->contents
= first_wv
;
2438 /* No selection has been chosen yet. */
2439 menu_item_selection
= 0;
2441 /* Force a redisplay before showing the dialog. If a frame is created
2442 just before showing the dialog, its contents may not have been fully
2443 drawn, as this depends on timing of events from the X server. Redisplay
2444 is not done when a dialog is shown. If redisplay could be done in the
2445 X event loop (i.e. the X event loop does not run in a signal handler)
2446 this would not be needed. */
2449 /* Actually create and show the dialog. */
2450 create_and_show_dialog (f
, first_wv
);
2452 /* Free the widget_value objects we used to specify the contents. */
2453 free_menubar_widget_value_tree (first_wv
);
2455 /* Find the selected item, and its pane, to return
2456 the proper value. */
2457 if (menu_item_selection
!= 0)
2463 while (i
< menu_items_used
)
2467 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2470 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2471 i
+= MENU_ITEMS_PANE_LENGTH
;
2473 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2475 /* This is the boundary between left-side elts and
2482 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2483 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
2487 entry
= Fcons (entry
, Qnil
);
2489 entry
= Fcons (prefix
, entry
);
2493 i
+= MENU_ITEMS_ITEM_LENGTH
;
2498 /* Make "Cancel" equivalent to C-g. */
2499 Fsignal (Qquit
, Qnil
);
2504 #else /* not USE_X_TOOLKIT && not USE_GTK */
2506 /* The frame of the last activated non-toolkit menu bar.
2507 Used to generate menu help events. */
2509 static struct frame
*menu_help_frame
;
2512 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2514 PANE is the pane number, and ITEM is the menu item number in
2515 the menu (currently not used).
2517 This cannot be done with generating a HELP_EVENT because
2518 XMenuActivate contains a loop that doesn't let Emacs process
2522 menu_help_callback (help_string
, pane
, item
)
2526 extern Lisp_Object Qmenu_item
;
2527 Lisp_Object
*first_item
;
2528 Lisp_Object pane_name
;
2529 Lisp_Object menu_object
;
2531 first_item
= XVECTOR (menu_items
)->contents
;
2532 if (EQ (first_item
[0], Qt
))
2533 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
2534 else if (EQ (first_item
[0], Qquote
))
2535 /* This shouldn't happen, see xmenu_show. */
2536 pane_name
= empty_unibyte_string
;
2538 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
2540 /* (menu-item MENU-NAME PANE-NUMBER) */
2541 menu_object
= Fcons (Qmenu_item
,
2543 Fcons (make_number (pane
), Qnil
)));
2544 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
2545 Qnil
, menu_object
, make_number (item
), 1);
2552 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
2553 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
2555 FRAME_PTR f
= p1
->pointer
;
2556 XMenu
*menu
= p2
->pointer
;
2560 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
2561 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
2563 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2565 #ifdef HAVE_X_WINDOWS
2566 /* Assume the mouse has moved out of the X window.
2567 If it has actually moved in, we will get an EnterNotify. */
2568 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
2570 /* State that no mouse buttons are now held.
2571 (The oldXMenu code doesn't track this info for us.)
2572 That is not necessarily true, but the fiction leads to reasonable
2573 results, and it is a pain to ask which are actually held now. */
2574 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2576 #endif /* HAVE_X_WINDOWS */
2585 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
2595 int pane
, selidx
, lpane
, status
;
2596 Lisp_Object entry
, pane_prefix
;
2598 int ulx
, uly
, width
, height
;
2599 int dispwidth
, dispheight
;
2600 int i
, j
, lines
, maxlines
;
2603 unsigned int dummy_uint
;
2604 int specpdl_count
= SPECPDL_INDEX ();
2606 if (! FRAME_X_P (f
))
2610 if (menu_items_n_panes
== 0)
2613 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2615 *error
= "Empty menu";
2619 /* Figure out which root window F is on. */
2620 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
2621 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
2622 &dummy_uint
, &dummy_uint
);
2624 /* Make the menu on that window. */
2625 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
2628 *error
= "Can't create menu";
2632 /* Don't GC while we prepare and show the menu,
2633 because we give the oldxmenu library pointers to the
2634 contents of strings. */
2635 inhibit_garbage_collection ();
2637 #ifdef HAVE_X_WINDOWS
2638 /* Adjust coordinates to relative to the outer (window manager) window. */
2639 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
2640 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2641 #endif /* HAVE_X_WINDOWS */
2643 /* Adjust coordinates to be root-window-relative. */
2647 /* Create all the necessary panes and their items. */
2648 maxlines
= lines
= i
= 0;
2649 while (i
< menu_items_used
)
2651 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2653 /* Create a new pane. */
2654 Lisp_Object pane_name
, prefix
;
2657 maxlines
= max (maxlines
, lines
);
2659 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
2660 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2661 pane_string
= (NILP (pane_name
)
2662 ? "" : (char *) SDATA (pane_name
));
2663 if (keymaps
&& !NILP (prefix
))
2666 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
2667 if (lpane
== XM_FAILURE
)
2669 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2670 *error
= "Can't create pane";
2673 i
+= MENU_ITEMS_PANE_LENGTH
;
2675 /* Find the width of the widest item in this pane. */
2678 while (j
< menu_items_used
)
2681 item
= XVECTOR (menu_items
)->contents
[j
];
2689 width
= SBYTES (item
);
2690 if (width
> maxwidth
)
2693 j
+= MENU_ITEMS_ITEM_LENGTH
;
2696 /* Ignore a nil in the item list.
2697 It's meaningful only for dialog boxes. */
2698 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2702 /* Create a new item within current pane. */
2703 Lisp_Object item_name
, enable
, descrip
, help
;
2704 unsigned char *item_data
;
2707 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
2708 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
2710 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
2711 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
2712 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
2714 if (!NILP (descrip
))
2716 int gap
= maxwidth
- SBYTES (item_name
);
2717 /* if alloca is fast, use that to make the space,
2718 to reduce gc needs. */
2720 = (unsigned char *) alloca (maxwidth
2721 + SBYTES (descrip
) + 1);
2722 bcopy (SDATA (item_name
), item_data
,
2723 SBYTES (item_name
));
2724 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
2726 bcopy (SDATA (descrip
), item_data
+ j
,
2728 item_data
[j
+ SBYTES (descrip
)] = 0;
2731 item_data
= SDATA (item_name
);
2733 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
2734 menu
, lpane
, 0, item_data
,
2735 !NILP (enable
), help_string
)
2738 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
2739 *error
= "Can't add selection to menu";
2742 i
+= MENU_ITEMS_ITEM_LENGTH
;
2747 maxlines
= max (maxlines
, lines
);
2749 /* All set and ready to fly. */
2750 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
2751 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2752 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
2753 x
= min (x
, dispwidth
);
2754 y
= min (y
, dispheight
);
2757 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
2758 &ulx
, &uly
, &width
, &height
);
2759 if (ulx
+width
> dispwidth
)
2761 x
-= (ulx
+ width
) - dispwidth
;
2762 ulx
= dispwidth
- width
;
2764 if (uly
+height
> dispheight
)
2766 y
-= (uly
+ height
) - dispheight
;
2767 uly
= dispheight
- height
;
2769 if (ulx
< 0) x
-= ulx
;
2770 if (uly
< 0) y
-= uly
;
2774 /* If position was not given by a mouse click, adjust so upper left
2775 corner of the menu as a whole ends up at given coordinates. This
2776 is what x-popup-menu says in its documentation. */
2778 y
+= 1.5*height
/(maxlines
+2);
2781 XMenuSetAEQ (menu
, TRUE
);
2782 XMenuSetFreeze (menu
, TRUE
);
2786 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
2789 record_unwind_protect (pop_down_menu
,
2790 Fcons (make_save_value (f
, 0),
2791 make_save_value (menu
, 0)));
2793 /* Help display under X won't work because XMenuActivate contains
2794 a loop that doesn't give Emacs a chance to process it. */
2795 menu_help_frame
= f
;
2796 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
2797 x
, y
, ButtonReleaseMask
, &datap
,
2798 menu_help_callback
);
2804 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
2807 /* Find the item number SELIDX in pane number PANE. */
2809 while (i
< menu_items_used
)
2811 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2815 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2817 i
+= MENU_ITEMS_PANE_LENGTH
;
2826 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2829 entry
= Fcons (entry
, Qnil
);
2830 if (!NILP (pane_prefix
))
2831 entry
= Fcons (pane_prefix
, entry
);
2837 i
+= MENU_ITEMS_ITEM_LENGTH
;
2843 *error
= "Can't activate menu";
2848 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2849 the menu was invoked with a mouse event as POSITION). */
2851 Fsignal (Qquit
, Qnil
);
2856 unbind_to (specpdl_count
, Qnil
);
2861 #endif /* not USE_X_TOOLKIT */
2863 #endif /* HAVE_MENUS */
2865 /* Detect if a dialog or menu has been posted. */
2870 return popup_activated_flag
;
2873 /* The following is used by delayed window autoselection. */
2875 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2876 doc
: /* Return t if a menu or popup dialog is active. */)
2880 return (popup_activated ()) ? Qt
: Qnil
;
2883 #endif /* HAVE_MENUS */
2889 Qdebug_on_next_call
= intern ("debug-on-next-call");
2890 staticpro (&Qdebug_on_next_call
);
2892 #ifdef USE_X_TOOLKIT
2893 widget_id_tick
= (1<<16);
2894 next_menubar_widget_id
= 1;
2897 defsubr (&Sx_popup_menu
);
2898 defsubr (&Smenu_or_popup_active_p
);
2900 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2901 defsubr (&Sx_menu_bar_open_internal
);
2902 Ffset (intern ("accelerate-menu"),
2903 intern (Sx_menu_bar_open_internal
.symbol_name
));
2907 defsubr (&Sx_popup_dialog
);
2911 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2912 (do not change this comment) */