input
input 把用户对本应用绘图面的直接操作变成有界、类型化事件。它不暴露 DOM Event、浏览器全局监听器、原始设备对象或跨应用输入。
基本示例
下面在按下指针时记录逻辑坐标:
await host.input.focus('main');
host.events.on('input.pointer', (event) => {
if (event.canvasId !== 'main' || event.kind !== 'down') return;
beginStroke(event.pointerId, event.x, event.y, event.pressure);
});
适用场景
- 游戏、画板、图表和自绘控件的指针交互。
- 键盘快捷键和非文本按键。
- 鼠标、触控板或等价设备产生的滚轮/平移增量。
- 在多个应用绘图面之间请求焦点。
文本输入、输入法合成、候选词和字符边界查询使用 ime,不能只靠 input.key 重建。
能力声明
{
"capabilities": ["host:input.focus"]
}
指针、键盘和滚轮事件只有在应用拥有对应绘图面且获得焦点时才送达。宿主能力表仍应明确公布事件名和 schema。
Reference
方法
- input.focus():请求把输入焦点交给本应用绘图面。
事件
- input.pointer:指针进入、移动、按下、抬起、取消和离开。
- input.key:按键按下或抬起;用于控制键和快捷键。
- input.wheel:二维滚动增量。
事件数据
PointerEvent {
canvasId,
kind: "enter" | "move" | "down" | "up" | "cancel" | "leave",
pointerId: u32,
pointerType: "mouse" | "touch" | "pen" | "unknown",
x: f32, y: f32,
buttons: u16,
pressure?: f32,
modifiers: ModifierSet
}
KeyEvent {
canvasId,
kind: "down" | "up",
key: bounded-string,
code: bounded-string,
repeat: boolean,
modifiers: ModifierSet
}
坐标使用绘图面的逻辑像素,不是屏幕坐标。pointerId 只在当前指针活动期内有意义,不能作为设备标识。
原生 WASM 示例
原生 guest 从统一事件队列读取类型化事件:
HostEvent event;
while (host_event_next(&event)) {
if (event.type == INPUT_POINTER && event.pointer.kind == POINTER_DOWN) {
begin_stroke(event.pointer.pointer_id, event.pointer.x, event.pointer.y);
}
}
事件队列满时宿主可以合并连续 move 和 wheel,但不能静默丢弃 down、up、cancel 或焦点变化。
生命周期与焦点
- 事件仅在对应应用视图存活时送达。
- 绘图面失焦时,宿主必须为仍按下的指针发送
cancel,并终止未完成的按键状态。 focus是请求,不允许从后台窃取系统焦点;宿主可以返回denied。- 页面隐藏、系统手势或可信 UI 覆盖时暂停输入。
安全与预算
- 信任档位:green;provenance 为
app-context。 - 不返回屏幕绝对坐标、设备序列号、全局按键状态或其他应用输入。
- 字符串、坐标、压力和修饰键必须经过 schema 限制。
- 高频移动事件按绘图面合并并设时间窗预算。
- 宿主不得把密码管理器、系统快捷键或保留组合键泄露给 guest。
不属于本 API
手柄、传感器、全局热键、无障碍语义树和拖放文件都不是 v0.1 input。它们有不同资源、权限或生命周期,需要独立准入。
一致性测试
至少覆盖多指针、失焦取消、坐标缩放、事件合并、按键 repeat、保留快捷键、绘图面销毁、后台暂停,以及 JS/原生 guest 事件次序一致性。