コンテンツにスキップ

X Window Programming/XCB

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

XCB(X C Binding)は、X Window SystemのC言語バインディングで、Xlibに代わる低レベルのインタフェースを提供します。XCBは、Xlibに比べて高速で、非同期処理がより効率的に行えるため、パフォーマンス重視のアプリケーションでの利用が推奨されています。また、XCBは非同期イベント駆動型の設計を採用しており、Xlibにおける同期的な操作に関する制限を回避することができます。

本章では、XCBの基本的な使用方法とその利点について説明します。

XCBのインストール

[編集]

XCBを使用するには、まずXCBライブラリをインストールする必要があります。ほとんどのUnix系システムやLinuxディストリビューションには、XCBが標準で含まれています。

以下は、FreeBSDの例でXCBをインストールする方法です。

doas make -C /usr/ports/x11/libxcb install clean

以下は、debianの例でXCBをインストールする方法です。

sudo apt-get install libxcb1 libxcb1-dev

XCBを使用するには、プログラムでxcb/xcb.hをインクルードし、コンパイル時に-lxcbを指定してリンクします。

#include <xcb/xcb.h>
コンパイル例:
cc -o myapp myapp.c -lxcb

XCBの基本的な使用方法

[編集]

XCBを使ってウィンドウを作成し、描画するには、次の基本的な手順を踏みます。

1. Xサーバーへの接続

[編集]

まず、Xサーバーに接続するためにxcb_connect関数を使用します。xcb_connectは、Xサーバーへの接続を確立し、接続に成功した場合にはディスプレイへのポインタを返します。

xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
    fprintf(stderr, "Xサーバーへの接続に失敗しました\n");
    exit(1);
}

xcb_connect関数は、NULLを指定することでデフォルトのディスプレイに接続します。

2. ウィンドウの作成

[編集]

XCBでウィンドウを作成するためには、xcb_generate_idでウィンドウIDを生成し、xcb_create_windowでウィンドウを作成します。

xcb_window_t window = xcb_generate_id(connection);

xcb_create_window(connection,
                  XCB_COPY_FROM_PARENT,  /* 親ウィンドウ */
                  window,                /* 新しいウィンドウのID */
                  xcb_setup_roots_iterator(xcb_get_setup(connection)).data->root,  /* 親ウィンドウ */
                  100, 100, 400, 400, 0, /* 位置とサイズ */
                  XCB_WINDOW_CLASS_INPUT_OUTPUT,  /* ウィンドウクラス */
                  XCB_COPY_FROM_PARENT,  /* ビジュアル */
                  XCB_CW_BACK_PIXEL,     /* 属性 */
                  (uint32_t[]) { 0xFFFFFF });

このコードで、xcb_create_windowを使って基本的なウィンドウを作成します。ウィンドウの属性や背景色などを指定できます。

3. ウィンドウの表示

[編集]

作成したウィンドウを表示するには、xcb_map_windowを呼び出します。

xcb_map_window(connection, window);

これにより、ウィンドウが画面に表示されます。

4. イベントループの処理

[編集]

XCBでは、非同期イベント処理を行うためにイベントループを使用します。xcb_poll_for_eventを使ってイベントを待機し、処理します。

xcb_generic_event_t *event = NULL;
while ((event = xcb_poll_for_event(connection)) != NULL) {
    switch (event->response_type & ~0x80) {
        case XCB_EXPOSE:
            /* 再描画イベント */
            break;
        /* 他のイベントの処理 */
    }
    free(event);
}

このイベントループでは、xcb_poll_for_eventを使って発生したイベントを取得し、適切な処理を行います。

5. リソースの解放

[編集]

プログラムが終了した後は、接続を切断し、リソースを解放する必要があります。xcb_disconnectを使って接続を閉じます。

xcb_disconnect(connection);

これにより、接続が切断され、リソースが解放されます。

XCB拡張

[編集]

