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

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

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

2009年9月8日

Bug 6678 Bug-org 462809はXPレベルで実装されるべき 初回投稿日時: 2009年09月08日00時35分29秒
最終更新日時: 2009年09月08日01時00分23秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2009090800
SNS: (list)

Bug-org 462809でtrunkのWindows版にホイールによるスクロールの加速がアプリケーションレベルで実装されていました。これの評判が悪かったのはテスタには周知の事実かと思いますが、コードレベルで見てもそのコードがひどく、イベントモデルまわりを全く理解していない低品質なものでした。これらを本来あるべき形に修正するため、XPレベルでの実装を提案していましたが、完全に無視されていたので、パッチを作成して修正しています。

この修正により、MacやLinuxでも爆速スクロールが体感できますが、意外と慣れるとこの速度でも操作できてしまうようになるので不思議です(加速してしまわないペースを指が覚える)。

またこの修正でシステム設定のスクロールスピードが無視されるバグも修正されています(もっとも、それを加速してしまうのであまり修正された実感は無いかと思いますが)。

さらにバグは立てていませんが、スクロール以外でデルタ値が増幅されなくなったので、DOMでマウスホイールを取り扱うWebアプリの、今までのバージョンとの互換性は確保されています。また、ズームや、ページ単位でのスクロールをホイールで行う場合にも加速は行われなくなりました。

現在はBug-org 513817で後始末中ですが、同じFxのUIチームの(?)Dãoもこのシステム設定を無視した加速自体には反対なようなので、何が何だか外側からは分からない状況です。

まあしかし、愚痴だけ言ってても何も改善しないので適当な落し所へ向けて前向きにやっていくしかないですね。

REX-USBDVI2 初回投稿日時: 2009年09月08日02時35分52秒
最終更新日時: 2009年09月08日02時47分11秒
カテゴリ: 雑談
固定リンク: id=2009090801
SNS: (list)

一部で話題なのかもしれない、USBからフルHD(or WUXGA)で出力可能なアダプタです。

REX-USBDVI2のパッケージ写真

VM使う関係上、開発機はディスプレイ3台構成にしていますが、この構成の最大の問題点は普通のグラボなら、最低2枚必要、ということです。最近のグラボのGPUは平然と冷房効いた部屋でも70度前後、常温で風通し悪いとそのままハングアップしてしまうぐらいに温度が上がってしまいますので、なんとか一枚構成にしたいと考えていました。

Matroxの製品や、Quadroに手を出すことができれば、正攻法で一枚構成にできなくはないですが、GPGPUの利用やDirectX 10.x、そして最大の問題点である価格を考えるとこれらは手が出せません。そこで以前からUSB→DVIのアダプタには注目していたのですが、フルHD以上の解像度に対応したものが出ていなかったので見送り続けていましたが、ようやく、これが発売されたという訳です。

実際に使ってみると意外と実用には問題がありません。スクリーンがオフになった後の復帰に時間がかかるようになりましたが、それぐらいでしょうか。

ただ、アニメーションのレンダリング、特にAeroのWindowに対するさまざまな効果はさすがに厳しく、中割が少ないアニメのような表示になります。実速度は落ちていないっぽいので、単にレンダリングが追いつかない時にフレームを捨てている感じです。つまり、体感速度は遅く感じてしまいますので、この辺を我慢できない人には使えない製品かもしれません。スクロールも似たようなものですが、Aeroの効果よりは気にならないレベルです。動画の再生もなかなか厳しいレベルではありますが、そもそもHDCPに対応していないのでこれを動画再生目的のディスプレイで利用することは無いでしょう。

製品の仕組みは、PC上に仮想グラフィックボードを作って、そこにグラボのGPUを利用して画面を描画し、その結果を圧縮してUSB2.0で転送、そしてアダプタで解凍しているそうです。このため、メモリを若干(40MB程度)奪われるのと、CPUパワーを食ってしまう、という点がこの製品のデメリットのようです。また当然、USBバスや、CPU、もしくはGPUがビジー状態になると、画面が見た目、ハングアップした感じになります(マウスカーソルが動かないとか)。

フレームの破棄に関してはUSB2.0の転送速度が一番の原因なのではないか、という感じはします。USB3.0対応の製品が出てきて、これでフレームの破棄を軽減できたら本当に良いものになるかもしれません。

ただ、残念ながらグラボを2枚以上挿した状態では画面出力すらできませんでした。また、製品の仕様にもSLIやCrossFireとの併用はできないとありますので、この辺を利用したい人には全く使えません。一般的な用途では問題無く使えるものの、人は選ぶ、という感じでしょうか。

