-
Notifications
You must be signed in to change notification settings - Fork 77
Handle screen DPI changes on Windows #127
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
base: main
Are you sure you want to change the base?
Conversation
d5dd6dc
to
0f638db
Compare
Thanks a lot @lampysprites for the dedication to see this issue. I'll try to review this soon, not for the next release but probably for the other, and I'll try to merge this on beta branch (so we can release a preview of the fix to a small number of users first). |
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.
This works great! I've just suggested changing the use of std::max
by std::ceil
in three places, because I think it is a nice use case for it.
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.
While reviewing the Aseprite changes that make use of this changes I've found this issue: aseprite/aseprite#4934 (review)
Which is something that should be fixed in laf. The issue can be reproduced modifying the hello_laf example a bit, by just setting the window as floating. Then while this modified version of the hello_laf example is running, try to change the display scale from Windows configuration and you will see that the window is not updated until it is moved/resized.
Will try to create a bare minimum WinAPI app similar to hello_laf to see what happens in this case.
This is basically a default Windows Desktop Application generated by Microsoft Visual Studio Community 2022 with some modifications:
This solution demonstrates that the WM_DPICHANGED message is not arriving when the user changes the display's DPI and the window has the WS_EX_TOOLWINDOW style set. If this style is not set, it works as expected. Will try to send this to Microsoft and see what happens... |
Co-authored-by: Martín Capello <m.a.capello@gmail.com>
Co-authored-by: Martín Capello <m.a.capello@gmail.com>
Co-authored-by: Martín Capello <m.a.capello@gmail.com>
Thanks a lot for spending time on this! I'm really sorry it turned into this kind of troubleshooting🥲 |
No worries! Thanks to you actually for bringing this new feature.
Nothing else by me, maybe after David's review he could point out some changes. |
Issue aseprite/aseprite#4606, also possibly avoids having aseprite/aseprite#2740, and I think fixes aseprite/aseprite#4495.
On several displays with diffferent scale dragging the window from one screen to another makes everything either tiny or huge, depending on the direction it's dragged. This can be an issue when the screen with higher resolution is smaller in size, like a laptop with external monitor, or a pc with a screen tablet.
I tested these changes on 100%/200% and 150%/300% screen combination, windowed/maximized window, menu and preview windows, moving window with mouse and shift+wid+arrow key, and changing screen scale in settings w/ app running. As far as I can see it behaves same as other applications (namely, notepad) now. Except, rounding of 150% scale and 1x scale setting to 1x resolution feelt a bit confusing (personally) so i rounded it up.
PR aseprite/aseprite#4934 is needed to handle these changes properly.
Window decorations
src/main/settings.manifest
already set it to V1.Corresponding commit to Aseprite repo changes manifest file to enable V2 dpi awareness, although when it's not available V1 works identical to it. Also theorethically this can be applied without the next commit if it's too messy.
Window content
I think it's important that window content is intact when changing screen. Think of moving a preview window - doing additional zoom/pan would be annoying. It means we need to:
The easiest wai I think is to scale pixel coordinates in laf window as
scale = baseScale * displayDPI / defaultDPI
, where baseScale is now the scaling chosen by user in the settings. Scale is used for input and painting same as before, while baseScale replaces it in window settings and initial values. This however breaks backwards compatibility, and I can't think of a simple way to keep it (e.g. need to handle window sizing outside window class for that).There's also a few ways to sprovie API for this - i picked one with fewer changes. And maybe Window::setScale should now be setBaseScale but I don't think i got naming right anyway.
Corresponding commit to Aseprite repo replaces some scale() calls with baseScale() when needed.
I agree that my contributions are licensed under the MIT License.
You can find a copy of this license at https://opensource.org/licenses/MIT