Thunderbird(Version 115系)のアドオン「tbkeys」を使ってカーソルキーのみでメールを選択して本文を読めるようにする設定を紹介する。
カーソルキーの操作で行いたいこと
フォーカスの位置毎にどのような振る舞いを行いたいかを表にした。
フォーカス箇所 | rightキー | leftキー | upキー | downキー |
---|---|---|---|---|
Folder | Threadにフォーカスを移動 メッセージブラウザーを隠す | (上位フォルダーへ移動) メッセージブラウザーを隠す | (上のフォルダーへ移動) | (下のフォルダーへ移動) |
Thread | Messageにフォーカスを移動 メッセージブラウザーを表示 | Folderにフォーカスを移動 メッセージブラウザーを隠す | (上のスレッドに移動) | (下のスレッドに移動) |
Message | メッセージブラウザーを表示 | Threadにフォーカスを移動 メッセージブラウザーを隠す | (メッセージを上にスクロール) | (メッセージを下にスクロール) |
それ以外 | Threadにフォーカスを移動 メッセージブラウザーを隠す | Threadにフォーカスを移動 メッセージブラウザーを隠す | - | - |
対応するJavascript
leftキー
let tabmail = window.document.getElementById('tabmail');
let focusedElement = window.document.activeElement;
let { currentTabInfo } = tabmail;
if (currentTabInfo.mode.name == 'mail3PaneTab') {
let { contentWindow, contentDocument } = currentTabInfo.chromeBrowser;
let { paneLayout, folderTree, threadTree, webBrowser, messageBrowser, multiMessageBrowser, accountCentralBrowser, } = contentWindow;
if (focusedElement == currentTabInfo.chromeBrowser) {
focusedElement = contentDocument.activeElement;
if (focusedElement != folderTree && contentDocument.getElementById('folderPane').contains(focusedElement)) {
focusedElement = folderTree;
} else if (contentDocument.getElementById('threadPaneNotificationBox').contains(focusedElement)) {
focusedElement = threadTree.table.body;
} else if (focusedElement != threadTree.table.body && contentDocument.getElementById('threadPane').contains(focusedElement)) {
focusedElement = threadTree.table.body;
} else if (focusedElement == messageBrowser) {
focusedElement = messageBrowser.contentWindow;
}
if (focusedElement == folderTree) {
;
} else if (focusedElement == threadTree.table.body) {
folderTree.focus();
} else if (focusedElement == messageBrowser.contentWindow) {
threadTree.table.body.focus();
} else {
threadTree.table.body.focus();
}
}
paneLayout.messagePaneSplitter.collapse();
}
rightキー
let tabmail = window.document.getElementById('tabmail');
let focusedElement = window.document.activeElement;
let { currentTabInfo } = tabmail;
if (currentTabInfo.mode.name == 'mail3PaneTab') {
let { contentWindow, contentDocument } = currentTabInfo.chromeBrowser;
let { paneLayout, folderTree, threadTree, webBrowser, messageBrowser, multiMessageBrowser, accountCentralBrowser, } = contentWindow;
if (focusedElement == currentTabInfo.chromeBrowser) {
focusedElement = contentDocument.activeElement;
if (focusedElement != folderTree && contentDocument.getElementById('folderPane').contains(focusedElement)) {
focusedElement = folderTree;
} else if (contentDocument.getElementById('threadPaneNotificationBox').contains(focusedElement)) {
focusedElement = threadTree.table.body;
} else if (focusedElement != threadTree.table.body && contentDocument.getElementById('threadPane').contains(focusedElement)) {
focusedElement = threadTree.table.body;
} else if (focusedElement == messageBrowser) {
focusedElement = messageBrowser.contentWindow;
}
if (focusedElement == folderTree) {
threadTree.table.body.focus();
paneLayout.messagePaneSplitter.collapse();
} else if (focusedElement == threadTree.table.body) {
paneLayout.messagePaneSplitter.expand();
messageBrowser.contentWindow.focus();
} else if (focusedElement == messageBrowser.contentWindow) {
paneLayout.messagePaneSplitter.expand();
} else {
threadTree.table.body.focus();
paneLayout.messagePaneSplitter.collapse();
}
}
}
tbkeyの設定
上記の設定をtbkeyで行うためにはJavascriptを一行にするなどの制約があるため難読だが下記の設定をtbkeyのMain key bindingsで行う。
{
"left": "eval(\"let tabmail = window.document.getElementById('tabmail'); let focusedElement = window.document.activeElement; let { currentTabInfo } = tabmail; if (currentTabInfo.mode.name == 'mail3PaneTab') { let { contentWindow, contentDocument } = currentTabInfo.chromeBrowser; let { paneLayout, folderTree, threadTree, webBrowser, messageBrowser, multiMessageBrowser, accountCentralBrowser, } = contentWindow; if (focusedElement == currentTabInfo.chromeBrowser) { focusedElement = contentDocument.activeElement; if (focusedElement != folderTree && contentDocument.getElementById('folderPane').contains(focusedElement)) { focusedElement = folderTree; } else if (contentDocument.getElementById('threadPaneNotificationBox').contains(focusedElement)) { focusedElement = threadTree.table.body; } else if (focusedElement != threadTree.table.body && contentDocument.getElementById('threadPane').contains(focusedElement)) { focusedElement = threadTree.table.body; } else if (focusedElement == messageBrowser) { focusedElement = messageBrowser.contentWindow; } if (focusedElement == folderTree) { ; } else if (focusedElement == threadTree.table.body) { folderTree.focus(); } else if (focusedElement == messageBrowser.contentWindow) { threadTree.table.body.focus(); } else { threadTree.table.body.focus(); } } paneLayout.messagePaneSplitter.collapse(); }\")",
"right": "eval(\"let tabmail = window.document.getElementById('tabmail'); let focusedElement = window.document.activeElement; let { currentTabInfo } = tabmail; if (currentTabInfo.mode.name == 'mail3PaneTab') { let { contentWindow, contentDocument } = currentTabInfo.chromeBrowser; let { paneLayout, folderTree, threadTree, webBrowser, messageBrowser, multiMessageBrowser, accountCentralBrowser, } = contentWindow; if (focusedElement == currentTabInfo.chromeBrowser) { focusedElement = contentDocument.activeElement; if (focusedElement != folderTree && contentDocument.getElementById('folderPane').contains(focusedElement)) { focusedElement = folderTree; } else if (contentDocument.getElementById('threadPaneNotificationBox').contains(focusedElement)) { focusedElement = threadTree.table.body; } else if (focusedElement != threadTree.table.body && contentDocument.getElementById('threadPane').contains(focusedElement)) { focusedElement = threadTree.table.body; } else if (focusedElement == messageBrowser) { focusedElement = messageBrowser.contentWindow; } if (focusedElement == folderTree) { threadTree.table.body.focus(); paneLayout.messagePaneSplitter.collapse(); } else if (focusedElement == threadTree.table.body) { paneLayout.messagePaneSplitter.expand(); messageBrowser.contentWindow.focus(); } else if (focusedElement == messageBrowser.contentWindow) { paneLayout.messagePaneSplitter.expand(); } else { threadTree.table.body.focus(); paneLayout.messagePaneSplitter.collapse(); } } }\")"
}
この設定にたどり着くまで
F6キーでフォーカスを移動させることに似ていることからどのようなJavascriptになっているかを探すことから始まった。
- 「ツール」メニューから「開発ツール」→「開発ツールボックス」を選ぶ。
- リモートデバッグの接続を許可する。
- 「インスペクター」を選ぶ。
- keysetが怪しいと睨む
- keyset id="mailKeys"の中にkey keycode="VK_F6"があることに気づく。
- 呼び出す関数はSwitchPaneFocus()であることが分かる。
- 「デバッガー」に切り替え「検索」を選び、SwitchPaneFocusを検索する。
- function SwitchPaneFocus(event)が見つかる。
- 「コンソール」に切り替え、上記の関数の中身を理解するために1行ずつ実行する。