からふね屋珈琲本店の唐揚げパフェ 初回投稿日時: 2009年09月08日03時02分23秒
最終更新日時: 2009年09月08日03時02分41秒
カテゴリ: 雑談
固定リンク: id=2009090802
SNS: (list)

唐揚げパフェの写真

なんだかすっかりヤミツキになってしまって、この店へ行くたびに食ってる気がします。一見イロモノですが、パフェ自体がヨーグルトで酸っぱいので、唐揚げと不思議なぐらいに相性がぴったりです。


大きな地図で見る

ちなみに、納豆パフェなるものまでありますが、さすがにそれはどうなんだろう……

Bug-org 513955 Replace KL* APIs to TIS* APIs 初回投稿日時: 2009年09月08日17時26分38秒
最終更新日時: 2009年09月09日02時42分10秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2009090803
SNS: (list)

MacのKL APIが64bitアプリでは利用できないので、全てをTIS APIに置き換えるというバグです。tinderboxマシンがまだ10.4環境が残っているため、#ifdefを利用した汚い修正になっていますが、tinderboxマシンの移行が完了すれば10.4向けのコードは完全に削除される予定です。

TISになって結構すっきりとはしたんですが、最初、馬鹿正直にこれらのAPIを直接呼び出していると、行数がすごくなるし、キャストのコードばかりで本題がよく分からないようになりました。AppleのこのAPI設計は絶対下手だと思います。何でもかんでもプロパティをvoid *で返すよりも、TISGetBooleanProperty等として無駄なキャストを不要にしてしまうか、MSのようにプロパティという概念を隠蔽してそれぞれのプロパティごとにAPIを用意するとか、そっちの方が絶対可読性は良いのですが。

そしてなぜか、TISInputSourceを複製するAPIが用意されていないため、TISCreateInputSourceListで取得したTISInputSourceの寿命がその直接の戻り値のリストの寿命になってしまうという不思議仕様に対応しにくくなってます。下手に設計してしまうとメモリリークの温床になってしまうこと請けあいですし、何よりもコードが無駄に複雑化します。

結局、ラッパークラスを作り、TISInputSourceRef自体には直接アクセスできなくしてしまうことでこれらの問題に対処しています。

Bug-org 513948 Use TIS APIs directly 初回投稿日時: 2009年09月08日17時33分46秒
最終更新日時: 2009年09月09日02時42分35秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2009090804
SNS: (list)

TIS* APIは10.4では利用できないので、ダイナミックにこれらのAPIをロードしてアクセスしていました。これを直接利用するようにしよう、というバグです。

Bug-org 513955の修正で同時に修正していますが、やはりtinderboxのメンテナンス待ちです。

2009年9月13日

Bug 6685 ロジクールのマウスでチルトホイールを傾けても一回しかスクロールしないことが多い 初回投稿日時: 2009年09月13日14時52分51秒
最終更新日時: 2009年09月13日14時54分56秒
カテゴリ: Mozilla Core バグ報告 バグ検証中
固定リンク: id=2009091300
SNS: (list)

世界的なマウスメーカーのマウスは検証用に持っておいた方が良いだろう、ということでロジクール(日本以外だと Logitech)のMX-1100を購入してみました。ちょっとテストしてみるとなかなか、独特なソフトウェアとハードウェアの組み合わせに思えます。

早速ひとつ問題を見つけたのがこれです。チルトホイールを傾けたままにしても一回しかスクロールしないことが大半でした。希にそのまま連続してスクロールしますが、大半はこのバグか発生します。

バグの報告に書いていますが、直接的な原因は::GetMessagePos APIからゼロが返ってきていることです。::GetMessagePos APIは::GetMessage APIがメッセージを取得した時のマウスカーソルの位置、とのことですが、もちろん、マウスカーソルを(0, 0)に移動させていた、ということはありません。::SendMessage中だと駄目なのかとも考えましたが、メッセージのログを見ると、Sendでは成功して、その後のPost中に失敗しています。

何か情報をお持ちの方は情報よろしくお願いします。

それから、自分の持っているマウスのホイールの挙動がtrunk(または1.9.2 branch)でおかしい場合、バグを報告してください。widget removalの影響で多くのマウスドライバの挙動が壊れてしまっていても不思議ではありません。ちなみに、今報告しておかないとFx 3.6ではマウスドライバ側の対応待ち、ということになります。

2009年9月23日

Bug-org 517549 TISGetInputSourceProperty is 12.3% of my startup path 初回投稿日時: 2009年09月23日02時05分22秒
最終更新日時: 2009年09月23日02時59分49秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2009092300
SNS: (list)

