community icon indicating copy to clipboard operation
community copied to clipboard

- calculate dpi on window update

Open maho opened this issue 5 years ago • 12 comments

this is fix of issue #6144.

It's not ideal solution, as fonts are 2x larger after moving window from retina to non-retina, or 2x smaller if moved window from non-retina to retina.

However, it's way better than it was before, so I think it's worth to apply.

maho avatar May 04 '19 13:05 maho

There is also the issue of one having to manually resize the window to display the updated window. Where as this should happen automatically, we should be listening to the selector for BackingScaleFactor on osx to update the window automatically, ref: https://stackoverflow.com/questions/11067066/mac-os-x-best-way-to-do-runtime-check-for-retina-display .

akshayaurora avatar May 08 '19 10:05 akshayaurora

@matham @tito comment here https://github.com/kivy/kivy/issues/6144#issuecomment-475140897 it would make send to provide a density_dynamic kind of a new prop that user could listen to and update their own UI accordingly

let's keep this pr atomic, i.e not changing stuff like reify etc that would effect a lot of stuff, not just dpi etc.

We also should test things further in SDL2 as it currently manages moving from high density to low density without any issues. Only dpi-Fonts are wrong/double in that case. let's forget fonts and only focus on density we can talk about fonts/reify issue in another pr. Need to check maybe this can be fixed in sdl2 itself? Considering High to Low works automatically... so should Low to High

akshayaurora avatar May 09 '19 00:05 akshayaurora

This is related too; the Screen module would not work cause of this issue on a retina screen as we try to change the density * dpi after the window has already been initialized.

akshayaurora avatar May 09 '19 00:05 akshayaurora

I hadn't seen @tito 's comment. We can make this PR only add code to recompute window's dpi and leave Metrics for another PR. But I'm not really sure this PR would then solve anything, given that the dpi is cached in the two places I mentioned in my original comment.

But it is ok to be modular, and focus this PR only on Window. However, @tito did mention that this PR should make dpi more dynamic, which this PR doesn't solve as dpi is still not a kivy property.

matham avatar May 13 '19 19:05 matham

There is also the issue of one having to manually resize the window to display the updated window. Where as this should happen automatically, we should be listening to the selector for BackingScaleFactor on osx to update the window automatically, ref: https://stackoverflow.com/questions/11067066/mac-os-x-best-way-to-do-runtime-check-for-retina-display .

Dragging window from monitor to monitor is enough to update content (in my case ofc)

maho avatar May 15 '19 11:05 maho

@matham @tito comment here #6144 (comment) it would make send to provide a density_dynamic kind of a new prop that user could listen to and update their own UI accordingly

let's keep this pr atomic, i.e not changing stuff like reify etc that would effect a lot of stuff, not just dpi etc.

We also should test things further in SDL2 as it currently manages moving from high density to low density without any issues. Only dpi-Fonts are wrong/double in that case. let's forget fonts and only focus on density we can talk about fonts/reify issue in another pr.

I second that. I think that this change should make kivy "not worse than it was before" :). Thus I think that resolving problem with scope of _get_gl_size should be enough for this ticket.

Unfortunately I have no monitors in nearest days, so I need to wait until I will be able to work on it again (Monday?)

maho avatar May 15 '19 11:05 maho

As @akshayaurora said, this will likely break on other platforms that don't use sdl2 because self._win._get_gl_size is specific to sdl2 and doesn't exist on other platforms.

matham avatar Aug 10 '19 20:08 matham

@tshirtman this does not really work right now, it needs a architectural change. Recalculation of DPI on every frame is also not a wise thing to do.

Currently with his change you only get the window.dpi and window.density value change. The UI get’s changed to a invalid mix, with the metrics.dpi still in the old value and thus the fonts and widgets still use old values.

akshayaurora avatar Jun 25 '20 13:06 akshayaurora

@tshirtman this does not really work right now, it needs a architectural change. Recalculation of DPI on every frame is also not a wise thing to do.

