Chapter 11 イベント処理関数

11 章: イベント処理関数

この章では以下の処理を可能にする Xlib の関数群を説明する:

ほとんどのアプリケーションは単なるイベントループである: つまりイベントを待ち、どのようにイベントに対応するか決め、 結果として表示が変わるような何らかのコードを実行し、それから次のイベン トを待つという動作を行う。

イベントの選択

クライアントアプリケーションに通知したいイベントを選択する方法は 2 つ ある。一つの方法は、 XCreateWindowXChangeWindowAttributesを呼び出す際に XSetWindowAttributes構造体の event_mask メンバを設定することである。 もう一つの方法は、 XSelectInputを使うことである。

XSelectInput(display, w, event_mask)
Display *display;
Window w;
long event_mask;
display
X サーバへの接続を指定する。
w
ウィンドウを指定する。 このウィンドウが受け取るイベントに注目する。
event_mask
イベントマスクを指定する。

関数 XSelectInputは、指定されたイベントマスクに対応するイベントを X サーバが通知すること を要求する。最初は、X はこれらのイベントを全く通知しない。 イベントはウィンドウに関して通知される。 ウィンドウがデバイスイベントに注目していなければ、デバイスイベントは 通常、デバイスイベントに注目している最も近い祖先ウィンドウに伝播する。 ただし do_not_propagate マスクによって禁止されている場合には、伝播は行 われない。

あるウィンドウのイベントマスク属性を設定すると、同じウィンドウに対する 以前の設定は全て上書きされるが、他のウィンドウに対する設定は上書きされ ない。 以下の制限の下で、同じウィンドウ上の同じイベントを複数のクライアントで 受け取ることができる:

サーバは、そのイベントに注目している全てのクライアントに通知を行う。

関数 XSelectInputはエラー BadWindow を生成することがある。

出力バッファの処理

出力バッファとは、Xlib がリクエストを格納するために使う領域である。 この章で説明する 3 つの関数は、関数がブロックしているか、あるいは イベントを返さない場合に出力バッファをフラッシュする。つまり、 出力バッファに入っていて、まだ送られていない全てのリクエストが X サーバに送られる。 各関数は、バッファのフラッシュ以外の動作が異なる。

出力バッファをフラッシュするには、 XFlushを用いる。

XFlush(display)
Display *display;
display
X サーバへの接続を指定する。

関数 XFlushは出力バッファをフラッシュする。ほとんどのアプリケーションはこの関数を 必要としない。なぜなら、必要に応じて XPending ,XNextEvent ,XWindowEventの呼び出しによって出力バッファが自動的にフラッシュされるからである。 サーバが生成したイベントは、ライブラリのイベントキューに入れられること がある。

出力バッファをフラッシュし、全てのリクエストが処理されるまで待つ場合には、 XSyncを用いる。

XSync(display, discard)
Display *display;
Bool discard;
display
X サーバへの接続を指定する。
discard
XSyncがイベントキューに入っている全てのイベントを破棄するかどうかを示す Bool 値を指定する。

関数 XSyncは出力バッファをフラッシュした後、X サーバが全てのリクエストを受け取っ て処理するのを待つ。生成されるエラーは全て、エラーハンドラで処理しなけ ればならない。 Xlib が受け取った各プロトコルエラーについては、 XSyncはクライアントアプリケーションのエラー処理ルーチン(11.8.2 節を参照)を 呼び出す。サーバが生成した全てのイベントは、ライブラリのイベントキュー に入れられる。

最後になるが、 Falseを引き数 discard に渡すと、 XSyncはキューに入っているイベントを破棄しない。 Trueを渡すと、 XSyncはキューに入っているイベントを全て破棄する。 破棄されるイベントには、 XSyncが呼び出される前にキューに入っていたイベントも含まれる。 クライアントアプリケーションが XSyncを呼び出す必要があることはほとんどない。

イベントキューの管理

Xlib はイベントキューを管理する。 しかし、ネットワーク接続内の、まだイベントキューに読み込まれていない データのバッファリングはオペレーティングシステムが行うこともある。

イベントキューに入っているイベントの個数を調べるには、 XEventsQueuedを使う。

int XEventsQueued(display, mode)
Display *display;
int mode;
display
X サーバへの接続を指定する。
mode
モードを指定する。 QueuedAlready ,QueuedAfterFlush ,QueuedAfterReading .のいずれかを指定することができる。