TSテストと呼ばれる、スタートアップ時間の計測テストで、MacのTISGetInputSourcePropertyの呼び出しで一割以上もの時間がかかってるが、別スレッドに移すなりなんなりできないか、というバグです。

問題のコードはBug-org 513955の修正で追加されたスタートアップ時に全キーボードレイアウトの情報を取得するという部分なのですが、そもそもそんなところ、走るべきではありません。デバッグ用のコードなのですから。

で、nsChildView.mm内をよく見渡すと、リリースビルドでもログを吐くようになっていて、ログを吐かない場合であっても無条件にキーボードレイアウトの各種情報を取得するコードは走ってしまいます。これはいかん、ということで問題の部分をデバッグビルドでしかビルドしないように修正してチェックインしたところ、以下のような結果になりました。

TrunkでのTSテストの結果の折れ線グラフ

効果が予想以上に大きく、3割程度のパフォーマンス向上が見られます。ならば、これはおそらく1.9.2 branchでも効果でるだろう、ということで似たパッチを作って投入したのが以下の結果です。

1.9.2 BranchでのTSテストの結果の折れ線グラフ

グラフの上半分では顕著に改善が見られます(trunkに比べて荒れてますが……)。しかし、下半分の元々高速だったテスト機では改善が見られませんでした。この差は何だろうかと、各マシンを見てみると(スクリーンショットからでは分かりませんが)、今まで1400msかかっていたのが10.5、元々1000ms程度だったのが10.4でした。

Macは10.5からは従来のKeyboard Layout Servicesを捨て、新たにText Input Source Servicesに切り替えました。もちろん(互換性はともかく)好ましい修正ではあるのですが、パフォーマンスが劇的に低下していることが分かります(10.5や10.6でも、32bitアプリならKL APIは使えますが、背後ではTIS APIを呼んでいるだけか、それに近いことをやっているはずです)。TIS APIは主に、ユーザの入力時に利用することになるのであまり問題無いレベルかもしれませんが、気をつけておいた方が良さそうです。

結局、この問題は、10.4でパフォーマンスに問題なかったので元々のコードのチェックイン時には気付かなかったけれど、Bug-org 513955の修正の修正で若干、追加処理も入れたのでそれでパフォーマンスが低下し、これらのことが明るみにでた、ということです。

2009年9月29日

Bug 6685 ロジクールのマウスでチルトホイールを傾けても一回しかスクロールしないことが多い #2 初回投稿日時: 2009年09月29日02時20分30秒
最終更新日時: 2009年09月29日02時25分04秒
カテゴリ: Mozilla Core バグ修正 バグ原因判明
固定リンク: id=2009092900
SNS: (list)

既にtrunkでは修正済みです。1.9.2 branchには直接の原因となった修正が今はまだチェックインされていないので、この修正もまだ入っていません。

原因の究明にはかなり時間がかかりましたが、ちゃんと理解できました。元々、ロジクールのマウスのドライバはGeckoに対してWM_MOUSEHWHEELを送信することで横スクロールという結果が発生している訳ではありませんでした。キャレットブラウジングモードに切り替えると分かるのですが、最初のWM_MOUSEHWHEELの処理時に::GetMessagePosを一切利用せずに、常にゼロがセットされているlParamを見て処理していました。このため、最初の::SendMessageによる反応テストの段階で失敗し、その後はWM_KEYDOWNメッセージで矢印キーが押されたことにしてスクロールを実現していました(だからキャレットブラウジングモードだとスクロールせずにキャレットが動くのみ)。

ですがtrunkでは、::GetMessagePos APIを利用するようになったことで、最初の::SendMessage時にのみ正常なマウスカーソル位置が取得できてしまい、処理が成功したのを確認したロジクールのドライバが::PostMessageWM_MOUSEHWHEELを連射してくるものの、ここでは::GetMessagePos APIの戻り値も壊れていて処理に失敗し続けている、というのがこのバグの真相でした。

私のパッチでは、lParam値や、::GetMessagePos APIの戻り値から、ロジクールのマウスであるかを推測し、そうであると判断した場合には::GetCursorPos APIを利用するようにしています。もちろん、これらのAPIの違いの分、誤動作はあるかもしれませんが、よほど処理落ちした状況等以外で誤動作だと分かることもないのではないかと思います。

Bug 6689 一部しか表示されていないリンクをクリックするとスクロールする 初回投稿日時: 2009年09月29日02時27分40秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2009092901
SNS: (list)

focus refactoringのregressionで、このバグが再発していましたが、単なるフラグの指定し忘れだけだったので即、修正できました。今度は自動テストにも追加しているのでもう再発は無いと思います。

