# Input and Keyboard
This page documents the simulated input stack: pointer events, soft keyboard state, IME behavior, and the `adjustResize` layout contract.
For service API signatures, see [`README.md`](README.md). For app UI rules, see [`../../app/module-contract.md`](../../app/module-contract.md).
## Components
| Area | Implementation | Responsibility |
|---|---|---|
| Soft keyboard state | `os/keyboard/KeyboardService.ts` | Volatile store for visibility, height, and mode. |
| Keyboard overlay UI | `os/components/KeyboardOverlay.tsx` | Renders the keyboard, handles focus, text insertion, dismissal, and smart scroll. |
| Activity resize | `os/SystemShell.tsx` | Wraps each Activity in `data-adjust-resize` and shrinks the active one by keyboard height. |
| Global hide rule | `app.css` | Hides `[data-hide-on-keyboard]` inside an active resize container. |
| IME dictionary | `os/keyboard/pinyinData.ts`, `os/keyboard/pinyinLargeDict.ts`, `os/keyboard/pinyinIme.ts` | Chinese pinyin candidate generation. |
| IME build script | `scripts/ime/build_pinyin_dict.mjs` | Generates the large pinyin dictionary from source dictionaries. |
## KeyboardService
`KeyboardService` is exposed as `window.__OS__.keyboard`.
```ts
__OS__.keyboard.show();
__OS__.keyboard.hide();
__OS__.keyboard.isVisible();
__OS__.keyboard.getHeight();
__OS__.keyboard.setHeight(280);
__OS__.keyboard.setMode('zh'); // or 'en'
__OS__.keyboard.toggleMode();
__OS__.keyboard.subscribe(state => {});
```
Current state shape:
```ts
type KeyboardMode = 'en' | 'zh';
interface KeyboardServiceState {
visible: boolean;
mode: KeyboardMode;
height: number;
}
```
The store is volatile. Refreshing the simulator resets it to hidden, English mode, height `0`.
When `show()` is called, height is set from `SIMULATOR_CONFIG.framework.keyboardHeight` unless overridden later with `setHeight()`.
## Back behavior
The keyboard registers a `BackDispatcher` handler named `keyboard.dismiss` at priority `700`.
When the keyboard is visible, system back hides the keyboard and consumes the event. App-level back handlers should not duplicate this behavior.
## Focus and dismissal
`KeyboardOverlay` listens globally:
| Event | Behavior |
|---|---|
| `focusin` on an editable element | Shows the keyboard and schedules smart scroll. |
| `focusout` | Hides the keyboard unless the blurred editable itself is inside a `data-keep-keyboard` container. |
| capture-phase `click` on an already focused editable element | Reopens or scrolls without disturbing pointer sequences. |
| capture-phase `pointerdown` outside the keyboard, editable element, gesture bar, or `data-keep-keyboard` | Hides the keyboard; pointer down inside `data-keep-keyboard` does not dismiss it. |
| DOM removal of the focused input | Hides the keyboard during route changes or unmounts. |
Editable detection is handled inside `KeyboardOverlay`; app components generally only need ordinary ``, `