# MimoProvider

Wraps your wallpaper in Mimo, the Fluxlay SDK's synthetic input forwarder, so that ordinary React DOM events (`onClick`, `onPointerDown`, `onKeyDown`, drag-and-drop libraries, focus rings, etc.) fire inside the wallpaper window even though the OS cursor never enters it.

For background on what Mimo is and why a wallpaper needs it, see [Mimo: Interactive UI inside Wallpapers](/en/studio/developer/how-to/development/mimo.md).

## Import

`MimoProvider` lives on a separate subpath from the rest of the SDK to keep the main entry point free of Mimo's dependency tree:

```tsx
import { MimoProvider } from "@fluxlay/react/mimo";
```

## Quick start

Drop it at the root of your wallpaper. With no extra props, OS pointer and keyboard events are wired into the forwarder automatically:

```tsx
import { MimoProvider } from "@fluxlay/react/mimo";

export function Root() {
  return (
    <MimoProvider cursor>
      <App />
    </MimoProvider>
  );
}
```

`<App />` can now use plain React handlers — `<button onClick={...}>`, dnd-kit, Framer Motion drag, `<input>` focus rings via `useIsFocused`, etc. The `cursor` prop renders a virtual cursor div that follows the synthetic pointer, since the OS does not paint one inside wallpaper windows.

IME (Japanese / Chinese / Korean text input) is handled automatically: focusing an `<input>` or `<textarea>` activates the IME proxy, the user types, and the committed text is written into the field. No separate wiring is required. See [`useImeInput`](/en/studio/developer/reference/sdk/use-ime-input.md) if you need direct control.

## Signature

```tsx
function MimoProvider(props: MimoProviderProps): ReactNode;

interface MimoProviderProps extends Omit<MimoForwarderOptions, "pointerSource" | "keyboardSource"> {
  pointer?: boolean;
  keyboard?: boolean;
  children?: ReactNode;
}
```

`pointerSource` / `keyboardSource` are intentionally omitted — `MimoProvider` owns the input source and wires it to Fluxlay's OS hooks (`useMousePosition`, `useMouseEvents`, `useKeyboard`). To plug in a custom source (tests, replay, non-Fluxlay environments), use `MimoForwarderProvider` instead (see below).

## Props

| Prop                     | Type                       | Default            | Description                                                                                                                                                                                       |
| ------------------------ | -------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pointer`                | `boolean`                  | `true`             | When `false`, OS pointer events are not injected into the forwarder. Useful for temporarily detaching the cursor (demo toggles, modal overlays).                                                  |
| `keyboard`               | `boolean`                  | `true`             | When `false`, OS keyboard events are not injected.                                                                                                                                                |
| `cursor`                 | `boolean \| CursorOptions` | `false`            | Render a virtual cursor element following the synthetic pointer. Useful because wallpaper windows have no real OS cursor visible inside them.                                                     |
| `autoFocus`              | `boolean`                  | `true`             | Focus the nearest focusable ancestor on `pointerdown`, mirroring real browser behavior.                                                                                                           |
| `doubleClickThresholdMs` | `number`                   | `500`              | Maximum gap that still counts as a double click.                                                                                                                                                  |
| `clickMoveThresholdPx`   | `number`                   | `5`                | Beyond this drift, the up is treated as a drag and `click` is suppressed.                                                                                                                         |
| `keyboardTarget`         | `KeyboardTargetStrategy`   | `"active-element"` | Where to dispatch keyboard events: `"active-element"` (default — works with `useIsFocused` / `<input>` focus rings), `"pointer-target"`, or `"document"`.                                         |
| `pointerCapture`         | `boolean`                  | `true`             | Install a process-wide patch on `Element.prototype.{set,release,has}PointerCapture` to route captures through the forwarder. Required for dnd-kit, react-dnd Pointer backend, Framer Motion drag. |
| `children`               | `ReactNode`                | –                  | Your wallpaper tree.                                                                                                                                                                              |

## useMimoForwarder

Returns the underlying `MimoForwarder` instance owned by the surrounding provider. Throws if used outside one. Useful when you need to imperatively call methods on the forwarder (e.g. `injectPointer` / `injectKeyboard` for tests or replay).

```tsx
import { useMimoForwarder } from "@fluxlay/react/mimo";

function ReplayButton() {
  const forwarder = useMimoForwarder();
  return (
    <button
      onClick={() => {
        forwarder.injectPointer({ kind: "move", x: 100, y: 100 });
        forwarder.injectPointer({ kind: "button", x: 100, y: 100, button: "left", pressed: true });
        forwarder.injectPointer({ kind: "button", x: 100, y: 100, button: "left", pressed: false });
      }}
    >
      Replay click
    </button>
  );
}
```

`MimoForwarderContext` is also exported if you need optional access (returns `null` outside a provider).

## Custom input source: MimoForwarderProvider

The opinionated `MimoProvider` always pumps Fluxlay's OS hooks into the forwarder. When you need to provide your own `pointerSource` / `keyboardSource` — for unit tests with a synthetic stream, for replaying recorded sessions, or for embedding the wallpaper outside the Fluxlay desktop app — use the lower-level `MimoForwarderProvider`:

```tsx
import { MimoForwarderProvider, type PointerSource, type KeyboardSource } from "@fluxlay/react/mimo";

const pointerSource: PointerSource = handler => {
  const ws = new WebSocket("ws://localhost:9999/pointer");
  ws.onmessage = ev => handler(JSON.parse(ev.data));
  return () => ws.close();
};

const keyboardSource: KeyboardSource = handler => {
  // ...
  return () => {};
};

export function ReplayRoot() {
  return (
    <MimoForwarderProvider pointerSource={pointerSource} keyboardSource={keyboardSource}>
      <App />
    </MimoForwarderProvider>
  );
}
```

`MimoForwarderProvider` accepts the full `MimoForwarderOptions` set (the same prop list as `MimoProvider` plus `pointerSource` / `keyboardSource`). A `PointerSource` is a function that receives a handler and returns an unsubscribe; coordinates are CSS pixels in the target document's viewport. `KeyboardSource` follows the same shape.

## Exported types

The following identifiers are exported from `@fluxlay/react/mimo`:

- `MimoForwarder`, `MimoForwarderContext`, `useMimoForwarder`
- `MimoForwarderProvider`, `MimoForwarderProviderProps`
- `MimoForwarderOptions`, `CursorOptions`, `KeyboardTargetStrategy`
- `PointerSource`, `PointerSourceEvent`, `PointerSourceMoveEvent`, `PointerSourceButtonEvent`, `PointerSourceWheelEvent`, `PointerSourceCancelEvent`, `PointerButton`, `PointerType`
- `KeyboardSource`, `KeyboardSourceEvent`, `KeyboardModifiers`
- `Unsubscribe`

## Notes

- `MimoProvider` mounts a single forwarder per wallpaper window. Mounting multiple is supported (the most recently started one captures), but uncommon.
- The forwarder synthesizes events and is therefore subject to the browser's `isTrusted` gate. A handful of behaviors (HTML5 native drag-and-drop, raw text entry into `<input>` / `<textarea>`, OS context menus, autoplay unlock) cannot be triggered through synthetic events. Most have Fluxlay-side workarounds — IME composition is handled by [`useImeInput`](/en/studio/developer/reference/sdk/use-ime-input.md), the OS hover ring is replaced by [`useIsFocused`](/en/studio/developer/reference/sdk/use-is-focused.md) plus the virtual cursor.
