From 4e3fe6b4c0027dada181892c019e49f8003612fe Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 20 Oct 2021 10:54:27 +0800 Subject: [PATCH] Support opening the toolkit menu bar on NS * src/nsmenu.m (ns_activate_menubar, Fns_open_menubar): New functions. * src/nsterm.m (ns_create_terminal): Add activate_menubar_hook. * lisp/menu-bar.el (menu-bar-open): Use ns-menu-bar-open on Nextstep. --- lisp/menu-bar.el | 8 +++++--- src/nsmenu.m | 41 ++++++++++++++++++++++++++++++++++++++++- src/nsterm.m | 1 + 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 980ba2fcd1..2ef24cf111 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -2659,9 +2659,10 @@ menu-bar-open this is the numeric argument to the command. This function decides which method to use to access the menu depending on FRAME's terminal device. On X displays, it calls -`x-menu-bar-open'; on Windows, `w32-menu-bar-open'; otherwise it -calls either `popup-menu' or `tmm-menubar' depending on whether -`tty-menu-open-use-tmm' is nil or not. +`x-menu-bar-open'; on Windows, `w32-menu-bar-open'; +on NS, `ns-menu-bar-open'; otherwise it calls either `popup-menu' +or `tmm-menubar' depending on whether `tty-menu-open-use-tmm' +is nil or not. If FRAME is nil or not given, use the selected frame." (interactive @@ -2670,6 +2671,7 @@ menu-bar-open (cond ((eq type 'x) (x-menu-bar-open frame)) ((eq type 'w32) (w32-menu-bar-open frame)) + ((eq type 'ns) (ns-menu-bar-open frame)) ((and (null tty-menu-open-use-tmm) (not (zerop (or (frame-parameter nil 'menu-bar-lines) 0)))) ;; Make sure the menu bar is up to date. One situation where diff --git a/src/nsmenu.m b/src/nsmenu.m index 333a8b50a1..359a9c3bc8 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1451,7 +1451,30 @@ - (NSRect) frame @end /* EmacsTooltip */ +void +ns_activate_menubar (struct frame *frame) +{ + if (frame != SELECTED_FRAME () + || !FRAME_EXTERNAL_MENU_BAR (frame)) + return; + block_input (); + NSApplication *app = [NSApplication sharedApplication]; + NSMenu *menu = [app mainMenu]; + for (NSMenuItem *item in [menu itemArray]) + { + if ([item hasSubmenu]) + { +#ifdef NS_IMPL_GNUSTEP + [[item submenu] display]; +#else + [menu performActionForItemAtIndex: [menu indexOfItem: item]]; +#endif + break; + } + } + unblock_input (); +} /* ========================================================================== @@ -1883,7 +1906,6 @@ - (Lisp_Object)runDialogAt: (NSPoint)p @end - /* ========================================================================== Lisp definitions @@ -1906,6 +1928,22 @@ - (Lisp_Object)runDialogAt: (NSPoint)p return popup_activated () ? Qt : Qnil; } +DEFUN ("ns-menu-bar-open", Fns_menu_bar_open, Sns_menu_bar_open, 0, 1, "i", + doc: /* Start key navigation of the menu bar in FRAME. +This initially opens the first menu bar item and you can then navigate with the +arrow keys, select a menu entry with the return key or cancel with the +escape key. If FRAME has no menu bar this function does nothing. + +If FRAME is nil or not given, use the selected frame. */) + (Lisp_Object frame) +{ + struct frame *f = decode_window_system_frame (frame); + + ns_activate_menubar (f); + + return Qnil; +} + /* ========================================================================== Lisp interface declaration @@ -1917,6 +1955,7 @@ - (Lisp_Object)runDialogAt: (NSPoint)p { defsubr (&Sns_reset_menu); defsubr (&Smenu_or_popup_active_p); + defsubr (&Sns_menu_bar_open); DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); } diff --git a/src/nsterm.m b/src/nsterm.m index e0b7143e29..cd322b1fce 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -5071,6 +5071,7 @@ static Lisp_Object ns_new_font (struct frame *f, Lisp_Object font_object, terminal->delete_frame_hook = ns_destroy_window; terminal->delete_terminal_hook = ns_delete_terminal; terminal->change_tab_bar_height_hook = ns_change_tab_bar_height; + terminal->activate_menubar_hook = ns_activate_menubar; /* Other hooks are NULL by default. */ return terminal; -- 2.31.1