Skip to content

feat(ui): the interface scale is a zoom of the whole UI, smooth and without overflow - #1811

Merged
ZhuchkaTriplesix merged 2 commits into
devfrom
feat/ui-zoom
Oct 25, 2026
Merged

ZhuchkaTriplesix merged 2 commits into
devfrom
feat/ui-zoom

Conversation

@ZhuchkaTriplesix

Copy link
Copy Markdown
Member

Zoom for the interface scale (Preferences → Appearance → Interface scale).

Before. The scale multiplied the text scaler and was applied by hand (context.scaled) in 20 of 540 files: text grew, icons, paddings and fixed heights did not, so screens overflowed at high scales in small windows. A CI probe (PR #1810) counted RenderFlex overflows of the shell, Preferences, the PostgreSQL form and the palette: none up to 1.25, but at 2.0 in 1280x720 (form, 520 px), 1.5 in 900x600 (form) and 2.0 in 900x600 (shell, Preferences, form). The change also waited for the database write before the UI moved.

Now.

  • QueryaUiZoom (lib/core/layout/ui_zoom.dart) at the app root: the child is laid out in a window scale times smaller and painted scale times larger, so text, icons, paddings and hit areas grow together; dialogs, menus and tooltips (the Navigator below) zoom with it. MediaQuery size and insets are divided by the zoom; the text scaler is no longer multiplied.
  • Capped: effectiveUiScale never zooms the layout below kMinUiLayoutSize (900x600, the minimum window), so a big scale in a small window is lowered instead of overflowing (1280x720 allows 120%).
  • Smooth: a change of the scale is animated (180 ms, none under Motion Off / reduced OS motion); the window cap applies at once so a resize never lags.
  • UiScaleController.commitScale applies the new value and notifies first, then stores it; a failed write is logged and no longer undoes the choice.
  • The slider decides its range (presets / 1% steps with Shift) when a drag starts: letting go of Shift mid-drag used to change the range under the thumb. There is no live preview while dragging (the slider itself zooms with the UI, which would move it under the pointer); the zoom runs on release.
  • Pointer positions in window coordinates (grid cell tooltip, grid context menu, drag threshold) go through context.windowToApp; they were the only places that placed something at a raw event.position.
  • QueryaUiScaleScope stays (tests and context.scaled use it) but is 1.0 in the app now; the scaled call sites can go in a cleanup.

Tests. ui_zoom_test (cap, layout size, paint size, a tap hits the widget under the pointer, windowToApp, animation), and ui_scale_overflow_test runs the real QueryaApp at scales 0.75 to 2.0 in 1280x720 and 900x600 and fails on any overflow (the numbers above are its baseline). Not run locally (analyzer clean), CI will; please look at the zoom once by eye, at 75%, 150% and 200%, in a small window too.

@ZhuchkaTriplesix
ZhuchkaTriplesix merged commit 015b408 into dev Oct 25, 2026
27 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant