Proper way to draw viewport text when using hi-dpi displays

On Windows I have a 4k screen and run with the System UI scaling factor set at 2.0 (200%). All apps get this applied, including Blender. This means that Blender still has its own UI scale set to 1.0 (the default). Things are beautiful, except when it comes to drawing text in my python addon.

According to Blender the DPI setting is still 72 (but it’s really twice that) and the scaling factor is 1 so that means I can’t depend on those two system preferences when it comes time to use blf.size(…, dpi) or when positioning the text.

How should I go about adjusting my addon’s drawing routine to account for a System UI scaling factor instead of Blender’s own settings? For me to get correct font size I need to use 144 as the DPI. To get proper x,y positions I need to adjust certain offsets by 2x as well.

Are there any existing patterns or best practices around handling this? Some of Blenders own Addons that I’ve tried also fail in this regard giving me extremely small, sometimes poorly positioned, text (like Math Vis).

Are you using Blender 2.79 or 2.80? As far as I remember in 2.80 preferences.system.dpi does account for user interface scaling.

Using 2.8 here. The scaling doesn’t seem to here:

>>> bpy.context.preferences.system.dpi
72

>>> bpy.context.preferences.view.ui_scale
1.0

Even changing the Blender ui_scale to 2.0 leaves dpi at 72.

Well, in the absence of a better solution, I’m basically doing the following for now.

# 96 because that's Window's default
dpi_scale = get_ppi_win32() / 96
ui_scale = bpy.context.preferences.view.ui_scale

blf.size(font_id, int(font_size * ui_scale), int(72 * dpi_scale))

def get_ppi_win32():
    LOGPIXELSX = 88
    user32 = windll.user32
    user32.SetProcessDPIAware()
    dc = user32.GetDC(0)
    pix_per_inch = windll.gdi32.GetDeviceCaps(dc, LOGPIXELSX)
    user32.ReleaseDC(0, dc)
    return pix_per_inch

Ugh, ok, so after seeing someone else file https://developer.blender.org/T66673 it finally clicked for me. I had been using preferences.view.ui_scale instead of preferences.system.ui_scale and even missed that in Brecht’s reply above since I thought it was a typo…

Now things work as expected.

Some addons use view instead of system too, and some don’t use any form of scaling. I’ll work with metaandrocto to try to get those cleaned up.