From 6f9b7320e5b02f095c0f213cd9ddf79122783b05 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Wed, 17 Dec 2025 11:42:44 -0500 Subject: [PATCH 1/4] Re-fmt and `.info()` the `.configure_to_dpi()` DPI calcs for now --- piker/ui/_style.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/piker/ui/_style.py b/piker/ui/_style.py index 21fb3e74..e411b875 100644 --- a/piker/ui/_style.py +++ b/piker/ui/_style.py @@ -184,22 +184,25 @@ class DpiAwareFont: self._font_inches = inches font_size = math.floor(inches * pdpi) - log.debug( - f"screen:{screen.name()}\n" - f"pDPI: {pdpi}, lDPI: {ldpi}, scale: {scale}\n" - f"\nOur best guess font size is {font_size}\n" + ftype: str = f'{type(self)!r}' + log.info( + f'screen: {screen.name()}\n' + f'pDPI: {pdpi!r}\n' + f'lDPI: {ldpi!r}\n' + f'scale: {scale!r}\n' + f'{ftype}._font_inches={self._font_inches!r}\n' + f'\n' + f"Our best guess for an auto-font-size is,\n" + f'font_size: {font_size!r}\n' ) # apply the size self._set_qfont_px_size(font_size) def boundingRect(self, value: str) -> QtCore.QRectF: - - screen = self.screen - if screen is None: + if (screen := self.screen) is None: raise RuntimeError("You must call .configure_to_dpi() first!") - unscaled_br = self._qfm.boundingRect(value) - + unscaled_br: QtCore.QRectF = self._qfm.boundingRect(value) return QtCore.QRectF( 0, 0, -- 2.34.1 From 35744f666f97ac67d56be85150b66024674f3197 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 18 Dec 2025 18:12:04 -0500 Subject: [PATCH 2/4] Add some Qt DPI extras to `qt_screen_info.py` - set `QT_USE_PHYSICAL_DPI='1'` env var for Qt6 high-DPI * we likely want to do this in `piker.ui` as well! - move `pxr` calc from widget to per-screen in loop. - add `unscaled_size` calc using `pxr * size`. - switch from `.availableGeometry()` to `.geometry()` for full bounds. - shorten output labels, add `!r` repr formatting - add Qt6 DPI rounding policy TODO with doc links (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- snippets/qt_screen_info.py | 43 ++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/snippets/qt_screen_info.py b/snippets/qt_screen_info.py index 9862a9b8..807e6371 100644 --- a/snippets/qt_screen_info.py +++ b/snippets/qt_screen_info.py @@ -31,6 +31,7 @@ Resource list for mucking with DPIs on multiple screens: - https://doc.qt.io/qt-5/qguiapplication.html#screenAt ''' +import os from pyqtgraph import QtGui from PyQt6 import ( @@ -44,6 +45,10 @@ from PyQt6.QtCore import ( QRect, ) + +# https://doc.qt.io/qt-6/highdpi.html#environment-variable-reference +os.environ['QT_USE_PHYSICAL_DPI'] = '1' + # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute # must be set before creating the application if hasattr(Qt, 'AA_EnableHighDpiScaling'): @@ -58,13 +63,22 @@ if hasattr(Qt, 'AA_UseHighDpiPixmaps'): True, ) +# NOTE, inherits `QGuiApplication` +# https://doc.qt.io/qt-6/qapplication.html +# https://doc.qt.io/qt-6/qguiapplication.html app = QtWidgets.QApplication([]) +# +# ^TODO? various global DPI settings? +# [ ] DPI rounding policy, +# - https://doc.qt.io/qt-6/qt.html#HighDpiScaleFactorRoundingPolicy-enum +# - https://doc.qt.io/qt-6/qguiapplication.html#setHighDpiScaleFactorRoundingPolicy + window = QtWidgets.QMainWindow() main_widget = QtWidgets.QWidget() window.setCentralWidget(main_widget) window.show() -pxr: float = main_widget.devicePixelRatioF() +_main_pxr: float = main_widget.devicePixelRatioF() # explicitly get main widget and primary displays current_screen: QtGui.QScreen = app.screenAt( @@ -77,7 +91,13 @@ for screen in app.screens(): name: str = screen.name() model: str = screen.model().rstrip() size: QSize = screen.size() - geo: QRect = screen.availableGeometry() + geo: QRect = screen.geometry() + + # device-pixel-ratio + # https://doc.qt.io/qt-6/highdpi.html + pxr: float = screen.devicePixelRatio() + + unscaled_size: QSize = pxr * size phydpi: float = screen.physicalDotsPerInch() logdpi: float = screen.logicalDotsPerInch() is_primary: bool = screen is primary_screen @@ -88,11 +108,12 @@ for screen in app.screens(): f'|_primary: {is_primary}\n' f' _current: {is_current}\n' f' _model: {model}\n' - f' _screen size: {size}\n' - f' _screen geometry: {geo}\n' - f' _devicePixelRationF(): {pxr}\n' - f' _physical dpi: {phydpi}\n' - f' _logical dpi: {logdpi}\n' + f' _size: {size}\n' + f' _geometry: {geo}\n' + f' _devicePixelRatio(): {pxr}\n' + f' _unscaled-size: {unscaled_size!r}\n' + f' _physical-dpi: {phydpi}\n' + f' _logical-dpi: {logdpi}\n' ) # app-wide font info @@ -110,8 +131,8 @@ str_w: int = str_br.width() print( f'------ global font settings ------\n' - f'font dpi: {fontdpi}\n' - f'font height: {font_h}\n' - f'string bounding rect: {str_br}\n' - f'string width : {str_w}\n' + f'font dpi: {fontdpi!r}\n' + f'font height: {font_h!r}\n' + f'string bounding rect: {str_br!r}\n' + f'string width : {str_w!r}\n' ) -- 2.34.1 From 49bedb4912d80a8f851a3480066fffa4d4a46983 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 16 Dec 2025 18:22:05 -0500 Subject: [PATCH 3/4] Reorder imports in `qt_screen_info.py` ?? For wtv reason on nixos importing `pyqtgraph` first is causing `numpy` to fail import?? No idea, but likely something to do with recent `flake.nix`'s ld-lib-linking with `` marlarky? --- snippets/qt_screen_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/qt_screen_info.py b/snippets/qt_screen_info.py index 807e6371..4a18d7af 100644 --- a/snippets/qt_screen_info.py +++ b/snippets/qt_screen_info.py @@ -33,7 +33,6 @@ Resource list for mucking with DPIs on multiple screens: ''' import os -from pyqtgraph import QtGui from PyQt6 import ( QtCore, QtWidgets, @@ -44,6 +43,7 @@ from PyQt6.QtCore import ( QSize, QRect, ) +from pyqtgraph import QtGui # https://doc.qt.io/qt-6/highdpi.html#environment-variable-reference -- 2.34.1 From e63cffaf532d09d51469e38fffc60ef0db3a0e35 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Fri, 19 Dec 2025 19:27:01 -0500 Subject: [PATCH 4/4] Add `.xsh` script mentioned in gitea #50 Note since it's actually `xonsh` code run with either, - most pedantically: `xonsh ./snippets/calc_ppi.xsh` - or relying on how shebang: `./snippets/calc_ppi.xsh` * an sheboom. --- snippets/calc_ppi.xsh | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 snippets/calc_ppi.xsh diff --git a/snippets/calc_ppi.xsh b/snippets/calc_ppi.xsh new file mode 100755 index 00000000..56bbe8b9 --- /dev/null +++ b/snippets/calc_ppi.xsh @@ -0,0 +1,64 @@ +#!env xonsh +''' +Compute the pxs-per-inch (PPI) naively for the local DE. + +NOTE, currently this only supports the `sway`-TWM on wayland. + +!TODO! +- [ ] support Xorg (and possibly other OSs as well? +- [ ] conver this to pure py code, dropping the `.xsh` specifics + instead for `subprocess` API calls? +- [ ] possibly unify all this with `./qt_screen_info.py` as part of + a "PPI config wizard" or something, but more then likely we'll + have lib-ified version inside modden/piker by then? + +''' + +import math +import json + +# XXX, xonsh part using "subprocess mode" +disp_infos: list[dict] = json.loads($(wlr-randr --json)) +lappy: dict = disp_infos[0] + +dims: dict[str, int] = lappy['physical_size'] +w_cm: int = dims['width'] +h_cm: int = dims['height'] + +# cm per inch +cpi: float = 25.4 + +# compute "diagonal" size (aka hypot) +diag_inches: float = math.sqrt((h_cm/cpi)**2 + (w_cm/cpi)**2) + +# compute reso-hypot / inches-hypot +hi_res: dict[str, float|bool] = lappy['modes'][0] +w_px: int = hi_res['width'] +h_px: int = hi_res['height'] + +diag_pxs: float = math.sqrt(h_px**2 + w_px**2) +unscaled_ppi: float = diag_pxs/diag_inches + +# retrieve TWM info on the display (including scaling info) +sway_disp_info: dict = json.loads($(swaymsg -r -t get_outputs))[0] +scale: float = sway_disp_info['scale'] + +print( + f'output: {sway_disp_info["name"]!r}\n' + f'--- DIMENSIONS ---\n' + f'w_cm: {w_cm!r}\n' + f'h_cm: {h_cm!r}\n' + f'w_px: {w_px!r}\n' + f'h_cm: {h_px!r}\n' + f'\n' + f'--- DIAGONALS ---\n' + f'diag_inches: {diag_inches!r}\n' + f'diag_pxs: {diag_pxs!r}\n' + f'\n' + f'--- PPI-related-info ---\n' + f'(DE reported) scale: {scale!r}\n' + f'unscaled PPI: {unscaled_ppi!r}\n' + f'|_ =sqrt(h_px**2 + w_px**2) / sqrt(h_in**2 + w_in**2)\n' + f'scaled PPI: {unscaled_ppi/scale!r}\n' + f'|_ =unscaled_ppi/scale\n' +) -- 2.34.1