この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2010年9月)

2010年9月12日

Bug-org 587243 Textbox of tab group lost focus immediately by keypress Eenter(Conversion Enter Commit) while IME composition
初回投稿日時: 2010年09月12日12時53分20秒
最終更新日時: 2010年09月12日13時09分53秒
カテゴリ: Mozilla Core バグ修正
SNS: (list)

IMEで確定する時のEnterキーや、キャンセル時のESCキーの入力でtab group名を入れるエディタからフォーカスが失われてしまう、というバグです。

今回のtab candyはjQueryとHTMLで実装されているようで、このjQueryがバグの原因でした。

Geckoの流儀ではキーの入力処理は基本的にkeypressイベントを活用します。しかし、jQueryはおそらくクロスブラウザな動作を実現するためにESCキーのような文字を入力しないキーではkeypressイベントを発生させていません。このため、代わりにkeyupイベントが利用されていたことが直接の原因です。

GeckoのキーイベントとIMEのイベントの関係は次のようになっています。

アクション発生するイベント
最初の一文字のキー入力
  1. keydown
    (※ただし、gtkでSCIMのようなキーのイベントをまるごと横取りしてしまうようなIMEではこれと、次のkeypressイベントは発生しない)
  2. keypress
  3. compositionstart
  4. text
途中のキー入力
  1. text
最後のキー入力
  1. text
  2. compositionend
  3. keyup

そう、未確定文字列を確定、もしくはキャンセルさせた場合、keyupイベントは発生しているのですが、これはすでにOS側で消費されているはずのキー入力なのにもう一度アクションを起こしてしまうから変な動きになっていたのです。

対策として、EnterキーとESCキーで未確定文字列が発生することは無いことを利用してkeydownでフォーカスまわりの処理を行うようにし、またそのイベントをそこで消費してしまうようにしました。ただし、ラベルの保存等はkeydownイベントではテキストの入力がまだ終わっていない可能性が高いので引き続きkeyupイベントハンドラに残したままにしています。

テスト用URI

data:text/html,<script type="text/javascript">
  function printEvent(e) {
    var p = document.getElementById('p');
    p.innerHTML = e.type + "<br>" + p.innerHTML;
  }
</script>
<body onload="document.addEventListener('compositionstart',
                function (e) { printEvent(e); }, false);
              document.addEventListener('compositionend',
                function (e) { printEvent(e); }, false);
              document.addEventListener('text',
                function (e) { printEvent(e); }, false);">
  <input onkeypress="printEvent(event);"
         onkeydown="printEvent(event);"
         onkeyup="printEvent(event);">
  <p id="p"></p>
</body>

関連するかもしれないエントリ

bug-org 587243を含むエントリ