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, 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' +) diff --git a/snippets/qt_screen_info.py b/snippets/qt_screen_info.py index 9862a9b8..4a18d7af 100644 --- a/snippets/qt_screen_info.py +++ b/snippets/qt_screen_info.py @@ -31,8 +31,8 @@ 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 ( QtCore, QtWidgets, @@ -43,6 +43,11 @@ from PyQt6.QtCore import ( QSize, QRect, ) +from pyqtgraph import QtGui + + +# 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 @@ -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' )