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 と入力した
!CtrlA コントロールのみを押しながら a キーを押した
Button1a ボタン 1 を押しながら a キーを押した
Shifta シフトを押しながら 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 によりコンパイル, リンクされま
す.
ふぅ. 結構しんどいですね.
5. XToolkit を使いたくなったでしょう?
なんかすごく面倒そうに見えますが, Xlib だけで作った時よりはソフトウェ
アの使い勝手がかなり良くなると思います. Xlib しか使ったことのない人は
ぜひ XToolkit を使ってみましょう.
でわ〜
[戻る]
[email protected]