14

X Windows で Control キーのリリース イベントをリッスンし、それらを検出すると別のプロセスに警告するコマンド ライン アプリケーションを作成しています。

GNU/Linux は初めてなので、GCC をいじるのは避けたいので、スクリプト ベースのソリューションを探しています。私は Python を少し知っているので、Python ベースのソリューションを選択するのは当然のことのように思えました。インターネットで例を探し、Python Xlib のドキュメントを読んだ後、動作するこのプログラムをまとめましたが、注意点があります。それらをリッスンするだけでなく、イベント (つまり、そのようなイベントは、最初に送信されたアプリケーションに渡されなくなります)。

「xev」を実行して、コントロール キー コードを追跡しました。修飾キーを再マップしたので、あなたのシステムでは異なるかもしれません。

簡単にするために、外部プロセスを扱うコードは省略しています。

ご協力ありがとうございました。

ソフトウェア:

  • パイソン 2.7.2

  • Python Xlib 0.15 RC1

  • Perl v5.10.1

  • Debian GNU/Linux バージョン: 6.0.3

  • カーネル バージョン: Linux debian 2.6.32-5-686

編集:私が理解できないのは、キーボードイベントが処理されない限りトラップされないことです(私のプログラムでは、これは「print "KeyRelease"」という行が実行されることを意味します)。私のコードでは、Xlib でもイベント オブジェクトでもメソッドを呼び出していないので、処理の違いがどこにあるのかわかりません。

EDIT2: Xlib を使用する以外の代替ソリューションに関する提案も歓迎します。

EDIT3: 私は Perl も知っています。システム ライブラリの最新バージョンを必要としない限り、役立つ Perl ライブラリに関する提案も大歓迎です。Debian はリポジトリで利用可能なパッケージに関して遅れをとることで悪名高く、コンパイルライブラリの最新バージョンのインストールは、多くの依存関係がある場合は困難になる可能性があります (PyGTK をインストールしようとしましたが、インストールした最新の GLib を参照できなかったため、あきらめました)。

    #!/usr/bin/env python

    from Xlib.display import Display
    from Xlib import X

    Control_R  = 64 # Keycode for right Control.
    Control_L  = 108 # Keycode for left Control.
    keycodes = [Control_R, Control_L] # Keycodes we are listening for.

    # Handle X events.
    def handle_event(event):
        # Let us know whether this event is about a Key Release of
        # one of the key we are interest in.
        if event.type == X.KeyRelease:
            keycode = event.detail
            if keycode in keycodes:
                print "KeyRelease"

    # Objects needed to call Xlib.
    display = Display()
    root = display.screen().root

    # Tell the X server we want to catch KeyRelease events.
    root.change_attributes(event_mask = X.KeyReleaseMask)

    # Grab those keys.
    for keycode in keycodes:
        root.grab_key(keycode, X.AnyModifier, 1, X.GrabModeAsync, X.GrabModeAsync)

    # Event loop.
    while 1:
        event = root.display.next_event()
        handle_event(event)
4

4 に答える 4

13

Croad Langshan によって言及された pykeylogger ライブラリと、そのようなライブラリの作成者である Tim Alexander によって提供された役立つサンプル コードのおかげで、プログラムを次のように変更することができました。

    #!/usr/bin/env python

    from pyxhook import HookManager

    watched_keys = ["Control_R", "Control_L"]

    def handle_event (event):
        if event.Key in watched_keys:
            print "KeyRelease"


    hm = HookManager()
    hm.HookKeyboard()
    hm.KeyUp = handle_event
    hm.start()

このプログラムは問題なく私の目標を達成します。イベントの詳細については、「イベント」オブジェクトのフィールドを参照してください (「pyxhook.py」のソース コードを参照してください)。

于 2012-02-09T21:22:20.257 に答える
2

XRecord 拡張機能を使用する必要があります。pyxlib(他の回答で言及されているpykeyloggerはこれを使用)で使用するか、ctypesを介してlibX11とlibXtstをラップすることで使用できます(synaptiksで行ったように)。

ただし、API の文書化が不十分であり、非常にバロック的で直感に反しているため、xrecord (および一般的には XLib もある程度) を使用したプログラミングはやや難しいことに注意してください。

于 2012-02-08T23:56:41.880 に答える
1

おそらく、このプロジェクトには、その問題を解決するコードが必要です。

http://sourceforge.net/apps/mediawiki/pykeylogger/index.php?title=Main_Page

于 2012-02-08T23:50:34.133 に答える
1

XRecord 拡張機能は、いくつかのディストリビューションで壊れ続けていることに注意してください。しばらくそのライブラリに戻って更新しなかった理由は、複数のリリースで Ubuntu が壊れていたためです。XInput オーバーレイでも同様の方法がありますが (聞いたところ)、X イベントを直接フックするのではなく、オーバーレイを処理したくなかったので、それを追求することはありませんでした。

pyxhook lib のコードの使用に問題がある場合は、コメントしてください。できるだけシンプルで堅牢なものにしようとしましたが、まとめたときに見逃した可能性があります。少し前のことです。

于 2012-02-10T22:18:42.267 に答える