1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-28 07:45:00 +00:00

Make `toggle-frame-maximized' respect the dock on OS X (bug#22988).

* src/nsterm.m (ns_screen_margins): New function.
(ns_screen_margins_ignoring_hidden_dock): New function.
(ns_menu_bar_height): Reimplement in terms of `ns_screen_margins'.
([EmacsWindow zoom:]): Take all screen margins (except those
originating from a hidden dock) into account.
This commit is contained in:
Anders Lindgren 2016-03-22 20:18:33 +01:00
parent 38a43f1a8f
commit e643977b6b

View File

@ -646,41 +646,128 @@ Free a pool and temporary objects it refers to (callable from C)
}
/* True, if the menu bar should be hidden. */
static BOOL
ns_menu_bar_should_be_hidden (void)
/* True, if the menu bar should be hidden. */
{
return !NILP (ns_auto_hide_menu_bar)
&& [NSApp respondsToSelector:@selector(setPresentationOptions:)];
}
struct EmacsMargins
{
CGFloat top;
CGFloat bottom;
CGFloat left;
CGFloat right;
};
static struct EmacsMargins
ns_screen_margins (NSScreen *screen)
/* The parts of SCREEN used by the operating system. */
{
NSTRACE ("ns_screen_margins");
struct EmacsMargins margins;
NSRect screenFrame = [screen frame];
NSRect screenVisibleFrame = [screen visibleFrame];
/* Sometimes, visibleFrame isn't up-to-date with respect to a hidden
menu bar, check this explicitly. */
if (ns_menu_bar_should_be_hidden())
{
margins.top = 0;
}
else
{
CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height;
CGFloat visibleFrameTop = (screenVisibleFrame.origin.y
+ screenVisibleFrame.size.height);
margins.top = frameTop - visibleFrameTop;
}
{
CGFloat frameRight = screenFrame.origin.x + screenFrame.size.width;
CGFloat visibleFrameRight = (screenVisibleFrame.origin.x
+ screenVisibleFrame.size.width);
margins.right = frameRight - visibleFrameRight;
}
margins.bottom = screenVisibleFrame.origin.y - screenFrame.origin.y;
margins.left = screenVisibleFrame.origin.x - screenFrame.origin.x;
NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g",
margins.left,
margins.right,
margins.top,
margins.bottom);
return margins;
}
/* A screen margin between 1 and DOCK_IGNORE_LIMIT (inclusive) is
assumed to contain a hidden dock. OS X currently use 4 pixels for
this, however, to be future compatible, a larger value is used. */
#define DOCK_IGNORE_LIMIT 6
static struct EmacsMargins
ns_screen_margins_ignoring_hidden_dock (NSScreen *screen)
/* The parts of SCREEN used by the operating system, excluding the parts
reserved for an hidden dock. */
{
NSTRACE ("ns_screen_margins_ignoring_hidden_dock");
struct EmacsMargins margins = ns_screen_margins(screen);
/* OS X (currently) reserved 4 pixels along the edge where a hidden
dock is located. Unfortunately, it's not possible to find the
location and information about if the dock is hidden. Instead,
it is assumed that if the margin of an edge is less than
DOCK_IGNORE_LIMIT, it contains a hidden dock. */
if (margins.left <= DOCK_IGNORE_LIMIT)
{
margins.left = 0;
}
if (margins.right <= DOCK_IGNORE_LIMIT)
{
margins.right = 0;
}
if (margins.top <= DOCK_IGNORE_LIMIT)
{
margins.top = 0;
}
/* Note: This doesn't occur in current versions of OS X, but
included for completeness and future compatibility. */
if (margins.bottom <= DOCK_IGNORE_LIMIT)
{
margins.bottom = 0;
}
NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g",
margins.left,
margins.right,
margins.top,
margins.bottom);
return margins;
}
static CGFloat
ns_menu_bar_height (NSScreen *screen)
/* The height of the menu bar, if visible.
Note: Don't use this when fullscreen is enabled -- the screen
sometimes includes, sometimes excludes the menu bar area. */
sometimes includes, sometimes excludes the menu bar area. */
{
CGFloat res;
struct EmacsMargins margins = ns_screen_margins(screen);
if (ns_menu_bar_should_be_hidden())
{
res = 0;
}
else
{
NSRect screenFrame = [screen frame];
NSRect screenVisibleFrame = [screen visibleFrame];
CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height;
CGFloat visibleFrameTop = (screenVisibleFrame.origin.y
+ screenVisibleFrame.size.height);
res = frameTop - visibleFrameTop;
}
CGFloat res = margins.top;
NSTRACE ("ns_menu_bar_height " NSTRACE_FMT_RETURN " %.0f", res);
@ -7867,9 +7954,10 @@ - (void)zoom:(id)sender
// the menu-bar.
[super zoom:sender];
#elsif 0
#elif 0
// Native zoom done using the standard zoom animation, plus an
// explicit resize to cover the full screen.
// explicit resize to cover the full screen, except the menu-bar and
// dock, if present.
[super zoom:sender];
// After the native zoom, resize the resulting frame to fill the
@ -7889,6 +7977,9 @@ - (void)zoom:(id)sender
NSTRACE_FSTYPE ("fullscreenState", fs_state);
NSRect sr = [screen frame];
struct EmacsMargins margins
= ns_screen_margins_ignoring_hidden_dock(screen);
NSRect wr = [self frame];
NSTRACE_RECT ("Rect after zoom", wr);
@ -7897,15 +7988,15 @@ - (void)zoom:(id)sender
if (fs_state == FULLSCREEN_MAXIMIZED
|| fs_state == FULLSCREEN_HEIGHT)
{
newWr.origin.x = 0;
newWr.size.height = sr.size.height - ns_menu_bar_height(screen);
newWr.origin.y = sr.origin.y + margins.bottom;
newWr.size.height = sr.size.height - margins.top - margins.bottom;
}
if (fs_state == FULLSCREEN_MAXIMIZED
|| fs_state == FULLSCREEN_WIDTH)
{
newWr.origin.y = 0;
newWr.size.width = sr.size.width;
newWr.origin.x = sr.origin.x + margins.left;
newWr.size.width = sr.size.width - margins.right - margins.left;
}
if (newWr.size.width != wr.size.width
@ -7918,13 +8009,20 @@ - (void)zoom:(id)sender
}
}
#else
// Non-native zoom which is done instantaneously. The resulting frame
// covers the entire screen, except the menu-bar, if present.
// Non-native zoom which is done instantaneously. The resulting
// frame covers the entire screen, except the menu-bar and dock, if
// present.
NSScreen * screen = [self screen];
if (screen != nil)
{
NSRect sr = [screen frame];
sr.size.height -= ns_menu_bar_height (screen);
struct EmacsMargins margins
= ns_screen_margins_ignoring_hidden_dock(screen);
sr.size.height -= (margins.top + margins.bottom);
sr.size.width -= (margins.left + margins.right);
sr.origin.x += margins.left;
sr.origin.y += margins.bottom;
sr = [[self delegate] windowWillUseStandardFrame:self
defaultFrame:sr];