Now browsing the archives for the 'userChrome.js' category.
userChrome.js スクリプト集のページ
Firefox 2 の時代に作った userChrome.js スクリプト集のページ に掲載したスクリプトの一部が最近の Firefox 3.0 や 3.5 で動作しなかったため、修正しました。
変更点:
- 「Paste And Go」が Firefox 3.5 以降で動作しないバグを修正。
- 「Open Add-on Folder」でプラグインなどの項目を右クリックしたときに「Open Folder」メニュー項目を表示しないように改善。
- 「Restart Firefox」のショートカットキーの変更と再起動処理の改善。
- 「Colorful Tabs」が Firefox 3.0 以降で動作しないバグを修正。
- すべてのスクリプト中に @compatibility で Firefox の対応バージョンを明記。
- すべてのスクリーンショットを Firefox 3.5 のものに差し替え。
[userChrome.js] リアルタイムタブプレビュー
タブ上にマウスをかざすと、サムネイルプレビューをリアルタイムに表示する userChrome.js 用スクリプトです。
Opera や Seamonkey にある機能とほぼ同じですが、サムネイルのプレビューを一定間隔で更新するので、読み込み中のタブの状態を、タブを切り替えることなくチェックしたりできます。
スクリプトはこちら: xuldev.org :: userChrome.js scripts » Tab Preview
userChrome.js スクリプト配布ページ
これまでに掲載した userChrome.js 用スクリプトを整理して配布ページを作りました。
いくつかのスクリプトを新たに追加し、これまでのスクリプトも一通り見直して修正しています。
xuldev.org :: userChrome.js scripts
[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;
[userChrome.js] Vertical Toolbar
ウィンドウ左側に縦置きツールバーを配置するための userChrome.js 用スクリプト。
個人的には縦置きツールバー必須なのだが、それを実現するための拡張機能である Toolbar Enhancements が Firefox 1.5 時代から更新停止状態だし、かといって All-in-One Sidebar は余計な機能が多すぎるので、 userChrome.js で必要最低限な機能のみを実装した。
xuldev.org :: userChrome.js scripts » Vertical Toolbar
カスタマイズ方法
カスタマイズは全てスクリプト直接編集で行うという玄人志向である。残念ながら通常のツールバーのように「ツールバーのカスタマイズ」ウィンドウからボタンをドラッグ&ドロップして配置することはできない。現状のツールバーのカスタマイズ機能は複数の toolbox 要素に対するカスタマイズを考慮した作りになっていないからである。これを複数のtoolbox 要素に対して有効にさせるには、かなりの無茶をしないといけないので諦めた。
ツールバーに配置するアイテム
スクリプト内の currentSet という変数がツールバーに配置するボタンの要素IDの配列となっている。ツールバーボタン以外にも “separator” (区切り)、 “spring” (伸縮自在のスペース)、 “spacer” (スペース)も配置可能。
ツールバーの表示
変数 mode の値を “icons” とするとアイコンのみ表示、 “text” とするとテキストのみ表示、 “full” とするとアイコンとテキスト両方表示になる。
ツールバーアイコンのサイズ
変数 size の値を “large” とすると大きいサイズのアイコン、 “small” とすると小さいサイズのアイコンとなる。
[userChrome.js] 軽量マウスジェスチャー(ホイールジェスチャ・ロッカージェスチャ対応版) ~途中経過~
6/30 追記
ロッカージェスチャ有効時、選択範囲をテキストボックスへドラッグ&ドロップすると右クリックが効かなくなるバグを修正。
「Operaユーザは「右押しながら左クリック」をよく使う」というアンケート結果に衝撃を受けたわけではないですが、軽量マウスジェスチャへ、以下の2機能を追加したバージョンを作成しました。
・ホイールジェスチャ (右クリックしながらホイール回転でタブ切り替え)
・ロッカージェスチャ (右クリックしながら左クリックで戻る、左クリックしながら右クリックで進む)
ホイールジェスチャおよびロッカージェスチャ実行時には、 _performAction メソッドへ以下のような文字列が渡りますので、実行するアクションをカスタマイズ可能です。
・ホイールジェスチャ(下に回転): W+
・ホイールジェスチャ(上に回転): W-
・ロッカージェスチャ(右クリックしながら左クリック): L<R
・ロッカージェスチャ(左クリックしながら右クリック): L>R
ただし、ロッカージェスチャに未解決の問題点があって、例えば右クリックしながら左クリックを連続で何回か押して連続で戻る操作をしているとき、ページのローディングが行われている瞬間(くるくるアイコンが回転している瞬間)を狙って右クリックを放すと、放したことが認識されずに右クリックが続いていると誤認識され、その後の動作がおかしくなる。bfcache が効いていると再現しにくいので、いったんキャッシュをクリアするとページ遷移のたびにローディングされ、上記問題が再現しやすくなる。
とはいえ、そもそも All-in-One Gestures ではロッカージェスチャは連続でできない(右クリック押しながら一回左クリックをするとその時点で終了する)ため、 userChrome.js 版マウスジェスチャでもその動きにすれば上記問題点は解決すると思われる。反面、 Optimoz Mouse Gestures や本家 Opera では連続クリックが可能である。
ロッカージェスチャを望んでいる方は、この連続クリック機能が必須であるか、無くてもいい程度のものか、あるいはまったくもって不要かなどについて教えてくださるとありがたいです。ただ、連続クリックが必須という意見が大半であったとしても、今後がんばっても上記問題を解決できないままである可能性が高いです。
userChrome.js でE4Xを使う
これまで、userChrome.js スクリプトでスタイルシートを追加することはできなくて、別途 userChrome.css を使用しなければならないと思っていた。ところが、nanto_viさんによるE4X in Firefox 発表資料: Days on the Moon の userChrome.js 用スクリプトを見ればわかるように、 E4Xを使うことによって userChrome.js のみでスタイルの定義追加が可能であることが判明。それだけでなく、E4Xを使えば userChrome.js 内に XML を直接書いてそのままブラウザへオーバーレイなんてことも簡単に可能。ボタンやメニューをたくさん追加したいときなんかに、いちいち document.createElement する必要がなくなる。すばらしい。
さっそく、 Colorful Tabs を修正して、 userChrome.css への追記を不要にさせた。
[userChrome.js] 軽量マウスジェスチャをWindows/Linuxに対応させる
通りすがりさんによるパッチをベースに、[userChrome.js] 軽量マウスジェスチャを Windows/Linux に対応させました。以下は今回修正した内容についてメモです。
以前はマウスジェスチャ中の状態遷移を数値型のフラグ _state を使って以下のように制御していた。
イベント | _state フラグの変化 | 意味 |
---|---|---|
mousedown | 0 → 1 | 右クリック開始 |
mousemove | (1のまま変化なし) | 右クリックしたままマウス移動中 |
mouseup | 1 → 2 | ジェスチャ認識あり |
1 → 3 | ジェスチャ認識なし(マウスの移動量が微小) | |
contextmenu | 2 → 0 | コンテキストメニューの表示を抑止する |
3 → 0 | コンテキストメニューの表示を抑止しない |
しかしながら、 Windows では上記のように mousedown→mousemove→mouseup→contextmenu という順序でイベントが発生するものの、 Linux では mousedown→contextmenu→mousemove→mouseup という順序で発生するため、制御がうまくいかなかった。そこで、数値型のフラグを廃止し、代わりに以下のような3つの真偽値フラグを使うようにした。
フラグ | 意味 |
---|---|
_isMouseDown | 右クリックが押されているかどうか。 mousedown イベントで true になり、 mouseup イベントで false になる。 |
_suppressContext | この後の contextmenu イベントを抑止するかどうか。 mouseup イベント発生時にジェスチャの認識があれば true にし、その後の contextmenu イベントを抑止する。 |
_shouldFireContext | 後で contextmenu イベントを擬似的に発生させる必要があるかどうか。 Linux 専用。 Linux の場合は mousedown イベント直後に contextmenu イベントが発生するが、これを抑止した際にフラグを true にしておき、その後の mouseup イベント発生時にフラグが立っていれば擬似的に contextmenu を発生させる。 |
これによってスクリプトの一部は以下のように変更された。青色の部分が Linux 専用となる処理である。
_isMouseDown: false, _suppressContext: false, _shouldFireContext: false, handleEvent: function(event) { switch (event.type) { case "mousedown": // [1] ジェスチャ開始 if (event.button == 2) { this._isMouseDown = true; this._startGesture(event); } break; case "mousemove": // [2] ジェスチャ継続中 if (this._isMouseDown) { this._progressGesture(event); } break; case "mouseup": // [3] ジェスチャ終了~アクション実行 if (this._isMouseDown) { this._isMouseDown = false; this._suppressContext = !!this._directionChain; this._stopGesture(event); // [Linux] Win32を真似てmouseup後にcontextmenuを発生させる if (this._shouldFireContext) { this._shouldFireContext = false; this._displayContextMenu(event); } } break; case "contextmenu": // [4-1] アクション実行後のコンテキストメニュー表示を抑止する // [4-2] 方向が認識されない微小な動きの場合は抑止しない // [Linux] mousedown直後のcontextmenuを抑止して... if (this._suppressContext || this._isMouseDown) { this._suppressContext = false; event.preventDefault(); event.stopPropagation(); // [Linux] ...代わりにmouseup後にcontextmenuを発生させる if (this._isMouseDown) { this._shouldFireContext = true; } } break; } }, _displayContextMenu: function(event) { var evt = event.originalTarget.ownerDocument.createEvent("MouseEvents"); evt.initMouseEvent( "contextmenu", true, true, event.originalTarget.defaultView, 0, event.screenX, event.screenY, event.clientX, event.clientY, false, false, false, false, 2, null ); event.originalTarget.dispatchEvent(evt); },
[userChrome.js] 軽量マウスジェスチャ(モーダルダイアログに関する不具合修正)
これまでは、例えば「alert(“OK”);」のようなモーダルダイアログ(閉じないと親のウィンドウの操作ができないタイプのダイアログ)の表示をジェスチャに割り当てると、ダイアログを閉じたあとにコンテキストメニューが出てしまうバグがあった。やむを得ず、「setTimeout(function(){ alert(“OK”); }, 0);」のように時間差で処理を実行させるという策を講じていたが、さきほどコンテキストメニューが出てしまう原因を調べてみた。
すると、モーダルダイアログを表示することで一見親ウィンドウの処理が一時停止しているかのように見えるが、なぜかダイアログ上でマウスを動かすとmousemoveイベントが発生し、 mouseup→contextmenu というイベント発生の順序が崩れて mouseup→mousemove→contextmenu になり、結果的に不具合が生じることがわかった。
そこで、以下のように微修正。スクリプト全体はこちらにあります。
変更前:
... // [3] ジェスチャ終了~アクション実行 if (this._state == 1) { this._state = this._directionChain ? 2 : 3; // ジェスチャが認識されれば、この時点でthis._stateは2になる。 // _stopGestureメソッドが_performActionメソッドを呼び出し、 // 下記_stopGestureから呼ばれる_performActionメソッドの中でモーダルダイアログを表示すると… this._stopGesture(event); // ダイアログ上をマウスが通過した際に余計なmousemoveイベントが発生し、 // ここを通過するときにはthis._stateは0になってしまう。 } ...
変更後:
... // [3] ジェスチャ終了~アクション実行 if (this._state == 1) { var state = this._directionChain ? 2 : 3; this._stopGesture(event); this._state = state; } ...
この修正に伴い、
// プライバシー情報の消去 setTimeout(function(){ document.getElementById("Tools:Sanitize").doCommand(); }, 0); // オプション setTimeout(function(){ openPreferences(); }, 0);
はそれぞれ以下のようにしてもOKになります。
// プライバシー情報の消去 document.getElementById("Tools:Sanitize").doCommand(); // オプション openPreferences();