はじめに (対象読者・この記事でわかること)

この記事は、X Window Systemで低レベルなグラフィックスプログラミングを行いたいC言語プログラマーを対象にしています。特に、Xlibを使ってアプリケーション独自の色を確保する方法に興味がある方におすすめです。

この記事を読むことで、XlibのXAllocColorCells()関数を使って2つのプライベートカラーセルを確保する方法がわかります。カラーマップの仕組み、プライベートカラーセルの意味、実際のコードの書き方、エラーハンドリングまで、実用的な知識を習得できます。

X11環境で独自の色を使ったアプリケーションを開発しようとした際、カラーセルの確保に苦戦した経験から、この記事を書くことにしました。

前提知識

この記文を読み進める上で、以下の知識があるとスムーズです。 - C言語の基本的な文法とポインタの理解 - Xlibを使った基本的なWindowの作成方法 - X11のDisplay/Screen/Windowの基本概念

Xlibとカラーマップの基礎知識

X Window Systemでは、画面に表示される色は「カラーマップ」と呼ばれるテーブルで管理されています。各ピクセルの色は、このカラーマップのインデックスで指定されます。

カラーマップには2種類あります: - 読み取り専用カラーマップ:他のアプリケーションと色を共有します - 読み書き可能カラーマップ:アプリケーション専用の色を確保できます

XAllocColorCells()は、後者の読み書き可能カラーマップから「カラーセル」(色のスロット)を確保する関数です。プライベートカラーセルは、他のアプリケーションに干渉されることなく、自分だけで使用できる色の領域です。

1980年代のハードウェア制約から来るこの仕組みは、現代でもX11プロトコルの一部として残っており、特別な色効果やカラーテーブルアニメーションを実装する際に重要です。

XAllocColorCells()で2つのプライベートカラーセルを確保する

それでは実際に、XAllocColorCells()を使って2つのプライベートカラーセルを確保する方法を見ていきましょう。

ステップ1:基本的なコード構造

まず、必要なヘッダファイルと変数の宣言から始めます:

C
#include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <stdlib.h> int main() { Display *display; Window window; Colormap colormap; unsigned long pixels[2]; // 2つのカラーセルを格納 int ncolors = 2; // 確保したい色の数 // DisplayとWindowを開く display = XOpenDisplay(NULL); if (!display) { fprintf(stderr, "Cannot open display\n"); exit(1); } int screen = DefaultScreen(display); window = XCreateSimpleWindow( display, RootWindow(display, screen), 0, 0, 400, 300, 1, BlackPixel(display, screen), WhitePixel(display, screen) );

ステップ2:カラーマップの作成とカラーセルの確保

次に、読み書き可能なカラーマップを作成し、カラーセルを確保します:

C
// 読み書き可能なカラーマップを作成 colormap = XCreateColormap( display, window, DefaultVisual(display, screen), AllocAll // すべてのエントリを確保 ); // 2つのプライベートカラーセルを確保 Status result = XAllocColorCells( display, colormap, // カラーマップ False, // 既存のセルと競合しても構わない NULL, // プレーン・マスク(通常はNULL) 0, // プレーン数(通常は0) pixels, // 確保したピクセル値を格納する配列 ncolors // 確保したい色の数(今回は2) ); if (result == 0) { fprintf(stderr, "Failed to allocate color cells\n"); XCloseDisplay(display); exit(1); } printf("Successfully allocated %d color cells\n", ncolors); printf("Pixel values: %lu, %lu\n", pixels[0], pixels[1]);

ステップ3:確保したカラーセルに色を設定

確保したカラーセルに実際の色を設定します:

C
// 2つの色を定義(赤と青) XColor colors[2]; // 赤色を設定 colors[0].pixel = pixels[0]; colors[0].red = 65535; // 最大値 colors[0].green = 0; colors[0].blue = 0; colors[0].flags = DoRed | DoGreen | DoBlue; // 青色を設定 colors[1].pixel = pixels[1]; colors[1].red = 0; colors[1].green = 0; colors[1].blue = 65535; // 最大値 colors[1].flags = DoRed | DoGreen | DoBlue; // カラーセルに色を設定 XStoreColors(display, colormap, colors, ncolors); // Windowにカラーマップを設定 XSetWindowColormap(display, window, colormap);

ステップ4:確保した色を使って描画

最後に、確保した色を使って実際に描画します:

C
XSetWindowAttributes attrs; attrs.background_pixel = pixels[0]; // 赤色 XChangeWindowAttributes( display, window, CWBackPixel, &attrs ); // Windowを表示 XMapWindow(display, window); XFlush(display); // 5秒待つ sleep(5); // クリーンアップ XFreeColors(display, colormap, pixels, ncolors, 0); XFreeColormap(display, colormap); XCloseDisplay(display); return 0; }

ハマった点と解決策

実装中に遭遇する代表的な問題をいくつか紹介します。

問題1:XAllocColorCellsが常に失敗する

症状XAllocColorCells()が0を返し、カラーセルが確保できない。

原因:通常、デフォルトのカラーマップは読み取り専用であり、プライベートカラーセルを確保できません。

解決策:必ずXCreateColormap()で新しいカラーマップを作成してください。また、AllocAllではなくAllocNoneを使うことで、必要な数だけカラーセルを確保できます:

C
colormap = XCreateColormap( display, window, DefaultVisual(display, screen), AllocNone // カラーセルは後から確保 );

問題2:色が正しく表示されない

症状:確保した色が期待通りに表示されない、または真っ黒になる。

原因:カラーマップがWindowに正しく設定されていない、または色の値の範囲が間違っている。

解決策:以下の点を確認してください:

  1. XSetWindowColormap()でWindowにカラーマップを設定
  2. 色の値は0-65535の範囲(16ビット)
  3. XFlush()で変更を即座に反映

問題3:メモリリーク

症状:アプリケーションを終了しても、Xサーバーのリソースが解放されていない。

原因:確保したカラーセルやカラーマップを解放していない。

解決策:必ず以下の順序でクリーンアップしてください:

C
// 1. カラーセルを解放 XFreeColors(display, colormap, pixels, ncolors, 0); // 2. カラーマップを解放 XFreeColormap(display, colormap); // 3. Displayを閉じる XCloseDisplay(display);

まとめ

本記事では、XlibのXAllocColorCells()関数を使って2つのプライベートカラーセルを確保する方法を解説しました。

  • カラーマップの仕組み:X11が色を管理する方法と、プライベートカラーセルの重要性
  • XAllocColorCells()の使い方:読み書き可能なカラーマップの作成から、実際の色の設定まで
  • 実装のポイント:よくあるエラーとその解決策

この記事を通して、Xlibを使った低レベルなグラフィックスプログラミングの基礎を習得できました。プライベートカラーセルを使えば、他のアプリケーションと干渉することなく、独自の色効果を実装できます。

今後は、カラーテーブルアニメーションや、より多くのカラーセルを使った高度なグラフィックス効果についても記事にする予定です。

参考資料