diff options
| author | Anders Lindgren | 2016-03-22 20:18:33 +0100 |
|---|---|---|
| committer | Anders Lindgren | 2016-03-22 20:18:33 +0100 |
| commit | e643977b6b99466bfa872b61a4101d9937615876 (patch) | |
| tree | 90ce4ea49ababc42cd60b468e80019797bd5091b /src | |
| parent | 38a43f1a8f26f1ec8dbb9b2981f1d98f2b2bd228 (diff) | |
| download | emacs-e643977b6b99466bfa872b61a4101d9937615876.tar.gz emacs-e643977b6b99466bfa872b61a4101d9937615876.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.m | 142 |
1 files changed, 120 insertions, 22 deletions
diff --git a/src/nsterm.m b/src/nsterm.m index b796193af77..4048ac46546 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -646,42 +646,129 @@ ns_release_autorelease_pool (void *pool) | |||
| 646 | } | 646 | } |
| 647 | 647 | ||
| 648 | 648 | ||
| 649 | /* True, if the menu bar should be hidden. */ | ||
| 650 | |||
| 651 | static BOOL | 649 | static BOOL |
| 652 | ns_menu_bar_should_be_hidden (void) | 650 | ns_menu_bar_should_be_hidden (void) |
| 651 | /* True, if the menu bar should be hidden. */ | ||
| 653 | { | 652 | { |
| 654 | return !NILP (ns_auto_hide_menu_bar) | 653 | return !NILP (ns_auto_hide_menu_bar) |
| 655 | && [NSApp respondsToSelector:@selector(setPresentationOptions:)]; | 654 | && [NSApp respondsToSelector:@selector(setPresentationOptions:)]; |
| 656 | } | 655 | } |
| 657 | 656 | ||
| 658 | 657 | ||
| 659 | static CGFloat | 658 | struct EmacsMargins |
| 660 | ns_menu_bar_height (NSScreen *screen) | 659 | { |
| 661 | /* The height of the menu bar, if visible. | 660 | CGFloat top; |
| 661 | CGFloat bottom; | ||
| 662 | CGFloat left; | ||
| 663 | CGFloat right; | ||
| 664 | }; | ||
| 662 | 665 | ||
| 663 | Note: Don't use this when fullscreen is enabled -- the screen | 666 | |
| 664 | sometimes includes, sometimes excludes the menu bar area. */ | 667 | static struct EmacsMargins |
| 668 | ns_screen_margins (NSScreen *screen) | ||
| 669 | /* The parts of SCREEN used by the operating system. */ | ||
| 665 | { | 670 | { |
| 666 | CGFloat res; | 671 | NSTRACE ("ns_screen_margins"); |
| 672 | |||
| 673 | struct EmacsMargins margins; | ||
| 674 | |||
| 675 | NSRect screenFrame = [screen frame]; | ||
| 676 | NSRect screenVisibleFrame = [screen visibleFrame]; | ||
| 667 | 677 | ||
| 678 | /* Sometimes, visibleFrame isn't up-to-date with respect to a hidden | ||
| 679 | menu bar, check this explicitly. */ | ||
| 668 | if (ns_menu_bar_should_be_hidden()) | 680 | if (ns_menu_bar_should_be_hidden()) |
| 669 | { | 681 | { |
| 670 | res = 0; | 682 | margins.top = 0; |
| 671 | } | 683 | } |
| 672 | else | 684 | else |
| 673 | { | 685 | { |
| 674 | NSRect screenFrame = [screen frame]; | ||
| 675 | NSRect screenVisibleFrame = [screen visibleFrame]; | ||
| 676 | |||
| 677 | CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height; | 686 | CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height; |
| 678 | CGFloat visibleFrameTop = (screenVisibleFrame.origin.y | 687 | CGFloat visibleFrameTop = (screenVisibleFrame.origin.y |
| 679 | + screenVisibleFrame.size.height); | 688 | + screenVisibleFrame.size.height); |
| 680 | 689 | ||
| 681 | res = frameTop - visibleFrameTop; | 690 | margins.top = frameTop - visibleFrameTop; |
| 691 | } | ||
| 692 | |||
| 693 | { | ||
| 694 | CGFloat frameRight = screenFrame.origin.x + screenFrame.size.width; | ||
| 695 | CGFloat visibleFrameRight = (screenVisibleFrame.origin.x | ||
| 696 | + screenVisibleFrame.size.width); | ||
| 697 | margins.right = frameRight - visibleFrameRight; | ||
| 698 | } | ||
| 699 | |||
| 700 | margins.bottom = screenVisibleFrame.origin.y - screenFrame.origin.y; | ||
| 701 | margins.left = screenVisibleFrame.origin.x - screenFrame.origin.x; | ||
| 682 | 702 | ||
| 703 | NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g", | ||
| 704 | margins.left, | ||
| 705 | margins.right, | ||
| 706 | margins.top, | ||
| 707 | margins.bottom); | ||
| 708 | |||
| 709 | return margins; | ||
| 710 | } | ||
| 711 | |||
| 712 | |||
| 713 | /* A screen margin between 1 and DOCK_IGNORE_LIMIT (inclusive) is | ||
| 714 | assumed to contain a hidden dock. OS X currently use 4 pixels for | ||
| 715 | this, however, to be future compatible, a larger value is used. */ | ||
| 716 | #define DOCK_IGNORE_LIMIT 6 | ||
| 717 | |||
| 718 | static struct EmacsMargins | ||
| 719 | ns_screen_margins_ignoring_hidden_dock (NSScreen *screen) | ||
| 720 | /* The parts of SCREEN used by the operating system, excluding the parts | ||
| 721 | reserved for an hidden dock. */ | ||
| 722 | { | ||
| 723 | NSTRACE ("ns_screen_margins_ignoring_hidden_dock"); | ||
| 724 | |||
| 725 | struct EmacsMargins margins = ns_screen_margins(screen); | ||
| 726 | |||
| 727 | /* OS X (currently) reserved 4 pixels along the edge where a hidden | ||
| 728 | dock is located. Unfortunately, it's not possible to find the | ||
| 729 | location and information about if the dock is hidden. Instead, | ||
| 730 | it is assumed that if the margin of an edge is less than | ||
| 731 | DOCK_IGNORE_LIMIT, it contains a hidden dock. */ | ||
| 732 | if (margins.left <= DOCK_IGNORE_LIMIT) | ||
| 733 | { | ||
| 734 | margins.left = 0; | ||
| 735 | } | ||
| 736 | if (margins.right <= DOCK_IGNORE_LIMIT) | ||
| 737 | { | ||
| 738 | margins.right = 0; | ||
| 739 | } | ||
| 740 | if (margins.top <= DOCK_IGNORE_LIMIT) | ||
| 741 | { | ||
| 742 | margins.top = 0; | ||
| 743 | } | ||
| 744 | /* Note: This doesn't occur in current versions of OS X, but | ||
| 745 | included for completeness and future compatibility. */ | ||
| 746 | if (margins.bottom <= DOCK_IGNORE_LIMIT) | ||
| 747 | { | ||
| 748 | margins.bottom = 0; | ||
| 683 | } | 749 | } |
| 684 | 750 | ||
| 751 | NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g", | ||
| 752 | margins.left, | ||
| 753 | margins.right, | ||
| 754 | margins.top, | ||
| 755 | margins.bottom); | ||
| 756 | |||
| 757 | return margins; | ||
| 758 | } | ||
| 759 | |||
| 760 | |||
| 761 | static CGFloat | ||
| 762 | ns_menu_bar_height (NSScreen *screen) | ||
| 763 | /* The height of the menu bar, if visible. | ||
| 764 | |||
| 765 | Note: Don't use this when fullscreen is enabled -- the screen | ||
| 766 | sometimes includes, sometimes excludes the menu bar area. */ | ||
| 767 | { | ||
| 768 | struct EmacsMargins margins = ns_screen_margins(screen); | ||
| 769 | |||
| 770 | CGFloat res = margins.top; | ||
| 771 | |||
| 685 | NSTRACE ("ns_menu_bar_height " NSTRACE_FMT_RETURN " %.0f", res); | 772 | NSTRACE ("ns_menu_bar_height " NSTRACE_FMT_RETURN " %.0f", res); |
| 686 | 773 | ||
| 687 | return res; | 774 | return res; |
| @@ -7867,9 +7954,10 @@ not_in_argv (NSString *arg) | |||
| 7867 | // the menu-bar. | 7954 | // the menu-bar. |
| 7868 | [super zoom:sender]; | 7955 | [super zoom:sender]; |
| 7869 | 7956 | ||
| 7870 | #elsif 0 | 7957 | #elif 0 |
| 7871 | // Native zoom done using the standard zoom animation, plus an | 7958 | // Native zoom done using the standard zoom animation, plus an |
| 7872 | // explicit resize to cover the full screen. | 7959 | // explicit resize to cover the full screen, except the menu-bar and |
| 7960 | // dock, if present. | ||
| 7873 | [super zoom:sender]; | 7961 | [super zoom:sender]; |
| 7874 | 7962 | ||
| 7875 | // After the native zoom, resize the resulting frame to fill the | 7963 | // After the native zoom, resize the resulting frame to fill the |
| @@ -7889,6 +7977,9 @@ not_in_argv (NSString *arg) | |||
| 7889 | NSTRACE_FSTYPE ("fullscreenState", fs_state); | 7977 | NSTRACE_FSTYPE ("fullscreenState", fs_state); |
| 7890 | 7978 | ||
| 7891 | NSRect sr = [screen frame]; | 7979 | NSRect sr = [screen frame]; |
| 7980 | struct EmacsMargins margins | ||
| 7981 | = ns_screen_margins_ignoring_hidden_dock(screen); | ||
| 7982 | |||
| 7892 | NSRect wr = [self frame]; | 7983 | NSRect wr = [self frame]; |
| 7893 | NSTRACE_RECT ("Rect after zoom", wr); | 7984 | NSTRACE_RECT ("Rect after zoom", wr); |
| 7894 | 7985 | ||
| @@ -7897,15 +7988,15 @@ not_in_argv (NSString *arg) | |||
| 7897 | if (fs_state == FULLSCREEN_MAXIMIZED | 7988 | if (fs_state == FULLSCREEN_MAXIMIZED |
| 7898 | || fs_state == FULLSCREEN_HEIGHT) | 7989 | || fs_state == FULLSCREEN_HEIGHT) |
| 7899 | { | 7990 | { |
| 7900 | newWr.origin.x = 0; | 7991 | newWr.origin.y = sr.origin.y + margins.bottom; |
| 7901 | newWr.size.height = sr.size.height - ns_menu_bar_height(screen); | 7992 | newWr.size.height = sr.size.height - margins.top - margins.bottom; |
| 7902 | } | 7993 | } |
| 7903 | 7994 | ||
| 7904 | if (fs_state == FULLSCREEN_MAXIMIZED | 7995 | if (fs_state == FULLSCREEN_MAXIMIZED |
| 7905 | || fs_state == FULLSCREEN_WIDTH) | 7996 | || fs_state == FULLSCREEN_WIDTH) |
| 7906 | { | 7997 | { |
| 7907 | newWr.origin.y = 0; | 7998 | newWr.origin.x = sr.origin.x + margins.left; |
| 7908 | newWr.size.width = sr.size.width; | 7999 | newWr.size.width = sr.size.width - margins.right - margins.left; |
| 7909 | } | 8000 | } |
| 7910 | 8001 | ||
| 7911 | if (newWr.size.width != wr.size.width | 8002 | if (newWr.size.width != wr.size.width |
| @@ -7918,13 +8009,20 @@ not_in_argv (NSString *arg) | |||
| 7918 | } | 8009 | } |
| 7919 | } | 8010 | } |
| 7920 | #else | 8011 | #else |
| 7921 | // Non-native zoom which is done instantaneously. The resulting frame | 8012 | // Non-native zoom which is done instantaneously. The resulting |
| 7922 | // covers the entire screen, except the menu-bar, if present. | 8013 | // frame covers the entire screen, except the menu-bar and dock, if |
| 8014 | // present. | ||
| 7923 | NSScreen * screen = [self screen]; | 8015 | NSScreen * screen = [self screen]; |
| 7924 | if (screen != nil) | 8016 | if (screen != nil) |
| 7925 | { | 8017 | { |
| 7926 | NSRect sr = [screen frame]; | 8018 | NSRect sr = [screen frame]; |
| 7927 | sr.size.height -= ns_menu_bar_height (screen); | 8019 | struct EmacsMargins margins |
| 8020 | = ns_screen_margins_ignoring_hidden_dock(screen); | ||
| 8021 | |||
| 8022 | sr.size.height -= (margins.top + margins.bottom); | ||
| 8023 | sr.size.width -= (margins.left + margins.right); | ||
| 8024 | sr.origin.x += margins.left; | ||
| 8025 | sr.origin.y += margins.bottom; | ||
| 7928 | 8026 | ||
| 7929 | sr = [[self delegate] windowWillUseStandardFrame:self | 8027 | sr = [[self delegate] windowWillUseStandardFrame:self |
| 7930 | defaultFrame:sr]; | 8028 | defaultFrame:sr]; |