XCBは、基本的なX11プロトコルの機能に加えて、様々な拡張機能をサポートしています。これらの拡張は、より高度なグラフィックス処理や入力デバイスの制御を可能にします。

主要な拡張機能

[編集]
  1. XCB-RENDER
    #include <xcb/render.h>
    
    // RenderCreatePictureを使用した例
    xcb_render_picture_t create_picture(xcb_connection_t *conn, 
                                      xcb_drawable_t drawable) {
        xcb_render_picture_t picture = xcb_generate_id(conn);
        xcb_render_pictforminfo_t *fmt = find_format(conn, XCB_PICT_STANDARD_RGB_24);
        
        xcb_render_create_picture(conn, picture, drawable, fmt->id, 0, NULL);
        return picture;
    }
    
  2. XCB-SHAPE
    #include <xcb/shape.h>
    
    // ウィンドウの形状を設定する例
    void set_window_shape(xcb_connection_t *conn, xcb_window_t window) {
        xcb_pixmap_t mask = xcb_generate_id(conn);
        // マスクの作成とシェイプの設定
        xcb_shape_mask(conn, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
                       window, 0, 0, mask);
    }
    
  3. XCB-RANDR (Resolution and Rotation)
    #include <xcb/randr.h>
    
    void get_screen_info(xcb_connection_t *conn) {
        xcb_randr_get_screen_resources_cookie_t cookie =
            xcb_randr_get_screen_resources(conn, screen->root);
        xcb_randr_get_screen_resources_reply_t *reply =
            xcb_randr_get_screen_resources_reply(conn, cookie, NULL);
        
        // 出力情報の取得
        xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(reply);
        int num_outputs = xcb_randr_get_screen_resources_outputs_length(reply);
        
        free(reply);
    }
    

拡張機能の初期化と確認

[編集]

拡張機能を使用する前に、その機能が利用可能かどうかを確認することが重要です:

void check_extension(xcb_connection_t *conn, const char *extension_name) {
    xcb_query_extension_cookie_t cookie = 
        xcb_query_extension(conn, strlen(extension_name), extension_name);
    xcb_query_extension_reply_t *reply = 
        xcb_query_extension_reply(conn, cookie, NULL);
    
    if (reply && reply->present) {
        printf("%s 拡張が利用可能です\n", extension_name);
    } else {
        printf("%s 拡張は利用できません\n", extension_name);
    }
    
    free(reply);
}

COMPOSITE拡張の活用

[編集]

コンポジットマネージャーとの連携に使用される重要な拡張機能です:

#include <xcb/composite.h>

void setup_composite(xcb_connection_t *conn, xcb_window_t window) {
    // コンポジット拡張の初期化
    xcb_composite_query_version_cookie_t cookie =
        xcb_composite_query_version(conn, XCB_COMPOSITE_MAJOR_VERSION,
                                  XCB_COMPOSITE_MINOR_VERSION);
    xcb_composite_query_version_reply_t *reply =
        xcb_composite_query_version_reply(conn, cookie, NULL);
    
    if (reply) {
        // ウィンドウのリダイレクト設定
        xcb_composite_redirect_window(conn, window,
                                    XCB_COMPOSITE_REDIRECT_AUTOMATIC);
        free(reply);
    }
}

XKB (X Keyboard Extension)の使用

[編集]

キーボード入力の高度な制御に使用します:

#include <xcb/xkb.h>

void setup_xkb(xcb_connection_t *conn) {
    xcb_xkb_use_extension_cookie_t cookie =
        xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION,
                             XCB_XKB_MINOR_VERSION);
    xcb_xkb_use_extension_reply_t *reply =
        xcb_xkb_use_extension_reply(conn, cookie, NULL);
    
    if (reply && reply->supported) {
        // XKBイベントの設定
        uint16_t required_events = XCB_XKB_EVENT_TYPE_STATE_NOTIFY;
        xcb_xkb_select_events(conn, XCB_XKB_ID_USE_CORE_KBD,
                             required_events, 0, 0, 0, 0, NULL);
    }
    free(reply);
}

