widget という概念を導入することによって, クライアントの作成を容易にす ることを図ったライブラリです. widget とは, 押しボタンやメニューといっ たクライアントのユーザーインターフェースを構成する部品のようなものと考 えてください. XToolkit を用いる場合, この部品を組合せ, その動作を調整 することにより, クライアントを作成していきます.XToolkit の中にはそのまま利用できる widget は入っていません. XToolkit を用いてクライアントを作成する場合には, XToolkit とは別に Widget セッ トのライブラリをリンクする必要があります.
X ウィンドウシステムでは標準的な widget セットライブラリとして, Athena widget セットを用意しています.
(略) widget はオブジェクト指向の考え方から設計されたもので, クラスという概 念と継承という概念が導入されています. (略) Xtoolkit を使ってクライアントを作成する場合, 必要な部品のクラスのイン スタンスを生成し, そのインスタンスを組み合わせてクライアントとしま す. ちょうど, タイヤというクラスのインスタンスであるフロントタイヤ, リ アタイヤを作り, これらを組み合わせてバイクを作ると言ったようなものです.
だそうですが, 以下の説明では widget セットは利用しません. Athena Widget や Motif や OPEN LOOK を使うことが目的ではないのです. 又, widget のクラスを自分で作成したりもしません. 継承も考えません. これか らやろうとしていることは, 「あくまで Xlib がメイン. でも XToolkit の便 利な所だけは利用してしまえ〜」 ということなのです. よって, XToolkit の 一番基本的な部分である XToolkit intrinsics と, 基本的な 3 つの widget class しか使わないことになります.
コマンドラインの自動解析は説明するまでもありませんね. 自分で解析するの
は結構面倒ですから. それから, -geometry
や -iconic
や
-fg
や -bg
などなどのオプションをディフォルトで解釈して
くれるようになります.
リソースの利用については, 例えば, ~/.Xresources
(人によっては
~/.Xdefaults
かもしれません)に次のような記述をしたとしましょう.
*Foreground: White *Background: Redすると, XToolkit を利用していれば, window の背景色が赤になり, 前景 色が白になります. 又, キーカスタマイズも非常に簡単に設定できるようにな ります.
イベントドリブンのプログラムが書き易くなるのは, あるイベントが起こった
時に XToolkit がそれを処理する関数を直接呼んでくれる為です. Xlib だけ
を利用していたとしたら, イベントごとに switch
などで自分で振り
分けなければなりません.
そうそう, XToolkit とは関係ありませんが shape window の作り方について
も少しだけ説明することにします. shape window とは, oclock
や,
xeyes
で使用されている矩形でないウィンドウのことです.
widget はそれぞれの widget class に応じて色々な属性を持っています. 例
えば, button
と書いてあるボタンの widget では背景色が黄色で文字
の色 (前景色) が紫で文字列が button
でフォントが
-*-courier-*-16*
であるとか, oclock
の widget は長針の色
が赤で短針の色が柿色で, 縁の色が黒であるとか, mule
のフォントは
-*-marumoji-*--16-*-jisx0208.1983-0
であるとかです.
これらの属性をリソースといいます. そして, そのリソースを参照するために 使用される名前をリソース名といいます. widget と同じようにリソースもそ れぞれのリソースクラスに属しています.
さて, kterm
はスクロールバーを使用していなければ, 普通 2 つの
widget からできています. インスタンス名 (クラス名) です.
kterm(KTerm) | +--vt100(VT100)
kterm
という widget の上を vt100
という widget が覆っ
ています. 例えば次のようにして, kterm
の vt100
の
forground
というリソースの値を青にできます.
% xrdb kterm.vt100.foreground: Blue ^D
xrdb
はリソースを X Server にロードするためのコマンドで
す. ~/.Xresources
なども xrdb
を使ってロードされます.
kterm
では文字は vt100
widget の window に表示されますの
で, 文字が青くなります.
さて, XToolkit を使用していれば -name
オプションでインスタンス
名が変更できます. kterm -name console
を実行してみて下さい. 文
字は青くありませんね. これを青くするためには,
console.vt100.foreground: Blue
としなければなりません.
ところが, 普通はインスタンス名にこだわらず, kterm
の文字の色を
一括して指定したいと思うでしょう. そういう時はクラス名を指定します.
KTerm.vt100.foreground: Blue
こうしておけば, kterm
の文字の色はいつも青くなります. ただし,
次のように,
login.vt100.foreground: Red
としておいて, kterm -name login
とすれば文字の色は赤となり
ます. リソースを決定する時はより詳しく指定されている方が採用されるので
す.
また, リソース名 foreground
をクラス名 Foreground
で書く
こともできます.
さて, 基本的にはこれでいいのですが, リソース名, インスタンス名, クラス 名はワイルドカードにより省略ができます. 例えば,
kterm.?.foreground: Red
とか,
kterm*foreground: Red
とかです. 意味は分かりますね. さて, この時どうなるのでしょう ? 実
は kterm
は vt100 端末のエミュレーション機能だけでなく,
tektronix 端末のエミュレーション機能ももっています. tek4014 端末をエミュ
レートしている時は,
kterm(KTerm) | +--tek4014(Tek4014)
となっています. kterm.vt100.foreground
では, vt100
の方の色しか指定されていませんが, kterm.?.foreground
や
kterm*foreground
では当然ワイルドカードに tek4014
もマッ
チしてしまいますので, 線の色が赤になります.
そして, 省略が極端になると,
*Foreground: Green
などという指定もでてきます, これは, Foreground
クラスに属す
るリソースの値を緑にするという指定です. 例えば, oclock
の短針と
長針の色はそれぞれ, oclock.clock.hour
と
oclock.clock.minute
で指定されますが, どちらもクラスは
Clock.Clock.Foreground
なので緑色になってしまいます.
次の xtsample.cc
を利用して説明することにします. C++ プログラム
ですが, C++ の機能で利用しているのは, //
によるコメントと, 構造
体の前にいちいち struct
を付ける必要がないこと, ローカル変数は
ブロックの先頭でなくても宣言できることだけですから, C しか知らない人で
も大丈夫だと思います.
実際に利用してみるとリソースの利用の仕方などが良く分かりますので, 駒場
のアカウントがある人は, ~g440604/c/xtsample/
の下の
xtsample
を実行してみて下さい.
とりあえす, 実行すると日の丸と右上にアメリカの国旗がでるはずです. リソー
スで変な設定をしている人は, 色が変かもしれません. 大きい旗の上では
[space]
で旗の模様が変わり, 小さい旗の上では j
,
a
, f
で大きい旗の種類を直接していできます. q
か
[ESC]
か, Window Manager の close(fvwm), delete(twm) で正常終了
します.
つぎにリソースを書いてみます.
% xrdb xtsample*translations: #override \n\ <Key>q: change()resize()redraw(ALL)\n\ <Key>space: quit() xtsample*foreground: Orange ^D
どうでしょう ? さっきとは, [space]
と, q
の機能が入れ替
わっていますね. 又, 日の丸の色がオレンジになっています. 同じことが,
% xtsample -fg Orange -xrm 'xtsample*translations:#override\n<Key>q: change()resize()redraw(ALL)\n<Key>space:quit()'
でも指定できます.
xtsample
では, widget tree は次のようになっています.
xtsample(XTsample) | +--flag(Composite) | +--miniFlag(Core)
Composite
という widget class は子 widget を複数持てる widget
の一番基本のものです. Core
という widget class は widget の最も
基本なものです. (全ての widget は Core
から派生しています)
では, ソースを見ていきましょう.
xtsample.cc
001 // 002 // Xt Sample - GANA 003 // xtsample.cc 004 // 005 006 007 #include <X11/IntrinsicP.h> // ふつうはいらない 008 #include <X11/Intrinsic.h> // X toolkit insrinsics 009 #include <X11/StringDefs.h> // リソース名の定義 010 #include <X11/Shell.h> // shell widget 011 #include <X11/Composite.h> // composite widget 012 #include <X11/Core.h> // core widget 013 #include <X11/extensions/shape.h> // shape window 014 #include <stdlib.h> 015 #include <stdio.h> 016 017 018 #include "icon.xbm" 019 #include "mask.xbm"
この二つはアイコンを表示するためのデータです. このソースの後ろに載して おきます.
020 021 022 // ディフォルトリソース 023 static String default_resources[]= 024 { 025 "XTsample.Title: Xt Sample", 026 "XTsample.Geometry: 11x7", 030 "XTsample*BorderWidth: 0", 031 NULL, 032 };
ここでこれらのリソースが最初から設定されているために, タイトルバーに ``Xt Sample'' と表示されたり, 日の丸が赤色だったりします.
033 034 035 // オプションの指定 036 static XrmOptionDescRec options[]= 037 { 038 //{ "-option", "resource", Xrmoption*, (XPointer)value }, 039 {"--help", ".help", XrmoptionNoArg, (XPointer)"True"}, 040 {"-help", ".help", XrmoptionNoArg, (XPointer)"True"}, 041 {"-h", ".help", XrmoptionNoArg, (XPointer)"True"}, 042 {"-f", ".flag", XrmoptionSepArg, (XPointer)NULL}, 043 {"-flag", ".flag", XrmoptionSepArg, (XPointer)NULL}, 044 {"-blue", ".blue", XrmoptionSepArg, (XPointer)NULL}, 045 };
ここは, コマンドラインの自動解析に関するデータを指定しています. 例えば,
--help
が引数に指定されると, xtsample.help
のリソースが
"True"
に設定されます. 又, -flag 1
と指定されれば,
xtsample.flag
のリソースが "1"
に設定されます. 3 番目の
定数 XrmOption...
によって, オプションの解析方法が変わってきま
す.
XrmOptionDescRec options[x] コマンドライン xtsample.option に 設定されるリソース {"-option", ".option", XrmoptionNoArg, "True"} -option "True" {"-option", ".option", XrmoptionIsArg, NULL} -option "option" {"-opt", ".option", XrmoptionStickyArg, NULL} -option "ion" {"-option", ".option", XrmoptionSepArg, NULL} -option this "this" {"-option", ".option", XrmoptionResArg, NULL} -option "*a:b" 名称 a の全リソースに "b" {"-option", ".option", XrmoptionSkipArg, NULL} -option skip この 2 つを無視 {"-option", ".option", XrmoptionSkipLine, NULL} -option ignore この先全てを無視
XrmOptionDescRec
は以下のように定義されています.
typedef struct { char *option; /* Option abbreviation in argv */ char *specifier; /* Resource specifier */ XrmOptionKind argKind; /* Which style of option it is */ XPointer value; /* Value to provide if XrmoptionNoArg */ } XrmOptionDescRec, *XrmOptionDescList;
046 047 048 // shell widget のリソースの内容が読み込まれる構造体 049 static struct ShellAppData 050 { 051 Bool help; 052 String foreground; 053 String background; 054 String blue; 055 int flag; 056 int base_size; 057 int inc_size; 058 }shell_app_data; 059 060 061 // 前出の構造体のどのメンバにどのリソースを読み込むか 062 static XtResource shell_resources[]= 063 { 064 { "help", "Help", XtRBoolean, sizeof(Boolean), XtOffset(ShellAppData*, help), XtRImmediate, (XtPointer)False}, 065 { "foreground", "Foreground", XtRString, sizeof(String), XtOffset(ShellAppData*, foreground), XtRString, (XtPointer)"Red"}, 066 { "background", "Background", XtRString, sizeof(String), XtOffset(ShellAppData*, background), XtRString, (XtPointer)"White"}, 067 { "blue", "Blue", XtRString, sizeof(String), XtOffset(ShellAppData*, blue), XtRString, (XtPointer)"Blue"}, 068 { "flag", "Flag", XtRInt, sizeof(int), XtOffset(ShellAppData*, flag), XtRImmediate, (XtPointer)0}, 069 { "baseSize", "BaseSize", XtRInt, sizeof(int), XtOffset(ShellAppData*, base_size), XtRImmediate, (XtPointer)200}, 070 { "incSize", "IncSize", XtRInt, sizeof(int), XtOffset(ShellAppData*, inc_size), XtRImmediate, (XtPointer)32}, 071 };
333 行で, ShellAppData
構造体にリソースを読み込みますが, その時
どのリソースをどの変数に読み込むかを指定するものです. リソースのディフォ
ルトの値は, default_resources
で設定できるだけでなくここでも設
定できます.
XtResource
は以下のように定義されています.
typedef struct _XtResource { String resource_name; /* Resource name */ String resource_class; /* Resource class */ String resource_type; /* Representation type desired */ Cardinal resource_size; /* Size in bytes of representation */ Cardinal resource_offset; /* Offset from base to put resource value */ String default_type; /* representation type of specified default */ XtPointer default_addr; /* Address of default resource */ } XtResource, *XtResourceList;
072 073 static Widget shell; // shell widget 074 static Window shell_w=0; // shell widget の window ID
shell widget というのは, 自分の作るアプリケーションのウィンドウの中で
最も親となるべき widget です. つまり, window になった時にタイトルバー
がついたりする widget です. インスタンス名は xtsample
でクラス
名は Shell
ではなくて, XTsample
となります.
075 076 static Widget composite; // composite widget 077 static Window composite_w=0; // composite widget の window ID 078 static GC composite_gc=0; // composite widget の GC 079 080 static Widget core; // core widget 081 static Window core_w=0; // core widget の window ID 082 static GC core_gc=0; // core widget の GC 083 084 static Pixmap shape_pxm=0; // shape の pixmap の ID 085 static GC shape_gc=0; // shape の GC 086 static int can_use_shape=True; // shape extension は使用可能?
この shape_pxm
で, ウィンドウにマスクをかけて, 矩形でないウィン
ドウを作ります. 又, shape extension 機能が使えない X Server も存在しま
す.
087 088 static XtAppContext acr; // なんでしょ?これ。 089 static Display *d=NULL; // display 構造体 090 091 static Pixmap icon, mask; // icon の絵の白黒 pixmap ID 092 static XColor fore, back, blue; // それぞれの色のパレット番号 093 static Atom atom_wm_protocols, atom_wm_delete_window;
この Atom は, Window Manager が送ってくるメッセージのうち,
WM_DELETE_WINDOW
の Atom です. (ある X Server の中では, 色々な
定数や文字列が色々な用途に使用されていますが, それらを一意に識別するた
めに, それらに唯一の数を与えています. Atom とは, その数のことです. )
094 095 096 static void get_window_size (const Window w, unsigned int *width, unsigned int *height) 097 { 098 Window root; 099 int x, y; 100 unsigned int border, depth; 101 XGetGeometry(d, w, &root, &x, &y, width, height, &border, &depth); 102 } 103 104 105 static void japan(Window w, GC gc) 106 { 107 unsigned int width, height; 108 get_window_size(w, &width, &height); 109 int r=((widthこの辺りが shape extension による window のくりぬき処理で す.
shell_pxm
に絵を書いて, それをマスクとして window (shell_w
) にセットしています. この辺はoclock
のソースか らの見よう見まねなので何が行なわれているのかいまいちよく分かっていませ ん. X の man page も, ``This manual pages needs a lot more work.'' と 言ってほとんど何も書いてありません.
void XShapeCombineMask ( Display*, /* display */ Window, /* dest */ int, /* dest_kind */ int, /* x_off */ int, /* y_off */ Pixmap, /* src */ int /* op */ );
215 216 217 static void core_redraw(void) 218 { 219 switch (shell_app_data.flag) 220 { 221 case 0: 222 america(core_w, core_gc); break; 223 case 1: 224 france (core_w, core_gc); break; 225 case 2: 226 japan (core_w, core_gc); break; 227 } 228 } 229 230 231 static void change_flag (Widget widget, XEvent *e, String *params, Cardinal *num_params) 232 { 233 if (*num_params>0) shell_app_data.flag=atoi(params[0])%3; 234 else shell_app_data.flag=(shell_app_data.flag+1)%3; 235 fprintf(stderr, "flag changed to %d\n", shell_app_data.flag); 236 } 237 238 239 static void quit (Widget widget, XEvent *e, String *params, Cardinal *num_params) 240 { 241 fprintf(stderr, "quit\n"); 242 exit(0); 243 } 244 245 246 static void redraw (Widget widget, XEvent *e, String *params, Cardinal *num_params) 247 { 248 fprintf(stderr, "redraw\n"); 249 if (*num_params>0) 250 { 251 composite_redraw(); 252 core_redraw(); 253 } 254 else if (widget==composite) composite_redraw(); 255 else if (widget==core) core_redraw(); 256 XFlush(d); 257 } 258 259 260 static void resize (Widget widget, XEvent *e, String *params, Cardinal *num_params) 261 { 262 fprintf(stderr, "resize\n"); 263 shell_resize(); 264 } 265 266 267 static void close_window (Widget widget, XEvent *e, String *params, Cardinal *num_params) 268 // window manager からの delete window メッセージ 269 // (fvwm なら close 、twm なら delete) を受けとった 270 { 271 if (e->type==ClientMessage && 272 e->xclient.message_type==atom_wm_protocols && 273 e->xclient.data.l[0]==atom_wm_delete_window) 274 { 275 fprintf(stderr, "close\n"); 276 exit(0); 277 } 278 }ここで, 93 行目の Atom を使用しています.
279 280 281 static XtActionsRec actions[]= 282 { 283 {"quit", quit}, 284 {"change", change_flag}, 285 {"redraw", redraw}, 286 {"resize", resize}, 287 {"close", close_window}, 288 };ここで, 実際の関数と, リソースで設定される関数名を対応させています.
typedef struct _XtActionsRec{ String string; XtActionProc proc; } XtActionsRec;
typedef void (*XtActionProc)( Widget, /* widget */ XEvent*, /* event */ String*, /* params */ Cardinal* /* num_params */ );
289 290 291 static String shell_translation= 292 "<ClientMessage>: close()\n" 293 "<ConfigureNotify>: resize()redraw(ALL)\n"; 294 295 296 static String composite_translation= 297 "<Key>space: change()resize()redraw(ALL)\n" 298 "<Key>q: quit()\n" 299 "<Key>Escape: quit()\n" 300 "<Expose>: redraw()\n"; 301 302 303 static String core_translation= 304 "<Key>j: change(0)resize()redraw(ALL)\n" 305 "<Key>a: change(1)resize()redraw(ALL)\n" 306 "<Key>f: change(2)resize()redraw(ALL)\n" 307 "<Key>q: quit()\n" 308 "<Key>Escape: quit()\n" 309 "<Expose>: redraw()\n";イベントが起こった時, どの関数がどんな引数でどういう順番に呼ばれるかを 指定します.
translation に指定するもの X Event どういうイベントか BtnDown, Btn1Down, Btn2Down... ButtonPress マウスのボタンが押された BtnUp, Btn1Up, Btn2Up ... ButtonRelease マウスのボタンが離された Motion, PtrMoved, MouseMoved MotionNotify マウスが移動した Enter, EnterWindow EnterNotify マウスがウィンドウ内に入った Leave, LeaveWindow LeaveNotify マウスがウィンドウから出た Key, KeyDown KeyPress キーが押された KeyUp KeyRelease キーが離された FocusIn FocusIn フォーカスを得た FocusOut FocusOut フォーカスを失った KeyMap KeymapNotify 全キーの状態を検知した Mapping MappingNotify キーボードのマップ状態が変わった Expose Expose 最描画要求 GrExp GraohicExpose NoExp NoExpose Visible VisibilityNotify 可視/不可視状態の変化 Clrmap ColormapNotify Message ClientMessage WM からのメッセージなど Prop PropertyNotify SelClr SelectionClear Select SelectionNotify Circ CirculateNotify ウィンドウの重なり方の変化 Configure ConfigureNotify リサイズされた, など Create CreateNotify ウィンドウが生成された Destroy DestroyNotify ウィンドウが消滅した Map MapNotify ウィンドウがマップされた Unmap UnmapNotify ウィンドウがアンマップされた Grav GravityNotify Reparent ReparentNotify 親ウィンドウの変更 CircReq CirculateRequest ConfigureReq ConfigureRequest MapReq MapRequest マップ要求 ResizeReq ResizeRequest リサイズ要求
表記例 意味ボタン 1 を押した Shift シフトを押しながらボタン 1 を押した Ctrl コントロールを押しながらボタン 1 を離した (2) ダブルクリック (2+) ダブルクリック以上 a a キーを押した (大文字・小文字関係なし) "Try" Try と入力した !Ctrl A コントロールのみを押しながら a キーを押した Button1 a ボタン 1 を押しながら a キーを押した Shift a シフトを押しながら a キーを押した Ctrl, Shift, Lock, Meta, Alt, Mod1, Button1 などが使える
310 311 312 int main(int argc, char *argv[]) 313 { 314 // widgets 315 shell=XtVaAppInitialize 316 (&acr, "XTsample", 317 options, XtNumber(options), 318 &argc, argv, 319 default_resources, NULL);まず, shell widget を作成します. クラス名を
XTsample
とし, イン スタンス名はコマンドラインから自動的にせっていされます (大抵,xtsample
となりますが,-name
オプションなどが指定されれ ば別です).argc
,argv
を指定することによりコマンドライン の解析が行なわれ, 解析されたコマンドライン引数はargc
,argv
からとりのぞかれます. 又, X Server との接続を確立し, リソー スを読み込みます. ただし, この時点では shell widget の window は作成さ れていません.
Widget XtVaAppInitialize( XtAppContext*, /* app_context_return */ _Xconst _XtString, /* application_class */ XrmOptionDescList, /* options */ Cardinal, /* num_options */ int*, /* argc_in_out */ String*, /* argv_in_out */ String*, /* fallback_resources */ ... );
320 composite=XtVaCreateManagedWidget 321 ("flag", compositeWidgetClass, 322 shell, 323 NULL); 324 core=XtVaCreateManagedWidget 325 ("miniFlag", coreWidgetClass, 326 composite, 327 XtNwidth, 40, 328 XtNheight, 30, 329 NULL);
flag
とminiFlag
を作成します. インスタンス名は,miniFlag
のように, 先頭を子文字にすることが推奨されてます.
Widget XtVaCreateManagedWidget( _Xconst _XtString, /* name */ WidgetClass, /* widget_class */ Widget, /* parent */ ... );
330 331 XtAppAddActions(acr, actions, XtNumber(actions));ここで, 実際の関数と, リソースで設定される関数名の対応を登録しています. (281〜288 行目参照)
void XtAppAddActions( XtAppContext, /* app_context */ XtActionList, /* actions */ Cardinal /* num_actions */ );
332 d=XtDisplay(shell); 333 XtGetApplicationResources 334 (shell, 335 XtPointer(&shell_app_data), 336 shell_resources, XtNumber(shell_resources), 337 NULL, 0);ここで, 61〜71 行で設定した情報に基づいてリソースの値を
app_data
構造体に代入しています.
void XtGetApplicationResources( Widget, /* widget */ XtPointer, /* base */ XtResourceList, /* resources */ Cardinal, /* num_resources */ ArgList, /* args */ Cardinal /* num_args */ );
338 if (shell_app_data.help || argc>1) 339 { 340 fprintf(stderr, 341 "usage: xtsample [options ...]\n" 342 " -h, -help, -flag <n>, -blue <color>, ...\n"); 343 return 1; 344 } 345 346 // translations 347 XtAugmentTranslations(shell, XtParseTranslationTable(shell_translation)); 348 XtAugmentTranslations(composite, XtParseTranslationTable(composite_translation)); 349 XtAugmentTranslations(core, XtParseTranslationTable(core_translation));291〜309 行目で設定したディフォルトの
translation
を登録します. ただし, 同じtranslation
が既に設定されていたら, それは登録しま せん.
void XtAugmentTranslations( Widget, /* widget */ XtTranslations /* translations */ );
350 351 // shape 352 int shape_event_base, shape_error_datas; 353 can_use_shape=XShapeQueryExtension(d, &shape_event_base, &shape_error_datas);shape extension が使用可能かどうかの問い合わせをします.
Bool XShapeQueryExtension ( Display*, /* display */ int*, /* event_base */ int* /* error_base */ );
354 355 // icon 356 icon=XCreateBitmapFromData(d, RootWindow(d, 0), (char *)icon_bits, icon_width, icon_height); 357 mask=XCreateBitmapFromData(d, RootWindow(d, 0), (char *)mask_bits, mask_width, mask_height); 358 XtVaSetValues(shell, XtNiconPixmap, icon, XtNiconMask, mask, NULL);shell widget のリソースとしてアイコンを登録します. このリソースは Window Manager によってアイコンとして利用されます.
void XtVaSetValues( Widget, /* widget */ ... );
359 360 // color 361 XColor dummy; 362 XAllocNamedColor(d, DefaultColormap(d, 0), shell_app_data.foreground, &fore, &dummy); 363 XAllocNamedColor(d, DefaultColormap(d, 0), shell_app_data.background, &back, &dummy); 364 XAllocNamedColor(d, DefaultColormap(d, 0), shell_app_data.blue, &blue, &dummy);リソースで指定された色の名前から, その色のパレット番号と, rgb の値を取 得します.
365 366 // resources 367 XtVaSetValues 368 (shell, 369 // XtNwidth, 0, 370 // XtNheight, 0, 371 // XtNmaxWidth, 0, 372 // XtNmaxHeight, 0, 373 // XtNminWidth, 0, 374 // XtNminHeight, 0, 375 XtNbaseWidth, shell_app_data.base_size, 376 XtNbaseHeight, shell_app_data.base_size, 377 XtNwidthInc, shell_app_data.inc_size, 378 XtNheightInc, shell_app_data.inc_size, 379 XtNinput, True, 380 NULL);shell widget にさらに大きさなどのリソースを設定します. まず, base サイ ズは, これ以上ちじまない大きさで, inc サイズ単位で大きくなることができ ます. kterm のようなサイズの変更が可能になると考えて下さい.
コメントアウトされている, max と min を指定すればウィンドウの最大と最 小の大きさが指定できます. base, inc との併用はできないようです.
XtNwidth
とXtNheight
はウィンドウが生成された時の大きさ ですが, これは, 26 行目で既に設定してあるのでここでは設定しません.
XtNinput
はマウスがウィンドウ内に入った時フォーカスを渡すように Window Manager に指示しています. こうしておかないと, Window Manager は フォーカスを渡してくれません.
381 XtRealizeWidget(shell);ここでやっと 3 つの widget の window が実際に生成されます.
void XtRealizeWidget( Widget /* widget */ );
382 383 shell_w =XtWindow(shell); 384 composite_w =XtWindow(composite); 385 composite_gc=XCreateGC(d, composite_w, 0, 0); 386 core_w =XtWindow(core); 387 core_gc =XCreateGC(d, core_w, 0, 0); 388 389 // close 390 atom_wm_protocols =XInternAtom(d, "WM_PROTOCOLS", False); 391 atom_wm_delete_window=XInternAtom(d, "WM_DELETE_WINDOW", False); 392 XSetWMProtocols(d, shell_w, &atom_wm_delete_window, 1);Window Manager に,
WM_DELETE_WINDOW
メッセージを送るように指示 しています. (93, 267〜278 行目参照)
393 394 XtAppMainLoop(acr);イベント待ちループに入ります. この関数は制御を返しません. だから, 395 行目に到達することは決してないのです.
395 }次の
icon.xbm
とmask.xbm
はbitmap
で生成しまし た.xv
などでも生成可能です.
icon.xbm
001 #define icon_width 49 002 #define icon_height 25 003 static unsigned char icon_bits[] = { 004 0x00, 0x7c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x0a, 0x0f, 005 0x00, 0x00, 0x00, 0x10, 0x01, 0x85, 0x08, 0x00, 0x00, 0x00, 0x20, 0x82, 006 0xe2, 0x38, 0x00, 0x00, 0x00, 0x40, 0x44, 0x21, 0x20, 0x00, 0x00, 0x00, 007 0x80, 0xa8, 0xe0, 0x38, 0x00, 0x00, 0x00, 0x00, 0x55, 0x80, 0x08, 0x00, 008 0x00, 0x00, 0x80, 0x8a, 0x80, 0x08, 0x00, 0x00, 0x00, 0x40, 0x11, 0x81, 009 0x08, 0x00, 0x00, 0x00, 0xa0, 0x20, 0x82, 0x08, 0x00, 0x00, 0x00, 0x50, 010 0x40, 0x84, 0x30, 0x00, 0x00, 0x00, 0x28, 0x80, 0x08, 0x21, 0x00, 0x00, 011 0x00, 0x1c, 0x00, 0x1f, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 012 0x00, 0x00, 0x7e, 0x3e, 0xee, 0xfc, 0x3c, 0xfc, 0x01, 0x41, 0x41, 0x11, 013 0x05, 0x25, 0x04, 0x01, 0x79, 0x49, 0x11, 0x25, 0x25, 0xe4, 0x01, 0x09, 014 0x49, 0x11, 0x25, 0x25, 0x24, 0x00, 0x39, 0x49, 0x11, 0x25, 0x25, 0xe4, 015 0x00, 0x41, 0x41, 0x01, 0x05, 0x25, 0x84, 0x00, 0x4e, 0x49, 0x29, 0xe5, 016 0x24, 0xe4, 0x00, 0x48, 0x49, 0x29, 0x25, 0x24, 0x24, 0x00, 0x4f, 0x49, 017 0x29, 0x25, 0xe4, 0xe5, 0x01, 0x41, 0x49, 0x29, 0x25, 0x04, 0x05, 0x01, 018 0x3f, 0x7f, 0xff, 0x3d, 0xfc, 0xfd, 0x01};
mask.xbm
001 #define mask_width 49 002 #define mask_height 25 003 static unsigned char mask_bits[] = { 004 0x00, 0x7c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x0e, 0x0f, 005 0x00, 0x00, 0x00, 0xf0, 0x01, 0x87, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x83, 006 0xe3, 0x3f, 0x00, 0x00, 0x00, 0xc0, 0xc7, 0xe1, 0x3f, 0x00, 0x00, 0x00, 007 0x80, 0xef, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x77, 0x80, 0x0f, 0x00, 008 0x00, 0x00, 0x80, 0xfb, 0x80, 0x0f, 0x00, 0x00, 0x00, 0xc0, 0xf1, 0x81, 009 0x0f, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x83, 0x0f, 0x00, 0x00, 0x00, 0x70, 010 0xc0, 0x87, 0x3f, 0x00, 0x00, 0x00, 0x38, 0x80, 0x0f, 0x3f, 0x00, 0x00, 011 0x00, 0x1c, 0x00, 0x1f, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 012 0x00, 0x00, 0x7e, 0x3e, 0xee, 0xfc, 0x3c, 0xfc, 0x01, 0x7f, 0x7f, 0xff, 013 0xfd, 0x3d, 0xfc, 0x01, 0x7f, 0x7f, 0xff, 0xfd, 0x3d, 0xfc, 0x01, 0x0f, 014 0x7f, 0xff, 0xfd, 0x3d, 0x3c, 0x00, 0x3f, 0x7f, 0xff, 0xfd, 0x3d, 0xfc, 015 0x00, 0x7f, 0x7f, 0xff, 0xfd, 0x3d, 0xfc, 0x00, 0x7e, 0x7f, 0xff, 0xfd, 016 0x3c, 0xfc, 0x00, 0x78, 0x7f, 0xff, 0x3d, 0x3c, 0x3c, 0x00, 0x7f, 0x7f, 017 0xff, 0x3d, 0xfc, 0xfd, 0x01, 0x7f, 0x7f, 0xff, 0x3d, 0xfc, 0xfd, 0x01, 018 0x3f, 0x7f, 0xff, 0x3d, 0xfc, 0xfd, 0x01};さて, プログラムを作ったならば, 次はコンパイルです. しかし, X のライブ ラリは
ld
(リンカ) のサーチパスから外れていたり, socket のライ ブラリを要求したりと, 機種によって様々でいろいろ面倒です. そこで, うま くコンパイルできるようにImakefile
というものを使います.
Imakefile
001 LOCAL_LIBRARIES = $(XLIB) $(XTOOLLIB) 002 DEPLIBS = $(DEPXLIB) $(DEPXTOOLLIB) 003 OBJS = xtsample.o 004 SRCS = xtsample.cc 005 006 ComplexProgramTarget(xtsample)これを作ってから
% xmkmf % make depend % makeとします (このプログラムの場合は depend の必要はありませんが). す ると,
xmkmf
により, 適当なライブラリがリンクされるようなMakefile
が生成され,make
によりコンパイル, リンクされま す.ふぅ. 結構しんどいですね.
なんかすごく面倒そうに見えますが, Xlib だけで作った時よりはソフトウェ アの使い勝手がかなり良くなると思います. Xlib しか使ったことのない人は ぜひ XToolkit を使ってみましょう. 5. XToolkit を使いたくなったでしょう?
でわ〜
[戻る]
g541119@komaba.ecc.u-tokyo.ac.jp