I'd like my QGIS map canvas scale to be accurate, e.g. so if the scale is 1:10000, then 100m on the ground should show in 1 cm of screen.
My Windows laptop screen has 157 ppi (dpi) based on its physical dimensions and pixel resolution. That, of course, varies on the laptop and/or external screen.
QGIS however behaves as if the ppi is 96. This is if the overall system scaling (under Windows'
Settings / Display / Scale) is 100%. If it is 125% (which improves font legibility), then QGIS uses a ppi of 120. 150% (fonts too large on all Windows applications) yields a QGIS canvas ppi of 144. These figures are confirmed by running
iface.mapCanvas().mapSettings().outputDpi() from the Python console.
How can I adjust the canvas dpi? I've tried
iface.mapCanvas().mapSettings().setOutputDpi(157.0) but that has no visible effect on the canvas, and
.outputDpi() continues to return 120 (or 96).
Either a Python console solution or a
startup.py solution would be fine. Or, some magic incantation in QGIS settings. Of course, something that magically identified the actual physical ppi (the 157 in my case) would be even better, but I doubt Windows supports that.
I've also tried fiddling with High-DPI compatibility settings in the Windows program options for the QGIS app. As expected, those affect the scaling of QGIS' UI fonts and icons, but don't change the canvas dpi.
This is not about changing the DPI of a print layout, which is easily customizable; it's about the canvas on-screen.
Editing to add: I've followed some breadcrumbs to https://stackoverflow.com/questions/16561879/what-is-the-difference-between-logicaldpix-and-physicaldpix-in-qt, and note in PyQGIS,
iface.mainWindow().logicalDpiX() returns 120 while
iface.mainWindow().physicalDpiX() is correctly 158. So I'm trying to find how to force the QGIS map canvas to set its DPI from
.physicalDpi, or a custom figure, rather than from
.logicalDpi. Ideally, it should keep UI font and icons scaled according to
.logicalDpi (as is usual behaviour in all applications), and shouldn't force me to adjust
.logicalDpi via operating system settings, which has side effects (on all open applications!) and allows only DPIs of 96,120,144,168 or 192.