モードが QueuedAlreadyならば、 XEventsQueued は既にイベントキューに入っているイベントの個数を返す(システムコールは全 く実行しない)。 モードが QueuedAfterFlushの場合、既にイベントキューに入っているイベントの個数が 0 でなければ、 XEventsQueuedはその数を返す。 キューに入っているイベントがなければ、 XEventsQueuedは出力バッファをフラッシュし、アプリケーションとの接続から追加のイベン トを読み込もうとし、読み込めたイベントの個数を返す。 モードが QueuedAfterReadingの場合、既にイベントキューに入っているイベントの個数が 0 でなければ、 XEventsQueuedはその数を返す。 キューに入っているイベントがなければ、アプリケーションとの接続から追加 のイベントを読み込もうとし、読み込めたイベントの個数を返す。この際には 出力バッファのフラッシュは行われない。

既にイベントがキューに入っていれば必ず、 XEventsQueuedは I/O を行うことなく即座に復帰する。 モードが QueuedAfterFlushである XEventsQueuedの動作は XPendingと全く同じである。 モードが QueuedAlreadyである XEventsQueuedは関数 XQLengthと全く同じである。

ペンディングされているイベントの個数を得るには、 XPendingを用いる。

int XPending(display)
Display *display;
display
X サーバへの接続を指定する。

関数 XPendingは、X サーバが既に受け取っているが、イベントキューからはまだ削除されて いないイベントの個数を返す。 XPendingは、モードに QueuedAfterFlushを指定している XEventsQueuedと同じである。

イベントキューの操作

Xlib にはイベントキューを操作するための関数が用意されている。 この章では以下のことを行う方法を説明する:

次のイベントの返却

次のイベントを取得し、これをイベントキューから削除するには、 XNextEventを用いる。

XNextEvent(display, event_return)
Display *display;
XEvent *event_return;
display
X サーバへの接続を指定する。
event_return
イベントキューに入っている次のイベントが返される。

関数 XNextEventは、イベントキューに入っている最初のイベントを XEvent構造体にコピーし、このイベントをキューから削除する。 イベントキューが空の場合、 XNextEventは出力バッファをフラッシュし、イベントを 1 つ受け取るまでブロックされる。

イベントキューの内容を調べるには XPeekEventを用いる。

XPeekEvent(display, event_return)
Display *display;
XEvent *event_return;
display
X サーバへの接続を指定する。
event_return
マッチするイベントに対応する構造体のコピーを返す。

関数 XPeekEventはイベントキューの最初のイベントを返すが、このイベントはキューからは削 除されない。 キューが空の場合、 XPeekEventは出力バッファをフラッシュし、イベントを 1 つ受け取るまでブロックされる。 それから XPeekEventはこのイベントをクライアントが用意した XEvent構造体にコピーする。この際に、このイベントがイベントキューから消される ことはない。

述語手続きを用いたイベントの選択

この章で説明する関数にはそれぞれ、述語手続きを渡す必要がある。述語手続 きとは、あるイベントが希望するイベントにマッチするかどうかを決める手続き である。 用意した述語手続きは、そのイベントが使えるかどうかを Xlib の関数を全 く呼び出すことなく決めなければならない。 述語手続きがイベントキューの状態を直接・間接的に変える場合、その結果は 未定義である。 Xlib がスレッド対応するように初期化されていると、述語手続きはロックさ れているディスプレイを使って呼び出されるので、呼び出し側が最初に XLockDisplayを呼んでいなければ、ディスプレイをロックしている Xlib の関数を述語手続き から呼び出した結果は定義されていない。

述語手続きとこれに対応する引き数を以下に示す:

Bool (*predicate)(display, event, arg)
Display *display;
XEvent *event;
XPointer arg;
display
X サーバへの接続を指定。
event
XEvent構造体を指定。
arg
関数 XIfEvent ,XCheckIfEvent ,XPeekIfEvent のいずれかから渡された引き数を指定。

述語手続きは、マッチするのものが見つかるまで、 キューに入っているイベント 1 つごとに 1 回呼び出される。 マッチするものが見つかると、述語手続きは Trueを返さなければならない。 マッチするものが見つからないと、述語手続きは Falseを返さなければならない。

イベントキューを調べてマッチするイベントを探し、マッチするイベントがあっ た場合にはそのイベントをキューから削除するには、 XIfEventを使う。

