Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

attachCustomKeyEventHandler inverts xterm.js's return-value contract (silently swallows all input)

オープン
#192 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
52/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript
領域
frontend

調査の方向性

lib/input-handler.ts#L377-L385 から始め、issue にある xterm.js-style の例を使って handler の動作を再現してください。どの return-value contract を maintainers が求めているかを確認する前に、README の移行ガイダンス、互換性表、attachCustomKeyEventHandler の JSDoc を読んでください。完了条件は、通常の入力が動作し、記載されている shortcut が引き続き処理され、選択した contract がユーザーに見つけてもらえる場所にドキュメント化されていることです。

索引モデルが issue の本文から書いたものです。

説明

Summary

attachCustomKeyEventHandler returns the opposite of what xterm.js's handler of the same name returns. Because the README's migration story is "change your import: @xterm/xterm → ghostty-web", an app that carries its existing handler across ends up with a terminal that ignores every keystroke — while connecting, rendering, scrolling and showing the shell prompt perfectly. There is no error and nothing on screen to suggest the keyboard is the problem.

The two contracts

xterm.js — the return value says let the terminal have this key:

The function returns whether the event should be processed by xterm.js.

So a handler that only wants to claim a shortcut or two returns true for everything else.

ghostty-web — the return value says I already handled it, drop it (lib/input-handler.ts#L377-L385):

// Check custom key event handler
if (this.customKeyEventHandler) {
  const handled = this.customKeyEventHandler(event);
  if (handled) {
    // Custom handler consumed the event
    event.preventDefault();
    return;
  }
}

That same xterm-shaped handler now returns true for every ordinary key, so every ordinary key is swallowed — and the one or two keys it deliberately claimed (returning false) are the only ones that reach the pty, inverted in both directions.

Reproduction
import { init, Terminal } from 'ghostty-web';

await init();
const term = new Terminal();
term.open(el);
term.onData(d => ws.send(d));

// Straight from an xterm.js app: claim Ctrl+F, let everything else through.
term.attachCustomKeyEventHandler((e) => {
  if (e.ctrlKey && e.key === 'f') { e.preventDefault(); return false; }
  return true;
});

Expected: typing works, Ctrl+F is swallowed.
Actual: nothing can be typed at all, and Ctrl+F is the only key that reaches the shell.

Removing the handler entirely makes typing work again, which is what makes this hard to attribute — the handler is usually old, unrelated code that was correct before the migration.

Versions

[email protected], and the code above is current main.

Suggestion

Either is fine from where I sit, but the ambiguity is the expensive part:

  1. Invert it to match xterm.js — treat a falsy return as "consumed". Most faithful to the stated API compatibility, but silently changes behaviour for anyone who already adapted, so it would want a note in the changelog.
  2. Keep the current meaning and document it — call it out in the README migration line and in the JSDoc on attachCustomKeyEventHandler, since that method is the one place a reader would look. Today the JSDoc says "Returns true to prevent default handling", which is accurate but only visible if you already suspect the handler.

A line in the compatibility table would also have caught this for me before I shipped it.

Happy to send a PR for whichever direction you prefer.

主要言語
TypeScript
スター
2.9k
フォーク
174
PR マージ指標
30日以内にマージされた PR はありません

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

coder/ghostty-web のほかの issue

coder/ghostty-web の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。