-
-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-37039: Make IDLE's Zoom Height adjust to users' screens #13678
bpo-37039: Make IDLE's Zoom Height adjust to users' screens #13678
Conversation
On my computer (Windows 10, resolution: 3000 x 2000, scaling of UI elements set to 200%), clicking on Zoom Height makes Idle go full screen. Clicking on the same menu (now called Restore Height) does absolutely nothing: Idle stays in full screen mode. If I run the program on a secondary monitor (4k), the height only changes, but nowhere enough to be equal to the height of the screen. |
On Windows 10, I'm seeing the same thing as @aroberge, but there's some more. I'll enumerate the steps.
Another path:
This seems like a different bug/enhancement (to not allow zooming when the window is maximized), but I wanted to mention it since I was checking the behavior. Thanks! |
1. Tk's wm_geometry() doesn't report the actual position for maximized windows, but thankfully does report their actual dimensions. 2. The title bar height is different for normal vs. maximized windows.
Also clean up code and add comments where needed.
It works correctly on my system. It is a bit surprising to see the window taking the full screen for a second and then having its width reduced again, but it only does that when changing the zoom status for the first time. Moving the window to a second monitor with a different resolution after having clicked on zoom height at least once results in the zoom height feature not working properly as it remembers the settings from the first window. However, if one first moves the window to a second monitor and then clicks on the button, it works. |
This is true and very unfortunate. Many people use multiple monitors with different resolutions these days, so this should be considered a common scenario. To avoid this, we could check the screen dimensions and only cache values for screens with identical dimensions. We'll also need to properly handle screens with identical resolutions but different scaling settings. |
The test failures were all for test_enum. False positives with respect to this patch. Since test_idle passed on my machine, no need to retest with close/open -- wait until another commit. |
Testing and commenting without looking at the code yet. There seem to be three issues, starting with what I think is the highest priority.
After this, Zoom and Restore work as they should. Thanks Tal. I think reducing the flash annoyance would be enough to merge.
|
The newest change calculates and caches the needed info once per screen resolution. This will still misbehave slightly in truly rare edge-cases, such as changing the size or position of the taskbar/dock. |
IMO the number of users who actually use "zoom height" is small, so I don't think this justifies annoying 100% of the users with a maximized (i.e. almost full-screen) splash screen. I've been working around and through the limitations of Tk as far as possible, and have reached the limit of what is possible, to the best of my understanding and research. To do better would require using OS APIs directly, e.g. as done by the screeninfo library, but IMO this is not warranted in this case.
I've currently made "zoom height" be a no-op when the window isn't in the "normal" state, e.g. when it is maximized. I can handle the case where the screen is already maximized if you find the current "do nothing" behavior surprising. Or I can just add a
These days, with widespread use of laptops, it is very common: People connect and disconnect to/from external screens, using them instead of/in addition to the laptop screen. Also, multi-monitor desktop setups are increasingly common for developers, and often they do not have the same resolution, e.g. having one monitor situated in a "portrait" orientation.
The latest commit in the PR handles this properly. (Note that as far as Tk is concerned, scaling simply means a different resolution.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I addressed my points 1 and 2 in the comments. Without a multiscreen setup, I cannot comment much on 3. I am willing to have zoomheight be imperfect if someone changes their taskbar or screen settings. I will add this also to the doc, something like "After the first zoom on a screen, zoomheight assumes that taskbar and screen settings remain the same."
I have not yet looked at the rest of the code of zoom_height
and that of get_max...
, but I expect this should get into 3.7.4b1 on 6/17.
if self.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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I now agree that this is correct. Previously, touching the window when maximized messed up the behavior of the OS WM Restore button (at least on Windows, which is enough). Besides which, restoring only the height and not the width would be wrong and restoring both would be redundant. So add top.beep()
.
This should be added to the doc and blurb. I plan to edit both when code is settled.
Lib/idlelib/zoomheight.py
Outdated
newgeom = '' if height >= newheight else f"{width}x{newheight}+{x}+{newy}" | ||
top.wm_geometry(newgeom) | ||
return newgeom != "" | ||
return width, height, x, y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just return map...
and unpack where used.
Lib/idlelib/zoomheight.py
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By PEP 8, this should be return None
because of explicit return below. But unpacking None at the call site will crash IDLE anyway. So we might as well remove the check here.
https://www.tcl.tk/man/tcl8.6/TkCmd/tkvars.htm says
"The following variables are only guaranteed to exist in wish executables; the Tk library does not define them itself but many Tk environments do.
geometry
If set, contains the user-supplied geometry specification to use for the main Tk window. "
idlelib, including tests, is loaded with unguarded geometry calls, so IDLE and the test suite would fail on any tk without geometry. So there must be none on systems Python and IDLE currently run on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this part of the code is unchanged...
If the existing norm is not guarding against geometry()
returning bad values, I'll remove the check.
When you're done making the requested changes, leave the comment: And if you don't make the requested changes, you will be poked with soft cushions! |
I have made the requested changes; please review again. |
Adjust "Zoom Height" zooms to individual screens by momemtarily maximizing | ||
the window the first time one is zoomed on a particular screen. Zooms will | ||
not be correct if the resolution and scaling for a screen is subsequently | ||
changed. While a window is maximized, "Zoom Height" has no effect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, changing the resolution and/or scaling of a screen will simply cause Tk to observe a different screen resolution, after which the current implementation will again maximize a screen once to get the proper values for the new screen configuration. So this is incorrect: "Zooms will not be correct if the resolution and scaling for a screen is subsequently changed."
The only cases where we could get things slightly wrong is when the dock/taskbar is moved or changed, or perhaps moving a window to a screen with identical effective resolution but with other differences, e.g. with/without a dock/taskbar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course. The dict key will change and not be found. I will simplify to "Zooms may not be correct if the screen is subsequently changed." and then merge.
@terryjreedy, indeed this appears ready to merge IMO, apart for my comment regarding the NEWS entry. |
Thanks @taleinat for the PR, and @terryjreedy for merging it 🌮🎉.. I'm working now to backport this PR to: 3.8. |
Thanks @taleinat for the PR, and @terryjreedy for merging it 🌮🎉.. I'm working now to backport this PR to: 3.7. |
Sorry @taleinat and @terryjreedy, I had trouble checking out the |
GH-14167 is a backport of this pull request to the 3.7 branch. |
Thanks @taleinat for the PR, and @terryjreedy for merging it 🌮🎉.. I'm working now to backport this PR to: 3.8. |
GH-14168 is a backport of this pull request to the 3.8 branch. |
…-13678) Measure required height by quickly maximizing once per screen. A search for a better method failed.
…-13678) Measure required height by quickly maximizing once per screen. A search for a better method failed.
When "zoom height" is first activated, this implementation measures the window manager's size for maximized windows by maximizing IDLE, and from that point uses that size. Subsequent activations will use the cached value for the dimensions of maximized windows.
This avoids hard-coded values which aren't always correct, e.g. because docks/taskbars can be resized, moved or hidden and window-manager themes can be customized.
This does cause a one-time visual artifact on macOS, where on the first activation, the window is maximized, un-maximized, and then set to the maximum height. Subsequent activation uses cached information, so this doesn't happen again.
https://bugs.python.org/issue37039