拡張機能使用時の注意点

[編集]
  1. バージョン互換性の確認
    使用する拡張機能のバージョンを必ず確認し、必要に応じて機能の使用を調整します。
    エラー処理
    拡張機能の使用時は、より慎重なエラー処理が必要です:
    void handle_extension_error(xcb_generic_error_t *error) {
        if (error) {
            fprintf(stderr, "拡張機能エラー: %d\n", error->error_code);
            free(error);
            return;
        }
    }
    
  2. リソース管理
    拡張機能で作成したリソースは適切に解放する必要があります:
    void cleanup_extension_resources(xcb_connection_t *conn,
                                   xcb_render_picture_t picture,
                                   xcb_pixmap_t pixmap) {
        xcb_render_free_picture(conn, picture);
        xcb_free_pixmap(conn, pixmap);
    }
    

XCB拡張機能を使用することで、より高度なグラフィックス処理や入力デバイスの制御が可能になります。ただし、拡張機能の使用には適切な初期化とエラー処理が重要です。

XCBの利点と制限

[編集]

利点

[編集]
  • パフォーマンスの向上: XCBは、Xlibに比べて非同期処理が効率的であり、レスポンスが速く、リソースの消費が少ないため、高パフォーマンスなアプリケーションに適しています。
  • 非同期イベント処理: XCBは、非同期イベント駆動型であり、イベントを非同期に処理できるため、効率的にユーザーインターフェースを操作できます。
  • 低レベルなインターフェース: XCBは低レベルなインターフェースを提供し、より柔軟で細かな制御が可能です。

制限

[編集]
  • 低レベルで複雑: XCBは低レベルなAPIであるため、Xlibに比べてコードが冗長になりがちです。また、非同期処理を適切に管理するためには、プログラム設計に注意が必要です。
  • ドキュメントの不足: XCBはXlibに比べてドキュメントが少なく、学習コストが高いと感じることがあります。

XCBとXlibの比較

[編集]

XCBはXlibの後継として設計されましたが、いくつかの重要な違いがあります。以下に、XCBとXlibの主な違いを示します。

特徴 Xlib XCB
処理の方式 同期処理(ブロッキング) 非同期処理(イベント駆動)
パフォーマンス 比較的低速 高速
使用感 シンプルだが遅い 複雑だが高速で効率的

XCBは、Xlibに比べてより柔軟で高速な動作を実現しており、特に大規模なグラフィカルアプリケーションでの使用が推奨されます。

附録

[編集]

XCBコア関数

