feat(viewport): two-finger trackpad pan and pinch zoom

A trackpad could only zoom: every scroll delta, wheel notch or not, went
into the same zoom step, and a pinch never arrived at all. iced's winit
layer converts only the window events it has an iced equivalent for, so
winit's `PinchGesture` was dropped before the app saw it.

Scroll deltas now split by what produced them: a wheel reports notches and
still zooms, a precise-scrolling device reports pixels and pans. The same
pixel split keeps working everywhere else — the browser build reports every
wheel notch as pixels, so there they keep zooming.

The pinch is read straight from AppKit with a local `NSEvent` monitor, since
the app cannot see the gesture through iced at all, and handed to the app
through a subscription shaped like the SpaceMouse bridge. It maps 1:1 onto
the camera: fingers 5% further apart leave the view 5% closer.

The pan and zoom bodies are now shared by the mouse and the gestures, so the
middle-button drag, the wheel, two fingers and a pinch all move the view
through one path — in model space, in a tiled pane and inside a floating
viewport alike.
This commit is contained in:
Alexey Bagno committed 2026-09-21 23:47:32 +03:00
1 parent baba5bccd3
commit 13b6a08e77
8 files changed
+250 -37

No files matched your search

+1
View File
@@ -2719,6 +2719,7 @@ impl OpenCADStudio {
Subscription::none()
},
self.spacemouse.subscription().map(|_| Message::SpaceMouseWake),
crate::input::trackpad::subscription().map(Message::TrackpadPinch),
event::listen_with(|event, _, id| match event {
iced::Event::Window(window::Event::Focused) => {
Some(Message::SpaceMouseFocus(id, true))