On the glasses
Input
Handle taps, swipes and holds from the touch bar and the MIRA Ring.
Every gesture arrives in your app_event(event) export, and the MIRA Ring sends the same events as the touch bar.
Events
| Value | Event |
|---|---|
0 | Tap |
1 | Swipe forward |
2 | Swipe backward |
3 | Double tap (only if your app claims it) |
9 | Long press (only if your app claims holds) |
10 | Hold start (only if your app claims holds) |
12 | Hold end (only if your app claims holds) |
In menus and readers, event 1 moves to the previous item (up, left or earlier) and event 2 moves to the next one (down, right or later). MIRA’s sidebar and cards follow the same rule, so keep it and your app will feel familiar. Games can map the two swipes however they like.
#[no_mangle]
pub unsafe extern "C" fn app_event(event: i32) {
match event {
0 => select(), // tap
1 => move_focus(-1), // previous item
2 => move_focus(1), // next item
_ => {}
}
}Double tap and the sidebar
MIRA’s shell sees every gesture first. By default, double tap opens the sidebar so people can switch apps or go Home. To use double tap inside your app, claim it:
#[path = "../Shared/content.rs"] mod content;
unsafe fn start_game() {
content::double_tap_local(true); // double tap now reaches app_event as 3
}A notification or an open sidebar still gets double tap first. Claims reset whenever the wearer switches apps, so claim again in app_init if you always need it.
Long press and holds
Call content::holds_local(true) to receive long press (9), hold start (10) and hold end (12).
- Always handle hold end, even if you ignored the start.
- Before starting a held action, check that MIRA isn’t covering your app with
content::sidebar_open()andcontent::overlay_visible().
The cursor
MIRA draws one shared cursor that glides from control to control. Tell it where your focused control is, and MIRA animates it there:
content::cursor(x, y, true); // beside the focused item
content::cursor(0, 0, false); // hide it on screens with nothing to select- Use the same position and scroll offset as your highlight, so the cursor and highlight never disagree.
- Update it on every focus change, including frames that reuse retained content.
- Place it beside the selection rather than on top of its label.
The sidebar, dashboard and notifications show their own pointer, so you never need to draw one yourself.
Sidebar icon
Your app’s icon in the glasses sidebar is a 32 × 32 one-color image defined in Rust, next to your code:
#[path = "../Shared/content.rs"] mod content;
app_icon!(content::app_icon::Icon::new()
.circle(16, 16, 12).line(10, 16, 22, 16).line(16, 10, 16, 22).0);The builder draws two-pixel lines, rectangle outlines and circles. You can also pass a 128-byte mask directly: four bytes per row, most significant bit first. Define the icon once per app. Apps without a valid icon get a generic one.