新しいノートPCに英字キーボードがついていた
先日PCを新調したところ、キーボードが英字キーボードだった。
僕はノートPCをメインで使っているけれど、大半の作業は外部ディスプレイと外付けキーボードで行っている。今まで使っていた外付けキーボードは日本語配列だ。
英字キーボードのIME切替はAlt+~だ。これは覚えれば問題ない。
僕はIMEの切り替えは同じボタンでオン・オフするトグルではなく、IMEオフ用のキーとIMEオン用のキーを使う方法で行っている。
日本語キーボードの場合は、無変換キーをIMEオフに、変換キーをIMEオンにしている。これでなんの問題もない。
英語キーボードでは、左AltをIMEオフに、右AltをIMEをオンにしたいのだが、ここでいろいろと問題が出た。
課題は次の2つだ。まず、AltをIMEの切り替えに使うと、Altを押すことでフォーカスがメニューバーに移ってしまう。次に、日本語キーボードでは右Altがなかったり、押しにくかったりする。僕の外付けキーボードはFn+Menu(?)だ。
最終解:AutoHotKeyで設定する
日本語入力の切り替えだけでなく、キーの役割を変えるツールはいろいろあるけれど、今回はKeyhacとAutoHotKeyを試して、AutoHotKeyを採用した。両方の設定を試していて、最終的にうまく動いたのがAutoHotKeyだったというだけだ。Keyhacもおそらく同じような処理ができる。
試行錯誤した結果の最終的なコードは本文の途中に掲載しておく。
課題
その1:Altを別のキーとして使用する
両AltでIMEをオン・オフする方法としては、左Altを無変換、右Altを変換に置き換える方法がある。
MicrosoftのPowerToysを使えば、簡単に両Altをそれぞれ変換・無変換に割り当てることができる。ただしこれには深刻な不都合がある。キーボードからAltキーがなくなってしまう。当初はそれでもいいか?と思ったのだが、Alt+Tabでのウインドウ切り替えが使えなくなって不便だった。この機能をオフにしてみると、いかにAlt+Tabを多用しているか実感した。左下のCtrlキーをAltに変えることもできるが、それでは押しにくい。左Alt+Tabはそれだけよく使う。やはりAltキーは必要だ。
左下のキーとしてあまり使用しないキーはと見れば、左Ctrlぐらいだ。Aの左にあるCaps Lockを左Ctrlに変更しているので、左下のCtrlキーは余る。だが、できたら、左の親指でIMEをオフにしたい!もうしばらく試行錯誤して、どうしようもなければ、左Ctrlを左Altにする。
以上から、Altキーの機能を残しながら、Altの空打ちでメニューが開くことを防止することにする。Excelなどで空打ちでメニューにうつる機能はなくなるが、よく考えたらこの機能は使ったことがない。
その2:Altでメニューが開いてしまう
単にAltキーの役割を変更すると、Altでメニューが開いてしまう。Altの空打ちでメニューを開くような機能がWindowsでは一般に備わっている。メニューに移ったフォーカスを戻すには、Escを押す、Altをもう一度押すなどアプリによって挙動が微妙に違う。Escでの復帰はChromeとNotepadで確認している。そこで、そういうアプリを場合分けして、必要な処理をそれぞれ追加してみた。
Emacsでは、Altの空打ちでメニューに移行して、Altでは戻ってこれない。しかも、EscもM-の待機状態になる。このへんはもう一度ESCを押せばESC+ESCになるからよさそうなものだが、うまく行かない。
AutoHotKeyでの解決策
上記のような課題を解決するべく、さまざまな試行錯誤を繰り返した末に、AutoHotKeyのとてもシンプルなスクリプトで問題が解決した。
次項で紹介する試行錯誤の記録に疲れて、AIをPerplexityに変えたら一発でうまくいく答えが得られた。AutoHotKeyの以下のスクリプトだ。
こちらで公開してくれているスクリプトだ。左右のAltキーが離されたとき、その直前のキーイベントが、同じキーを押したものであったばあい、IMEのON/OFFを行う。右Altは単にひらがな・カタカナキーを押しているが、左Altはひらがな・カタカナを押した後、半角・全角を押している。普通のキーボードでもひらがな・カタカナキーは、常にIME ONなのかな?知らなかった。
今までの苦労は、なんだったんだろう。。。こんな事があると、もうChatGPTからPerplexityに移行したくなるな。ほんとのところ、どちらが高性能なのかはわからないけれど、一度の成功体験がその後のツールの使用を左右するってありそうだ。
あとはこれを日本語キーボードでも動くようにする必要があるけど、Google日本語入力では、設定でIMEのOn/OFFを変換・無変換に割り当てているから、あえてAutoHotKeyでやる必要もなさそうだ。
; 左Altキーの空打ちでIMEをオフ
~LAlt Up::
if (A_PriorKey = "LAlt") {
Send, {vkF2sc070}{vkF3sc029}; {ひらがな・カタカナ}{半角・全角}
}
Return
; 右Altキーの空打ちでIMEをオン
~RAlt Up::
if (A_PriorKey = "RAlt") {
Send, {vkF2sc070} ; {ひらがな・カタカナ}
}
Return
; カーソルがメニューに移動する挙動を無効化
*~LAlt::Send {Blind}{vk07}
*~RAlt::Send {Blind}{vk07}
試行錯誤の記録
行ったり来たり
IMEのON/OFFを実現したいだけだったのだけれど、簡単にはうまく行かないので、試行錯誤を繰り返してしまった。最初はKeyhacで頑張って、それが行き詰まるとAutoHotKeyを試して、またKeyhacに戻って・・・という感じだ。
それぞれの解ではそもそもうまく行かないのかも・・・と思ってしまうと、そこを深堀りしてドハマリするよりも別の方法を試したほうがいいのかな?なんて思って別のものに手を出してしまう。
ついでに、試行錯誤の途中でいろいろなことを思いついて試すうちに、記録を忘れてしまう。そうすると、PCを変えるときなどにまた同じ問題にぶつかり、試行錯誤を繰り返すことになる。成功したものだけではなく、うまくいかなかったことを記録しておくことも大切だ。そうじゃないと、「なぜこれを試さなかったんだろう。このほうがベターじゃ?」と思ってしまって、また、同じ問題にはまりこむ。今やっていること以外も試したうえで、「これがベストだったのだ」ということがわかるように、試行錯誤の記録こそ残しておくべきだ。
ツールを組み合わせる
おなじようなことを考える方がいて、詳しい記事を出してくれている。それを参照すると、Altの空打ちをキャンセルするツール(TAALT)が存在していることもわかる。
TAALT+AutoHotKeyまたはKeyhacで希望することは実現できるのだが、それではなんとなくおもしろくない。なにより、別ツールを使うこと、このツールの更新日が2016年であることを考えると、TAALTには頼りにくい。すくなくともソースが公開されていればよいのだが、それがないと、このツールが動かなくなったときに詰む。
やはり、AutoHotKeyまたはKeyhac単独で目的の機能を実装したい。
ChatGPTにきいて、AutoHotKeyを試す
ChatGPTにスクリプトを聞いてみたところ、AutoHotKeyV1系のスクリプトを教えてくれて、V2に対応させるのに四苦八苦する。おまけに、最終的にはいい感じには動かなかった。
以下がある程度うまくいくものなのだが、挙動に不審な点がある。
#Requires AutoHotkey v2.0
#Include IMEv2.ahk
; 主要なキーを HotKey に設定し、何もせずパススルーする
; ここには必要なキーを全部登録する
hotkeys := [
"a", "b", "c", "d", "e"
]
for key in hotkeys
{
; ホットキーを動的に登録
Hotkey("*~" key, Func("PassThrough"))
}
; パススルー関数
PassThrough() {
return
}
; 上部メニューがアクティブになるのを抑制
Hotkey("*~LAlt", () => Send("{Blind}{vk07}"))
Hotkey("*~RAlt", () => Send("{Blind}{vk07}"))
; 左 Alt 空打ちで IME を OFF
Hotkey("LAlt up", Func("LAltUp"))
; 右 Alt 空打ちで IME を ON
Hotkey("RAlt up", Func("RAltUp"))
; 左 Alt キーのリリース処理
LAltUp() {
if (A_PriorHotkey == "*~LAlt") {
IME_SET(0)
}
}
; 右 Alt キーのリリース処理
RAltUp() {
if (A_PriorHotkey == "*~RAlt") {
IME_SET(1)
}
}
Keyhacでも試してみる
Keyhacでは、こんな感じだ。大体の動作はうまくいくのだが、微妙なところが妙で少しストレスがある。
import sys
import os
import datetime
import pyauto
from keyhac import *
def configure(keymap):
# グローバルキー設定
keymap_global = keymap.defineWindowKeymap()
# 特定アプリケーションでESCを送信する処理
def handle_chrome_alt():
keymap.InputKeyCommand("Esc")() # ESCキーを送信
def set_ime_on_simple():
active_window = keymap.getWindow().getProcessName()
keymap.getWindow().setImeStatus(1) # IMEをオンに設定
def set_ime_off_simple():
active_window = keymap.getWindow().getProcessName()
keymap.getWindow().setImeStatus(0) # IMEをオンに設定
# IMEをオンにする関数
def set_ime_on():
set_ime_on_simple()
if "chrome.exe" or "notepad.exe" in active_window: # Chromeの場合
handle_chrome_alt()
else:
keymap.InputKeyCommand("Alt")() # Altキーを再送信してフォーカスをリセット
# IMEをオフにする関数
def set_ime_off():
set_ime_on_simple()
if "chrome.exe" or "notepad.exe" in active_window: # Chromeの場合
handle_chrome_alt()
else:
keymap.InputKeyCommand("Alt")() # Altキーを再送信してフォーカスをリセット
# 右Altキー単押しでIMEをオンに設定
keymap_global["O-RAlt"] = set_ime_on
# 「変換」キーでIMEをオンに設定
keymap_global["O-(255)"] = set_ime_on_simple
# 左Altキー単押しでIMEをオフに設定
keymap_global["O-LAlt"] = set_ime_off
# 「無変換」キーでIMEをオフに設定
keymap_global["O-(235)"] = set_ime_off_simple