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

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

もずはっく日記(2014年1月)

2014年1月29日

Bug-org 953146 Shouldn't allow other applications to set focus to popup window 初回投稿日時: 2014年01月29日20時29分12秒
最終更新日時: 2014年01月29日20時30分20秒
カテゴリ: Firefox Mozilla Core Mozilla29 Windows バグ修正
固定リンク: id=2014012900
SNS: (list)

一部のSynapticsや、Elantechのタッチパッドで、ドロップダウンの中身をスクロールしようとすると、そのドロップダウンが閉じてしまう、というバグです。

Synapticsでは、二本指でスワイプすることでスクロールものが、いくつかこの症状を持っている様です。Elantechのドライバは、HKEY_CURRENT_USER\Software\Elantech\OtherSetting\ScrollSupportAutoFocusが非ゼロになっている場合や、レジストリで設定不能な形で再構成してあると思われる、ASUS SmartGestureで発生していました。

Windowsでは本来、フォーカスを持ったコントロールに対して、ホイールイベントのメッセージが送信されます。

しかし、この仕様は評判があまりよくないようで、各ブラウザはカーソルの下にあるスクロール可能なエリアをスクロールしますし、一部のサードパーティ製のマウスドライバでは、フォーカスの有無を無視して、マウスカーソルの下にあるウインドウにホイールメッセージを送信します。

今回のバグは、そのようなドライバ側でのハックが不適切なものだったのが原因です。

どちらのケースでも、カーソルの下にあるウインドウに強制的にフォーカスを与えてから、ホイールメッセージを送信することで、この挙動を実現しようとしていましたが、Geckoの出すドロップダウンはフォーカスを受け取ることがないという前提で設計されています。そのため、ドロップダウンを開いていたウインドウが非アクティブになってしまい、これをトリガーに、ドロップダウンが閉じられていました。

色々と調べてみたんですが、API経由でドロップダウンが強制的にアクティブにされるのをキャンセルする手段が無いようなので、Geckoのウインドウがフォーカスを失う時に、そのフォーカスの移動先がドロップダウンの場合にだけ、特殊処理を入れることによって、ドロップダウンを閉じないようにすることにしました。

具体的には、まず、ドロップダウンを開いたウインドウが非アクティブ化のWM_NCACTIVATEを受け取り、非クライアント領域を非アクティブ時の色で再描画しようとしますが、これを抑制しておかなければホイールを回す度にウインドウの非クライアント領域がちらつくことになります。このため、このメッセージをGeckoのポップアップウインドウ以外が受けとった場合には、直接、Default WndProcにメッセージをリダイレクトした後、このメッセージを受け入れたと返します。これで、描画のみが抑制され、フォーカスの移動は継続します。

次に、ポップアップではないウインドウは、WA_INACTIVEWM_ACTIVATEを受け取ります。この時に、フォーカスの移動先が分かりますので、ポップアップに移動しようとしている場合はそのまま流し、それ以外の場合は、非クライアント領域をきちんと非アクティブな見た目に描画しないといけないので、そのまま処理するようにフラグをたててから、WM_NCACTIVATESendMessage()で再送します。

最後に、ポップアップウインドウが、WA_ACTIVEWM_ACTIVATEを受け取った場合は、ディアクティブイベントが発生するのを抑制した後に、アプリ定義のメッセージをキューにポストします。そして、そのメッセージを受け取った時に、直前にアクティブだったウインドウをAPIをつかってアクティブ化します。

これにより、フォーカスの移動があたかも発生していないかのように見せつつ、ポップアップにフォーカスが移動させられた場合にはポップアップを閉じずに、フォーカスを直前のウインドウに戻す、ということを行っています。興味のある方は、この変更だけを行っているパッチを参照してみてください。

Bug-org 951023 Gonk widget should set modifier state at dispatching events derived from WidgetInputEvent 初回投稿日時: 2014年01月29日20時42分29秒
カテゴリ: Events Firefox OS Gonk Mozilla Core Mozilla29 バグ修正
固定リンク: id=2014012901
SNS: (list)

