Open amstaff8 opened 5 years ago
The wxpython.py example supports High DPI by default. Does it work for you?
Please provide exact steps to reproduce your issue from the screenshot.
Same result. My steps:
This is the output:
[wxpython.py] System DPI settings: (192, 192) [wxpython.py] wx.GetDisplayPPI = (267, 267) [wxpython.py] wx.GetDisplaySize = (2736, 1824) [wxpython.py] MainFrame declared size: (900, 640) [wxpython.py] MainFrame DPI scaled size: (1800, 1280) [wxpython.py] MainFrame actual size: (1800, 1280)
And this is the result:
This is my resolution:
This is DPI awareness issue. The example sets DPI awareness via a call to cef.DpiAware.EnableHighDpiSupport
, but the call occurs too late in Python programs on some machines, it's a race condition. DPI awareness needs to be set for the executable before Python program executes. Same for the subprocess.exe executable that runs the Renderer subprocess. If you remove the call to EnableHighDpiSupport
you will get rid of double rendering, but it will result in a different rendering issue with app appearing blurry.
It is recommended to set High DPI awareness through manifest that is attached inside or next to executable. Such manifest must be added for both main executable and subprocess executable. Sometimes it is too late to set DPI awareness during runtime, so it must be set through manifest. If you want to fix the issue on a developer machine then go find python.exe executable and set appropriate file properties. On Windows 7 select "Compatibility" tab and check "Disable display scaling on high DPI settings".
For example to set DPI awareness through manifest create two files: myapp.exe.manifest
and subprocess.exe.manifest
in the same directory where myapp.exe
and subprocess.exe
executables reside. Edit both of these manifest files, so that they contain these contents:
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</asmv1:assembly>
Some users report that this still doesn't work for them and it works only after embedding manifest inside the exe with such command:
mt.exe -nologo -manifest myapp.exe.manifest -outputresource:"myapp.exe;1"
mt.exe -nologo -manifest subprocess.exe.manifest -outputresource:"subprocess.exe;1"
When using pyinstaller you might not be able to embed manifest inside myapp.exe executable, in my case it resulted in errors. In such case you have to modify the existing manifest file that is placed next to exe, it was generated by pyinstaller. You cannot overwrite it entirely with a new file, because it contains other necessary options, so manual editing is required. Embedding manifest inside subprocess.exe executable will alway work fine.
I've recently spent some time working through a similar issue in our cefpython-based app.
The app is intended to run on a Dell tablet running Windows 10 where the system Display Scale setting is very likely to be greater than 100%. It is using CEF 66, python 3.7.3 and wxPython 4.0.6.
The app was exhibiting the rendering artefact described and illustrated in this issue whereby the UI is drawn twice - once at the desired scale, and a duplicated, smaller version aligned in the top left of the screen. Touch and mouse events would go to the right place in the full-sized UI, but the updates would only be rendered in the smaller version.
Setting a chrome switch to disable GPU compositing has 'fixed' this issue.
Using any of these switches 'fixes' the issue.
--disable-gpu
--disable-gpu-compositing
--disable-gpu-driver-bug-workarounds
The solution in my situation is;
cef.Initialize(settings={}, switches={'disable-gpu-compositing': None})
I've seen this issue on Dell machines with integrated Intel GPUs and with an Nvidia card.
I haven't identified a root cause.
@pi-slh Have you embedded a DPI aware manifest in your app? See my comment: https://github.com/cztomczak/cefpython/issues/530#issuecomment-505066492
@cztomczak I saw the comment and tried putting a .manifest next to both the python.exe and the subprocess.exe that are the entry points for our app. I'm not sure that they are doing anything - my reading suggests the python.exe has an embedded manifest and therefore ignores the .manifest next to it. We're not building our own executable at the moment, just running python.exe scriptname.py
to startup.
I've been unable to get the layout I want in the browser by setting the High DPI scaling override on the application executable, so I haven't looked into manifests any further, assuming that it wouldn't give me the result I was after.
Thanks for your attention :)
@pi-slh The issue is with DPI support and fixing it by disabling GPU is not a good idea. Unless you have a different issue. What do you mean by "I've been unable to get the layout I want in the browser by setting the High DPI scaling override on the application executable"? Are you sure you've checked the right option? Have you tested with original wxpython.py example?
For anyone stuck on this, it never worked for me using a manifest file next to the exe, but it did work if I embedded the manifest inside the exe:
mt.exe -nologo -manifest subprocess.exe.manifest -outputresource:"subprocess.exe;1"
We should update the pyinstaller example to embed the necessary High DPI manifest files in the exe's. Marking this for next release.
@cztomczak I think I found an easier solution... check this out...
import ctypes
errorCode = ctypes.windll.shcore.SetProcessDpiAwareness(0)
success = ctypes.windll.user32.SetProcessDPIAware()
More info here: https://stackoverflow.com/questions/44398075/can-dpi-scaling-be-enabled-disabled-programmatically-on-a-per-session-basis
It might fix the issue, but it's still not guaranteed.
It might fix the issue, but it's still not guaranteed.
FWIW we tried this fix but it didn't work reliably for us - so far only the embedded manifest file approach has worked.
It might fix the issue, but it's still not guaranteed.
FWIW we tried this fix but it didn't work reliably for us - so far only the embedded manifest file approach has worked.
It didn't work reliably or didn't work at all for you? Since I am not having any issues with setting dpi scale programmatically
It didn't work reliably or didn't work at all for you? Since I am not having any issues with setting dpi scale programmatically
IIRC it seemed to work on some machines but not others, or it seemed to work sometimes but not always (which is consistent with the problem being a race condition). But with the manifest file embedded, it has worked reliably.
Tried embedding the manifest on subprocess.exe. However, the browser stopped loading, giving the below error
[1005/141244.841:ERROR:browser_gpu_channel_host_factory.cc(119)] Failed to launch GPU process. [1005/141244.859:ERROR:gpu_process_transport_factory.cc(1017)] Lost UI shared context.
@bnbchu What does the manifest look like?
@bnbchu What does the manifest look like?
@cztomczak thanks for the follow-up
I couldn't find a manifest file for subprocess.exe so created one based on the guide above.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<dpiAware>true</dpiAware>
</windowsSettings>
</application>
</assembly>
For my main exe, I edited the manifest file generated by pyinstaller.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity name="JD Tool" processorArchitecture="amd64" type="win32" version="1.0.0.0"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity language="*" name="Microsoft.Windows.Common-Controls" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" type="win32" version="6.0.0.0"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>
@bnbchu Try embedding this manifest in subprocess.exe:
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</asmv1:assembly>
@bnbchu Try embedding this manifest in subprocess.exe:
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS> </application> </compatibility> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <requestedExecutionLevel level="asInvoker"></requestedExecutionLevel> </requestedPrivileges> </security> </trustInfo> <asmv3:application> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <dpiAware>true/PM</dpiAware> </asmv3:windowsSettings> </asmv3:application> </asmv1:assembly>
@cztomczak That worked! Appreciate the support and much thanks!
Can someone show how to include the manifest data with just a basic cefpython script? I don't have any exe's. Just running a script that uses cefpython that launches an HTML file in the cef browser. Calling: cef.DpiAware.EnableHighDpiSupport() does not work.
Hi
I can't get cef python to work with dpi adware. I have cef python 66 with pywin32 224 (python 3.6.8).
I added the method cef.DpiAware.EnableHighDpiSupport() after line 28 of your example cefpython/examples/pywin32.py
But it doesn’t work (see the screenshot). I’ve tested it also with PyQt but the result is the same.