イベントについて
クライアントが X 関数を使って、X サーバーに対して何らかの要求をした場合、そのリクエストはまず、Xlib 内の出力バッファに追加されます。
クライアントが XFlush 関数 や、XFlush を内部で呼び出す XNextEvent などの関数を実行した場合、出力バッファはフラッシュされ、X サーバーにまとめて送信されます。
X サーバーはそのリクエストを受信した後、実際にリクエストを処理していきます。
X サーバーが受信したリクエストを処理した後、クライアントに対して、何らかのイベント通知が必要になる場合は、そのイベントを、クライアントのイベントキューに追加します。
クライアントは、イベントループ内で XNextEvent 関数などを使うことで、キューにあるイベントを順次読み込み、処理していきます。
クライアントが XFlush 関数 や、XFlush を内部で呼び出す XNextEvent などの関数を実行した場合、出力バッファはフラッシュされ、X サーバーにまとめて送信されます。
X サーバーはそのリクエストを受信した後、実際にリクエストを処理していきます。
X サーバーが受信したリクエストを処理した後、クライアントに対して、何らかのイベント通知が必要になる場合は、そのイベントを、クライアントのイベントキューに追加します。
クライアントは、イベントループ内で XNextEvent 関数などを使うことで、キューにあるイベントを順次読み込み、処理していきます。
イベントマスク
ウィンドウが各イベントを受け取るためには、まず、ウィンドウに対して、必要なイベントのマスクを設定する必要があります。
これを設定していないと、ほとんどのイベントは送られてきません。
(一部のイベントは、イベントマスクに関係なく、常に送られてきます)
ウィンドウの作成時に、XSetWindowAttributes 構造体の event_mask メンバで指定するか、XSelectInput 関数でイベントマスクを変更することができます。
指定ウィンドウのイベントマスクを変更 (上書き) します。
これを設定していないと、ほとんどのイベントは送られてきません。
(一部のイベントは、イベントマスクに関係なく、常に送られてきます)
ウィンドウの作成時に、XSetWindowAttributes 構造体の event_mask メンバで指定するか、XSelectInput 関数でイベントマスクを変更することができます。
XSelectInput 関数
void XSelectInput(Display *display, Window w, long event_mask);
指定ウィンドウのイベントマスクを変更 (上書き) します。
イベントマスクの値
NoEventMask | イベントマスクなし |
---|---|
KeyPressMask | キーが押された時 |
KeyReleaseMask | キーが離された時 |
ButtonPressMask | ポインタボタンが押された時 |
ButtonReleaseMask | ポインタボタンが離された時 |
EnterWindowMask | ポインタがウィンドウ上で表示される状態になった |
LeaveWindowMask | ポインタがウィンドウ上に表示されなくなった |
PointerMotionMask | ポインタの位置が移動した時 (ボタンが押されていない場合) |
PointerMotionHintMask | 特定のタイミングでのみ、ポインタ移動のイベントを送る。 他の Motion マスクと共に選択されている場合、次のいずれかが行われた時のみ、MotionNotify イベントが1つだけ送られる。 (この時、XMotionEvent 構造体の is_hint メンバーは、NotifyHint に設定されている) ・キーまたはボタンの状態が変化した時。 ・ポインタがウィンドウ上で表示された時。 ・クライアントが XQueryPointer を呼び出して、ポインタの位置を参照した時。 |
Button1MotionMask | ボタン1が押されている間のポインタ移動 |
Button2MotionMask | ボタン2〃 |
Button3MotionMask | ボタン3〃 |
Button4MotionMask | ボタン4〃 |
Button5MotionMask | ボタン5〃 |
ButtonMotionMask | 1つ以上のボタンが押されている間のポインタ移動 |
KeymapStateMask | 各キーの押し状態の取得 |
ExposureMask | 描画関連 |
VisibilityChangeMask | ウィンドウの可視性が変化した時 |
StructureNotifyMask | ウィンドウの構造が変化した時 |
ResizeRedirectMask | ウィンドウのサイズ変更をリダイレクトする |
SubstructureNotifyMask | 子ウィンドウの構成が変化した時 |
SubstructureRedirectMask | 子ウィンドウの構成変更をリダイレクトする |
FocusChangeMask | 入力フォーカスの変更時 |
PropertyChangeMask | プロパティの変更時 |
ColormapChangeMask | カラーマップの変更時 |
OwnerGrabButtonMask | このマスクがある場合、ボタンが押された時に、X サーバーによって行われる自動グラブについて、XGrabPointer() の owner_events 引数を True に指定してグラブする。 グラブ中、このクライアントがポインタイベントを処理する対象の場合は通常通りのイベントとして送り、他のクライアントが対象となるポインタイベントであれば、グラブウィンドウに送る。 |
イベントの構造体
イベントは、XEvent 共用体で情報を取得できます。
XEvent はこのように、各イベントタイプ別の構造体がすべて収まるような共用体になっているので、実際に使う時は、xev.xbutton.button というような形で参照するか、XEvent のポインタを各構造体のポインタに型変換して使います。
XAnyEvent は、すべてのイベントに含まれている先頭の値が定義されています。
typedef union _XEvent { int type; XAnyEvent xany; XKeyEvent xkey; XButtonEvent xbutton; XMotionEvent xmotion; XCrossingEvent xcrossing; XFocusChangeEvent xfocus; XExposeEvent xexpose; XGraphicsExposeEvent xgraphicsexpose; XNoExposeEvent xnoexpose; XVisibilityEvent xvisibility; XCreateWindowEvent xcreatewindow; XDestroyWindowEvent xdestroywindow; XUnmapEvent xunmap; XMapEvent xmap; XMapRequestEvent xmaprequest; XReparentEvent xreparent; XConfigureEvent xconfigure; XGravityEvent xgravity; XResizeRequestEvent xresizerequest; XConfigureRequestEvent xconfigurerequest; XCirculateEvent xcirculate; XCirculateRequestEvent xcirculaterequest; XPropertyEvent xproperty; XSelectionClearEvent xselectionclear; XSelectionRequestEvent xselectionrequest; XSelectionEvent xselection; XColormapEvent xcolormap; XClientMessageEvent xclient; XMappingEvent xmapping; XErrorEvent xerror; XKeymapEvent xkeymap; long pad[24]; } XEvent; typedef struct { int type; unsigned long serial; Bool send_event; Display *display; Window window; } XAnyEvent;
XEvent はこのように、各イベントタイプ別の構造体がすべて収まるような共用体になっているので、実際に使う時は、xev.xbutton.button というような形で参照するか、XEvent のポインタを各構造体のポインタに型変換して使います。
XAnyEvent は、すべてのイベントに含まれている先頭の値が定義されています。
type | イベントのタイプ |
---|---|
serial | プロトコルのシリアル番号 |
send_event | XSendEvent 関数によって、他のクライアントから直接送られたイベントか |
display | イベントを読み込んだディスプレイ |
window | イベントが送られたウィンドウ |
マスクとイベントタイプと構造体
各イベントマスクに対応するイベントタイプ、そのイベントの構造体、そして各イベントで共通して使える構造体のリストは、以下になります。
※ClientMessage、SelectionClear、SelectionRequest、SelectionNotify、MappingNotify イベントには、マスク値がないため、常に送られてきます。
※ClientMessage、SelectionClear、SelectionRequest、SelectionNotify、MappingNotify イベントには、マスク値がないため、常に送られてきます。
イベントマスク | イベントタイプ | 構造体 | 汎用構造体 |
ButtonMotionMask Button1MotionMask Button2MotionMask Button3MotionMask Button4MotionMask Button5MotionMask | MotionNotify | XPointerMovedEvent | XMotionEvent |
---|---|---|---|
ButtonPressMask | ButtonPress | XButtonPressedEvent | XButtonEvent |
ButtonReleaseMask | ButtonRelease | XButtonReleasedEvent | XButtonEvent |
ColormapChangeMask | ColormapNotify | XColormapEvent | - |
EnterWindowMask | EnterNotify | XEnterWindowEvent | XCrossingEvent |
LeaveWindowMask | LeaveNotify | XLeaveWindowEvent | XCrossingEvent |
ExposureMask | Expose | XExposeEvent | - |
グラフィック関数によるイベント | GraphicsExpose NoExpose | XGraphicsExposeEvent XNoExposeEvent | - |
FocusChangeMask | FocusIn FocusOut | XFocusInEvent XFocusOutEvent | XFocusChangeEvent |
KeymapStateMask | KeymapNotify | XKeymapEvent | - |
KeyPressMask | KeyPress | XKeyPressedEvent | XKeyEvent |
KeyReleaseMask | KeyRelease | XKeyReleasedEvent | XKeyEvent |
OwnerGrabButtonMask | - | - | - |
PointerMotionMask | MotionNotify | XPointerMovedEvent | XMotionEvent |
PointerMotionHintMask | - | - | - |
PropertyChangeMask | PropertyNotify | XPropertyEvent | - |
ResizeRedirectMask | ResizeRequest | XResizeRequestEvent | - |
StructureNotifyMask | CirculateNotify ConfigureNotify DestroyNotify GravityNotify MapNotify ReparentNotify UnmapNotify | XCirculateEvent XConfigureEvent XDestroyWindowEvent XGravityEvent XMapEvent XReparentEvent XUnmapEvent | - |
SubstructureNotifyMask | CirculateNotify ConfigureNotify CreateNotify DestroyNotify GravityNotify MapNotify ReparentNotify UnmapNotify | XCirculateEvent XConfigureEvent XCreateWindowEvent XDestroyWindowEvent XGravityEvent XMapEvent XReparentEvent XUnmapEvent | - |
SubstructureRedirectMask | CirculateRequest ConfigureRequest MapRequest | XCirculateRequestEvent XConfigureRequestEvent XMapRequestEvent | - |
- | ClientMessage | XClientMessageEvent | - |
- | MappingNotify | XMappingEvent | - |
- | SelectionClear | XSelectionClearEvent | - |
- | SelectionNotify | XSelectionEvent | - |
- | SelectionRequest | XSelectionRequestEvent | - |
VisibilityChangeMask | VisibilityNotify | XVisibilityEvent | - |
イベントの読み込み関数
イベントキューからイベントを読み込む場合は、以下の関数を使います。
キューにイベントがない場合や、条件に一致するイベントがない場合、自動で出力バッファがフラッシュされます。
イベントが来るまで処理をブロックする関数については、イベントを受け取るまで関数が戻らないので、注意してください。
以下以外にも、イベントの読み込み関数はあります。
キューにあるイベントの数を返します。
キューにイベントがない場合は、出力バッファをフラッシュした後、さらにイベントを読み込み、その数を返します。
0 であれば、現在処理できるイベントはないということです。
キューの最初のイベントをコピーして返します。
キューが空の場合、出力バッファをフラッシュし、イベントが受信されるまでブロックします。
XNextEvent は、キューからイベントを削除します。
XPeekEvent は、キューからイベントを削除しません。
指定した関数でキュー内のイベントを検索し、一致したイベント (関数が True を返したもの) を返します。
XIfEvent は、一致するイベントが見つかるまでブロックし、イベントをキューから削除します。
XCheckIfEvent はブロックせず、イベントが見つからなかった場合は False を返します。見つかったイベントはキューから削除されます。
XPeekIfEvent はブロックしますが、キューからイベントを削除しません。
キューにイベントがない場合や、条件に一致するイベントがない場合、自動で出力バッファがフラッシュされます。
イベントが来るまで処理をブロックする関数については、イベントを受け取るまで関数が戻らないので、注意してください。
以下以外にも、イベントの読み込み関数はあります。
キュー内のイベントの数
int XPending(Display *display);
キューにあるイベントの数を返します。
キューにイベントがない場合は、出力バッファをフラッシュした後、さらにイベントを読み込み、その数を返します。
0 であれば、現在処理できるイベントはないということです。
先頭から読み込み
void XNextEvent(Display *display, XEvent *event_return); void XPeekEvent(Display *display, XEvent *event_return);
キューの最初のイベントをコピーして返します。
キューが空の場合、出力バッファをフラッシュし、イベントが受信されるまでブロックします。
XNextEvent は、キューからイベントを削除します。
XPeekEvent は、キューからイベントを削除しません。
条件一致
void XIfEvent(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg); Bool XCheckIfEvent(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg); void XPeekIfEvent(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg); //比較関数 Bool func(Display *display, XEvent *event, XPointer arg);
指定した関数でキュー内のイベントを検索し、一致したイベント (関数が True を返したもの) を返します。
XIfEvent は、一致するイベントが見つかるまでブロックし、イベントをキューから削除します。
XCheckIfEvent はブロックせず、イベントが見つからなかった場合は False を返します。見つかったイベントはキューから削除されます。
XPeekIfEvent はブロックしますが、キューからイベントを削除しません。