Как уже отмечалось выше в 3.1.3., каждое приложение вызывает процедуру XtAppMainLoop( ) или XtMainLoop( ) для организации процесса получения и рассылки событий. Данные процедуры, в свою очередь, вызывают две процедуры XtAppNextEvent( ) (XtNextEvent( )) и XtDispatchEvent( ). Другими словами работа XtAppMainLoop( ) эквивалентна следующей последовательности операторов:
. . . . . . .
XtAppContext prAppContext
. . . . . . .
for ( ; ; ) {
XEvent rEvent;
XtAppNextEvent (prAppContext, &rEvent);
XtDispatchEvent (&rEvent);
}
. . . . . . .
|
Процедура XtAppNextEvent( ) имеет прототип:
void XtAppNextEvent (XtAppContext prAppContext,
XEvent *prEvent);
|
Здесь prAppContext - это контекст приложения, а второй аргумент используется для хранения информации о следующем событии в очереди событий программы. (XtNextEvent( ) отличается только тем, что отсутствует аргумент prAppContext).
Работает XtAppNextEvent( ) так: если в очереди первым идет событие о готовности данных в файле (внешнем устройстве), или там находится событие, инициирующее вызов соответствующей таймер-процедуры, то вызывается процедура (процедуры), зарегистрированные с помощью процедур XtAppAddInput( ) (XtAddInput( )) или XtAppAddTimeOut( ) (XtAddTimeOut( )). Если никаких событий в очереди нет, то вызываются work-процедуры, зарегистрированные процедурой XtAppAddWorkProc( ). Если же в очереди есть событие от сервера, то XtAppNextEvent( ) удаляет его из очереди и переносит в структуру, на которую указывает ее второй аргумент.
Процедура XtDispatchEvent( ) имеет прототип:
void XtDispatchEvent (XEvent *prEvent);
|
Она анализирует событие и вызывает соответствующую callback-процедуру, action-процедуру или обработчик событий. Если таковых нет, то событие игнорируется. Если для события зарегистрировано несколько event handler или action-процедур, то порядок их выполнения не определен.
Каждое приложение может модифицировать описанный цикл получения и рассылки (обработки) событий. Ниже приводится фрагмент кода, показывающий, как это можно сделать:
void MyMainLoop (XtAppContext prAppContext)
{
XEvent prEvent;
. . . . . . .
for ( ; ; )
{
XtAppNextEvent (prAppContext, &prEvent);
. . . . . . .
/* Предобработка события */
. . . . . . .
XtDispatchEvent (&prEvent);
. . . . . . .
/* Постобработка события */
. . . . . . .
}
}
|
Xt предусматривает целый набор процедур для работы с очередью событий. Например, функция XtAppPeekEvent( ) позволяет получить информацию о следующем событии без удаления его из очереди. Процедура имеет следующий прототип:
Boolean XtAppPeekEvent (XtAppContext prAppContext,
XEvent *prEvent);
|
Здесь prAppContext - это контекст приложения; второй аргумент используется для хранения информации о следующем событии в очереди. Функция возвращает True, если событие в очереди есть X событие, в противном случае (т.е., если это событие, инициирующее вызов соответствующей таймер-процедуры, или какое-либо другое событие) возвращается False. Событие из очереди не удаляется.
Процедура XtAppProcessEvent( ) позволяет, задавая маску событий, выбирать из очереди нужные события и обрабатывать их. Функция имеет следующий прототип:
void XtAppProcessEvent (XtAppContext prAppContext,
XtInputMask nMask);
|
Здесь первый аргумент задает контекст приложения. Второй аргумент определяет маску событий, при этом последняя может состоять из одной или нескольких констант, разделенных оператором OR ( | ). Указанные константы следующие:
XtIMXEvent | - X событие |
XtIMTimer | - событие, инициирующее вызов таймер-процедуры |
XtIMAlternateInput | - событие о готовности данных |
XtIMAll | - все события. |
Аналогичные описанным выше процедурам функции XtPeekEvent( ) и XtProcessEvent( ) отличаются только отсутствием аргумента prAppContext. Более подробную информацию о приведенных и других функциях, позволяющих работать с событиями в очереди, можно найти например в [9, 10].