Firefox OSのGonkウイジットから、イベントが生成される際(例えば、Bluetooth接続等による、物理デバイスからの入力イベント)、モディファイアキーの状態が正しく初期化されていませんでした。

今回の修正により、AltCtrlMeta (Windowsロゴキーや、Mac用キーボードのCommandキー)、ShiftCapsLockNumLockScrollLockFnに対応しています。ただし、最後のFnキーは実際にアクティブになっていることがあるかどうかは不明です。

Bug-org 957019 Don't check cursor position in nsWindow::DealWithPopups() for non-mouse events 初回投稿日時: 2014年01月29日20時48分22秒
カテゴリ: Mozilla Core Mozilla29 Windows バグ修正
固定リンク: id=2014012902
SNS: (list)

Bug-org 953146の修正時に、ポップアップが開いている際のメッセージハンドラのコードをクリーンナップしたのですが、この際に、マウスのイベントでなくても、カーソル位置を調べて、ポップアップを閉じる、閉じないを変更している、変なバグを見つけました。例えば、Alt+Spaceで、ウインドウのメニューが開くのですが、カーソルがドロップダウンの外にある場合は、ドロップダウンが閉じられるのですが、カーソルがドロップダウンの上にある場合には閉じない、という状況でした。

このバグでは、マウスに関係ないメッセージでは、カーソル位置を意識しないように一括修正しています。

Bug-org 951966 [TSF] IMEs implemented with IMM don't work well in TSF mode 初回投稿日時: 2014年01月29日20時58分46秒
カテゴリ: Mozilla Core Mozilla29 TSF Windows バグ修正
固定リンク: id=2014012903
SNS: (list)

Bug-org 840409の修正で、デスクトップ版のGeckoは、IMEHandlerクラスが、nsIMM32Handlerクラスと、nsTextStoreクラスのメソッドを、TSFモードかどうかを判定して、必要最小限のパスでTSFモードが動作するようにしましたが、この際に、IMM-IMEであっても、TSFモードでは、nsIMM32Handlerクラスを利用しないように修正してしまいました。

実際には、これは間違った修正で、IMM-IMEはTSFモードであっても、nsIMM32Handlerで従来通りにハンドリングする必要がありました。この修正では、アクティブなIMEが、IMM-IMEな場合、TSFモードであっても、nsTextStoreのメソッドを呼び出した後、nsIMM32Handlerのメソッドにもフォールバックするようにしています。

Bug-org 835262 [TSF] Should keep composition when we are deactivated 初回投稿日時: 2014年01月29日21時18分09秒
最終更新日時: 2014年01月29日21時42分51秒
カテゴリ: Mozilla Core Mozilla29 TSF Windows バグ修正
固定リンク: id=2014012904
SNS: (list)

TSFモードでも、未確定文字列が、Firefox自体がディアクティブになった際に、強制確定すべきではない、というバグです。

強制確定のトリガを引いていたのは、nsIMEStateManagerで、全てのウインドウがディアクティブになる際に、nsTextStateManagerを破棄していました。このため、nsTextStoreが、フォーカスを失ったという通知を受け、強制確定を行っていました。

今回の修正で、nsIMEUpdatePreferenceに、NOTIFY_DURING_DEACTIVEという値を追加し、nsTextStoreはこの値を含めて返すようにしました。これが設定されていると、nsIMEStateManagerは、ウインドウのディアクティベイト時にはnsTextStateManagerを破棄しないようになりました。これにより、nsTextStoreが、フォーカスを失ったという通知を受け取らなくなっています。

なお、MS-IMEは、WinXP以降、全てのバージョンで、TSF-awareアプリ上では、そのスレッドがフォーカスを失う際に自動的に強制確定するため、ウインドウがディアクティブになった際に確定されてしまうことに注意してください。これは、MS-IME固有の仕様です。

Bug-org 959999 [TSF] Clean up nsTextStore::Initialize() 初回投稿日時: 2014年01月29日21時24分07秒
カテゴリ: Mozilla Core Mozilla29 TSF Windows バグ修正
固定リンク: id=2014012905
SNS: (list)

