diff options
author | Tal Einat <taleinat+github@gmail.com> | 2019-06-17 19:41:00 (GMT) |
---|---|---|
committer | Terry Jan Reedy <tjreedy@udel.edu> | 2019-06-17 19:41:00 (GMT) |
commit | 5bff3c86ab77e9d831b3cd19b45654c7eef22931 (patch) | |
tree | 097f3b35d0a94d952f7889bf9588dc27a34d90a8 | |
parent | a268edd6a411480281222b1fdb0f78053434d17f (diff) | |
download | cpython-5bff3c86ab77e9d831b3cd19b45654c7eef22931.zip cpython-5bff3c86ab77e9d831b3cd19b45654c7eef22931.tar.gz cpython-5bff3c86ab77e9d831b3cd19b45654c7eef22931.tar.bz2 |
bpo-37039: Make IDLE's Zoom Height adjust to users' screens (GH-13678)
Measure required height by quickly maximizing once per screen.
A search for a better method failed.
-rw-r--r-- | Doc/library/idle.rst | 5 | ||||
-rw-r--r-- | Lib/idlelib/NEWS.txt | 8 | ||||
-rw-r--r-- | Lib/idlelib/help.html | 16 | ||||
-rw-r--r-- | Lib/idlelib/zoomheight.py | 121 | ||||
-rw-r--r-- | Misc/NEWS.d/next/IDLE/2019-06-04-23-27-33.bpo-37039.FN_fBf.rst | 4 |
5 files changed, 125 insertions, 29 deletions
diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index bd24695..d494c97 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -289,7 +289,10 @@ Show/Hide Code Context (Editor Window only) Zoom/Restore Height Toggles the window between normal size and maximum height. The initial size defaults to 40 lines by 80 chars unless changed on the General tab of the - Configure IDLE dialog. + Configure IDLE dialog. The maximum height for a screen is determined by + momentarily maximizing a window the first time one is zoomed on the screen. + Changing screen settings may invalidate the saved height. This toogle has + no effect when a window is maximized. Window menu (Shell and Editor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 982af77..7646aed 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,14 @@ Released on 2019-10-20? ====================================== +bpo-37039: Adjust "Zoom Height" to individual screens by momemtarily +maximizing the window on first use with a particular screen. Changing +screen settings may invalidate the saved height. While a window is +maximized, "Zoom Height" has no effect. + +bpo-35763: Make calltip reminder about '/' meaning positional-only less +obtrusive by only adding it when there is room on the first line. + bpo-35610: Replace now redundant editor.context_use_ps1 with .prompt_last_line. This finishes change started in bpo-31858. diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 228b319..e27ec8d 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -6,7 +6,7 @@ <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - <title>IDLE — Python 3.8.0a4 documentation</title> + <title>IDLE — Python 3.9.0a0 documentation</title> <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" /> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> @@ -19,7 +19,7 @@ <script type="text/javascript" src="../_static/sidebar.js"></script> <link rel="search" type="application/opensearchdescription+xml" - title="Search within Python 3.8.0a4 documentation" + title="Search within Python 3.9.0a0 documentation" href="../_static/opensearch.xml"/> <link rel="author" title="About these documents" href="../about.html" /> <link rel="index" title="Index" href="../genindex.html" /> @@ -50,6 +50,7 @@ </head><body> + <div class="related" role="navigation" aria-label="related navigation"> <h3>Navigation</h3> <ul> @@ -72,7 +73,7 @@ <li> - <a href="../index.html">3.8.0a4 Documentation</a> » + <a href="../index.html">3.9.0a0 Documentation</a> » </li> <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li> @@ -320,7 +321,10 @@ of the code which has scrolled above the top of the window. See <dt>Zoom/Restore Height</dt> <dd>Toggles the window between normal size and maximum height. The initial size defaults to 40 lines by 80 chars unless changed on the General tab of the -Configure IDLE dialog.</dd> +Configure IDLE dialog. The maximum height for a screen is determined by +momentarily maximizing a window the first time one is zoomed on the screen. +Changing screen settings may invalidate the saved height. This toogle has +no effect when a window is maximized.</dd> </dl> </div> <div class="section" id="window-menu-shell-and-editor"> @@ -912,7 +916,7 @@ also used for testing.</p> <li> - <a href="../index.html">3.8.0a4 Documentation</a> » + <a href="../index.html">3.9.0a0 Documentation</a> » </li> <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li> @@ -943,7 +947,7 @@ also used for testing.</p> <br /> <br /> - Last updated on May 25, 2019. + Last updated on Jun 17, 2019. <a href="https://docs.python.org/3/bugs.html">Found a bug</a>? <br /> diff --git a/Lib/idlelib/zoomheight.py b/Lib/idlelib/zoomheight.py index 523f5d5..cd50c91 100644 --- a/Lib/idlelib/zoomheight.py +++ b/Lib/idlelib/zoomheight.py @@ -2,42 +2,119 @@ import re import sys +import tkinter -from idlelib import macosx + +class WmInfoGatheringError(Exception): + pass class ZoomHeight: + # Cached values for maximized window dimensions, one for each set + # of screen dimensions. + _max_height_and_y_coords = {} def __init__(self, editwin): self.editwin = editwin + self.top = self.editwin.top def zoom_height_event(self, event=None): - top = self.editwin.top - zoomed = zoom_height(top) - menu_status = 'Restore' if zoomed else 'Zoom' - self.editwin.update_menu_label(menu='options', index='* Height', - label=f'{menu_status} Height') + zoomed = self.zoom_height() + + if zoomed is None: + self.top.bell() + else: + menu_status = 'Restore' if zoomed else 'Zoom' + self.editwin.update_menu_label(menu='options', index='* Height', + label=f'{menu_status} Height') + return "break" + def zoom_height(self): + top = self.top + + width, height, x, y = get_window_geometry(top) + + if top.wm_state() != 'normal': + # Can't zoom/restore window height for windows not in the 'normal' + # state, e.g. maximized and full-screen windows. + return None + + try: + maxheight, maxy = self.get_max_height_and_y_coord() + except WmInfoGatheringError: + return None + + if height != maxheight: + # Maximize the window's height. + set_window_geometry(top, (width, maxheight, x, maxy)) + return True + else: + # Restore the window's height. + # + # .wm_geometry('') makes the window revert to the size requested + # by the widgets it contains. + top.wm_geometry('') + return False + + def get_max_height_and_y_coord(self): + top = self.top + + screen_dimensions = (top.winfo_screenwidth(), + top.winfo_screenheight()) + if screen_dimensions not in self._max_height_and_y_coords: + orig_state = top.wm_state() -def zoom_height(top): + # Get window geometry info for maximized windows. + try: + top.wm_state('zoomed') + except tkinter.TclError: + # The 'zoomed' state is not supported by some esoteric WMs, + # such as Xvfb. + raise WmInfoGatheringError( + 'Failed getting geometry of maximized windows, because ' + + 'the "zoomed" window state is unavailable.') + top.update() + maxwidth, maxheight, maxx, maxy = get_window_geometry(top) + if sys.platform == 'win32': + # On Windows, the returned Y coordinate is the one before + # maximizing, so we use 0 which is correct unless a user puts + # their dock on the top of the screen (very rare). + maxy = 0 + maxrooty = top.winfo_rooty() + + # Get the "root y" coordinate for non-maximized windows with their + # y coordinate set to that of maximized windows. This is needed + # to properly handle different title bar heights for non-maximized + # vs. maximized windows, as seen e.g. in Windows 10. + top.wm_state('normal') + top.update() + orig_geom = get_window_geometry(top) + max_y_geom = orig_geom[:3] + (maxy,) + set_window_geometry(top, max_y_geom) + top.update() + max_y_geom_rooty = top.winfo_rooty() + + # Adjust the maximum window height to account for the different + # title bar heights of non-maximized vs. maximized windows. + maxheight += maxrooty - max_y_geom_rooty + + self._max_height_and_y_coords[screen_dimensions] = maxheight, maxy + + set_window_geometry(top, orig_geom) + top.wm_state(orig_state) + + return self._max_height_and_y_coords[screen_dimensions] + + +def get_window_geometry(top): geom = top.wm_geometry() m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) - if not m: - top.bell() - return - width, height, x, y = map(int, m.groups()) - newheight = top.winfo_screenheight() - - # The constants below for Windows and Mac Aqua are visually determined - # to avoid taskbar or menubar and app icons. - newy, bot_y = ((0, 72) if sys.platform == 'win32' else - (22, 88) if macosx.isAquaTk() else - (0, 88) ) # Guess for anything else. - newheight = newheight - newy - bot_y - newgeom = '' if height >= newheight else f"{width}x{newheight}+{x}+{newy}" - top.wm_geometry(newgeom) - return newgeom != "" + return tuple(map(int, m.groups())) + + +def set_window_geometry(top, geometry): + top.wm_geometry("{:d}x{:d}+{:d}+{:d}".format(*geometry)) if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/IDLE/2019-06-04-23-27-33.bpo-37039.FN_fBf.rst b/Misc/NEWS.d/next/IDLE/2019-06-04-23-27-33.bpo-37039.FN_fBf.rst new file mode 100644 index 0000000..71c8c89 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-06-04-23-27-33.bpo-37039.FN_fBf.rst @@ -0,0 +1,4 @@ +Adjust "Zoom Height" to individual screens by momemtarily maximizing the +window on first use with a particular screen. Changing screen settings +may invalidate the saved height. While a window is maximized, +"Zoom Height" has no effect. |