Как уже отмечалось выше в 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].