I don't think this recomputes on every frame, i only see it being recomputed on window resize (which would be triggered by the dpi change of the system.

Currently with his change you only get the window.dpi and window.density value change. The UI get’s changed to a invalid mix, with the metrics.dpi still in the old value and thus the fonts and widgets still use old values.

Is it better or worse than the current result when dpi changes? Is it an acceptable stepping stone to a more complete solution later?

tshirtman avatar Jun 25 '20 15:06 tshirtman

I can’t honestly count this as a stepping stone or a stop gap solution, you see currently. This is what happens.

If you start on a window with high res dpi you get this

Screenshot 2020-06-25 at 10 31 13 PM

Moving to lowers dpi gives you this

Screenshot 2020-06-25 at 10 27 10 PM

This is with master. Issue in the second sshot is the metrics don’t change so ui is not adjusted.

Now going reverse from low dpi to high dpi

Starting on a low res display, you get this Screenshot 2020-06-25 at 10 33 45 PM

Moving to a high res display you get this Screenshot 2020-06-25 at 11 02 28 PM

With the change you should get something like Screenshot 2020-06-25 at 10 37 19 PM ^ This result from my local branch with some similar testing

I guess you could call the last case a improvement.

Is it acceptable stepping stone? We need to update the metric.dpi density etc without which the behaviour and display would not be correct. To be clear both behaviours moving from high-res to low-res and low-res to high-res are currently wrong, even with this change.

Screen module is still broken on high res displays as a result of reify props being static and having no ability to change dynamically.

From what I understand of what needs to be done with change in reify and windows and linux support. I would say this can’t act as a stepping stone for that change.

I wanted to check when the update_viewport get’s called. It’s quite often https://youtu.be/LD2lG_ZGNHE

akshayaurora avatar Jun 25 '20 17:06 akshayaurora

https://github.com/kivy/kivy/pull/7293 adds support for dynamic dpi/density updating. However, that PR does not add the changes to Window to reload the DPI.

So something like this is needed to recalculate the dpi. However, it needs to be done properly, like @akshayaurora suggested above:

In light of this probably a better idea is to implement get_content_size abstract function in window.init and have it be overridden in specific implementations like window_sdl2 etc.

Even if SDL2 does not directly support DPI on windows yet, we could always call direct WINAPI's and OSX API with if platform == checks. We do not have to depend on sdl2 to implement this considering we also have other window providers too.

matham avatar Dec 28 '20 03:12 matham

Just want to drop a workaround on Apple MacBook Air M1:

def dpupdate(self, *args):
    arg1 = args[0]
    return dp(arg1)*(1/kivy.metrics.Metrics.density)

The idea behind dpupdate is that you know dp returns a value that is offset by a fixed ratio (and you can optionally check if you're on a mac using from sys import platform / platform == "darwin" )... With a higher pixel density, you draw a smaller text font, with less pixel density, you draw a larger text font. I was going to find a "sweet spot" fixed number but I got lucky with what I initially wrote.

However, I don't think that's the case with what's happening. kivy.metrics.Metrics.density for the M1 is 2.0, whereas on my PC it is 1.0. I think I just got lucky that dividing by 2 gets me a consistently nice font size. I suspect that sdl2 is already adjusting for the retina display, so kivy is trying to adjust an already fixed issue and accidentally makes text twice as large. I tried using using screen module with -m screen:one, -m :screen:onex, -m screen:note2 and they all look fine BUT I'm not sure that's a good substitute for using the actual hardware.

Hope this helps out someone with Mac M1 font issues, cheers

with regular dp (too large):

https://github.com/kivy/kivy/assets/138998466/3c18268a-563d-4449-a081-17de2d1f4876

with dpupdate (just right):

https://github.com/kivy/kivy/assets/138998466/c6d122c3-fddc-4beb-97cf-551fa11407dc

AccelQuasarDragon avatar Dec 13 '23 17:12 AccelQuasarDragon