Windowsで言うところのトップレベルウィンドウ(一番親のウィンドウ)を作る時は、XCreateSimpleWindowなどに、ルートウィンドウのWindow(実態はXID==unsigned long)を渡す。
で、RootWindowマクロで指定のディスプレイの指定のスクリーンのWindowが返る。
基本的には、ディスプレイ0のスクリーン0がデフォルトルートウィンドウなので、それ以外を指定することはあまりないが、今回は0以外を指定するパターンをやってみる。
普通は、xdpyinfoコマンドで
$ xdpyinfo name of display: :0 version number: 11.0 vendor string: Fedora Project . . . (中略) . . . default screen number: 0 number of screens: 1 screen #0: dimensions: 1280x960 pixels (0x0 millimeters) . . . (中略) . . .
ディスプレイ名は":0"、デフォルトスクリーン番号は0、スクリーンの数は1。
マルチモニタならディスプレイ名や数は変わるかもしれないが、シングルならこうなる。
この状態で、
/* ヘッダファイルのインクルード */ #include <stdio.h> /* C標準入出力 */ #include <unistd.h> /* UNIX標準 */ #include <X11/Xlib.h> /* Xlib */ /* main関数 */ int main(void){ /* 変数の宣言 */ Display *d; /* Display構造体へのポインタd. */ Window wr; /* ウィンドウ生成の結果を表す値wr.(Window == XID == unsigned long) */ int result; /* マップの結果result. */ unsigned long white; /* 白のRGB値white. */ unsigned long black; /* 黒のRGB値black. */ /* Xサーバとの接続. */ d = XOpenDisplay(NULL); /* XOpenDisplayでXサーバに接続し, 戻り値のアドレスをdに格納. */ /* dを出力. */ printf("d = %08x\n", d); /* dの値を16進数で出力. */ /* 白のRGB値を取得. */ white = XWhitePixel(d, 1); /* XWhitePixelでスクリーン1における白のRGB値を取得し, whiteに格納. */ /* 黒のRGB値を取得. */ black = XBlackPixel(d, 1); /* XBlackPixelでスクリーン1における黒のRGB値を取得し, blackに格納. */ /* ウィンドウの生成. */ wr = XCreateSimpleWindow(d, RootWindow(d, 1), 100, 100, 640, 480, 1, white, white); /* XCreateSimpleWindowでウィンドウ生成し, 結果はwrに格納.(RootWindowでスクリーン1を指定.) */ /* ウィンドウ生成の結果を出力. */ printf("wr = %08x\n", wr); /* wrを出力. */ /* ウィンドウのマッピング(表示要求) */ result = XMapWindow(d, wr); /* XMapWindowでマッピング. */ /* マッピング結果を出力. */ printf("result = %d\n", result); /* resultの値を出力. */ /* 表示要求イベントをフラッシュ. */ XFlush(d); /* XFlushでフラッシュ. */ /* 10秒待つ. */ printf("sleep 10 seconds...\n"); /* "sleep 10 seconds..."と出力. */ sleep(10); /* sleepで10秒休止. */ /* プログラムの終了 */ return 0; /* 0を返して正常終了. */ }
ディスプレイはNULLなので":0"を指してて、RootWindowやXWhitePixelなどに存在しないスクリーン番号1を指定して、ウィンドウ表示のプログラムを実行しても、
表示されない。
X Window System, Programming, No.1
@IT:X Window Systemの情報を表示するには
基本的にスクリーンは1つで、意図的に増やす方法が見つからないが、
Xvfb を使って仮想ディスプレイを作る - CUBE SUGAR CONTAINER
Xvfbを使って、仮想ディスプレイを作れるらしいので、これを使ってみる。
$ sudo yum install xorg-x11-server-Xvfb [sudo] bg1 のパスワード: メタデータの期限切れの最終確認: xx:xx:xx 時間前の xxxx年xx月xx日 xx時xx分xx秒 に実施しました。 パッケージ xorg-x11-server-Xvfb-1.20.4-1.fc29.x86_64 は既にインストールされています。 依存関係が解決しました。 行うべきことはありません。 完了しました! $
すでに入ってた。
$ Xvfb :1 -screen 1 1280x960x24 The XKEYBOARD keymap compiler (xkbcomp) reports: > Warning: Unsupported high keycode 372 for name <I372> ignored > X11 cannot support keycodes above 255. > This warning only shows for the first high keycode. Errors from xkbcomp are not fatal to the X server
ディスプレイ名1のスクリーン番号1で起動する。
別のターミナルを開いて、
$ export DISPLAY=:1 $
をしてから、xdpyinfoすると、
$ xdpyinfo name of display: :1 . . . (中略) . . . default screen number: 0 number of screens: 2
ディスプレイは1、ただしデフォルトスクリーン番号が0。
この状態でこの後の作業をやったら、うまくいかなかったので、
いろいろさらに別のディスプレイ名で仮想ディスプレイを作ってみたりすると、
$ xdpyinfo . . . (中略) . . . default screen number: 1 number of screens: 2
このような状態になる時がある。
これならデフォルトスクリーン番号も0じゃないので、この後の作業でスクリーン1のウィンドウ表示が見れる。
で、このスクリーン1は直接見ることはできないので、スクリーンショットを撮るしかない。
xwdをインストール。
$ sudo yum install xwd netpbm-progs [sudo] bg1 のパスワード: メタデータの期限切れの最終確認: xx:xx:xx 時間前の xxxx年xx月xx日 xx時xx分xx秒 に実施しました。 依存関係が解決しました。 ================================================================================ パッケージ アーキテクチャー バージョン リポジトリ サイズ ================================================================================ インストール: netpbm-progs x86_64 10.84.03-3.fc29 updates 1.9 M xorg-x11-apps x86_64 7.7-22.fc29 fedora 328 k アップグレード: netpbm x86_64 10.84.03-3.fc29 updates 173 k 依存関係をインストール中: xorg-x11-fonts-misc noarch 7.5-20.fc29 fedora 5.8 M xorg-x11-xbitmaps noarch 1.1.1-15.fc29 fedora 38 k トランザクションの概要 ================================================================================ インストール 4 パッケージ アップグレード 1 パッケージ ダウンロードサイズの合計: 8.2 M これでよろしいですか? [y/N]: y パッケージのダウンロード中です: (1/5): xorg-x11-apps-7.7-22.fc29.x86_64.rpm 160 kB/s | 328 kB 00:02 (2/5): xorg-x11-xbitmaps-1.1.1-15.fc29.noarch.r 43 kB/s | 38 kB 00:00 (3/5): netpbm-10.84.03-3.fc29.x86_64.rpm 169 kB/s | 173 kB 00:01 (4/5): netpbm-progs-10.84.03-3.fc29.x86_64.rpm 487 kB/s | 1.9 MB 00:04 (5/5): xorg-x11-fonts-misc-7.5-20.fc29.noarch.r 1.0 MB/s | 5.8 MB 00:05 -------------------------------------------------------------------------------- 合計 924 kB/s | 8.2 MB 00:09 トランザクションの確認を実行中 トランザクションの確認に成功しました。 トランザクションのテストを実行中 トランザクションのテストに成功しました。 トランザクションを実行中 準備 : 1/1 Upgrade: netpbm-10.84.03-3.fc29.x86_64 アップグレード中 : netpbm-10.84.03-3.fc29.x86_64 1/6 Upgrade: netpbm-10.84.03-3.fc29.x86_64 Installed: xorg-x11-xbitmaps-1.1.1-15.fc29.noarch インストール中 : xorg-x11-xbitmaps-1.1.1-15.fc29.noarch 2/6 Installed: xorg-x11-xbitmaps-1.1.1-15.fc29.noarch Installed: xorg-x11-fonts-misc-7.5-20.fc29.noarch インストール中 : xorg-x11-fonts-misc-7.5-20.fc29.noarch 3/6 scriptletの実行中: xorg-x11-fonts-misc-7.5-20.fc29.noarch 3/6 Installed: xorg-x11-fonts-misc-7.5-20.fc29.noarch Installed: xorg-x11-apps-7.7-22.fc29.x86_64 インストール中 : xorg-x11-apps-7.7-22.fc29.x86_64 4/6 Installed: xorg-x11-apps-7.7-22.fc29.x86_64 Installed: netpbm-progs-10.84.03-3.fc29.x86_64 インストール中 : netpbm-progs-10.84.03-3.fc29.x86_64 5/6 Installed: netpbm-progs-10.84.03-3.fc29.x86_64 Upgraded: netpbm-10.84.03-1.fc29.x86_64 整理 : netpbm-10.84.03-1.fc29.x86_64 6/6 Upgraded: netpbm-10.84.03-1.fc29.x86_64 scriptletの実行中: netpbm-10.84.03-1.fc29.x86_64 6/6 検証 : netpbm-progs-10.84.03-3.fc29.x86_64 1/6 検証 : xorg-x11-apps-7.7-22.fc29.x86_64 2/6 検証 : xorg-x11-fonts-misc-7.5-20.fc29.noarch 3/6 検証 : xorg-x11-xbitmaps-1.1.1-15.fc29.noarch 4/6 検証 : netpbm-10.84.03-3.fc29.x86_64 5/6 検証 : netpbm-10.84.03-1.fc29.x86_64 6/6 アップグレード済み: netpbm-10.84.03-3.fc29.x86_64 インストール済み: netpbm-progs-10.84.03-3.fc29.x86_64 xorg-x11-apps-7.7-22.fc29.x86_64 xorg-x11-fonts-misc-7.5-20.fc29.noarch xorg-x11-xbitmaps-1.1.1-15.fc29.noarch 完了しました! $
で、改めてだけれども、
さっきからずっとXvfbは実行状態のままで、別ターミナルで、
$ export DISPLAY=:1
となっていて、いちおうxdpyinfoを確認すると、
$ xdpyinfo . . . (中略) . . . default screen number: 1 number of screens: 2
この状態で、
これを実行する。
XOpenDisplayのディスプレイ名は、xdpyinfoに合わせたものになるので、":1"とは限らない。xdpyinfoのものを使う。
あと、ポイントは、XWhitePixelとかXBlackPixelは、ちゃんと白や黒が出るかわからないので、今回は使わない。0xffffffで、白を指定。
で白じゃないと、スクリーンショットが真っ黒でウィンドウがあるかわからないので、白にしている。
そして、RootWindowでは、dとデフォルトスクリーン番号1をセット。
0じゃない場合という要件を満たしている。
あと、作業に時間がかかるので、sleepを60秒にしてる。
これで実行してもここには表示されないが、さらに別ターミナルを開いて、"export DISPLAY=:1"とxdpyinfoによる確認をしてから、
$ xwd -display :1 -root | xwdtopnm | pnmtopng > screenshot.png
これでスクリーンショットを撮ると、
ディスプレイ1のスクリーン1に白いウィンドウがあることがわかる。
Sample/xlib/RootWindow/RootWindow/src/RootWindow at master · bg1bgst333/Sample · GitHub