XIfEvent(display, event_return, predicate, arg)
Display *display;
XEvent *event_return;
Bool (*predicate)();
XPointer arg;
display
X サーバへの接続を指定する。
event_return
マッチしたイベントに対応する構造体が返される。
predicate
キューに入っているイベントが欲しいイベントであるかどうかを決める際に呼 び出す手続きを指定する。
arg
述語手続きに渡される、ユーザ指定の引き数を指定する。

関数 XIfEventが終了するのは、あるイベントに対して、指定された述語手続きが True を返した時だけである。これはキューに入っているイベントがマッチしたこと を示す。 XIfEventがさらなるイベントを待ってブロックされている場合には、 XIfEventは出力バッファをフラッシュする。 XIfEventはマッチするイベントをキューから削除し、そのイベント構造体を クライアントが与えた XEvent構造体にコピーする。

ブロックされることなく、イベントキューを調べてマッチするイベントを探す には、 XCheckIfEventを使う。

Bool XCheckIfEvent(display, event_return, predicate, arg)
Display *display;
XEvent *event_return;
Bool (*predicate)();
XPointer arg;
display
X サーバへの接続を指定する。
event_return
マッチするイベントに対応する構造体のコピーが返される。
predicate
キューに入っているイベントが欲しいイベントであるかどうかを決める際に呼 び出す手続きを指定する。
arg
述語手続きに渡される、ユーザ指定の引き数を指定する。

マッチするものを述語手続きが見つけると、 XCheckIfEventはマッチしたイベントをクライアントが与えた XEvent構造体にコピーして Trueを返す。 (このイベントはイベントキューから削除される。) マッチするものを述語手続きが見つけられなかった場合には、 XCheckIfEventFalseを返し、出力バッファをフラッシュする。 これ以前にイベントキューに入っていたイベントが破棄されることは全くない。

イベントキューを調べ、イベントキューからイベントを消すことなくマッチす るイベントを探すには、 XPeekIfEventを使う。

XPeekIfEvent(display, event_return, predicate, arg)
Display *display;
XEvent *event_return;
Bool (*predicate)();
XPointer arg;
display
X サーバへの接続を指定する。
event_return
マッチするイベントに対応する構造体のコピーが返される。
predicate
イベントキューに入っている次のイベントが欲しいイベントかどうかを調べる ために呼び出す手続きを指定する。
arg
述語手続きに渡すためにユーザが与える引き数を指定する。

関数 XPeekIfEventが復帰するのは、指定された述語手続きが、 あるイベントに対して Trueを返した時だけである。 マッチするものを述語手続きが見つけた後は、 XPeekIfEventはマッチしたイベントをクライアントが用意した XEvent構造体にコピーする。この際にイベントがイベントキューから削除されること はない。 XPeekIfEventは、追加のイベントを待ってブロックされている場合、出力バッファを フラッシュする。

ウィンドウまたはイベントマスクを用いたイベントの選択

この章で説明する関数を使うと、ウィンドウまたはイベント型によってイベン トを選択することができ、乱雑なイベントを処理することができる。

次のイベントがウィンドウにもイベントマスクにもマッチする場合、これを削 除するには XWindowEventを使う。

XWindowEvent(display, w, event_mask, event_return)
Display *display;
Window w;
long event_mask;
XEvent *event_return;
display
X サーバへの接続を指定する。
w
ウィンドウを指定する。 このウィンドウで起こったイベントに注目する。
event_mask
イベントマスクを指定する。
event_return
マッチしたイベントに対応する構造体が返される。

関数 XWindowEventはイベントキューを調べ、指定されたウィンドウとイベントマスクの両方に マッチするイベントを見つける。 マッチするものが見つかると、 XWindowEventはそのイベントをイベントキューから削除し、 指定された XEvent構造体にこれをコピーする。 キューに入っている他のイベントが破棄されることはない。 マッチするイベントがキューに入っていなければ、 XWindowEventは出力バッファをフラッシュし、マッチするイベントを受け取るまでブロック される。

次のイベントで、ウィンドウと(もしあれば)イベントマスクの両方にマッチす るものを削除するには XCheckWindowEventを使う。 この関数は XWindowEvent と似ているが、ブロックされることがなく、イベントが返されたかどうかを示す Bool 値を返す点が異なる。

