2011年7月29日
私が修正した訳では無いんですが、レビューでパッチの設計を変更してもらって、Webアプリケーションに影響があるので紹介しておきます。
SolarisではCutキーをF20に、CopyキーをF16に、PasteキーをF18に、UndoキーをF14キーに割り当てて、XBL側でもこれらのキーを元の意味に読み替えて動作していました(写真さがしてみたところ、Sun Microsystem's Type 6 Keyboardというページを発見。二つ目の写真で確認できます)。
これを、GDK_Copy、GDK_Cut、GDK_Paste、GDK_Undoも利用できるようにし、さらにGDK_Redoも追加しようとしていました。
さすがにそのままやられてしまうと、非常に分かりにくくなってしまうので、以前、WindowsでWM_COPY
等のサポートで作成した内部用のcontent commandイベント
を利用するように修正してもらいました。
その結果、どうなったかと言うと、これらのキーを押した場合に、キーイベントは発生しなくなりました。これは何故かと言うと、これらのキーをWebアプリがハンドリングする際にキーコード等を見たりせず、直接、テキストの変化を見て欲しいからです(将来的にはDOM3 Eventsのtextinputイベント
を見て下さい)。つまり、Windowsでもマルチメディアキーボードや、他のユーティリティソフトがWM_PASTE
等を直接送信してきてもキーイベントは発生しませんので、それと同じ結果になるようにしました。また、もうひとつ言えば、この操作は編集メニューから操作したのと同じ結果になります。
逆にユーザの視点に立つと、Linuxでしか発生しないキーイベントで、本来は可能だったクリップボード関連の操作を、このことを知らずに作成されたWebアプリに邪魔されないようになっています。
そういう訳ですので、シビアなことをやっているWebアプリでは意図せずクリップボード関連の操作ができてしまうかもしれませんが、それは意図せずできないよりはユーザにとって良い、ということでこのような設計になりました。
uriloader
もPreferences
のユーティリティメソッドを利用するように修正終わりました。
IMEの強制確定処理が、Firefoxのウインドウの切替で発生した場合にはうまく動かない、というバグです。
原因は、切替先のウインドウでアクティブなIMEのコンテキストが存在しない場合に、::ImmNotifyIME()
による強制確定処理が空振りに終わっていたことです。
このAPIが呼ばれる直前に、一時的にそのウインドウのデフォルトのコンテキストを与えるようにすることで修正しました。
また、今まではコンテキストをウインドウから切り離す際に、切り離したコンテキストを保存しておいて、それを再び関連づける、という形で処理していましたが、Win98/Win2000以降で使える::ImmAssociateContextEx()
APIが現在のGeckoのサポート状況だと利用できるので、こちらを使って常にデフォルトのコンテキストを割り当てるようになりました。このため、何らかのバグや、他のユーティリティの影響で保存していたコンテキストを万が一、失ってしまってもフォーカス移動だけで問題が解決するようになっています。このため、時々見かける、Firefoxを再起動するまでIMEが希に利用できなくなる、というバグを修正しているかもしれません。
content
以下もPreferences
を利用するように修正しました。
intl
のコードもPreferences
を利用するように修正しました。
ユーザがスクロール速度や、スクロール方向、またはホイールとアクセラレーションキーの組み合わせによるアクションをカスタマイズしていた場合にも、高精度スクロールをWindowsでも使えるように修正するバグです。
本来はFirefox 7に入れる予定でしたが、Preferences
でころっと忘れていて、Firefox 8になってしまいました。
chrome
配下のコードもPreferences
を利用するように、というバグでしたが、リスクを嫌って、wontfixとなりました。
かなり長い間かかりましたが、ようやくnsChildView.mm
からキーボード、IME関連のコードをTextInputHandler.mm
に分離する作業が完了しました。これにより、MacOS X 10.5の時のように、キーボード周りのAPIがまるごと変更された場合にも今までよりは対応しやすくなります。
この修正ではバグを見つけてもバグを修正せずにそのまま移植していますので、何か挙動に変化があるとバグと言えますので、発見された方は報告をお願いします。
今後の予定では、まず、現在進めているキーコードの整理処理(Linux版のレビューさえ進めばFirefox 9か?)が終わったら、いよいよATOKの確定アンドゥの修正のための下準備に入ります。
Mac版のデバッグビルドのスタートアップ時にデバッグ用のキーボードの一覧を作成、表示する処理でスタートアップの80%の時間を消費していた、というバグです。
Bug-org 519972の修正でCocoaのキーボードやIMEの処理内容も細かくログを吐くように修正し、この処理もログの一部に変更しましたので、ログを有効にしている場合以外では問題の処理が走らなくなりました。
後ほどmodestの方に書きますが、NSPR_LOG_MODULES=TextInputHandlerWidgets:1
でログを取れます。
マウスでテキストを選択中に、選択を開始した要素に一番近い、スクロール可能な要素がマウスをキャプチャしてしまい、それ以外のスクロール可能な要素をスクロールする手段もないし、キャプチャしてる要素の外側の選択状態も変更できるのはおかしい、というバグです。これの修正が今、闘っているregression祭りの元凶です。
まだ対応中のバグで挙動が変更されますので、詳しい説明は後日に回しますが、ざっくりと説明すると、まず、マウスの左ボタンが押された時、選択範囲のルートとなる要素がマウスイベントをキャプチャします。そして、これより外側の要素の内容は選択できません。つまり、意図的に特定要素内に選択範囲を制限できます。
<body>
<div id="div1">
<p>aaaaaaaaaaaaa</p>
<p>bbbbbbbbbbbbb</p>
</div>
<div id="div2">
<p>ccccccccccccc</p>
</div>
</body>
このケースで、マウスのボタンを#div1
内で押した場合、#div1
内のみが選択できた方が便利だとします。その場合、以下のように記述します。
<script type="text/javascript">
var div1 = document.getElementById("div1");
function div1MouseDownHandler(event)
{
if (event.button == 0) {
div1.setCapture(false); // not event.target!
}
}
div1.addEventListener("mousedown", div1MouseDownHandler, false);
</script>
ただし、文字列のマウスでの選択は特に標準化されている訳ではありませんので、他のブラウザでこの手法で選択範囲を制限できなくてもそれはバグであるという話ではありません。これはあくまでFirefoxでの挙動を利用した手法であることに注意してください。
話を戻すと、これにより、マウスカーソルを選択範囲のルート要素の外側にまで移動すると、その要素は今まで通りにスクロールすることが可能ですが、問題はその内側にある他のスクロール可能な要素です。
これらは、そのスクロール可能な要素の辺(bugzilla上でedgeと呼んでいる部分)にカーソルを移動した時に自動的にスクロールするようにしました。このため、選択中にあらゆるスクロール可能な要素は(ただし、その時に選択可能な要素であること。例えば、textareaやiframeの様に、外側から選択できない要素は除き)、全てスクロールできるようになりました。
Facebookのコメント欄でクリックすると(正確にはクリック中にマウスを動かして、mousedown
、mousemove
とイベントが発生した時に)クラッシュしていたバグです。
Facebookはコメント欄にフォーカスが来たら、要素の移動やらなんやらが多々発生し、Gecko内部ではそのエディタ自体の作り直しが発生していました。この際にnsFrameSelection
がPresShell
をデタッチしているのですが、その時同時に選択自体を中止していなかったため、選択範囲の拡張処理が想定していない状況に陥ってクラッシュしていました。
Bug-org 670058で修正したはずのクラッシュがまだ発生しているよ、ということで、とりあえず再現する最小限のテストケース(人間の脳みそでは発生タイミングのシミュレーション不能)からGecko側の処理を見つめ直していきました。
その結果、マウスのキャプチャが解除される時には、選択を中断すべきであるという結論に至りました。例えば、document.releaseCapture();
で強制的にリリースさせられると、もうどうしようもありません。
最終的に、このバグ修正で添付した、まだ多少現実的なテストケースは、マウスを二つ利用した場合にのみ発生するものとなっています(例えばノートPC付属のタッチパッドと外付けのマウスとか)。
Linuxではデフォルト設定で中クリックで貼り付けができますが、この際に使われるのは通常のクリップボードではなく、Primary selectionと呼ばれるものだそうです。知りませんでした。で、このPrimary selectionは文字を選択してマウスのボタンを離した時に自動的に記録されるのですが、Bug-org 671319の修正で、nsFrame
側の修正を怠ったのが原因でした。
nsFrame
では通常のmouseup
時に先にマウスキャプチャをリリースしていました。このため、正常終了にも関わらず、nsFrameSelection
側で異常終了したと判断されてしまい、nsISelectionListener
の変更通知理由がNO_REASON
になってしまい、Primary selectionのauto copy処理が処理をしなくなってしまっていました。
まだ修正は完了していませんが、ひとまず正常終了時のreasonは正しくなるように、処理順序を正しく入れ替えました。srを依頼しているrocが来週戻ってくれば異常終了時にもauto copyが行われるようになります。
contenteditable="true"
がスクロール不可能な要素に設定されていて、これをCtrl+クリックするとクラッシュするというバグです。
単に、nsIScrollableFrame
のポインタのNULLチェック不足でした。
フルスクリーンモード等、選択時のルート要素がデスクトップの端まで広がりきっていると選択中にドラッグではスクロールできない、というバグです。Firefox Inputでも以前からちょこちょこと報告されていた問題ですね。
Bug-org 552707の修正ではそれまでの動作とできるだけ似せて混乱を与えないように、ルート要素ではその辺にマウスカーソルがあってもスクロールしないようにしていましたが、このバグの修正でその制限を取り払いました。