64bit版WindowsのためのXKeymacsを作ってみた

[2011-08-30] XKeymacsの開発を元の作者から引き継いで、64bit版Windowsへの対応も含めさまざまな改良を加えたXKeymacsを開発しています。今後は新しいXKeymacsのホームページからダウンロードできるものを利用してください。

Unix使いがWindowsを使うときには、Emacsライクなキー操作を実現するために何かキー操作の割り当てを入れ替えるソフトウェアに頼ることになる。その一つがXKeymacsである。
残念ながら長い間メンテナンスが止まっていて、Windows 7Cygwinを動かしたときに、割り当ての変更を止めることができないなどの不具合がある。Cygwinbashは最初からEmacsライクなので、割り当ての変更を止めないとまずい。ほかのバージョンのWindowsではうまくいくのだが7ではだめだ。幸いオープンソースソフトウェアなので自分で直して使っていた。

先日、Lenovo G560を購入してしばらく使うことになったので、64bit版のWindows 7で暮らすことになった。そのときに問題になったのがXKeymacsである。

XKeymacsはグローバルフックを利用して、ほかのアプリケーションにDLLをinjectしてキー操作を入れ替える。32bitのDLLは64bitのアプリケーションにはinjectできないので、32bitのXKeymacsが64bitのアプリケーションに対して機能するとは思っていなかった。

しかし、中途半端に機能したので悩ましかった。64bitのアプリケーションのエクスプローラーやメモ帳でも、カーソル移動などの基本的な操作は動いていた。マークなどの動作はおかしかったが。

64bitとXKeymacsでググって見つけたのが64bit版のXKeymacsのバイナリ。64bit版と32bit版を両方動かせばいいらしいのだけど64bit版が起動しなかった。x64のVisual C++ 2008のランタイムを入れたら起動したんだけど、エクスプローラーが固まってしまった。

自分でもVisual C++ 2010 Expressで64bit版のバイナリを作って、32bit版と両方動かしてみたところ、先のバイナリほどおかしくはならなかったけどやっぱりおかしい。32bit版のXKeymacsが64bitのアプリケーションに対して、ある程度機能している時点で何かおかしいので、32bit版と64bit版を両方動かすだけでうまくいくはずがない。

調べてみたら、32bit版と64bit版のXKeymacsの仕掛けたキーボードフックの両方が32bitと64bitのアプリケーションの両方に機能していて、ほかのフックは32bitか64bitのいずれかに機能していることがわかった。そのせいでキーボードフックの動作がおかしくなっている。

じゃあどうするか。いろいろ、本当にいろいろ試行錯誤を重ねた結果、キーボードフックはグローバルフックにせずに、ほかのフックのためにDLLがプロセスやスレッドにinjectされるタイミングで、スレッドごとにキーボードフックを仕掛ければよいことがわかった。

これで32bit版XKeymacsと64bit版XKeymacsを両方動かせば、期待通りに機能するようになった。しかし、これでは両方のアイコンが通知領域に表示されてしまうし、設定も32bit版と64bit版で共有されないので美しくない。

先の試行錯誤で、共有メモリを使って32bit版と64bit版のバイナリを連携させて、両方のキーボードフックを排他的に動かす試みをしていた。このアイデアを使って、32bit版と64bit版を連携させて通知領域のアイコンを一つにして、設定も共有メモリで共有するようにしてみた。しかし、これはうまくなくて、プロセスにinjectするDLLが共有メモリを使っていると、Avir Antivirがリアルタイムスキャンで執拗に介入して重くなってしまった。

仕方ないのでプロセス間通信を共有メモリから名前付きパイプに替えたころ、うまく動くようになった。こうしてできたのがXKeymacs for 64bit Windowsである。Visual C++ 2010でXKeymacsを使っていて気になったバグも取ってある。Internet ExplorerでControl+Sを押しても検索できないバグは取り切れなかった。これはどうやったら直せるんだろうなあ。