Bool XCheckWindowEvent(display, w, event_mask, event_return)
Display *display;
Window w;
long event_mask;
XEvent *event_return;
display
X サーバへの接続を指定する。
w
ウィンドウを指定する。 このウィンドウのイベントに注目する。
event_mask
イベントマスクを指定する。
event_return
マッチするイベントに対応する構造体が返される。

関数 XCheckWindowEventはイベントキュー、そしてその後にサーバとの接続上で取得できるイベントを 調べ、指定されたウィンドウとイベントマスクにマッチする最初のイベントを 探す。 マッチするものが見つかれば XCheckWindowEventはそのイベントを削除し、指定された XEvent構造体にこれをコピーし、 Trueを返す。 キューに入っている他のイベントが破棄されることはない。 要求されたイベントが取得できない場合は、 XCheckWindowEventFalseを返し、出力バッファをフラッシュする。

次のイベントのうち、イベントマスクにマッチするものを削除するには XMaskEventを使う。

XMaskEvent(display, event_mask, event_return)
Display *display;
long event_mask;
XEvent *event_return;
display
X サーバへの接続を指定する。
event_mask
イベントマスクを指定する。
event_return
マッチするイベントに対応する構造体が返される。

関数 XMaskEventはイベントキューを調べ、指定されたマスクに対応するイベントを探す。 マッチするものが見つかると、 XMaskEventはそのイベントを削除し、指定された XEvent構造体にこれをコピーする。 キューに入っている他のイベントが削除されることはない。 要求されたイベントがキューに入っていなければ、 XMaskEventは出力バッファをフラッシュし、要求されたイベントを受け取るまでブロック される。

次のイベントのうち(もしあれば)イベントマスクにマッチするものを返し、 削除するには XCheckMaskEventを使う。 この関数は XMaskEvent に似ているが、ブロックされることがなく、イベントが返されたかどうかを示す Bool 値を返す点が異なる。

Bool XCheckMaskEvent(display, event_mask, event_return)
Display *display;
long event_mask;
XEvent *event_return;
display
X サーバへの接続を指定する。
event_mask
イベントマスクを指定する。
event_return
マッチするイベントに対応する構造体が返される。

関数 XCheckMaskEventはイベントキュー、そしてその後に X サーバとの接続上で取得できるイベン トを調べ、指定されたマスクにマッチする最初のイベントを探す。 マッチするイベントが見つかると、 XCheckMaskEventはそのイベントを削除し、指定された XEvent構造体にこれをコピーし、 Trueを返す。 キューに入っている他のイベントが削除されることはない。 要求されたイベントを取得することができなければ、 XCheckMaskEventFalseを返し、出力バッファはフラッシュされる。

キューに入っている次のイベントのうち、あるイベント型にマッチするものを 返し、削除するには XCheckTypedEventを用いる。

Bool XCheckTypedEvent(display, event_type, event_return)
Display *display;
int event_type;
XEvent *event_return;
display
X サーバへの接続を指定する。
event_type
比較するイベント型を指定する。
event_return
マッチするイベントに対応する構造体が返される。

関数 XCheckTypedEventはイベントキュー、そしてその後に X サーバとの接続上で取得できるイベン トを調べ、指定された型にマッチする最初のイベントを探す。 マッチするイベントが見つかれば、 XCheckTypedEventはそのイベントを削除し、指定された XEvent構造体にこれをコピーし、 Trueを返す。 キューに入っている他のイベントが破棄されることはない。 イベントが取得できなければ、 XCheckTypedEventFalseを返し、出力バッファはフラッシュされる。

キューに入っている次のイベントで、あるイベント型とウィンドウにマッチす るものを返し、削除するには XCheckTypedWindowEventを使う。

Bool XCheckTypedWindowEvent(display, w, event_type, event_return)
Display *display;
Window w;
int event_type;
XEvent *event_return;
display
X サーバへの接続を指定する。
w
ウィンドウを指定する。
event_type
比較するイベント型を指定する。
event_return
マッチするイベントに対応する構造体が返される。

関数 XCheckTypedWindowEventはイベントキュー、そしてその後に X サーバとの接続上で取得できるイベン トを調べ、指定された型とウィンドウにマッチする最初のイベントを探す。 マッチするイベントが見つかれば、 XCheckTypedWindowEventはそのイベントをキューから削除し、指定された XEvent構造体にこれをコピーし、 Trueを返す。 キューに入っている他のイベントが破棄されることはない。 イベントが取得できなければ、 XCheckTypedWindowEventFalseを返し、出力バッファはフラッシュされる。

