2017/12/11

Firefox Quantumでホイールでのタブ切り替え

Firefoxのバージョン57で旧式アドオンが切り捨てられてしまい、制限された新しいアドオン仕様 “WebExtensions” では代替できなくなったことが多い。

そんな中でも “userChrome.js” 系のスクリプトを用いた方法で代替できることが一部あり、ここではタブ上のマウスホイールでタブを切り替えるものと全ページで動作するシンプルなマウスジェスチャの2つを扱う。

これらは個人的にはかなり役に立っているが、この仕組みは古い技術を用いており、Firefoxの方向性に逆らっている部分があるため、いつ切り捨てられるか分からないという点は頭に入れておく必要がある。今後WebExtensionsが拡張されたり本体に機能が追加されたりしてスクリプトを使う必要がなくなれば、できるだけそれらの真っ当な方法に移行したほうがよい。

(2018/9/8)その後、内部的な変更によりマウスジェスチャについては動作しなくなっており、手元の環境ではアドオンへ切り替えた。マウスホイールによるタブ切り替えについては以前とは別の手順を用いることでバージョン62時点では動作している。

  1. 環境整備とスクリプト配置場所
  2. 使用しているスクリプト
    1. タブ部分のマウスホイールでタブ切り替え
    2. 任意のページでマウスジェスチャ (シンプル)

環境整備とスクリプト配置場所

Firefox本体のディレクトリとプロファイルのディレクトリに対して指定されたファイルをそれぞれ配置しなければならず、導入作業の中でも面倒な部分となる。

今回はuserChrome.js用スクリプトの “Firefox57以降でuserChrome.js用スクリプトを利用する方法” の “その2” の方法を行った。これは https://github.com/Endor8/userChrome.js/tree/master/userChrome の内容に基づいている。

(2018/9/8)バージョン62時点では “サンドボックスが有効になった以降でもuserChrome.js用スクリプトを利用する方法” で作業する。本体側のディレクトリへの変更は必要なくなった。

GNU/Linuxではプロファイルのディレクトリは[ホームディレクトリ]/.mozilla/firefox/[文字列].[プロファイル名]/となり、この直下にchromeという名前のディレクトリを(無ければ)作成してuserChrome.js(1行だけのもの)と.uc.jsファイル群を配置する。

いったん配置したスクリプトを後からカスタマイズなどで編集する場合、変更の反映には環境変数XDG_CACHE_HOMEのディレクトリ(未定義時は[ホームディレクトリ]/.cache/)の下のmozilla/firefox/以下のスクリプトキャッシュを削除する必要がある。

使用しているスクリプト

以下で扱っている2つのスクリプトが意図した通りに動作しているが、片方は一部に修正が必要だった。他に流通しているuserChrome.js用スクリプトはたくさんあるが、修正が必要だったり、上記ページのもう一方の方法でないと動かなかったりするものもあるようだ。

タブ部分のマウスホイールでタブ切り替え

Firefoxはタブ部分のマウスホイールでタブを切り替えることができず、旧式アドオンからこれを実現していたが、今後は.uc.jsスクリプトで行うことになる。将来本体側が改善されて標準機能でできるようになった場合は必要なくなるが、バージョン57時点ではタブ部分のマウスホイールはタブ数が多いときのスクロールという振る舞いで固定されており、今後どうなるかは不明。

これを実現するスクリプトは https://www.camp-firefox.de/forum/viewtopic.php?p=1045772&sid=07b11ac565c2b30985a9fe6580a9e59c#p1045772 にあり、このコードをTabWheelScroll.uc.jsなどの名前で前述のディレクトリに保存する。

カスタマイズとしては、コード内のscrollRightの値をfalseにするとホイールの上下の挙動が逆になり、wrapの値をfalseにすると端のタブで循環しなくなる。

任意のページでマウスジェスチャ (シンプル)

新しいWebExtensions仕様の拡張ではアドオンの配布サイトやブラウザ内の一部のページでマウスジェスチャが動作せず、非常に不便なのだが、.uc.jsスクリプトにより従来のアドオンのようにマウスジェスチャで操作を行うことが可能になる。

今回使用したものは以前使えたアドオンの “FireGestures” を開発した作者によるもので、10年ほど前に公開された基本機能のみの軽量版だが、個人的にはこれで事足りる上に他に幾つか試したマウスジェスチャ用スクリプトがうまく動かなかったためにこれを選択した。

ファイルは http://www.xuldev.org/misc/ucjs.php にある他のスクリプトと同じ階層にMouseGestures.uc.jsの名前で配置されている。同ページからリンクはされていない。また、このスクリプトは他サイトに転載もされている。

Firefoxのバージョン57とWaterfoxのバージョン56時点ではこれをそのまま使用するとGNU/Linuxではマウスジェスチャ自体は(基本的には)動作するものの、右ボタンクリック時にコンテキストメニューが表示されない問題がある。

手元の環境ではif (event.button == 2) {とある行の21に変更してジェスチャに中ボタンを用いるようにしている(この変更によりコンテキストメニューは正しく表示されるようになり、中ボタンでのジェスチャも慣れれば問題なく使える)。また、switch (this._directionChain) {の中をいじってジェスチャの効果をカスタマイズし、そのままでは動かないものについてはFireGesturesのコード(chrome/content/firegestures/browser.js)を参考にして修正している。

下は変更箇所を含む一部のみを抜粋したもの。ジェスチャを変更したい場合は効果に対応するcase "[文字列]"部分を変更する(U,D,L,Rが順に上下左右に対応する)。

ズームの代わりに文字サイズのみの変更を行う場合、gBrowser.fullZoomgBrowser.textZoomで置き換える。

[引用][任意]ファイル名:MouseGestures_custom.uc.js
// ==UserScript==
// @name           Mouse Gestures (Lite Version) custom
// @namespace      http://www.xuldev.org/
// @description    Lightweight customizable mouse gestures.
// @include        main
// @compatibility  Firefox 3.0, 3.5, 3.6b4
// @author         Gomita
// @version        1.0.20080201
// @homepage       http://www.xuldev.org/misc/ucjs.php
// ==/UserScript==

var ucjsMouseGestures = {


// ... //


 handleEvent: function(event)
 {
  switch (event.type) {
   case "mousedown":
    if (event.button == 1) {  // Middle button
     this._isMouseDown = true;
     this._startGesture(event);
    }
    break;


// ... //


 _performAction: function(event)
 {
  // These are the mouse gesture mappings. Customize this as you like.
  switch (this._directionChain) {
   // Back
   case "L": document.getElementById("Browser:Back").doCommand(); break;
   // Forward
   case "R": document.getElementById("Browser:Forward").doCommand(); break;
   // Reload
   case "UD": document.getElementById("Browser:Reload").doCommand(); break;
   // Reload (Skip Cache)
   case "UDU": document.getElementById("Browser:ReloadSkipCache").doCommand(); break;
   // Minimize Window
   case "RUD": window.minimize(); break;
   // Maximize Window or Restore Window Size
   case "RDU": window.windowState == 1 ? window.restore() : window.maximize(); break;
   // Open New Tab
   case "LR": document.getElementById("cmd_newNavigatorTab").doCommand(); break;
   // Close Tab
   case "DR": document.getElementById("cmd_close").doCommand(); break;
   // Undo Close Tab
   case "DL": document.getElementById("History:UndoCloseTab").doCommand(); break;
   // Undo Close Tab (If you are using Tab Mix Plus's Session Manager, use this instead.)
   // case "DL": gBrowser.undoRemoveTab(); break;
   // Previous Tab
   case "DUL": gBrowser.tabContainer.advanceSelectedTab(-1, true); break;
   // Close Left Tabs
   case "UL": var tabs = gBrowser.visibleTabs.filter(function(tab) !tab.pinned); var pos = tabs.indexOf(gBrowser.mCurrentTab); tabs = tabs.slice(0, pos); tabs.reverse().forEach(function(tab) gBrowser.removeTab(tab)); break;
   // Next Tab
   case "DUR": gBrowser.tabContainer.advanceSelectedTab(+1, true); break;
   // Close Right Tabs
   case "UR": var tabs = gBrowser.visibleTabs.filter(function(tab) !tab.pinned); var pos = tabs.indexOf(gBrowser.mCurrentTab); tabs = tabs.slice(pos + 1, tabs.length); tabs.reverse().forEach(function(tab) gBrowser.removeTab(tab)); break;
   // Scroll To Top
   case "U": goDoCommand("cmd_scrollTop"); break;
   // Scroll To Bottom
   case "D": goDoCommand("cmd_scrollBottom"); break;
   // Page Up
   case "LU": goDoCommand("cmd_scrollPageUp"); break;
   // Page Down
   case "LD": goDoCommand("cmd_scrollPageDown"); break;
   // Zoom Out
   case "LRD": gBrowser.fullZoom -= 0.1; break;
   // Zoom In
   case "LRU": gBrowser.fullZoom += 0.1; break;
   // Full Screen
   case "LDRU": document.getElementById("View:FullScreen").doCommand(); break;
   // Unknown Gesture
   default: throw "Unknown Gesture: " + this._directionChain;
  }
 }

};
使用したバージョン:
  • Firefox 57.0.1