コンテンツにスキップ

X Window Programming/イベントの基本

出典: フリー教科書『ウィキブックス(Wikibooks)』

イベントの基本

[編集]

X Window Systemでは、イベントはユーザー入力やシステムからの通知など、ウィンドウシステムに関するさまざまな状況に対して発生します。これらのイベントは、X11のイベントモデルを通じて管理され、プログラムがそれに応じて動作することが求められます。本章では、X11のイベントモデルの概要と、イベントマスクの設定方法、動作例について解説します。

X11のイベントモデル

[編集]

X11のイベントモデルは、基本的に「イベントキュー」による非同期的な処理が特徴です。クライアントアプリケーションは、Xサーバーからのイベントを待ち受け、処理するために、イベントをリスン(待機)する必要があります。イベントは、例えばユーザーがマウスをクリックしたり、キーボードで入力したり、ウィンドウが再描画されるなど、さまざまな状況で発生します。

イベントには以下の種類があり、アプリケーションはそれぞれに対応した処理を行います。

  1. 入力イベント
    ユーザーのキーボード入力やマウス操作に関するイベントです。例えば、KeyPress(キーが押された)やButtonPress(マウスボタンが押された)などがあります。
  2. ウィンドウイベント
    ウィンドウに関するイベントです。ウィンドウが表示された、再描画された、移動されたなどのイベントです。例えば、Expose(ウィンドウの再描画要求)やConfigureNotify(ウィンドウの配置変更)などがあります。
  3. タイマーイベント
    一定時間が経過した後に発生するイベントです。X11ではタイマーイベントを直接扱う機能はありませんが、XSelectInput()を使って関連するイベントをトラップできます。
  4. その他のシステムイベント
    システムやセッション管理から送られてくるイベントです。たとえば、ウィンドウのアイコン化、終了、状態変更などに関するイベントです。

イベントは非同期的に発生するため、アプリケーションはこれらのイベントを適切に処理する必要があります。

イベントマスクの設定と動作例

[編集]

X11では、特定のイベントが発生したときのみ処理するように指定できる「イベントマスク」の仕組みが提供されています。XSelectInput()関数を使って、クライアントが関心のあるイベントを選択し、そのイベントが発生したときに通知を受け取ります。

イベントマスクの設定

[編集]

XSelectInput()関数を使用して、特定のイベントを監視することができます。この関数は、以下のように使用されます。

XSelectInput(display, window, event_mask);

event_maskは、どのイベントを受け取るかを指定するフラグです。以下はよく使用されるイベントマスクの例です:

  1. ExposureMask — ウィンドウの再描画イベント
  2. KeyPressMask — キーが押されたときのイベント
  3. ButtonPressMask — マウスボタンが押されたときのイベント
  4. StructureNotifyMask — ウィンドウのサイズ変更や移動、アイコン化などに関するイベント

例えば、ウィンドウが再描画されるExposeイベントと、キーが押されるKeyPressイベントを監視する場合、次のように設定します。

XSelectInput(display, window, ExposureMask | KeyPressMask);

これにより、プログラムは再描画イベントとキー入力イベントを監視し、次に発生するこれらのイベントに応じた処理を実行できます。

動作例:キーボード入力とウィンドウの再描画

[編集]

以下は、ExposeイベントとKeyPressイベントを監視し、再描画時にメッセージを表示し、Escapeキーが押されたときにアプリケーションを終了する例です。

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    // Xサーバーへの接続
    Display *display = XOpenDisplay(NULL);
    if (!display) {
        fprintf(stderr, "Xサーバーに接続できません\n");
        exit(1);
    }

    int screen = DefaultScreen(display);
    Window window = XCreateSimpleWindow(display, RootWindow(display, screen),
                                        10, 10, 800, 600, 1,
                                        BlackPixel(display, screen),
                                        WhitePixel(display, screen));

    // イベントマスクの設定(再描画とキー入力)
    XSelectInput(display, window, ExposureMask | KeyPressMask);

    // ウィンドウの表示
    XMapWindow(display, window);

    // イベントループ
    for (;;) {
        XEvent event;
        XNextEvent(display, &event);
        switch (event.type) {
            case Expose:
                printf("ウィンドウが再描画されました\n");
                break;
            case KeyPress:
                if (XLookupKeysym(&event.xkey, 0) == XK_Escape) {
                    printf("Escapeキーが押されました。終了します。\n");
                    XCloseDisplay(display);
                    exit(0);
                }
                break;
        }
    }

    return 0;
}

このプログラムでは、XSelectInput()を使用してウィンドウの再描画(Expose)イベントとキーボードのキー入力(KeyPress)イベントを監視します。再描画イベントが発生したときには、メッセージを表示し、Escapeキーが押されるとプログラムが終了します。

イベントマスクの応用

[編集]

イベントマスクを適切に設定することで、アプリケーションは効率的に動作し、必要なイベントのみを受け取ることができます。例えば、特定のウィンドウ操作だけを監視したい場合や、キーボード入力やマウス操作の種類に応じた異なる処理を行いたい場合に便利です。

まとめ

[編集]

X11のイベントモデルは、非同期的に発生する多くのイベントを適切に処理するための仕組みを提供します。XSelectInput()を使用してイベントマスクを設定し、必要なイベントを監視することで、アプリケーションはユーザー入力やシステムの状態変更に応じた柔軟な動作を実現できます。イベントマスクを正しく設定することで、効率的なリソースの利用と反応性の高いインターフェースが提供できます。