イベントをキューに戻す

イベントをイベントキューに戻すには XPutBackEventを使う。

XPutBackEvent(display, event)
Display *display;
XEvent *event;
display
X サーバへの接続を指定する。
event
イベントを指定する。

関数 XPutBackEventはイベント 1 つをディスプレイのイベントキューに戻す。これはイベントを キューにコピーすることによって行う。 この関数が便利なのは、イベントを読み込んだ後で、そのイベントを後で処理 しようと決めた時である。 XPutBackEventを繰り返して呼び出す回数の制限はない。

他のアプリケーションへのイベントの送信

イベント 1 つを指定されたウィンドウに送るには XSendEventを使う。 この関数はセレクションを処理する時によく使われる。 例えばセレクションの所有者は、セレクションが変換されプロパティとして 格納されたとき、 XSendEventを使って SelectionNotifyイベントをリクエスト側に送る。

Status XSendEvent(display, w, propagate, event_mask, event_send)
Display *display;
Window w;
Bool propagate;
long event_mask;
XEvent *event_send;
display
X サーバへの接続を指定する。
w
イベントの送り先となるウィンドウ、 PointerWindow ,InputFocusのいずれかを指定する。
propagate
Bool 値を指定する。
event_mask
イベントマスクを指定する。
event_send
送るイベントを指定する。

関数 XSendEventは送り先のウィンドウを識別し、指定されたイベントをどのクライアントが受 け取るべきかを決め、全ての能動的グラブを無視する。 この関数にはイベントマスクを渡さなければならない。 有効なイベントマスクの名称については、10.3 節を参照すること。 この関数は引き数 w を使って、以下のように送り先ウィンドウを識別する:

指定されたイベントを受け取るクライアントを決めるため、 XSendEventは引き数 propagate を以下のように用いる:

XEvent構造体が持つイベントは、コアイベントのいずれかか、あるいは拡張によって 定義されているイベントのいずれかでなければならない(さもなくば BadValueエラーとなる)。これは、X サーバが必要に応じて構造体の内容を正しく バイト交換できるようにするためである。 これ以外の場合には、イベントの内容を X サーバが変更したり調べることは ない。 ただし例外として、イベントを転送する時に send_event を Trueにすることや、イベントのシリアル番号を正しく設定することがある。 したがって、 XSendEventはこれらのフィールドや display フィールドを無視する。

XSendEventは通信プロトコル形式への変換が失敗すると 0 を返し、それ以外の場合に は 0 でない値を返す。

XSendEventはエラー BadValue ,BadWindow を起こすことがある。

ポインタの動作履歴の取得

一部の X サーバの実装は、ポインタの動作履歴について、イベント通知によっ て報告されるよりも多くの履歴を管理している。 ポインタのハードウェアが割り込みを起こした際のポインタの位置は、後で 取得するためにバッファに格納される。 このバッファは動作履歴バッファと呼ばれる。 例えばお絵描きプログラムのような一部のアプリケーションでは、ポインタが 通った軌跡に関する正確な履歴が必要である。 しかし大抵のアプリケーションにとっては、このような履歴情報はまったく 余計である。

動作バッファのおおよその最大要素数を決めるには XDisplayMotionBufferSizeを使う。

unsigned long XDisplayMotionBufferSize(display)
Display *display;
display
X サーバへの接続を指定する。

サーバによっては、ポインタの動作の最近の履歴を保持し、 MotionNotifyイベントが通知するよりも細かい粒度で履歴を通知することができる。 関数 XGetMotionEventsはこの履歴を利用可能にする。

指定されたウィンドウと時間に関して動作履歴を得るには、 XGetMotionEventsを使う。

XTimeCoord *XGetMotionEvents(display, w, start, stop, nevents_return)
Display *display;
Window w;
Time start, stop;
int *nevents_return;
display
X サーバへの接続を指定する。
w
ウィンドウを指定する。
start

stop
イベントが動作履歴バッファから返される時刻の範囲を指定する。 タイムスタンプまたは CurrentTimeを指定することができる。
nevents_return
動作履歴バッファから返されたイベント数が返される。

