Skip to content

Android: pinch to zoom the map through simulated WM_GESTURE - #3863

Merged
meee1 merged 1 commit into
masterfrom
android-pinch-zoom
Nov 8, 2026
Merged

meee1 merged 1 commit into
masterfrom
android-pinch-zoom

Conversation

@meee1

@meee1 meee1 commented Nov 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Pinch to zoom on the map, done the Windows way. Two fingers on the Android touch screen now send real WM_GESTURE / GID_ZOOM messages, and the map reads them as it would with GetGestureInfo on a Windows touch screen. This replaces the old pinch handling, which sent one mouse-wheel notch each time the finger spread doubled or halved.

Changes

mono submodule → meee1/mono@708e58479a9 (simulated-touch-gestures, on top of nc-borders)

  • Add WM_GESTURE / WM_GESTURENOTIFY to Msg.
  • XplatUIMine.SendGesture posts WM_GESTURE (gesture id in wParam) to the control under the point where the gesture began, for every message of that gesture.
  • lParam is the HGESTUREINFO: an HGLOBAL holding a GESTUREINFO with the Windows layout. The handler frees it when it handles the gesture.
  • DefWndProc does what DefWindowProc does on Windows. An unhandled gesture goes to the parent. At the top level, a zoom becomes the legacy Ctrl+mouse wheel (one notch per doubling or halving of the spread).

WinForms.xaml.cs (Android touch input)

  • A second finger turns the touch into a pinch, sent as GID_BEGIN, GID_ZOOM (GF_BEGIN, updates, GF_END) and GID_END, at the centre of the fingers with the distance between them.
  • As on Windows, a touch only becomes the mouse once it moves (> 4 px), lifts (tap) or is held (500 ms). Fingers of a gesture send no mouse messages. Before, a pinch on the Plan map could end in a mouse-up with no move, which counts as a click and adds a waypoint. Mouse input (e.g. macOS) is unchanged.

myGMAP

  • The existing WM_GESTURE handler reads the gesture with the real GetGestureInfo on Windows (net472) and from the simulated handle under netstandard2.0.
  • The zoom follows the finger spread from the start of the gesture (doubling it is one level), and the point between the fingers stays under them. The two debug markers it used to add to the map are gone.
  • A handled zoom is closed and not passed to DefWindowProc. On Windows, DefWindowProc would also zoom again through the legacy Ctrl+wheel.

Testing

Pixel 7 API 35 emulator, Xamarin.Android Debug (x86_64), with two-finger pinches injected through the emulator console:

  • Flight Data: a 4× spread zooms 3.0 → 5.0, and a 3× spread 5.0 → 6.585. With temporary logging, the lat/lng between the fingers stayed within 1–2 px of the finger centre at every step.
  • Plan: a pinch zooms the map and adds no waypoint. A single tap still adds one, and a one-finger drag still pans.
  • MissionPlanner.Controls builds for net472 and netstandard2.0. Not tested on a real Windows touch screen.

Known limitation

The zoom box on Flight Data / Plan only updates when the whole-number zoom level changes. GMap raises OnMapZoomChanged from ZoomStep, so after a pinch it can show 4.0 while the map is at about 4.9. This is existing behaviour, and mouse-wheel zoom never hit it because it always lands on whole levels.

🤖 Generated with Claude Code

Two fingers on the Android touch screen now send Windows touch gestures
(XplatUIMine.SendGesture, in the mono submodule) instead of a mouse
wheel notch each time the finger spread doubled or halved:

- WinForms page: a second finger turns the touch into a pinch, sent as
  GID_BEGIN, GID_ZOOM (GF_BEGIN, updates, GF_END) and GID_END at the
  centre of the fingers with the distance between them. As on Windows,
  a touch is only promoted to the mouse once it moves, lifts or is held
  (500 ms), and fingers of a gesture send no mouse messages, so a pinch
  on the plan map no longer ends in a click that adds a waypoint.
- myGMAP: the existing WM_GESTURE handler reads the gesture with the
  real GetGestureInfo on Windows and from the simulated handle under
  netstandard. The zoom now follows the finger spread from the start of
  the gesture (doubling it is one level) and keeps the point between
  the fingers under them, without the debug markers. A handled zoom is
  closed and not passed to DefWindowProc, which on Windows would also
  zoom again through the legacy Ctrl+mouse wheel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@meee1

meee1 commented Nov 8, 2026

Copy link
Copy Markdown
Collaborator Author

CI note: two of the red checks aren't from this PR. Both fail the same way on master.

  • submit-nuget (Automatic Dependency Submission (NuGet)) fails on master at the base commit 4b24f74 and the commit before it (ebc8d90). This PR changes no package references.
  • Build OSX / Build IOS is cancelled on master the same way for both of those commits.

No fix exists for either yet, and they're outside this change, so I haven't widened the PR for them. The DotNet, Android and Linux builds are still running.


Generated by Claude Code

@meee1
meee1 merged commit a64d768 into master Nov 8, 2026
8 of 13 checks passed
@meee1
meee1 deleted the android-pinch-zoom branch November 8, 2026 22:59
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