リアルタイムなキーボード状態の取得

概要

現在のキーボード状態をイベントを使わずに取得する。

アクションゲームなどでキーイベントを使わないで現在のキーボード状態を取得したい 場合があるが、gtkにはそのような関数は用意されていない(と思う)。 そこであまり好ましくない方法であるがxlibのXQueryKeymap()関数を使用する。 Display のポインタは次のようにして取得できる。

Display* disp = GDK_WINDOW_XDISPLAY( Glib::unwrap( get_window() ) );

あとはXQueryKeymap()とXKeysymToKeycode()の組み合わせでボタン状態を取得できる。

ソース

xqkey.cpp

#include <gtkmm.h>

#include <gdk/gdkx.h>  // GDK_WINDOW_XDISPLAY

#define XK_LATIN1
#define XK_MISCELLANY
#include <X11/keysymdef.h> // XK_*

class MainWin : public Gtk::Window
{
public:
    MainWin(){ add_events( Gdk::BUTTON_PRESS_MASK ); }

protected:
    virtual bool on_button_press_event( GdkEventButton* ev );
};


bool MainWin::on_button_press_event( GdkEventButton* ev )
{
    bool press_a = false;

    // キーボード状態取得
    char keys[ 32 ]; 
    Display* disp = GDK_WINDOW_XDISPLAY( Glib::unwrap( get_window() ) );
    XQueryKeymap( disp, keys );
    for( int i = 0; i < 32; ++i ){
        for( unsigned char i2 = 0; i2 < 8  ; ++i2 ){
            if( keys[ i ] & ( 1 << i2 ) ){
                KeyCode code = i*8 + i2;
                if( XKeysymToKeycode( disp, XK_a ) == code ) press_a = true;
            }
        }
    }

    if( press_a ){
        Gtk::MessageDialog diag( *this, "press a" );
        diag.run();
    }
}


int main( int argc, char *argv[] )
{
    Gtk::Main kit( argc, argv );
    MainWin mainwin;
    Gtk::Main::run( mainwin );

    return 0;
}

コンパイル

必要なコンパイルオプションは pkg-config を使って取得する。

g++ xqkey.cpp -o xqkey `pkg-config gtkmm-2.4 --cflags --libs`

結果

"a"キーを押しながらクリックするとダイアログが表示される。