関数 XGetMotionEventsは、指定された開始時刻と終了時刻の間にあり(開始時刻と終了時刻も含む)、 かつ座標が指定されたウィンドウの現在位置の内部(境界を含む)にある全ての イベントを動作履歴バッファから返す。 サーバが動作履歴をサポートしていない場合、開始時刻が終了時刻よりも早い 場合、開始時刻が未来である場合には、イベントは全く返されない。 この場合には XGetMotionEventsは NULL を返す。 終了時刻に未来を指定するのは CurrentTimeを指定することと同じである。 この関数の返り値の型は、以下の定義を持つ構造体である:

typedef struct {
	Time time;
	short x, y;
} XTimeCoord;

time メンバには時間が設定される。単位はミリ秒である。 x, y メンバにはポインタの座標が設定される。この座標は指定された ウィンドウに関する座標で通知される。 この関数が返すデータを解放するには XFreeを使う。

XGetMotionEventsはエラー BadWindow を起こすことがある。

プロトコルエラーの処理

Xlib には、同期の有効・無効を設定したり、デフォルトのエラーハンドラを 使うための関数群が用意されている。

同期の有効・無効の設定

X のアプリケーションのデバッグを行う際には、Xlib を同期的に動作させ、 エラーが起きた時点でこれを報告させるようにすると便利なことが多い。 以下の関数を使うと同期動作の有効・無効を設定することができる。 同期を有効にすると、グラフィックスの速度は 30 倍あるいはそれ以上遅くな る場合があるので注意すること。 POSIX 準拠のシステムには _Xdebug というグローバル変数も用意されている。この変数がプログラムをデバッガの 下で実行する前に 0 でない値に設定されていると、ライブラリが同期的に 動作する。

動作を終了した後、プロトコルリクエストを生成した全ての Xlib 関数は、 後処理関数(after function)と呼ばれる関数を呼び出す。 XSetAfterFunctionは、これにより呼び出される関数を設定する。

int (*XSetAfterFunction(display, procedure))()
Display *display;
int (*procedure)();
display
X サーバへの接続を指定する。
procedure
呼び出される手続きを指定する。

指定された手続きは、ディスプレイへのポインタだけを引き数にして 呼び出される。 XSetAfterFunctionは、以前の後処理関数を返す。

同期動作の有効・無効を設定するには、 XSynchronizeを使う。

int (*XSynchronize(display, onoff))()
Display *display;
Bool onoff;
display
X サーバへの接続を指定する。
onoff
同期動作の有効・無効を指示する Bool 値を指定する。

XSynchronizeは以前の後処理関数を返す。 onoff が Trueならば、 XSynchronizeは同期動作を有効にする。 onoff が Falseならば、 XSynchronize は同期動作を無効にする。

デフォルトのエラーハンドラの使用

Xlib には、デフォルトのエラーハンドラが 2 つ用意されている: 一方は通常、致命的な状態(例えば、マシンのクラッシュ等により ディスプレイサーバへの接続が切れた場合等)を扱い、もう一方は X サーバか らのプロトコルエラーを扱う。 ユーザ独自のエラー処理を行いたければ、これらのエラーハンドラをユーザが 用意した関数に変更することができる。変更は何度でも行うことができる。 それぞれの関数にヌルポインタが渡された場合、デフォルトのハンドラが再び 設定される。 デフォルトのハンドラの動作は、説明のメッセージを表示し、プログラムを終 了させるというものである。

エラーハンドラを設定するには XSetErrorHandlerを使う。

int (*XSetErrorHandler(handler))()
int (*handler)(Display *, XErrorEvent *)
handler
プログラムに用意されているエラーハンドラを指定する。

Xlib は一般的に、エラーを受信すると必ず、プログラムに用意されている エラーハンドラを呼び出す。 このエラーハンドラは、 OpenFont ,LookupColor ,AllocNamedColorプロトコルリクエストによって起きた BadNameエラーや、 QueryFontプロトコルリクエストによって起きた BadFontエラーに関しては呼び出されない。 これらのエラーは一般的に、手続きインタフェースを通してプログラムに反映 される。 この状態は致命的でないものと考えられるので、ユーザが用意した エラーハンドラが復帰することが認められる。 この場合の返り値は無視される。 しかしエラーハンドラは、プロトコルリクエストを生成したり、入力イベント を要求するディスプレイを使うどんな関数も(直接・間接的に係わらず)呼び出 してはならない。 返り値は以前のエラーハンドラである。

XErrorEvent構造体の内容を以下に示す:

