JRubyでグローバルフックとかグローバルホットキーと呼ばれる、OSの機能を使う。

普通のホットキーはアプリがアクティブの時しかキー入力やマウス入力を取得できないが、jnativehookというjavaのライブラリを使うとアクティブじゃなくても取得できる。


コードはgistに置いた。
global keyhook with JRuby

下の方に書いたけどマウスはちゃんと取れるけどキーボードがshiftとctrlとcommandしか取れず、しかも全部shift扱いになる。
まあ今考えてる用途には十分なので別にいいか・・

jnativehookのインストール

jnativehook – A library to provide global keyboard and mouse listeners for Java. – Google Project Hosting
からJNativeHook-1.1.4.zipをダウンロードして解凍し、JNativeHook.jarをget

Macの場合
/Library/Java/Extensions/
にjarを置けばパスが通る。


アプリケーションにコンピュータの制御を許可する

Macの場合、グローバルフックへのアクセス権限をアプリに許可する必要がある。
システム環境設定から許可するけど、先にプログラムを動かさないとチェックボックスが現れないと思う。


プログラム書く

Ruby好きなのでJRubyで書く。
JRubyの場合includeでjavaのインタフェースをimplementできる。
examplesを参考に、キーボードとマウス両方を取得した。

hook.rb
require 'java'
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;

class KeyHook
include NativeKeyListener

def nativeKeyPressed(e)
puts NativeKeyEvent.getKeyText e.getKeyCode
end

def nativeKeyReleased(e)
puts NativeKeyEvent.getKeyText e.getKeyCode
end

def nativeKeyTyped(e)
puts NativeKeyEvent.getKeyText e.getKeyCode
end

end

class MouseHook
include NativeMouseInputListener

def nativeMouseMoved(e)
puts "#{e.getX}, #{e.getY}"
end

end

GlobalScreen.registerNativeHook
GlobalScreen.getInstance.addNativeKeyListener KeyHook.new
GlobalScreen.getInstance.addNativeMouseMotionListener MouseHook.new

loop do
sleep 1
end
すごいすっきり書けた。

なおマウスはクリックなども取れるけど省略した


動かす


% jruby hook.rb



マウスの動きはちゃんと取れた。
キーボード入力がctrlとshiftとcommandしか取れないし、全部shiftになる。
Javaのサンプルでもshiftしか取れないし、同じことをissueで質問してる人がいるのでバグだと思う。