From 9260c475cd762f62fbf17b363df4c8d497351f64 Mon Sep 17 00:00:00 2001 From: jesse23 Date: Fri, 9 Oct 2026 08:05:25 -0400 Subject: [PATCH] fix(client): show IME and dictation composition at the cursor Keep focus on ghostty-web's input textarea, anchor it at the cursor cell, and draw the composition over the cursor in the theme's font and colours, instead of as a stray line under the canvas. See ADR 038. --- .../038.client.ime-composition-at-cursor.md | 47 +++++ docs/specs/client.md | 3 +- src/client/compose.test.ts | 34 ++++ src/client/compose.ts | 181 ++++++++++++++++++ src/client/index.ts | 4 + 5 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 docs/adrs/038.client.ime-composition-at-cursor.md create mode 100644 src/client/compose.test.ts create mode 100644 src/client/compose.ts diff --git a/docs/adrs/038.client.ime-composition-at-cursor.md b/docs/adrs/038.client.ime-composition-at-cursor.md new file mode 100644 index 0000000..008a5d0 --- /dev/null +++ b/docs/adrs/038.client.ime-composition-at-cursor.md @@ -0,0 +1,47 @@ +# ADR 038: client — Composition (IME / dictation) text at the cursor + +**SPEC:** [client](../specs/client.md) +**Status:** Accepted +**Date:** 2026-10-09 + +--- + +## Context + +macOS dictation (and IME input such as Pinyin or Japanese kana) shows its in-progress text as a *composition*: the browser fires `compositionstart` / `compositionupdate` / `compositionend` and renders the uncommitted text in whichever editable element has focus. In webtty, that text appears on a new line under the terminal, in the browser's default text color. The extra line pushes the canvas up until the composition ends. + +The cause is in how ghostty-web (`Terminal.open`) sets up input: + +- The `#terminal` container gets `contenteditable="true"` and `tabindex="0"`. ghostty-web also adds a hidden `