typedef struct {
	int type;
	Display *display;	/* イベントが読み出されたディスプレイ */
	unsigned long serial;		/* 失敗したリクエストのシリアル番号 */
	unsigned char error_code;	/* 失敗したリクエストのエラーコード */
	unsigned char request_code;	/* 失敗したリクエストのメジャーオペコード */
	unsigned char minor_code;	/* 失敗したリクエストのマイナーオペコード */
	XID resourceid;		/* リソース ID */
} XErrorEvent;

シリアル番号はリクエストの番号である。これは 1 から始まる数値で、 ネットワーク接続が始まって以降、ネットワーク接続上で送られる。 これは、失敗した呼び出しの直前に NextRequest を呼び出していれば得られた値である。 request_code メンバは失敗した手続きのプロトコルリクエストであり、 <X11/Xproto.h>で定義されている。 この章で説明した関数は、以下のエラーコードを返すことがある:
.ne 13

エラーコード 説明
BadAccess 他のクライアントが既にグラブしているキーやボタンの組合せをグラブしようとした。まだ割り当てられていないカラーマップエントリを解放しようとしたか、全てのエントリを書き込み可能にして生成したカラーマップエントリを解放しようとした。読み取り専用、あるいは割り当てられていないカラーマップエントリ内に書き込みしようとした。ローカルホスト(または認可されたホスト)以外のホストから、アクセス制御リストを変更しようとした。他のクライアントが既に選択しているイベント型を選択しようとした。
BadAlloc 要求されたリソースの割り当てにサーバが失敗した。リクエストで明示的に列挙されるBadAllocエラーは、非常に粗いレベルでの割り当てエラーしか網羅していない。またこれは、サーバがサービスの途中に割り当て用の空間を使い果たす全ての場合を網羅するためのものではない(網羅することを実際に期待することもできない)。サーバが割り当て用の空間を使い果たした際のセマンティクスの仕様は決められていないが、どんなリクエストの場合にもこれが原因でサーバがBadAllocエラーを生成する可能性がある。したがってクライアントはこのようなエラーを受け取る用意をしておき、これらを処理または破棄しなければならない。
BadAtom アトム型の引き数に指定された値が、定義されているアトムを指していない。
BadColor カラーマップ型の引き数に指定された値が、定義されているカラーマップを指していない。
BadCursor カーソル型の引き数に指定された値が、定義されているカーソルを指していない。
BadDrawable ドロウアブル型の引き数に指定された値が、定義されているドロウアブルを指していない。
BadFont フォント型の引き数に指定された値が、定義されているフォント(場合によってはGContext)を指していない。
BadGC GContext 型の引き数に指定された値が、定義されているGContextを指していない。
BadIDChoice リソース識別子に選ばれた値が、クライアントに割り当てられた範囲に含まれていないか、既に使用されている。通常の環境ではこのエラーが起こることはなく、サーバまたは Xlib のエラーと考えられる。
BadImplementation リクエストの何らかの機能をサーバが実装していない。コアリクエストに対してこのエラーを生成するサーバには欠陥がある。このように、このエラーはどのリクエストでも列挙されないが、クライアントはこのようなエラーを受け取って、処理または破棄できるようにしておかなければならない。
BadLength リクエストの長さが、引き数を保持するのに要求される長さよりも短すぎるか、あるいは長すぎる。これは Xlib 内部またはサーバのエラーである。リクエストの長さが、サーバが許す最大長を超えている。
BadMatch グラフィックスリクエストにおいて、ルートまたはグラフィックスコンテクストの深さが、ドロウアブルの深さと一致していない。InputOnly ウィンドウがドロウアブルとして使われた。引き数、または引き数の組が正しい型と範囲を持っているが、リクエストが要求する別の条件に適合できなかった。InputOnly ウィンドウにこの属性が欠けている。
BadName 指定された名前のフォントまたは色が存在しない。
BadPixmap ピックスマップ型の引き数が、定義されているピックスマップを指していない。
BadRequest メジャーオペコードまたはマイナーオペコードが、有効なリクエストを指定していない。これは通常、Xlib またはサーバのエラーである。
BadValue 一部の数値の値が、リクエストが認める範囲を超えている。ある引き数に対して特定の範囲が指定されていなければ、引き数の型で定義されている全ての範囲が許される。選択肢として定義されている全ての引き数は普通、(符号化のために)このエラーを生成する可能性がある。
BadWindow ウィンドウ型の引き数に指定された値が、定義されているウィンドウを指していない。
注意: エラー BadAtom , BadColor , BadCursor , BadDrawable , BadFont , BadGC , BadPixmap , BadWindowは、固定された選択肢によって引き数の型が拡張された時にも使われる。

