キー入力

今日はGTK+のキー入力について調べました。
WindowsのGetAsyncKeyStateやDirectInputのポーリングと違って明示的にキーの状態を問い合わせることは出来なくて*1、キーが押されたらkey-press-eventシグナルが、放されたらkey-release-eventシグナルが発行されるので、これをコールバック関数で処理することになります。
DirectInputのキーボード/マウス入力は既に非推奨だったと思うので、こっちで統一したほうがよいでしょうね。


キー情報は次の構造体で渡されます。

typedef struct {
  GdkEventType type;
  GdkWindow *window;
  gint8 send_event;
  guint32 time;
  guint state;
  guint keyval;
  gint length;
  gchar *string;
  guint16 hardware_keycode;
  guint8 group;
  guint is_modifier : 1;
} GdkEventKey;

keyvalにGDKのキーコードが入るんですが、大文字/小文字が区別されるのが難点です。
このため、「Shift+A」を押してから「Shift」だけ放すと、「A」に対するkey-release-eventシグナルは発行されずに、(キーリピートで)「a」のkey-press-eventシグナルが発行されます。
これだとkey-press-eventシグナルが役に立たない気がします。


ただ、hardware_keycodeに実装依存のキーコードが入っているので、これを使えば同一キーの判定は出来そうです。
Win32では仮想キーコード(VK_〜)、X11ではXEventのxkey.keycodeが入っている模様。
せっかくマルチプラットフォームのツールキットを使っているのに、実装ごとに処理を切り替えるのはアレですが、「どの文字が入力されたか」という視点か、「どのキーが押されたか」という視点かの違いだと思って諦めるしかないですね。

*1:gdk_device_get_state()という関数もありますが、少なくともWin32版ではキーボードに対応していないっぽいです。