-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
update Window
's width
& height
methods to return f32
#1033
Conversation
55d85bc
to
e75d8fe
Compare
Is there an Operating System that creates non-integer sized windows? |
When running in high DPI monitors the logical resolution is scaled down from the physical resolution (physical pixels). On my current workstation, I run a 125% scaling factor so each physical pixel is 0.8 logical pixels, then depending on what size my window is, the resulting logical width may not be integral. |
Cool cool having looked into the details of winit a bit (and considering the example above), this looks like its the right call. |
I think we need to align WindowDescriptor::width/height and set_resolution. They are the "same" property in my mind (they are both logical resolutions). We should either allow people to specify fractional sizes (which I expect to behave counterintuitively for computers with a scale factor of 1) or we shouldn't. They also currently behave differently right now. If i set my os scale factor to 2.0, then create a window that is initially Calling
Changing set_resolution back to u32, removing the manual scaling "up" to a physical scale, then in the winit backend using LogicalScale instead of PhysicalScale when responding to SetResolution commands resolves the bug (and make the behavior consistent). |
After Looking into this a little bit, its a catch 22. We can't know what the quantization of the logical size will be until we know the scale factor, but we can't know the scale factor until we have created the window on a particular monitor. Specifying the size in logical values will always be a guess, and we will find out the truth once the system has created or resized the window. This creates a some challenges. For one, prior to creation we currently have no way to store the guess for the size to use during the create. It also raises some questions about the behavior of the width and height properties with respect to their values once we learn the scale factor. From where we are now, it seems to me that the solution is to store the "requested" logical size and an optional physical size that is updated when we learn the truth about it. The In the scenario @cart highlights where the OS clamps one of the dimensions, the In my mind the difference between f32 and u32 is fairly minor (sans potential layout alignment issues). The real issue is that what is passed via the window descriptor or the set_resolution call is only a request, and what you actually get could be quite different dependent on you environment. I have begun implementing what I described above, but I fear that this effort has opened a small can of worms that should have saved for later. |
Maybe we can sort of "punt" this problem:
This way, both apis can be consistent, and both apis can just be "requests". |
also removes `logical_width` & `logical_height` as they are not longer different
e75d8fe
to
df81e1c
Compare
* values in the `WindowDescriptor` and the `set_resolution` call are now "requested" sizes * once the window is created, the actual width and height are learned along with the scale factor * `width` and `height` return the actual size or the requested size if the window has not been created yet * add some documentation for the window size APIs * update a handfull of examples to change the window size of f32
df81e1c
to
e242233
Compare
I have update this PR based on comments from @cart. It seems like a little much for something so minor, but I think something like this is necessary to cover to properly handle high DPI. While playing with this I started to notice an issue with the UI layout. In the squash crate, all coordinates are rounded to the nearest whole number, and we pass logical coordinates. On a high DPI monitor this prevents that final placements from aligning to the physical pixel grid which produces artifacts. I have a commit based on this PR that converts everything to physical coordinates before passing to squash, then converts back to logical coordinates once squash produces a layout. This aligns everything to the pixel grid which cleans up the issues. It still needs a little work though before it is ready for review. |
My changes to flex are ready for review. I was going to wait until this PR is resolved before submitting them as a separate PR since the issue it addresses is related but independent of what this PR addresses. I could add it to this PR though, if that is preferred. |
Awesome! Looking now. Lets do the stretch changes in a separate PR. |
Turns out we can remove the "option" returns and simplify the code by making winit/bevy window creation "atomic". Theres no need to "wait". Everything works as expected for me in all permutations of 1x + 2x scale factors / windowed / fullscreen |
I tested it on some non-integral scaling factors, and it looks good in my setup. The window creation change really did the trick! |
Awesome. Thanks for adding the WASM fix :) |
This allows for better precision of the width and height when the scaling factor and physical resolution come together to produce a logical resolution that is not an integer. Admittedly, this will have little effect on most usages. An issue would occur if things were being laid out relative to the right or bottom edge. In this case it would be common to subtract some offset from the width or height.
It was requested to provide a demonstration of the ill effects this PR would resolve. Producing an example in engine is difficult (for me at least) and unreliable due to having no control over the scaling factor. Instead I created the following illustration of a scenario where trouble could occur.
In the example below imagine a line is being placed along the right most edge by subtracting 0.4 logical pixels (0.5 physical pixels) from the width to get the line to fall in the middle of the last pixel. Because the width is not precise enough the bounds of the line do not align with the pixel grid. This causes the line to bleed into the neighboring pixels and not achieve the target color.