ログイン
編集不可のページディスカッション情報添付ファイル
"clear/wm_devel/2012-12-14"の差分

MMA
4と5のリビジョン間の差分
2013-01-03 18:18:02時点のリビジョン4
サイズ: 3962
編集者: clear
コメント:
2013-02-01 12:01:39時点のリビジョン5
サイズ: 4316
編集者: clear
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 8: 行 8:
  * 後発だがより低レイヤー   * 後発だがより低レイヤー。ほぼプロトコルと1対1対応
   * Xlibは複数のリクエストを送ったり、レスポンスの一部だけを取り出すようなラッパーがある
行 17: 行 18:
   * リクエストキューをflushするタイミングをある程度制御できる。逆に言えば、必要な場面でflushを忘れるとリクエストが実行されない

XCBの基本

XCBのチュートリアルを見ながら写経。

Xlibと何が違うのか

今のところの理解。

  • Xlibよりダイレクトにプロトコルを操作する
    • 後発だがより低レイヤー。ほぼプロトコルと1対1対応
      • Xlibは複数のリクエストを送ったり、レスポンスの一部だけを取り出すようなラッパーがある
    • ライブラリの実装自体が仕様(xcb-proto)から自動生成されているらしい
  • 同期/非同期の違い
    • Xlib: リクエストに対するレスポンスは同期(リクエストを行う関数の戻り値)、エラー通知は非同期(エラーハンドラ)
      • エラーはいきなり天から降ってくる
    • XCB: リクエストに対して、レスポンスもエラー通知も非同期
      • リクエストを投げる際に関数の戻り値としてcookieを得る
      • cookieを使ってレスポンスあるいはエラーを得る
        • エラー取得のタイミングを自分で制御できる
      • リクエストキューをflushするタイミングをある程度制御できる。逆に言えば、必要な場面でflushを忘れるとリクエストが実行されない
  • 適切に使えばXlibよりかなり速い
    • ここにある500個のアトム値を作るサンプルだと、手元の環境ではXCBの方が10から20倍速かった

  • そもそも今のXlibはXCBの上に互換レイヤーとして実装されているとかいないとか

矩形を描画するだけの何の面白みもないプログラム

   1 #include <stdio.h>
   2 #include <stdlib.h>
   3 #include <xcb/xcb.h>
   4 
   5 xcb_connection_t *conn;
   6 xcb_screen_t *screen;
   7 xcb_window_t win;
   8 xcb_gcontext_t gc;
   9 
  10 int main(void)
  11 {
  12     int screen_num, i;
  13     xcb_screen_iterator_t iter;
  14     uint32_t mask, values[10];
  15 
  16     conn = xcb_connect(NULL, &screen_num);
  17 
  18     /* get screen information */
  19     iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
  20     for (i = 0; i < screen_num; ++i)
  21         xcb_screen_next(&iter);
  22     screen = iter.data;
  23     puts("screen information:");
  24     printf("%dx%d, root = %x\n", screen->width_in_pixels,
  25         screen->height_in_pixels, screen->root);
  26 
  27     /* create gc */
  28     gc = xcb_generate_id(conn);
  29     mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
  30     values[0] = screen->black_pixel;
  31     values[1] = 0;
  32     xcb_create_gc(conn, gc, screen->root, mask, values);
  33 
  34     /* create window */
  35     win = xcb_generate_id(conn);
  36     mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
  37     values[0] = screen->white_pixel;
  38     values[1] = XCB_EVENT_MASK_EXPOSURE;
  39     xcb_create_window(conn, XCB_COPY_FROM_PARENT,
  40         win, screen->root, 0, 0, 200, 100, 1,
  41         XCB_WINDOW_CLASS_INPUT_OUTPUT,
  42         screen->root_visual, mask, values);
  43 
  44     /* show window */
  45     xcb_map_window(conn, win);
  46     xcb_flush(conn);
  47 
  48     xcb_generic_event_t *event;
  49     while (event = xcb_wait_for_event(conn)) {
  50         /* SendEventリクエストによって送信されたイベントの場合、response_typeのMSBが1になる
  51            そのままではイベントの種類を正しく判別できないので~0x80でマスクしてMSBを除去する
  52            詳しくはxcb_event.hを参照*/
  53         switch (event->response_type & ~0x80) {
  54         case XCB_EXPOSE:
  55             xcb_poly_rectangle(conn, win, gc, 1,
  56                 &(xcb_rectangle_t){ 10, 10, 100, 50 }); /* C99の複合リテラル */
  57             /* どうやらXCBでもリクエストはバッファリングされるらしい
  58                この場合特にバッファをフラッシュする要因が無いようなので、
  59                明示的にxcb_flushしないとリクエストがサーバに送られない = 描画されない */
  60             xcb_flush(conn);
  61             break;
  62         default:
  63             break;
  64         }
  65         free(event);
  66     }
  67     xcb_disconnect(conn);
  68     return 0;
  69 }
  • ウィンドウやGCのためのXIDは先にxcb_generate_idによって自分で作る

  • valuesはただの配列なので値の順序が重要(maskの値の小さい順に並べる)

clear/wm_devel/2012-12-14 (最終更新日時 2013-03-07 16:57:27 更新者 clear)