Bug-org 513817 Switch scrolling to 6 lines in the default case for 3.6 on windows 初回投稿日時: 2009年09月29日03時07分51秒
最終更新日時: 2009年09月29日03時12分35秒
カテゴリ: Mozilla Core バグ修正
固定リンク: id=2009092902
SNS: (list)

物議をかもしたマウスホイールによるスクロール速度の問題にひとまず決着がつきました。既に1.9.2 branchにも修正が入っています。

現在の仕様は、ホイールの回転速度に応じた加速(acceleration)はデフォルトでは無効になりました。マウスドライバがこの機能を持っていない環境で有効にしたい場合は、プラットフォームを問わず、mousewheel.acceleration.startを0以上に設定し、mousewheel.acceleration.factorで加速度を調整できます。startは、何回目のホイールイベントから加速を開始するのか、factorは加速する時の倍率を算出するための係数です。加速された行数の算出は、

PRInt32(NS_round(aDelta * sScrollSeriesCounter * (double)aFactor / 10));

となっています。aDeltaはホイールイベントで指定されたスクロール行数、sScrollSeriesCounterは80ms以内にホイールイベントが連続している時の、ホイールイベントの発生回数(80ms以内に発生したイベントの回数ではありません、80ms発生しなかったらリセットされますが、80ms以内にホイールイベントが発生すると加算されつづけ、加速し続けます)、aFactorが上記の係数です。sScrollSeriesCounterが無造作に大きくなる可能性がある明らかに変なロジックですが、これがそのまま残らずに助かりました。

ですが、無効にして終わりともならないのでシステム設定のスクロール速度をGecko内部で乗算し、上書きするメカニズムを用意しました(override)。ただし、出来る限りユーザの設定を尊重する形で制限が加えてあります。

まず、このメカニズムを有効にするにはmousewheel.system_scroll_override_on_root_content.enabledtrueにします。Windowsではデフォルトで有効になっていますが、他のプラットフォームではデフォルトでオフです。

ただし、この設定で有効にしても、ドキュメントのルートのスクロールでしか上書きは行われません。つまり、textareaやリストボックス、ツリービュー等のコントロールや、overflowautoscrollに指定しただけの要素ではシステムの設定速度でのスクロールのままになります。

さらに、デフォルトで有効なWindowsではシステム設定の速度設定をユーザ、もしくはマウスのドライバが変更していない場合にのみ上書きするように制限しています。つまり、縦、横ともにWindowsのデフォルトである3行(3文字)スクロールの場合にのみ上書きが行われ、どちらかでも3以外の数値になっている場合には上書きされません(XP以前のWindowsでは横方向のホイールはOSレベルではサポートしていなかったため、検証されません。縦方向のみで判断されます)。

このようになった理由は

  • ユーザが数値を変更している場合、ユーザの好みの速度なのでそれを尊重すべき
  • マウスドライバが数値を変更している場合、そのドライバは加速機能をそもそも持っているのではないかと推測される(Microsoft、Logitech(Logicool)は共に変更し加速機能つき、VAIOのAlpsのタッチパッドでは変更しているものの加速機能はない)

となっています。おそらく後者の方で実際には上書きが発生しない環境がほとんどではないかと思います(素のWindowsで、特殊なドライバを使わない安いマウスでなければなかなか条件には該当しないと思います)。結局、この考え方で救えないのはWindowsそのもののデフォルト設定が好きなユーザです。その人たちには残念ながら上記の設定から無効にしてもらうしかありません。

乗算する際の倍数はmousewheel.system_scroll_override_on_root_content.vertical.factormousewheel.system_scroll_override_on_root_content.horizontal.factorで、それぞれ垂直方向と水平方向への値を個別に指定できます。値は、100で割ってから利用されるので、初期値の200だと、2.00倍の意味となります。ただし乗算後は整数に四捨五入されるので小数はdelta値がぶれるマウスドライバ(例えばMicrosoftのInteliPoint)との組み合わせでなければあまり意味がないかもしれません。

乗算結果がシステム設定の速度に対する乗算結果を超えた場合、その数値はシステム設定の速度に制限されます。たとえば、システム設定が3行なのに対して、deltaが4のイベントだった場合、4×2で8が採用されるのではなく、3×2の6に制限された値で上書きされます。これにより、マウスドライバが設定を変更しないままに加速機能を持っていた場合、必要以上に加速してしまうことを防止しています。

最後に、これら二つの仕組みを含めた計算結果が1ページ以上スクロールしてしまう場合、1ページのみのスクロールに制限されます。つまり、一回のホイールイベントでスクロールしすぎて行の存在を見過ごすことがないようにしています。