[編集]
Detailed XCB Core Function Reference
関数名 機能 パラメータ 戻り値 備考
接続管理
xcb_connect X サーバーへの接続を確立 displayname, screenp xcb_connection_t* 失敗時はNULL。環境変数DISPLAYを参照
xcb_disconnect X サーバーとの接続を終了 connection void 全てのリソースを解放
xcb_get_setup 接続のセットアップ情報を取得 connection xcb_setup_t* スクリーン情報などを含む
ウィンドウ操作
xcb_create_window 新しいウィンドウを作成 connection, depth, wid, parent, x, y, width, height, border_width, _class, visual, value_mask, value_list xcb_void_cookie_t 非同期操作
xcb_create_window_checked エラーチェック付きでウィンドウ作成 (同上) xcb_void_cookie_t 同期操作
xcb_destroy_window ウィンドウを破棄 connection, window xcb_void_cookie_t 子ウィンドウも破棄
xcb_map_window ウィンドウを表示 connection, window xcb_void_cookie_t 実際の表示はマップリクエスト後
xcb_unmap_window ウィンドウを非表示 connection, window
イベント処理
xcb_wait_for_event 次のイベントを待機 connection xcb_generic_event_t* ブロッキング操作
xcb_poll_for_event イベントの有無を確認 connection xcb_generic_event_t* ノンブロッキング
xcb_flush 要求をサーバーに送信 connection int バッファをフラッシュ
描画操作
xcb_create_gc グラフィックスコンテキスト作成 connection, cid, drawable, value_mask, value_list xcb_void_cookie_t 描画属性の設定に必要
xcb_free_gc GCを解放 connection, gc
xcb_copy_area 領域をコピー connection, src_drawable, dst_drawable, gc, src_x, src_y, dst_x, dst_y, width, height xcb_void_cookie_t ビットブロック転送
プロパティ
xcb_change_property プロパティを変更 connection, mode, window, property, type, format, data_len, data xcb_void_cookie_t アトムやウィンドウ属性の設定
xcb_get_property プロパティを取得 connection, _delete, window, property, type, long_offset, long_length
同期制御
xcb_get_input_focus 入力フォーカスを取得 connection
xcb_set_input_focus 入力フォーカスを設定 connection, revert_to, focus, time
エラー処理
xcb_request_check リクエストのエラーを確認 connection, cookie xcb_generic_error_t* エラーがなければNULL
xcb_get_extension_data 拡張機能の情報を取得 connection, extension xcb_query_extension_reply_t* 拡張機能のサポート確認
画面情報
xcb_setup_roots_iterator ルート画面の反復子を取得 setup xcb_screen_iterator_t スクリーン情報の列挙
xcb_screen_next 次のスクリーンに移動 iterator void イテレータを進める
通信制御
xcb_prefetch_maximum_request_length 最大リクエスト長を事前取得 connection void パフォーマンス最適化
xcb_get_maximum_request_length 最大リクエスト長を取得 connection
原子操作
xcb_intern_atom アトムを取得または作成 connection, only_if_exists, name_len, name xcb_intern_atom_cookie_t プロパティ名の管理に使用
xcb_intern_atom_reply アトム取得の応答を取得 connection, cookie, error

XCB拡張