プロセスが起動された初期段階で、nsTextStore::Initialize()が呼び出され、TSFに必要なグローバルオブジェクトを取得、生成、初期化していくのですが、参照カウンタが絡んでいる関係で、途中でエラーが発生した場合のクリーンナップ処理等が非常に汚くなっていました。

この修正で、各種オブジェクトをそのままグローバル変数に取得せず、一旦、スタック上のnsRefPtr<T>に取得し、エラーが発生したらそのままnsTextStore::Initialize()からreturnし、全てに成功した場合にのみ、nsRefPtr<T>から、グローバル変数にポインタを保存しなおす、という形でシンプルにしています。

Bug-org 544779 [TSF] Remove WM_USER_TSF_TEXTCHANGE 初回投稿日時: 2014年01月29日21時33分18秒
カテゴリ: Mozilla Core Mozilla29 TSF Windows バグ修正
固定リンク: id=2014012906
SNS: (list)

初期設計のTSF対応では、nsTextStateManagerが、エディタ内のコンテンツの変更通知を受け取ると、そのまま、同期的にnsTextStoreに、それを通知していました。しかし、変更通知が発行されている間に新たに未確定文字列の生成や、変更、確定を行うことができないため、WM_USER_TSF_TEXTCHANGEというメッセージを定義し、これをキューにポストしておくことで、「安全」になってからnsTextStoreが何でもできるようになっていました。

しかし、nsTextStateManagerからの通知を利用するAndroid側でも同じ問題に直面したため、nsTextStateManagernsRunnableを利用して、「安全」になってから、nsIWidgetに通知するように既に修正されていました。

このため、nsTextStore独自のこのメッセージハックはすでに不要になっているので、これを単に削除しました。

Bug-org 961703 [TSF] Avoid making TIP confused by odd behavior 初回投稿日時: 2014年01月29日21時39分16秒
カテゴリ: Mozilla Core Mozilla29 TSF Windows バグ修正
固定リンク: id=2014012907
SNS: (list)

弊社のm_katoの検証によると、TSFの仕様上は問題無いはずなんですが、未確定文字列がある時に、選択範囲やエディタのコンテンツの内容の変更をIMEに通知すると、MS-IME、Google日本語入力、ATOKで、それ以降、動作しなくなるということでした。

これは非常に良くない現象ですので、未確定文字列がある際にこれらの通知が発生した場合は、通知せずに未確定文字列を強制確定するようにしました。

また、nsTextStoreが、ITfContextを削除する際に未確定文字列が残っていると、TSF内でフォーカスの管理がおかしくなるのも分かっていたので、あわせて修正してあります。

2014年1月30日

Bug-org 935876 <select> element shouldn't consume key events which don't cause any default action 初回投稿日時: 2014年01月30日12時47分33秒
カテゴリ: Events Mozilla Core Mozilla29 バグ修正
固定リンク: id=2014013000
SNS: (list)

Bug-org 501496の修正によるregressionです。<select>要素で文字入力キー以外のハンドリングを、keypressイベントから、keydownイベントに変更し、keydownイベントのpreventDefault()が呼び出された場合に、keypressが発生しなくなっているため、現状の<select>要素では、文字入力キー以外のキー入力に対して、一切、keypressイベントが発生しなくなっている、というバグです。

混乱を避けるため、<select>要素が処理する可能性があるキーのみ、常にpreventDefault()を呼び出すようにし、それ以外のキーでは呼び出さないように変更しました。

例えば、一番上にある<option>要素が選択されている状態で、キーを押しても、何もおきませんが、この場合にもpreventDefault()は呼び出され、keypressイベントは発生しません。

元々、Gecko以外では、keypressイベントは原則として、文字入力キーでしか発生しないので、このバグで実際に改善されるのは、Enterキーぐらいかなという気がします。

Bug-org 962005 Make mozilla::TextComposition refcountable 初回投稿日時: 2014年01月30日12時51分31秒
カテゴリ: Mozilla Core Mozilla29 バグ修正
固定リンク: id=2014013001
SNS: (list)

