From f0a1382af3afa31708d3ce2f4c28bce61565aada Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jan=20Dj=C3=A4rv?= Date: Sun, 27 Mar 2011 12:36:44 +0200 Subject: [PATCH] Introduce ns-auto-hide-menu-bar to hide menubar for Emacs frames. Code by Anders Lindgren. * nsterm.m (ns_menu_bar_is_hidden): New variable. (ns_constrain_all_frames, ns_menu_bar_should_be_hidden) (ns_update_auto_hide_menu_bar): New functions. (ns_update_begin): Call ns_update_auto_hide_menu_bar. (applicationDidBecomeActive): Call ns_update_auto_hide_menu_bar and ns_constrain_all_frames. (constrainFrameRect): Return at once if ns_menu_bar_should_be_hidden. (syms_of_nsterm): DEFVAR ns-auto-hide-menu-bar, init to Qnil. --- src/ChangeLog | 11 +++++ src/nsterm.m | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/src/ChangeLog b/src/ChangeLog index eb03806b33a..96f60877fce 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2011-03-27 Anders Lindgren + + * nsterm.m (ns_menu_bar_is_hidden): New variable. + (ns_constrain_all_frames, ns_menu_bar_should_be_hidden) + (ns_update_auto_hide_menu_bar): New functions. + (ns_update_begin): Call ns_update_auto_hide_menu_bar. + (applicationDidBecomeActive): Call ns_update_auto_hide_menu_bar and + ns_constrain_all_frames. + (constrainFrameRect): Return at once if ns_menu_bar_should_be_hidden. + (syms_of_nsterm): DEFVAR ns-auto-hide-menu-bar, init to Qnil. + 2011-03-27 Jan Djärv * nsmenu.m (runDialogAt): Remove argument to timer_check. diff --git a/src/nsterm.m b/src/nsterm.m index c7cd411c614..ebfa875ae0e 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -170,6 +170,7 @@ BOOL ns_in_resize = NO; static BOOL ns_fake_keydown = NO; int ns_tmp_flags; /* FIXME */ struct nsfont_info *ns_tmp_font; /* FIXME */ +static BOOL ns_menu_bar_is_hidden = NO; /*static int debug_lock = 0; */ /* event loop */ @@ -505,6 +506,118 @@ ns_resize_handle_rect (NSWindow *window) } +// +// Window constraining +// ------------------- +// +// To ensure that the windows are not placed under the menu bar, they +// are typically moved by the call-back constrainFrameRect. However, +// by overriding it, it's possible to inhibit this, leaving the window +// in it's original position. +// +// It's possible to hide the menu bar. However, technically, it's only +// possible to hide it when the application is active. To ensure that +// this work properly, the menu bar and window constraining are +// deferred until the application becomes active. +// +// Even though it's not possible to manually move a window above the +// top of the screen, it is allowed if it's done programmatically, +// when the menu is hidden. This allows the editable area to cover the +// full screen height. +// +// Test cases +// ---------- +// +// Use the following extra files: +// +// init.el: +// ;; Hide menu and place frame slightly above the top of the screen. +// (setq ns-auto-hide-menu-bar t) +// (set-frame-position (selected-frame) 0 -20) +// +// Test 1: +// +// emacs -Q -l init.el +// +// Result: No menu bar, and the title bar should be above the screen. +// +// Test 2: +// +// emacs -Q +// +// Result: Menu bar visible, frame placed immediately below the menu. +// + +static void +ns_constrain_all_frames (void) +{ + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_NS_P (f)) + { + NSView *view = FRAME_NS_VIEW (f); + /* This no-op will trigger the default window placing + * constriant system. */ + f->output_data.ns->dont_constrain = 0; + [[view window] setFrameOrigin:[[view window] frame].origin]; + } + } +} + + +/* True, if the menu bar should be hidden. */ + +static BOOL +ns_menu_bar_should_be_hidden (void) +{ + return !NILP (ns_auto_hide_menu_bar) + && [NSApp respondsToSelector:@selector(setPresentationOptions:)]; +} + + +/* Show or hide the menu bar, based on user setting. */ + +static void +ns_update_auto_hide_menu_bar (void) +{ + BLOCK_INPUT; + + NSTRACE (ns_update_auto_hide_menu_bar); + + if (NSApp != nil + && [NSApp isActive] + && [NSApp respondsToSelector:@selector(setPresentationOptions:)]) + { + // Note, "setPresentationOptions" triggers an error unless the + // application is active. + BOOL menu_bar_should_be_hidden = ns_menu_bar_should_be_hidden (); + + if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden) + { + NSApplicationPresentationOptions options + = NSApplicationPresentationAutoHideDock; + + if (menu_bar_should_be_hidden) + options |= NSApplicationPresentationAutoHideMenuBar; + + [NSApp setPresentationOptions: options]; + + ns_menu_bar_is_hidden = menu_bar_should_be_hidden; + + if (!ns_menu_bar_is_hidden) + { + ns_constrain_all_frames (); + } + } + } + + UNBLOCK_INPUT; +} + + static void ns_update_begin (struct frame *f) /* -------------------------------------------------------------------------- @@ -515,6 +628,8 @@ ns_update_begin (struct frame *f) NSView *view = FRAME_NS_VIEW (f); NSTRACE (ns_update_begin); + ns_update_auto_hide_menu_bar (); + ns_updating_frame = f; [view lockFocus]; @@ -4205,7 +4320,13 @@ ns_term_shutdown (int sig) } - (void)applicationDidBecomeActive: (NSNotification *)notification { + NSTRACE (applicationDidBecomeActive); + //ns_app_active=YES; + + ns_update_auto_hide_menu_bar (); + // No constrining takes place when the application is not active. + ns_constrain_all_frames (); } - (void)applicationDidResignActive: (NSNotification *)notification { @@ -5689,7 +5810,10 @@ ns_term_shutdown (int sig) /* When making the frame visible for the first time, we want to constrain. Other times not. */ struct frame *f = ((EmacsView *)[self delegate])->emacsframe; - if (f->output_data.ns->dont_constrain) + NSTRACE (constrainFrameRect); + + if (f->output_data.ns->dont_constrain + || ns_menu_bar_should_be_hidden ()) return frameRect; f->output_data.ns->dont_constrain = 1; @@ -6361,6 +6485,10 @@ allowing it to be used at a lower level for accented character entry."); staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; + DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar, + "Non-nil means that the menu bar is hidden, but appears when the mouse is near. Only works on OSX 10.6 or later."); + ns_auto_hide_menu_bar = Qnil; + /* TODO: move to common code */ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, doc: /* If not nil, Emacs uses toolkit scroll bars. */); -- 2.11.4.GIT