[編集]
Detailed XCB Extensions Reference
名称 機能 主要な関数 依存関係 備考
composite 合成ウィンドウマネージャ向けの機能を提供。ウィンドウのオフスクリーンバッファリングと合成処理をサポート xcb_composite_redirect_window()
xcb_composite_redirect_subwindows()
xcb_composite_unredirect_window()
libxcb-xfixes Version 0.4以降で利用可能。コンポジットマネージャの実装に必須
damage ウィンドウやピクセル領域の変更を追跡し、効率的な画面更新を実現 xcb_damage_create()
xcb_damage_destroy()
xcb_damage_subtract()
libxcb-xfixes compositeと組み合わせて使用することが多い
dbe Double Buffer Extension。ちらつきのない描画のためのダブルバッファリングを提供 xcb_dbe_allocate_back_buffer()
xcb_dbe_swap_buffers()
xcb_dbe_begin_idiom()
libxcb アニメーションや滑らかな画面更新に使用
dpms Display Power Management Signaling。モニタの電源管理機能を制御 xcb_dpms_enable()
xcb_dpms_disable()
xcb_dpms_force_level()
libxcb VESA DPMSと互換性あり
dri2 Direct Rendering Infrastructure 2。GPU による直接レンデリングを可能にする xcb_dri2_connect()
xcb_dri2_authenticate()
xcb_dri2_copy_region()
libxcb Mesa 3Dと統合して使用可能
dri3 Direct Rendering Infrastructure 3。DRI2 の後継として改良された直接レンダリング機能を提供 xcb_dri3_open()
xcb_dri3_pixmap_from_buffer()
xcb_dri3_buffer_from_pixmap()
libxcb
libxcb-present
現代的なGPUアクセラレーションに推奨
glx OpenGL の X Window System 実装。3Dグラフィックス描画をサポート xcb_glx_render()
xcb_glx_create_context()
xcb_glx_make_current()
libxcb OpenGLアプリケーションの開発に必須
present 表示タイミングの制御とフレーム同期を提供 xcb_present_pixmap()
xcb_present_notify_msc()
xcb_present_select_input()
libxcb VSync対応の表示制御に使用
randr Resize and Rotate。画面の解像度変更、回転、マルチディスプレイ管理を担当 xcb_randr_get_screen_info()
xcb_randr_set_screen_config()
xcb_randr_get_output_primary()
libxcb モニタのホットプラグにも対応
record キーボードやマウスなどの入力イベントを記録・再生 xcb_record_enable_context()
xcb_record_create_context()
xcb_record_free_context()
libxcb 入力の記録・再生機能の実装に使用
render ハードウェアアクセラレーションを活用した2D描画機能を提供 xcb_render_composite()
xcb_render_create_picture()
xcb_render_set_picture_transform()
libxcb アンチエイリアス、アルファブレンド対応
res X-Resource。クライアントのリソース使用状況を監視 xcb_res_query_client_resources()
xcb_res_query_client_pixmap_bytes()
libxcb リソース管理ツールの実装に使用
screensaver スクリーンセーバーの制御と管理 xcb_screensaver_suspend()
xcb_screensaver_select_input()
xcb_screensaver_set_attributes()
libxcb 省電力機能との連携も可能
shape 非矩形ウィンドウの作成と操作をサポート xcb_shape_mask()
xcb_shape_rectangles()
xcb_shape_combine()
libxcb 特殊形状のウィンドウやメニューの作成に使用
shm Shared Memory。共有メモリを使用した高速な画像転送を実現 xcb_shm_create_segment()
xcb_shm_attach()
xcb_shm_put_image()
libxcb 大規模画像処理の高速化に有効
sync クライアント間の同期とイベントの順序制御を提供 xcb_sync_create_counter()
xcb_sync_set_counter()
xcb_sync_await()
libxcb マルチクライアント環境での同期に使用
xf86dri XFree86 DRI。旧式の直接レンダリングインターフェース xcb_xf86dri_query_version()
xcb_xf86dri_query_direct_rendering_capable()
libxcb 互換性のために維持。新規開発はDRI3推奨
xfixes ウィンドウシステムの基本機能の改善と拡張を提供 xcb_xfixes_save_set_add()
xcb_xfixes_create_region()
xcb_xfixes_fetch_region()
libxcb 多くの他の拡張の基盤として使用
xinerama 複数の物理ディスプレイを単一の論理スクリーンとして扱う xcb_xinerama_query_screens()
xcb_xinerama_get_screen_count()
xcb_xinerama_is_active()
libxcb マルチディスプレイ環境の構築に使用
xinput 拡張入力デバイス(タブレット、タッチスクリーンなど)のサポート xcb_xinput_xi_query_version()
xcb_xinput_xi_select_events()
xcb_xinput_xi_get_property()
libxcb マルチタッチやペン入力のサポートに必須
xkb X Keyboard Extension。高度なキーボード設定と制御を提供 xcb_xkb_use_extension()
xcb_xkb_get_state()
xcb_xkb_get_map()
libxcb 国際キーボード対応に必須
xtest 入力イベントの生成とテストを可能にする xcb_test_fake_input()
xcb_test_get_version()
xcb_test_compare_cursor()
libxcb 自動化テストの実装に使用
xv X-Video。動画再生のハードウェアアクセラレーションを提供 xcb_xv_query_adaptors()
xcb_xv_put_video()
xcb_xv_get_port_attribute()
libxcb ハードウェアビデオ処理の実装に使用
xvmc X-Video Motion Compensation。動画のモーション補完機能を提供 xcb_xvmc_query_version()
xcb_xvmc_list_surface_types()
xcb_xvmc_create_context()
libxcb-xv MPEG2のハードウェアデコードに対応

まとめ

[編集]

XCBは、X Window Systemの低レベルな操作を行うための強力なライブラリであり、非同期処理が効率的に行えるため、パフォーマンスの向上が期待できます。Xlibに比べて少し複雑なAPIを持ちますが、パフォーマンスを重視する場合には非常に有用です。XCBを使いこなすことで、より高度なGUIアプリケーションを開発することができます。