Now browsing the SCRAPBLOG weblog archives.

[userChrome.js] 軽量マウスジェスチャをMacに対応させる

9/1 訂正 やはり以前作った Linux 対応版でも、マウスジェスチャのみのバージョンは Mac にも対応していたようである。ただ、ロッカージェスチャ・ホイールジェスチャ機能追加版の方は Mac では動作せず、その原因は Mac で右クリックしたときの mouseup イベントが「event.button == 2」で判断不可で、代わりに「event.button == 0 && event.ctrlKey」としなければならないためであるようだ。

以前 userChrome.js 版マウスジェスチャを Linux 対応させたとき、勢い余って Mac にも対応と書いてしまっていたが実際はロッカージェスチャ・ホイールジェスチャ機能追加版の方は Mac では動作していなかった。ところが、 Windows / Linux で右クリックの mouseup イベントを「event.button == 2」として判断している箇所を、Mac ではCtrlキー+左クリックされたと読み替えて「event.button == 0 && event.ctrlKey」とすることでうまくいくようだ(筆者は未確認ですが)。そこで、下記の青字で示した部分が追加される。

ロッカージェスチャ・ホイールジェスチャ対応版

    _lastX: 0,
    _lastY: 0,
    _directionChain: "",
    _isMac: false,    // for Mac

    init: function()
    {
        this._isMac = navigator.platform.indexOf("Mac") == 0;
        gBrowser.mPanelContainer.addEventListener("mousedown", this, false);
        gBrowser.mPanelContainer.addEventListener("mousemove", this, false);
        gBrowser.mPanelContainer.addEventListener("mouseup", this, false);
        gBrowser.mPanelContainer.addEventListener("contextmenu", this, true);
            case "mouseup": 
                // [3] ジェスチャ終了~アクション実行
                if ((this._isMouseDownR && event.button == 2) || 
                    (this._isMouseDownR && this._isMac && event.button == 0 && event.ctrlKey)) {
                    this._isMouseDownR = false;
                    if (this._directionChain)
                        this._suppressContext = true;

TOP

tabbrowser.xml と関連ファイルの移動

Bug 339964 – move tabbrowser.xml out of mozilla/toolkit and into mozilla/browser
Firefox のタブブラウザ関連UI (<xul:tabbrowser> 要素) は Firefox 固有の性質が強いため、 toolkit.jar から browser.jar 配下へ移動された。これに伴い、関連する XBL や DTD などの URL が以下のように変更となった。

Firefox 2.0.0.6 Firefox 3.0a8pre
chrome://global/content/bindings/tabbrowser.xml chrome://browser/content/tabbrowser.xml
chrome://global/skin/tabbrowser.css chrome://browser/skin/browser.css へ統合?
chrome://global/locale/tabbrowser.dtd chrome://browser/locale/tabbrowser.dtd
chrome://global/locale/tabbrowser.properties chrome://browser/locale/tabbrowser.properties

TOP

createElement してから appendChild するまでの間のプロパティ変更

下記の value プロパティ変更は効果がない。

var elt = document.createElement("textbox");
elt.value = "It works!";
document.documentElement.appendChild(elt);

代わりに setAttribute を使うか、

var elt = document.createElement("textbox");
elt.setAttribute("value", "It works!");
document.documentElement.appendChild(elt);

appendChild してからプロパティを変更する。

var elt = document.createElement("textbox");
document.documentElement.appendChild(elt);
elt.value = "It works!";

TOP

en-US 言語パックの作り方

追記:コメントにて、わざわざ言語パックを作る必要の無いもっと簡単な手順を教えていただきました。

日本語版 Firefox 2 をインストールしたが、スクリーンショット撮影用に一時的に英語版 (en-US) に切り替えて使いたいときがある。ここを見てもイギリス英語版言語パック (en-GB.xpi) しか置いていない。もしかしてどこかで配布されているかもしれないが、何とかして自前で en-US の言語パックをインストールする。以下 Windows 版 Firefox 2 が前提。

手順

  1. firefox-2.0.0.6.en-US.win32.zip をダウンロードして展開する
  2. プロファイルフォルダの extensions フォルダ内にフォルダ「langpack-en-US@firefox.mozilla.org」を作成
  3. 1.で展開した chromeen-US.jar と en-US.manifest を2.のフォルダへ配置
  4. en-US.manifest を chrome.manifest にリネーム
  5. 2.で作成したフォルダにファイル「install.rdf」を作成し、以下の内容を記述
    <?xml version="1.0"?>
    
    <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:em="http://www.mozilla.org/2004/em-rdf#">
      <Description about="urn:mozilla:install-manifest"
                   em:id="langpack-en-US@firefox.mozilla.org"
                   em:name="English (US) Language Pack"
                   em:version="2.0"
                   em:type="8">
        <em:targetApplication>
          <Description>
            <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
            <em:minVersion>2.0</em:minVersion>
            <em:maxVersion>2.0.0.*</em:maxVersion>
          </Description>
        </em:targetApplication>
      </Description>
    </RDF>
    
  6. about:config から general.useragent.locale を en-US に変更して Firefox 再起動

TOP

Prefwindow のパネル切り替えの挙動がおかしい

prefwindow 要素で作成した設定ウィンドウで、ウィンドウ上部のパネル切り替えボタンと実際に選択されるパネルに食い違いが発生するおかしな挙動に悩まされた。

原因は prefwindow 要素直下に script 要素を配置していたことだった。
Preferences System:prefwindow – MDC にも書いてある通り、 prefpane 以外の要素を配置する場合は prefpane 要素よりも後に記述しなければならない。

<prefwindow ... >
    <prefpane label="General" ... >
        ...
    </prefpane>
    <prefpane label="Advanced" ... >
        ...
    </prefpane>
    <script type="application/x-javascript" src="prefs.js" />
</prefwindow>

TOP

Firefox 3 のフルページズーム使用時はスクリーン上でのピクセル量とCSS上でのピクセル量は一致しない

Firefox 3 Alpha に搭載されたフルページズーム(テキストと画像をともに拡大/縮小する機能)を使った場合、CSS レイアウトの座標上での「1ピクセル」という単位は、必ずしも画面上での1ピクセルに一致しないことになる。例えばフルページズーム機能でページを2倍に拡大した状態だと、CSSでの1pxのborderがスクリーン上では2pxとして表示される(下図参照)。

左:Firefox 2.0.0.5 で「文字サイズ」を約2倍に拡大した表示例
右:Firefox 3.0a8pre でフルページズームを使って2倍に拡大した表示例
Full Zoom

問題が生じるケース

All-in-One Gestures のマウストレイル(マウスジェスチャの軌跡描画機能)は、マウスポインタの移動に応じてスクリーン上の座標 (event.screenX, event.screenX) が変化したピクセル量分だけの点をページ上に配置することによって線を描画するという仕様である。
フルページズームでページを2倍に拡大した状態だと、スクリーン上の座標で4px移動しても、実際のCSSの座標上では2px分という計算になるが、現時点の AiOG のマウストレイルの実装はこれを考慮していない。したがって、 AiOG を無理やり Firefox 3 上で使用すると、スクリーン上の座標で4px移動したときもCSSの座標上で4px分の点を配置するため、実際のスクリーン上では8pxとして表示されてしまう。なおかつ、線の太さが2倍になる、軌跡の位置がマウスポインタから大きくずれるといった問題点が生じる。

結論

フルページズーム機能搭載に伴い、スクリーン上でのピクセル量とCSS上でのピクセル量が一致するという前提はもはや崩れ去った。両者の整合性を取るためには、 nsIMarkupDocumentViewer::fullZoom 値を常に意識する必要がある。例えば現在フォーカスしているブラウザの fullZoom 値は、以下のようにして取得可能である。

gBrowser.mCurrentBrowser.markupDocumentViewer.fullZoom

TOP

横幅に収まらずに crop されたテキストの末尾の「…」

2007/11/?? 追記
この問題は中野雅之氏・dynamis氏らのご尽力により解決しました。

2007/8/19 追記
Bugzilla-jp にバグが登録されていました。
Bug 5843 – UI に (U+2026 ‘HORIZONTAL ELLIPSIS’) が使われると見た目が不自然

タブやツリーセルのラベルが横幅に入りきらなかった場合、今までは「Mozilla Firef…」のように末尾に「…」という文字(ピリオド3つ)が表示されていたが、 Firefox 3 alpha ではいつの間にか「・・・」という表示(三点リーダ)に変わっていた。
少なくとも Windows では「…」が標準であるはずなので非常に違和感を感じる。

と思ったら日本語フォント特有の問題っぽい。

左: Firefox 2.0.0.5
右: Firefox 3.0a8pre
Cropped Text

TOP

ダイアログから開いたモーダルダイアログが Linux ではモーダルでない

Linux で、ダイアログ(dialog 要素)から window.openDialog メソッドを使ってモーダルダイアログを開いた状態で、親のウィンドウへフォーカスして Esc キーを押下すると、親のウィンドウを閉じることができてしまう。
Prefwindow 要素の openSubDialog で開いたモーダルダイアログについても同様。
前提が崩れてやっかいなことになった。

テストケース:

<?xml version="1.0"?>

<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        title="Linux Modal Dialog Test">

    <script type="application/x-javascript"><![CDATA[
    function showModalDialog() {
        window.openDialog(
            'chrome://browser/content/aboutDialog.xul',
            'About',
            'modal,centerscreen,chrome,resizable=no'
        );
        if (!document) {
            dump("*** Linux modal dialog problem");
            return;
        }
    }
    ]]></script>

    <button label="Show Modal Dialog" oncommand="showModalDialog();" />

</dialog>

環境: Ubuntu Linux 6.10 + Firefox 2.0.0.4

TOP

Custom Tree View でドラッグ&ドロップ時に固まる

Custom Tree Views を使って階層構造がない単純なデータを表示するツリーを作成し、ツリーアイテムのドラッグ&ドロップによる並び替えを実装しようとしたところ、ドロップ時に Firefox が固まる問題が発生。

原因は nsITreeView#getParentIndex で「return -1;」していなかったことであることに気付くまで、3時間くらい無駄にした。

CustomTreeView.prototype = {
    ...
    getParentIndex: function(rowIndex) { return -1; },
    ...
};

また、 nsDragAndDrop.js を使ってドラッグしたときの転送データを生成する際、データフレーバに「text/plain」とすると、なぜか実際に転送データの中身が文字化けしたようなデータになってしまうという問題にも悩まされた。これは、データフレーバを「text/unicode」にすることで解決した。

gDragAndDropObserver = {
    ...
    onDragStart: function(aEvent, aXferData, aDragAction) {
        aXferData.data = new TransferData();
        aXferData.data.addDataForFlavour("text/unicode", "Hello!");
        aDragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_MOVE;
    },
    ...
};

TOP

ロッカージェスチャの実装 Part 2

ロッカージェスチャの実装における問題点(ページロード遷移中の mouseup イベントが認識されない)への対策として、一度ロッカージェスチャを実行した後に少しでもマウスを動かすとロッカー状態を強制解除することに決めた。
つまり、マウスポインタを移動させないという制限付きで、左クリック(mousedown)→右クリック→右クリック→右クリック→・・・→左クリック(mouseup)での連続ロッカージェスチャを実行可能とする。

メリット

上記問題点が発生しても、ちょっとでもマウスを動かせば正常な状態に戻る。

デメリット

マウスを移動させながらの連続ロッカージェスチャが不可能。

TOP