-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
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
IDLE: Turn on DPI awareness on Windows #77837
Comments
On IDLE-dev today, Elisha Paine, from Ranelagh School in England, wrote: import ctypes
try: ctypes.windll.shcore.SetProcessDpiAwareness (True)
except: pass
'''
On my Win 10 system with a 2560 x 1440 27" monitor, the text is noticeably sharper, some colors are brighter, and some characters are better formed. The main effect seems to be from properly lining up vertical and horizontal lines with the pixels. Lines that are supposed to be 1 or 2 pixels wide are just that, instead of bleeding over onto additional rows or columns. By comparing IDLE's shell with Windows consoles with the same font and text, both for Command Prompt and Python x.y consoles, I determined that the Windows consoles have DPI awareness on. The text is longer with it off and some character shapes, such as for 2 and 3, don't match, whereas text length and shape matches perfectly with it on. At least some other apps also have DPO awareness on. With the patch, the Open and Save As dialogs opened opened by from IDLE, via the tkinter/tk function, match those opened by Firefox. Without the patch, not. I like the improvement and with 3.7.0rc1 delayed, would like to get it in now. My question for you Windows experts is 1. Is the above exactly the right thing? and 2. Should it be unconditional, or is there a possible downside? Do consoles always have DPI awareness, or is it conditional on the monitor? I will make a PR as soon as I post this and get an issue number. |
I changed the bare except: to 'except AttributeError:'. If ctypes.windll.shcore.SetProcessDpiAwareness exists, can calling it with True ever fail? |
I'm not a Windows expert, but looking that the API description [1] the patch is not entirely correct. The API takes an integer with 3 valid values, the patch effectively passes the value 1 (which means the application claims to be DPI aware, but won't scale itself when the DPI changes for some reason). The API can fail, but that shouldn't cause an exception as ctypes won't automaticly convert error return values to exceptions. P.S. The pull request seems to contain an unrelated change as well. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn302122(v=vs.85).aspx |
Does Tcl/Tk have a function for this, and/or should we expose this as a function in Tkinter? Do other platforms (macOS, X/Wayland) have similar functions? |
Perhaps the argument should be 2 for supporting multi-display configuration. Currently I can't do this, but will test this recipe with Hi-DPI monitor and multiple displays after 1-2 weeks. |
Thanks for the comments: Ronald: I agree that an int should be passed. I understand your ctype comment as saying that an attribute error before making the call should be the only possible exception. I should have explained the 'unrelated change' to the one entry box. With the default size of 20, it no longer fits properly after the change. Adding an explicit size was the easiest fix for something that is only present for test and demonstration purposes. A better fix, which is not needed for this issue, would probably be to add a 'expand=True' or something, somewhere else. I checked all the other panes on the settings dialog and the other major dialog boxes and found no problems. Zack: I had the same question. Now that I know that IDLE as a tk app *can* look 'sharp', the current fuzzyness is annoying. I would not be surprised if it contributes to some of the negative opinions about IDLE. Tk tries to look 'native' and this seems to be the main thing missing. To me, the only obvious reason for tk to not use this setting as default I don't know if other systems have such a setting, or any need for such. I will ask an someone who uses IDLE both in Windows and Ubuntu on the same machine to compare. Serhiy: I have a space monitor and I believe my graphics card will allow me to attach one, so I may give it a try.The linked article recommends "that you set the process-default DPI awareness via application manifest." I don't currently know what this The call does not appear to be available on Windows 7 or 8.0. |
Eryk Sun commented on the PR. |
Elisha wrote and I quoted: '[the call] sets DPI awareness'. After reading https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx PROCESS_DPI_AWARENESS, what the call sets is the system's idea of what DPI awareness the app/process has. As I understand, My own experience and Elisha's report that IDLE looks better (at any resolution setting) matches others. For instance, https://wiki.tcl.tk/8484 tk has a scaling function that gets and sets a scaling factor, dpi/72 = pixels per printer point. "The initial value for the scaling factor is set when the application starts, based on properties of the installed monitor." This also suggests to me also that default 0 for awareness is wrong value. Users (apps) can changes this, but I see no suggestion that monitor changes are tracked. |
https://msdn.microsoft.com/en-us/library/windows/desktop/mt748620(v=vs.85).aspx gives the syntax for adding dpiAwareness to the Windows manifest. |
As reported on bpo-26698, which was originally opened as an IDLE issue, but which I turned into a tkinter issue, one can also sharpen text buy opening python(w).exe properties, Compatibility tab, clicking [Change high DPI settings], and then checking [] Override high DPI scaling behavior while leaving the default 'Application'. The effect is the same as 'SetProcessDpiAwareness (1)' -- or (2) if monitor is not changed. |
Eric, thanks for the additional reference. From Window's viewpoint, Python, not IDLE, is the application. IDLE is just input data. I should not touch Python's manifest, and changing it would have to consider other possible gui module input data. This page says it applies only to Win10 desktop. The page for SetProcessDpiAwareness says it applies to 8.1+. That still excludes Vista and Win7, but is better than just Win10. |
So maybe add the dpiAware and dpiAwareness settings to the manifest for just Windows' pythonw.exe and leave the python.exe console interpreter alone? I'm going to guess that the pythonw.exe manifest already has some settings related to its unique status that align with this. |
I'm okay to add it to the manifest for both in 3.8, along with a What's New entry. High DPI screens are very common though, and adding it to existing releases won't allow existing apps or frameworks to account for the change. I don't want non-DPI aware apps to suddenly become unreadably small with a minor runtime update. Backporting Python-specific docs is fine. |
Steve, I would like to add the SetProcessDpiAwareness(1) call to IDLE tomorrow, for 3.7.0 and 3.6.6. Do I need to make it an avoidable option? Can it hurt people on some machines? It seems to me that if tk is doing dpi scaling, then it should always be correct to tell Windows that it is doing so. |
Yep, that should be fine. If you want to add it to the winapi module rather than use ctypes that's fine too. |
Thanks everyone for the help. I think this is the right patch, but as with many IDLE patches, it is hard to be sure until it is in use. At least there is no question here of tk Windows-Linux-MacOS differences. I checked that the Win 7 buildbots are OK with the PR. Serhiy: My interpretation of the tk scaling doc is that 1, not 2, is the right argument. But we can test to be sure. I meant 'spare monitor', not 'space monitor'. But I need to find one with a substantially different DPI. Steve: changing the binaries' manifests is a separate issue, not limited to IDLE or even tkinter. And 3.8 enhancements do nothing for IDLE on 3.6 and 3.7. Ditto for a new WinAPI. |
Reopening, temporarily, to add change requested by Eryk Sun after the merge. |
Since there should be time before .rcs are cut, I changed the idlelib NEWS.txt entry to mention color changes, based on editing with the change in place. |
I can't test on multiple monitors, but I tested on a single HiDPI monitor. With 1 it looks much better than with 0. With 2 it looks the same as with 1 on HiDPI, but doesn't scale well after changing the resolution of the display. I suppose there are the same problems on multi-monitor configuration. Thus the value 1 is the correct one. ctypes is optional. It would be better to catch an ImportError from importing it. |
I confirmed that IDLE did not import ctypes before this issue. Serhiy, I presume that the new code can be skipped, you are suggesting replacing import ctypes
<use ctypes....> with try: But, in what sense is ctypes optional *on Windows* more than most other modules? I don't see anything in the ctypes doc. It is normal to depend on stdlib modules being present and not wrap imports. Steve: does the Windows installer have an option to omit ctypes? I don't remember one. Anyone: do you know of any CPython Windows distributions that we care about that omit ctypes? Which of the following best describes the situation?
|
I just ran the 3.7.0rc1 installer and here is no option to omit ctypes. |
There's no option to omit ctypes, though I am aware of some custom builds of Python that exclude it. I don't think you need to worry about those being used for IDLE (but of course the general policy of the stdlib not relying on ctypes remains). |
I don't know whether this is a theoretical or a real concern, but I think this fix can wait for 3.7.1. |
Ping? Do we want to get this in for 3.7.1 and 3.6.7? |
There is still no rush as guarding the ctypes import on Windows builds that can run IDLE may never be needed. But I grepped the stdlib .py code and uuid is the only .py module that imports ctypes, and all are directly or indirectly guarded in the code or test_uuid. So I moved the import inside the existing try block and added ImportError to those caught. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: