読者です 読者をやめる 読者になる 読者になる

アドオン(拡張機能)でショートカットキーを優先的に登録する

[programming]
スポンサーリンク

追記@2008/02/14
Mac OS XFirefoxだと、動的に扱う部分で一部挙動が違う場合があるようです。
まとまり次第、追記したいと思っています。

                                  • -

キーボードショートカットは、key要素として先に登録されたものが優先されるようです。
なので、アドオンなどでkey要素を後から追加しただけでは、デフォルトのショートカットキーと重複していると、デフォルトの方が優先されてしまいます。


こないだ調べた下記を参考に、、

今回は追加するアドオン側で、デフォルトのキーボードショートカットより優先的に実行されるよう登録する方法を考えてみました。
(Windows XPFirefox 2.0.0.11で確認)

デフォルトのショートカットキーを退避することによって回避

重複するデフォルトのキーボードショートカットを別のショートカットキーに変更することにより回避する方法です。

<?xml version="1.0" encoding="UTF-8"?>
<overlay id="testOverlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <keyset id="mainKeyset">
    <key id="key1" modifiers="accel" key="B"
      oncommand="alert('新たに追加したショートカットです');" />
  </keyset>
  <script type="application/x-javascript">
  <![CDATA[
    window.addEventListener('load', function() {

      // デフォルトのショートカットキーを退避
      // accel + B を accel alt + B に
      var key = document.getElementById('viewBookmarksSidebarKb');
      key.setAttribute('modifiers', 'accel alt');

    }, false);
  ]]>
  </script>
</overlay>

もともとaccel+B(accelはOSによって違うキー(WinはCtrl,MacはCmd)になります)は、サイドバーにブックマーク一覧を開くショートカットですが、そのキーボードショートカットが定義されているkey要素を取得し、modifiers属性を変えて重複しないようにしています。
idを使ってkey要素を取得していますが、key要素のidは chrome://browser/content/browser.xul に対してDOM Inspectorを使えばわりと簡単に探せます。

デフォルトのショートカットキーと重複させたまま、新たに追加するショートカットキーを優先させる

デフォルトのショートカットキーの割り当てはそのままで、重複しながらも新たに追加するショートカットキーを優先的に実行させる方法です。

<?xml version="1.0" encoding="UTF-8"?>
<overlay id="testOverlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <keyset id="mainKeyset">
    <key id="key1" modifiers="accel" key="B"
      oncommand="alert('新たに追加したショートカットです');" />
  </keyset>
  <script type="application/x-javascript">
  <![CDATA[
    window.addEventListener('load', function() {

      // デフォルトのショートカットキーをDOMに再追加する
      var key = document.getElementById('viewBookmarksSidebarKb');
      key.parentNode.appendChild(key);

    }, false);
  ]]>
  </script>
</overlay>

デフォルトのショートカットキーのkey要素を付け替えることによって、key要素の削除->追加となります。
これによりデフォルトのショートカットキーが、新たに追加したショートカットキーより後に追加されたことになるので、新しいショートカットキーが優先的に実行されます。

全てにおいて優先させる

デフォルトだけでなく、他のアドオンで登録されているショートカットキーを含め、優先的に実行させる方法です。

<?xml version="1.0" encoding="UTF-8"?>
<overlay id="testOverlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="application/x-javascript">
  <![CDATA[
    window.addEventListener('load', function() {

      // 存在するkeysetを取得、配列に格納
      // (NodeListのままだと後から追加したkeysetも反映されてしまうので)
      var keysets = Array.prototype.slice.call(document.getElementsByTagName('keyset'));

      // 最優先にするショートカットを登録
      var keyset = document.documentElement.appendChild(document.createElement('keyset'));
      var key = keyset.appendChild(document.createElement('key'));
      key.setAttribute('modifiers', 'accel');
      key.setAttribute('key', 'B');
      key.setAttribute('oncommand', "alert('新たに追加したショートカットです')");

      // 最優先にするショートカット以外のkeysetを再追加
      for (var i = 0, len = keysets.length; i < len; i++) {
        keysets[i].parentNode.appendChild(keysets[i]);
      }

    }, false);
  ]]>
  </script>
</overlay>

既にあるkeyset要素を全て再追加することによって、それに紐づくkey要素のショートカットキーの実行優先度を下げています。
どうしても、そのアドオンで登録するショートカットキーは優先されないと困る!って時には、こんな感じで。(どんなとき??)