mozilla::TextCompositionクラスは、現在、インスタンスを予め確保済みのものを再利用し、フラグメント化を抑えているのですが、このままでは、同一の編集を意味するインスタンス間で情報の同期ができないため、参照カウンタによる管理のクラスに変更し、様々な場所から活用しよう、という修正です。

Bug-org 329127 Simplify nsDOMEvent::DuplicatePrivateData 初回投稿日時: 2014年01月30日12時59分51秒
カテゴリ: Events Mozilla Core Mozilla29 バグ修正
固定リンク: id=2014013002
SNS: (list)

nsDOMEvent::DuplicatePrivateData()は、DOMイベントがJSのハンドラ等に捕獲され、ディスパッチ終了後も情報を保持しないといけない場合に、ディスパッチ元が管理しているイベントの情報を、DOMイベント自身が管理するインスタンスを生成して、必要なものだけコピーする、というものです。このメソッドは、イベントの種類ごとにそれぞれ処理を書き、また、widget/配下にイベントクラスを追加しても自動的に対応する訳でもないので、修正漏れの原因になっていました。このバグはそれを解決しようというものです。

この修正により、仮想メソッド、Duplicate()を全てのイベントクラスが実装し、その内部でデータのコピーまで済ませてしまう、という形にしました。今後は、原則的に、新しいイベントを実装する際には、widget/配下に必要なメソッド一式を実装したイベントクラスを作るだけで、大半の仕事が終わることになります。

Bug-org 931378 [GTK3] Set input-purpose to GtkIMContext 初回投稿日時: 2014年01月30日13時13分00秒
最終更新日時: 2014年01月30日13時13分41秒
カテゴリ: GTK Mozilla Core Mozilla29 バグ修正
固定リンク: id=2014013003
SNS: (list)

GTK 3.6.0以降では、GtkIMContextに、input-purposeというプロパティが設定されており、IMEや、スクリーンキーボードがこれを参考にして、動作を変更することができます。このバグでは、GTK3ビルドが3.6.0以降で動作している場合にのみ、このプロパティを<input>要素のtype属性や、ime-modeプロパティを参考に、適切と思われる値を設定しています。

なお、ime-mode: disabled;<input type="text">や、ime-modeが設定されていない<input type="password">では、GTK_INPUT_PURPOSE_PASSWORDが設定されます。

逆に、ime-mode: normal;ime-mode: inactive;ime-mode: active;が指定されている<input type="password">では、GTK_INPUT_PURPOSE_PASSWORDが設定されないことに注意してください。

この挙動はタブレットでは好ましいスクリーンキーボードが表示されないという結果を生むかもしれませんが、今のところ、通常のIMEを無効化するには、GTK_INPUT_PURPOSE_PASSWORDを設定するしかないという、なんとも中途半端なGTK3の仕様から、このような修正になっています。

Bug-org 749123 [GTK3] Please do not use GtkIMContextSimple for password fields. 初回投稿日時: 2014年01月30日13時22分24秒
カテゴリ: GTK Mozilla Core Mozilla29 バグ修正
固定リンク: id=2014013004
SNS: (list)

GTK2では、パスワードフィールドでは、GtkIMContextSimpleを使って、デッドキーをサポートしつつ、IMEはサポートしない、という設計でしたが、GTK3では、通常のGtkIMMulticontextを利用し、IMEの仕組みを利用したスクリーンキーボードをパスワード入力欄でも利用可能にすべきだ、というバグです。

GTK 3.6.0で、input-purposeプロパティが追加されるまで、パスワード入力欄でIMEが有効になるのは、CJKユーザにとっては不便でしかないので、修正を見送っていましたが、bugdayに参加されたLinuxのIME開発者の方から偶然、この情報を得ることができたので、早速、修正を行いました。

なお、GTK3ビルドを3.6.0未満の環境で動かすと、パスワード入力欄でIMEが有効になってしまいますが、これは、intl.ime.use_simple_context_on_password_fieldabout:configからtrueに設定することで、GTK2ビルドと同じ挙動に戻すことができます(要再起動)。