指定されたエラーコードについての、文章による説明を得るには、 XGetErrorTextを使う。

XGetErrorText(display, code, buffer_return, length)
Display *display;
int code;
char *buffer_return;
int length;
display
X サーバへの接続を指定する。
code
説明を得たいエラーコードを指定する。
buffer_return
エラーの説明が返される。
length
バッファの大きさを指定する。

関数 XGetErrorTextは指定されたエラーコードを説明し、NULL で終わる文字列を指定されたバッ ファにコピーする。 返されるテキストのエンコーディングは、現在のロケールのエンコーディング となる。 エラーの説明を取得する際にはこの関数を使うことが望ましい。というのも、 Xlib に対する拡張では、独自のエラーコードとエラー文字列を定義すること があるからである。

エラーデータベースからエラーメッセージを取得するには XGetErrorDatabaseTextを使う。

XGetErrorDatabaseText(display, name, message, default_string, buffer_return, length)
Display *display;
char *name, *message;
char *default_string;
char *buffer_return;
int length;
display
X サーバへの接続を指定する。
name
アプリケーションの名前を指定する。
message
エラーメッセージの型を指定する。
default_string
データベース内で何も見つからない場合の、デフォルトのエラーメッセージを 指定する。
buffer_return
エラーの説明が返される。
length
バッファの大きさを指定する。

関数 XGetErrorDatabaseTextは、NULL 文字で終わるメッセージ(またはデフォルトのメッセージ)を エラーメッセージデータベースから 返す。 Xlib はこの関数を内部的に使って、エラーメッセージを探す。 引き数 default_string のテキストのエンコーディングは、現在のロケールの エンコーディングとして扱われ、引き数 buffer_return に格納されるテキス トのエンコーディングは、現在のロケールのエンコーディングとなる。

引き数 name は普通、使っているアプリケーションの名前にしなければならな い。 引き数 message は、要求するエラーメッセージの型を示していなければならない。 引き数 name と message の名前のエンコーディングが ホストポータブル文字集合でない場合、結果は実装依存である。 Xlib は、予め定義されている 3 つの「アプリケーション名」を使ってエラー を報告する。 この名前においては、大文字と小文字は区別される。

XProtoError
プロトコルエラー番号は、message 引き数のための文字列として使われる。
XlibMessage
これらは、ライブラリが内部的に使うメッセージ用文字列である。
XRequest
コアプロトコルリクエストの場合、メジャーリクエストプロトコル番号は 引き数 message に対して使われる。 拡張リクエストの場合は、拡張名(これは InitExtensionで与えられる )の後にピリオド (\.) とマイナーリクエストプロトコル番号を 続けたものが引き数 message に対して使われる。 エラーデータベースで文字列が見つからなかった場合は、 引き数 default_string が引き数 buffer_return に返される。

リクエストされたディスプレイが存在しないときにユーザにエラーを報告する には XDisplayNameを使う。

char *XDisplayName(string)
char *string;
string
文字列を指定する。

関数 XDisplayNameは、 XOpenDisplayが使おうとするディスプレイの名前を返す。 ヌル文字列が指定された場合、 XDisplayNameは環境変数 DISPLAY を参照し、 XOpenDisplayが使おうとするはずのディスプレイ名を返す。 これにより、初期接続の試みが失敗した時にプログラムがオープンしようとし ていたディスプレイをユーザに報告することが容易となる。

致命的な I/O エラーを処理するには XSetIOErrorHandlerを用いる。

int (*XSetIOErrorHandler(handler))()
int (*handler)(Display *);
handler
プログラムに用意されているエラーハンドラを指定する。

関数 XSetIOErrorHandlerは致命的な I/O エラー用のエラーハンドラを設定する。 何らかのシステムコールがエラーを起こした場合、Xlib はプログラムに用意 されているエラーハンドラを呼び出す。 これは致命的な状態であると考えられるので、呼び出された関数は復帰すべき ではない。 I/O エラーハンドラが復帰した場合には、クライアントのプロセスは終了する。

この関数は以前のエラーハンドラを返す点に注意すること。


目次に戻る