Skip to content

Commit

Permalink
bpo-37039: Make IDLE's Zoom Height adjust to users' screens (GH-13678)
Browse files Browse the repository at this point in the history
Measure required height by quickly maximizing once per screen.
A search for a better method failed.
(cherry picked from commit 5bff3c8)

Co-authored-by: Tal Einat <taleinat+github@gmail.com>
  • Loading branch information
miss-islington and taleinat committed Jun 17, 2019
1 parent ac4202e commit 0f31a2d
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 29 deletions.
5 changes: 4 additions & 1 deletion Doc/library/idle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
8 changes: 8 additions & 0 deletions Lib/idlelib/NEWS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Released on 2019-06-24?
======================================


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.

Expand Down
16 changes: 10 additions & 6 deletions Lib/idlelib/help.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 &#8212; Python 3.8.0a4 documentation</title>
<title>IDLE &#8212; 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" />

Expand All @@ -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" />
Expand Down Expand Up @@ -50,6 +50,7 @@


</head><body>

<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
Expand All @@ -72,7 +73,7 @@ <h3>Navigation</h3>


<li>
<a href="../index.html">3.8.0a4 Documentation</a> &#187;
<a href="../index.html">3.9.0a0 Documentation</a> &#187;
</li>

<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
Expand Down Expand Up @@ -320,7 +321,10 @@ <h3>Options menu (Shell and Editor)<a class="headerlink" href="#options-menu-she
<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">
Expand Down Expand Up @@ -912,7 +916,7 @@ <h3>Navigation</h3>


<li>
<a href="../index.html">3.8.0a4 Documentation</a> &#187;
<a href="../index.html">3.9.0a0 Documentation</a> &#187;
</li>

<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> &#187;</li>
Expand Down Expand Up @@ -943,7 +947,7 @@ <h3>Navigation</h3>
<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 />

Expand Down
121 changes: 99 additions & 22 deletions Lib/idlelib/zoomheight.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__":
Expand Down
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 0f31a2d

Please sign in to comment.