(filter (when (symbolp map)
(plist-get (get map 'menu-prop) :filter))))
(if filter (funcall filter (symbol-function map)) map)))))
- (frame (selected-frame))
+ (selected-frame (selected-frame))
+ (frame (if (and (eq (framep selected-frame) t) (frame-parent)
+ from-menu-bar
+ (zerop (or (frame-parameter nil 'menu-bar-lines) 0)))
+ ;; If the selected frame is a tty child frame
+ ;; without its own menu bar and we are called from
+ ;; the menu bar, the menu bar must be on the root
+ ;; frame of the selected frame.
+ (frame-root-frame)
+ (selected-frame)))
event cmd)
- (if from-menu-bar
- (let* ((xy (posn-x-y position))
- (menu-symbol (menu-bar-menu-at-x-y (car xy) (cdr xy))))
- (setq position (list menu-symbol (list frame '(menu-bar)
- xy 0))))
- (setq position (popup-menu-normalize-position position)))
- ;; The looping behavior was taken from lmenu's popup-menu-popup
- (while (and map (setq event
- ;; map could be a prefix key, in which case
- ;; we need to get its function cell
- ;; definition.
- (x-popup-menu position (indirect-function map))))
- ;; Strangely x-popup-menu returns a list.
- ;; mouse-major-mode-menu was using a weird:
- ;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
- (setq cmd
- (cond
- ((and from-menu-bar
- (consp event)
- (numberp (car event))
- (numberp (cdr event)))
- (let ((x (car event))
- (y (cdr event))
- menu-symbol)
- (setq menu-symbol (menu-bar-menu-at-x-y x y))
- (setq position (list menu-symbol (list frame '(menu-bar)
- event 0)))
- (setq map
- (key-binding (vector 'menu-bar menu-symbol)))))
- ((and (not (keymapp map)) (listp map))
- ;; We were given a list of keymaps. Search them all
- ;; in sequence until a first binding is found.
- (let ((mouse-click (apply 'vector event))
- binding)
- (while (and map (null binding))
- (setq binding (lookup-key-ignore-too-long (car map) mouse-click))
- (setq map (cdr map)))
- binding))
- (t
- ;; We were given a single keymap.
- (lookup-key map (apply 'vector event)))))
- ;; Clear out echoing, which perhaps shows a prefix arg.
- (message "")
- ;; Maybe try again but with the submap.
- (setq map (if (keymapp cmd) cmd)))
+ (with-selected-frame frame
+ (if from-menu-bar
+ (let* ((xy (posn-x-y position))
+ (menu-symbol (menu-bar-menu-at-x-y (car xy) (cdr xy))))
+ (setq position (list menu-symbol (list frame '(menu-bar)
+ xy 0))))
+ (setq position (popup-menu-normalize-position position)))
+
+ ;; The looping behavior was taken from lmenu's popup-menu-popup
+ (while (and map (setq event
+ ;; map could be a prefix key, in which case
+ ;; we need to get its function cell
+ ;; definition.
+ (x-popup-menu position (indirect-function map))))
+ ;; Strangely x-popup-menu returns a list.
+ ;; mouse-major-mode-menu was using a weird:
+ ;; (key-binding (apply 'vector (append '(menu-bar) menu-prefix events)))
+ (setq cmd
+ (cond
+ ((and from-menu-bar
+ (consp event)
+ (numberp (car event))
+ (numberp (cdr event)))
+ (let ((x (car event))
+ (y (cdr event))
+ menu-symbol)
+ (setq menu-symbol (menu-bar-menu-at-x-y x y))
+ (setq position (list menu-symbol (list frame '(menu-bar)
+ event 0)))
+ (if (not (eq frame selected-frame))
+ ;; If we are using the menu bar from the root
+ ;; frame, look up the key binding in the keymaps
+ ;; of the initially selected window's buffer to
+ ;; make sure that navigating the menu bar with the
+ ;; keyboard works as intended.
+ (setq map
+ (key-binding (vector 'menu-bar menu-symbol) nil nil
+ (frame-selected-window selected-frame)))
+ (setq map
+ (key-binding (vector 'menu-bar menu-symbol))))))
+ ((and (not (keymapp map)) (listp map))
+ ;; We were given a list of keymaps. Search them all
+ ;; in sequence until a first binding is found.
+ (let ((mouse-click (apply 'vector event))
+ binding)
+ (while (and map (null binding))
+ (setq binding (lookup-key-ignore-too-long (car map) mouse-click))
+ (setq map (cdr map)))
+ binding))
+ (t
+ ;; We were given a single keymap.
+ (lookup-key map (apply 'vector event)))))
+ ;; Clear out echoing, which perhaps shows a prefix arg.
+ (message "")
+ ;; Maybe try again but with the submap.
+ (setq map (if (keymapp cmd) cmd))))
+
;; If the user did not cancel by refusing to select,
;; and if the result is a command, run it.
(when (and (null map) (commandp cmd))
If FRAME is nil or not given, use the selected frame."
(interactive
(list nil (prefix-numeric-value current-prefix-arg)))
- (let ((type (framep (or frame (selected-frame)))))
+ (let* ((type (framep (or frame (selected-frame))))
+ root
+ (frame (if (and (eq type t) (frame-parent frame)
+ (null tty-menu-open-use-tmm)
+ (zerop (or (frame-parameter frame 'menu-bar-lines) 0))
+ (setq root (frame-root-frame))
+ (not (zerop
+ (or (frame-parameter root 'menu-bar-lines) 0))))
+ ;; If FRAME is a tty child frame without its own
+ ;; menu bar, 'tty-menu-open-use-tmm' is false and
+ ;; FRAME's root frame has a menu bar, use that root
+ ;; frame's menu bar.
+ root
+ frame)))
(cond
((eq type 'x) (x-menu-bar-open frame))
((eq type 'w32) (w32-menu-bar-open frame))
((eq type 'haiku) (haiku-menu-bar-open frame))
((eq type 'pgtk) (pgtk-menu-bar-open frame))
((and (null tty-menu-open-use-tmm)
- (not (zerop (or (frame-parameter nil 'menu-bar-lines) 0))))
+ (not (zerop (or (frame-parameter frame 'menu-bar-lines) 0))))
;; Make sure the menu bar is up to date. One situation where
;; this is important is when this function is invoked by name
;; via M-x, in which case the menu bar includes the "Minibuf"
(current-local-map) (vector 'menu-bar menu))
(cdar (minor-mode-key-binding (vector 'menu-bar menu)))
(mouse-menu-bar-map))
- (posn-at-x-y x 0 nil t) nil t)))
+ (posn-at-x-y x 0 frame t) nil t)))
(t (with-selected-frame (or frame (selected-frame))
(tmm-menubar))))))
struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
int, int);
static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
-static bool update_menu_bar (struct frame *, bool, bool);
+static bool update_menu_bar (struct frame *, bool, bool, struct window *);
static bool try_window_reusing_current_matrix (struct window *);
static int try_window_id (struct window *);
static void maybe_produce_line_number (struct it *);
/* True means that update_menu_bar has run its hooks
so any further calls to update_menu_bar shouldn't do so again. */
bool menu_bar_hooks_run = false;
+ struct window *sw = XWINDOW (selected_window);
+ struct frame *sf = WINDOW_XFRAME (sw);
+ struct frame *rf = NULL;
+
+ if (FRAME_PARENT_FRAME (sf) && !FRAME_WINDOW_P (sf)
+ && FRAME_MENU_BAR_LINES (sf) == 0
+ && FRAME_MENU_BAR_LINES (rf = root_frame (sf)) != 0
+ && NILP (Fdefault_value (Qtty_menu_open_use_tmm)))
+ /* If the selected window's frame is a tty child frame without
+ menu bar, that frame's root frame has a menu bar and
+ 'tty-menu-open-use-tmm' is nil, update the menu bar of the
+ root frame from the selected window. */
+ sf = rf;
+ else
+ {
+ sf = NULL;
+ sw = NULL;
+ }
record_unwind_save_match_data ();
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+ struct window *w
+ = sf == f ? sw : XWINDOW (FRAME_SELECTED_WINDOW (f));
/* Ignore tooltip frame. */
if (FRAME_TOOLTIP_P (f))
&& !XBUFFER (w->contents)->text->redisplay)
continue;
- if (!FRAME_PARENT_FRAME (f))
- menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
+ menu_bar_hooks_run
+ = update_menu_bar (f, false, menu_bar_hooks_run, w);
update_tab_bar (f, false);
#ifdef HAVE_WINDOW_SYSTEM
}
else
{
- struct frame *sf = SELECTED_FRAME ();
+ struct window *sw = XWINDOW (selected_window);
+ struct frame *sf = WINDOW_XFRAME (sw);
+ struct frame *rf = NULL;
- if (!FRAME_PARENT_FRAME (sf))
- update_menu_bar (sf, true, false);
+ if (FRAME_PARENT_FRAME (sf) && !FRAME_WINDOW_P (sf)
+ && FRAME_MENU_BAR_LINES (sf) == 0
+ && FRAME_MENU_BAR_LINES (rf = root_frame (sf)) != 0
+ && NILP (Fdefault_value (Qtty_menu_open_use_tmm)))
+ /* If the selected window's frame is a tty child frame without
+ menu bar, that frame's root frame has a menu bar and
+ 'tty-menu-open-use-tmm' is nil, update the menu bar of the
+ root frame from the selected window. */
+ sf = rf;
+
+ update_menu_bar (sf, true, false, sw);
update_tab_bar (sf, true);
#ifdef HAVE_WINDOW_SYSTEM
If HOOKS_RUN, a previous call to update_menu_bar
already ran the menu bar hooks for this redisplay, so there
is no need to run them again. The return value is the
- updated value of this flag, to pass to the next call. */
+ updated value of this flag, to pass to the next call.
+
+ W, if set, denotes the window that should be considered as selected.
+ For a tty child frame using F as surrogate menu bar frame, this
+ specifes the child frame's selected window and its buffer shall be
+ used for updating the menu bar of the root frame instead of the
+ buffer of the root frame's selected window. */
static bool
-update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
+update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run, struct window *w)
{
- Lisp_Object window;
- struct window *w;
-
/* If called recursively during a menu update, do nothing. This can
happen when, for instance, an activate-menubar-hook causes a
redisplay. */
if (inhibit_menubar_update)
return hooks_run;
- window = FRAME_SELECTED_WINDOW (f);
- w = XWINDOW (window);
-
if (FRAME_WINDOW_P (f)
?
#ifdef HAVE_EXT_MENU_BAR
/* When we reach a frame's selected window, redo the frame's menu
bar, tool bar, tab-bar, and the frame's title. */
- if (update_mode_line
- && EQ (FRAME_SELECTED_WINDOW (f), window))
+ if (update_mode_line && EQ (FRAME_SELECTED_WINDOW (f), window))
{
- bool redisplay_menu_p;
-
if (FRAME_WINDOW_P (f))
{
#ifdef HAVE_EXT_MENU_BAR
- redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
+ if (FRAME_EXTERNAL_MENU_BAR (f))
+ display_menu_bar (w);
#else
- redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
+ if (FRAME_MENU_BAR_LINES (f) > 0)
+ display_menu_bar (w);
#endif
}
else
- redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
+ {
+ struct frame *rf = NULL;
- if (redisplay_menu_p)
- display_menu_bar (w);
+ if (FRAME_PARENT_FRAME (f)
+ && FRAME_MENU_BAR_LINES (f) == 0
+ && FRAME_MENU_BAR_LINES (rf = root_frame (f)) != 0
+ && NILP (Fdefault_value (Qtty_menu_open_use_tmm)))
+ /* If F is a tty child frame without menu bar, that frame's root
+ frame has a menu bar and 'tty-menu-open-use-tmm' is nil,
+ display the menu bar of the root frame's selected window. */
+ display_menu_bar (XWINDOW (FRAME_SELECTED_WINDOW (rf)));
+ else if (FRAME_MENU_BAR_LINES (f) > 0)
+ display_menu_bar (w);
+ }
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
{
struct it it;
struct frame *f = SELECTED_FRAME ();
- struct window *w = XWINDOW (f->selected_window);
struct glyph_row *row;
size_t item_len = strlen (item_text);
+ struct frame *rf = NULL;
+
+ if (FRAME_PARENT_FRAME (f) && !FRAME_WINDOW_P (f)
+ && FRAME_MENU_BAR_LINES (f) == 0
+ && FRAME_MENU_BAR_LINES (rf = root_frame (f)) != 0
+ && NILP (Fdefault_value (Qtty_menu_open_use_tmm)))
+ f = rf;
+
+ struct window *w = XWINDOW (f->selected_window);
+
eassert (FRAME_TERMCAP_P (f));
/* Don't write beyond the matrix's last row. This can happen for
DEFSYM (Qnhdrag, "nhdrag");
DEFSYM (Qvdrag, "vdrag");
DEFSYM (Qhourglass, "hourglass");
+ DEFSYM (Qtty_menu_open_use_tmm, "tty-menu-open-use-tmm");
}