You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ZoomContentControl only supports mouse/keyboard interactions: Ctrl + wheel zoom, wheel scrolling, and middle-click-drag panning. On touch, nothing happens — no pinch-to-zoom, no single-finger panning. Consumers targeting touch have to drive ZoomLevel from buttons/sliders (which is what the docs currently recommend).
Interestingly, the implementation already anticipates pinch: SetScrollValue's doc comment mentions "we allow unconstrained panning for MouseWheelZoom(desktop) and PinchToZoom(mobile)", and CalculateNewOffset's vpAnchor is described as "typically the cursor position or the pinch center point" — the gesture just was never wired up.
Expected behavior
Standard touch manipulation gestures work out of the box:
Pinch/stretch zooms around the gesture's focal point, clamped to MinZoomLevel/MaxZoomLevel, gated on IsZoomAllowed.
Single-finger drag pans, with the content following the finger, gated on IsPanAllowed.
Proposed implementation
Wire ManipulationMode = Scale | TranslateX | TranslateY | TranslateInertia on the control and handle OnManipulationDelta, feeding the existing zoom/scroll pipeline:
the pinch focal point goes through the same CalculateNewOffset(...) anchor math the Ctrl + wheel path already uses (with the same "compute offset before setting ZoomLevel, apply after" ordering caveat);
translation deltas are converted to scroll-value space via K so the content follows the finger on both axes;
mouse-originated manipulations are ignored — mouse keeps its existing middle-drag/wheel semantics.
No new public API, no visual/template changes, no behavior change for mouse users.
Why not rebase onto ScrollViewer's zoom instead?
ScrollViewer optical zoom recently landed for Skia targets (unoplatform/uno#22337), which raises the question of rebasing ZoomContentControl on it to get gestures "for free". That trade doesn't hold up:
ZoomFactor/offsets are read-only there; everything funnels through the async, clamping ChangeView — which conflicts with ZCC's settable, two-way-bindable ZoomLevel (two sources of truth during manipulations).
Several ZCC features have no ScrollViewer equivalent at all: AllowFreePanning (offsets past the clamp range), the unscaledAdditionalMargin (anything wrapped inside a ScrollViewer scales with the zoom), ScaleWheelRatio/PanWheelRatio, middle-click panning.
ZCC's transform-based implementation behaves identically on every target by construction; per-platform native ScrollViewer behavior would not, and uno#22337 covers Skia only.
Handling manipulations directly gets gesture support on all targets (including WinAppSDK) for ~40 lines, keeping the control's single-source-of-truth model.
Anything else we need to know?
Builds on the anchor math fixed in fix(zoomcontentcontrol): keep content centered when zooming #1628 (pinch zooming across the "content fits viewport" boundary relies on the corrected K-sign handling), so the implementation branch is based on fix/zoomcontentcontrol-centering.
Docs (doc/controls/ZoomContentControl.md interactions section) should gain a Touch subsection; the warning that there is "no automatic pinch-to-zoom" becomes obsolete.
Current behavior
ZoomContentControlonly supports mouse/keyboard interactions: Ctrl + wheel zoom, wheel scrolling, and middle-click-drag panning. On touch, nothing happens — no pinch-to-zoom, no single-finger panning. Consumers targeting touch have to driveZoomLevelfrom buttons/sliders (which is what the docs currently recommend).Interestingly, the implementation already anticipates pinch:
SetScrollValue's doc comment mentions "we allow unconstrained panning for MouseWheelZoom(desktop) and PinchToZoom(mobile)", andCalculateNewOffset'svpAnchoris described as "typically the cursor position or the pinch center point" — the gesture just was never wired up.Expected behavior
Standard touch manipulation gestures work out of the box:
MinZoomLevel/MaxZoomLevel, gated onIsZoomAllowed.IsPanAllowed.Proposed implementation
Wire
ManipulationMode = Scale | TranslateX | TranslateY | TranslateInertiaon the control and handleOnManipulationDelta, feeding the existing zoom/scroll pipeline:CalculateNewOffset(...)anchor math the Ctrl + wheel path already uses (with the same "compute offset before settingZoomLevel, apply after" ordering caveat);Kso the content follows the finger on both axes;No new public API, no visual/template changes, no behavior change for mouse users.
Why not rebase onto ScrollViewer's zoom instead?
ScrollVieweroptical zoom recently landed for Skia targets (unoplatform/uno#22337), which raises the question of rebasingZoomContentControlon it to get gestures "for free". That trade doesn't hold up:ZoomFactor/offsets are read-only there; everything funnels through the async, clampingChangeView— which conflicts with ZCC's settable, two-way-bindableZoomLevel(two sources of truth during manipulations).ScrollViewerequivalent at all:AllowFreePanning(offsets past the clamp range), the unscaledAdditionalMargin(anything wrapped inside a ScrollViewer scales with the zoom),ScaleWheelRatio/PanWheelRatio, middle-click panning.ScrollViewerbehavior would not, and uno#22337 covers Skia only.Handling manipulations directly gets gesture support on all targets (including WinAppSDK) for ~40 lines, keeping the control's single-source-of-truth model.
Anything else we need to know?
K-sign handling), so the implementation branch is based onfix/zoomcontentcontrol-centering.doc/controls/ZoomContentControl.mdinteractions section) should gain a Touch subsection; the warning that there is "no automatic pinch-to-zoom" becomes obsolete.