# `Drafter.Runtime.AppLoop`
[🔗](https://github.com/jaman/drafter/blob/main/lib/drafter/runtime/app_loop.ex#L1)

The Drafter application event loop.

Owns the receive loop and all message dispatch. Rendering is delegated to
`Drafter.Runtime.Renderer`.

# `enter_loop`

```elixir
@spec enter_loop(module(), term(), map(), map(), map() | nil, keyword()) :: :ok
```

Turns the calling process into the application loop, returning when the app stops.

Registers the caller with `Drafter.AppRegistry` and applies `:refresh_rate`
from `opts`, then receives and dispatches events until the application returns
`{:stop, reason}` or the session shuts down. The message `:drafter_end_session`
sent to the loop's process stops its app and every app beneath it, so the call
returns.

Remote sessions call this directly. A local terminal goes through `run/2`,
which sets the terminal up first.

`timers` maps a timer id to the `:timer` reference already running for it,
`widget_hierarchy` is the hierarchy from a prior render or `nil` for none.

## Options

  * `:refresh_rate` - frame pacing, as accepted by
    `Drafter.Runtime.FrameClock.interval_for/1`. Default: the app's
    `refresh_rate/0`, or `"30fps"` when it defines none.

Unlike `start/3`, this function does not mount the app, so `:props` is not read here.

# `run`

```elixir
@spec run(
  module(),
  keyword()
) :: :ok
```

Set the local terminal up, then mount the app and run the loop until it stops.

Registers with the theme, skin and screen managers, drains any stale input, clears
the screen and sizes the compositor to the terminal, then hands off to `start/3`
with a screen rect covering the whole terminal.

## Options

Takes the same options as `start/3`.

# `settle_focus`

```elixir
@spec settle_focus(map() | nil) :: map() | nil
```

Apply the focus and blur the app has asked for so far to `hierarchy`, in the order
asked, before anything else the process has been sent is looked at.

For the render after `on_ready/1`: what `Drafter.focus/1` and `Drafter.blur/1` asked
for there takes effect in that render, whatever input arrived meanwhile.

# `start`

```elixir
@spec start(module(), map(), keyword()) :: :ok
```

Mount an app, run its ready hook, and enter the event loop for `screen_rect`.

This is everything `run/2` does once the terminal has been set up; a headless run
enters here directly. Returns when the loop returns.

`screen_rect` is a `%{x: x, y: y, width: w, height: h}` map. The app is rendered
once before its ready hook and once after, so intervals registered during the hook
are running before the first event is taken.

## Options

  * `:props` - map or keyword list of mount props passed to the app's `mount/1`.
    Default: `%{}`. See `Drafter.Runtime.mount_props/1`.
  * `:refresh_rate` - frame pacing, as accepted by
    `Drafter.Runtime.FrameClock.interval_for/1`. Default: the app's
    `refresh_rate/0`, or `"30fps"` when it defines none.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
