Input and controls¶
| Garmin | Wear OS | Apple Watch | |
|---|---|---|---|
| Status | ✅ | ✅ | ⏳ |
| Code | source/TripDelegate.mc, source/views/PauseView.mc (PauseDelegate), source/views/StatsSummaryView.mc (StatsSummaryDelegate), source/views/SyncView.mc (SyncDelegate), source/views/EphemeralView.mc (EphemeralDismissDelegate), source/views/SplashView.mc (SplashDelegate), source/PairingView.mc |
wear/…/presentation/TrackingScreen.kt, wear/…/presentation/MainActivity.kt (crown, stems), wear/…/presentation/Gestures.kt (swipeBack), wear/…/presentation/Menus.kt, wear/…/presentation/SailEverApp.kt, wear/src/main/res/values/styles.xml |
— |
Verified against code: 2026-10-13
Purpose¶
The WatchApp is used on deck, often with one hand on the tiller, wet fingers or gloves. Every control comes down to a few behaviours that each platform maps to what it has: buttons on Garmin, swipes, crown, taps and optional stem buttons on Wear OS, and (planned) Double Tap and the Action button on Apple Watch. All instruments work without any input.
Behaviours¶
These behaviours exist on every platform. The sections below map them to concrete inputs.
| Behaviour | Where | Effect |
|---|---|---|
| Next / previous instrument page | Recording screen | Dashboard → Track → Environment and back. Garmin buttons and the Wear OS crown and swipes wrap around (Environment → Dashboard). |
| Open the track controls | Recording screen | Action menu (Garmin) / Controls page (Wear OS) (menus.md) |
| Change the vessel state | Recording screen | Vessel state picker |
| Zoom in / out | Track view | One zoom step (track-view.md) |
| Dismiss an overlay | Alert or auto-stats overlay | Closes it; the input goes no further (alerts-and-auto-stats.md) |
| Resume | Pause view (Garmin), start menu (Wear OS) | Resumes the paused track (lifecycle.md) |
| Flip page | Stats summary | Page 1 ⇄ page 2 (stats.md) |
| Back | Menus and non-recording screens | Closes the screen; on the start menu it ends the app |
A recording track can never be left by a "back" input. The only ways out of a track are Stop Track and Discard Track.
Garmin¶
The input code is written against BehaviorDelegate, so one implementation serves button watches and touch watches. On touch watches the framework turns taps and swipes into the same behaviours; the app adds tap zones only on the Track view.
Button map (5-button watches)¶
| Button | Behaviour | Dashboard / Environment | Track view |
|---|---|---|---|
| START/STOP (top right) | onSelect |
Opens the action menu | Zoom in one step |
| BACK/LAP (bottom right) | onBack |
Opens the vessel state picker | Zoom out one step |
| UP (middle left) | onPreviousPage |
Previous page (wraps) | Previous page (wraps) |
| DOWN (bottom left) | onNextPage |
Next page (wraps) | Next page (wraps) |
| LIGHT (top left) | not handled | System backlight | System backlight |
BACK is taken over on purpose: it is the easiest button to reach with a hand on the tiller, so it changes the vessel state instead of closing the app. On the Track view START and BACK zoom; to open the action menu or the picker from there, page to another view first.
Page changes switch the view at once, without animation. The Track view starts at the default zoom each time it is shown.
Touch zones (Track view)¶
| Tap | Effect |
|---|---|
| Right half, upper half (x > 0.50, y < 0.50) | Zoom in |
| Right half, lower half (x > 0.50, y > 0.50) | Zoom out |
| Elsewhere | Passed to the framework |
Other screens¶
| Screen | START | BACK | UP / DOWN | Other keys / taps |
|---|---|---|---|---|
| Splash | Closes it | Closes it | Close it | Any key or tap closes it |
Menus (Menu2) |
Selects the focused item | Closes the menu | Move the focus | — |
| Stats summary | Closes stats and the action menu, back to the instruments | Back to the action menu | Flip page | — |
| Pause view | Resumes the track | Swallowed | Swallowed | All other keys swallowed |
| Overlay (alert, auto-stats) | Dismisses | Dismisses | Dismiss | Any key, tap, swipe or menu input dismisses and is swallowed |
| Save view (after Stop) | Swallowed | Skips the wait: the request in flight finishes, then the app ends | — | — |
| Upload view (from the start menu) | Swallowed | While uploading: cancel after the request in flight; when finished: close | — | — |
| Pairing view | — | Back to the start menu | — | — |
Wear OS¶
The Garmin button concept adapted to a touch screen and a crown. Pixel Watch apps receive neither the crown press nor the side button, so the action menu is a page and the picker is a tap target.
Recording screen¶
The recording screen has three horizontal pages: the Controls page on the left, the instruments in the middle and the vessel state picker on the right. The instruments are a vertical pager with Dashboard, Track and Environment. The app opens on the instruments.
| Input | Effect |
|---|---|
| Swipe up / down on the instruments | Next / previous page, wrapping (Environment ↔ Dashboard) |
| Turn the crown | Next / previous page, wrapping (Environment ↔ Dashboard). One page per 40 px of accumulated crown scroll. |
| Swipe right on the instruments | Controls page (opens at its first item every time) |
| Swipe left on the Controls page | Back to the instruments |
| Swipe left on the instruments | Vessel state picker page (menus.md). Picking a state returns to the instruments. |
| Swipe right on the picker page | Back to the instruments, state unchanged |
| Tap the vessel state header on the Dashboard (band y 0.60–0.80) | Vessel state picker, current state preselected |
| Track view: tap right half, upper half | Zoom in |
| Track view: tap right half, lower half | Zoom out |
| Track view: tap elsewhere | Toggles crown zoom mode: the crown zooms instead of paging (marked on screen, track-view.md). It ends when the sailor taps again or leaves the Track view. |
Stem buttons¶
On watches with extra stem buttons (KEYCODE_STEM_1 … STEM_3). Only the first press counts; held repeats are ignored.
| Button | Instruments | Track view | Vessel state picker, settings value picker | Overlay showing |
|---|---|---|---|---|
STEM_1 (Garmin BACK) |
Opens the vessel state picker | Zoom out | Picks the highlighted item | Dismisses only |
STEM_2, STEM_3 (Garmin START) |
Goes to the Controls page | Zoom in | Picks the highlighted item | Dismisses only |
On the start menu, Controls page and other lists the stem buttons do nothing.
Watches without usable buttons¶
Some watches give apps no buttons at all. On the OnePlus Watch 2 the crown doesn't turn and both buttons are system keys: the bottom button can only launch an app, and the system ignores it while that app is already in front. On such watches every control is a touch: swipes, the state header tap, hold to unlock.
Touch lock¶
Touch Lock on the Controls page protects against spray and rain:
- It returns to the instruments and ignores every touch, drags included.
- An orange
0xFF5500pill at the bottom (x 0.36–0.64, centred on y 0.955, height 0.06 of the screen) showsLOCKEDin black,FONT_XTINY. The screen above stays readable. - The first crown turn unlocks; that turn does not also page. Holding the screen for 2 s (released after at least 2 s) also unlocks, for watches whose crown doesn't turn.
- Stem buttons keep working while locked.
Overlays¶
An alert or auto-stats overlay covers the recording screen. Any touch (on release), any crown turn or any stem button closes it. Nothing reaches the screen below.
Other screens¶
| Screen | Close / back | Other |
|---|---|---|
| Splash | — | A tap closes it |
| Start menu | Swipe right ends the app | Crown scrolls |
| Other menus, picker, discard dialog, settings | Swipe right | Crown scrolls or moves the highlight (menus.md) |
| Stats summary | Swipe right, back to the instruments | Swipe up / down flips the page |
| Save view (after Stop) | — (no swipe-back) | Closes by itself |
| Upload view | Swipe right: while uploading, cancel after the request in flight; when finished, close | — |
| Pairing view | Swipe right | Closes by itself 2 s after pairing |
Swipe-back is the app's own gesture: a horizontal drag to the right of more than 25 % of the screen width. The window's system swipe-to-dismiss is off (android:windowSwipeToDismiss = false), so no screen can be swiped away by the system. While a track records, the recording screen, the pause view and the save view have no swipe-back at all.
Apple Watch¶
⏳ Planned mapping (port plan):
| Behaviour | Input |
|---|---|
| Next / previous page | Swipe up / down or turn the Digital Crown |
| Track controls | Controls page on the left (swipe right), as in Apple's Workout app |
| Change the vessel state | Tap the state header on the Dashboard; Double Tap on any instrument page opens the picker and a second Double Tap confirms the highlighted state; the Action button on Ultra runs a SailEver App Intent |
| Zoom | On-screen + / − buttons, or tap the map to put the crown into zoom mode until the next tap |
| Wet screen | Water Lock on the Controls page |
| Pause view | Always-On / reduced-luminance style |
The crown press and the side button are reserved by watchOS and are not used. Double Tap never cycles blindly through the states: a wrong state would go unnoticed and corrupt the sail / engine split.
States and edge cases¶
- Overlay over a menu: an overlay can appear on top of any screen while a track records; its dismiss rules apply first.
- Garmin touch-only watches: the framework decides which gesture becomes BACK, START, UP and DOWN; the app does not define gestures of its own outside the Track view.
- Wear OS without stem buttons (e.g. Pixel Watch): every behaviour is reachable by touch and crown alone.
Known deviations¶
- Wear OS stats summary has no "back to the instruments in one step" input like Garmin START, and swipe-back from stats goes to the instruments rather than the Controls page. Small parity gap.
- Wear OS save view cannot be skipped; Garmin BACK skips the wait. Parity gap on the Wear OS side.