2.5.2. Общение с менеджером окон.

    Менеджер окон - это специальный клиент, в задачи которого входит интерактивное перемещение окон по экрану, изменение их размеров, минимизация (превращение в пиктограмму) и многое другое. Чтобы облегчить менеджеру его нелегкую жизнь, программам рекомендуется при инициализации сообщить о себе определенную информацию. Передается она через предопределенные "свойства", которые известны менеджеру и могут быть им прочитаны. Некоторые из "свойств" (так называемые "стандартные") задавать обязательно. Все остальное определяется по усмотрению программы. Наиболее простой способ задать стандартные "свойства" - обратиться к процедурам XSetStandardProperties( ) (X11R3 и ниже) или XSetWMProperties( ) (X11R4 и выше ).

    Ниже перечисляются "свойства", создаваемые для менеджера окон программами, а также процедуры для работы с ними.

    Имя (заголовок) окна. Идентифицируется атомом XA_WM_NAME и имеет тип XA_STRING (X11R3 и ниже) или "TEXT" (X11R4 и выше). Данные "свойства" - строка (X11R3 и ниже) или структура XTextProperty (X11R4 и выше). Для задания "свойства" используется процедура XStoreName( ) (XSetWMName( )). Получить его можно с помощью XFetchName( ) (XGetWMName( )).

    Имя пиктограммы. Идентифицируется атомом XA_WM_ICONNAME и имеет тип XA_STRING (X11R3 и ниже) или "TEXT" (X11R4 и выше). Данные "свойства" - строка (X11R3 и ниже) или структура XTextProperty (X11R4 и выше). Для задания "свойства" используется процедура XSetIconName( ) (XSetWMIconName( )). Получить его можно с помощью XGetIconName( ) (XGetWMIconName( )).

    Рекомендации (hints) о геометрии окна. Идентифицируется атомом XA_WM_NORMAL_HINTS и имеет тип XA_WM_SIZE_HINTS. Данные "свойства" - структура типа XSizeHints. Для задания "свойства" используется процедура XSetNormalHints( ). В X11R3 и ниже предусматривались также рекомендации о размерах окна в максимальном (zoomed) состоянии.

    Дополнительные параметры окна: способ работы с клавиатурой, вид и положение пиктограммы. Идентифицируется атомом XA_WM_HINTS и имеет тип XA_WM_HINTS. Данные "свойства" - структура типа XWMHints. Для задания "свойства" используется процедура XSetWMHints( ). В X11R4 и выше структура типа XWMHints, передаваемая функции XSetWMHints( ), должна быть подготовлена с помощью XAllocWMHints( ). Получить данные "свойства" можно с помощью XGetWMHints( ).

    Атрибут, характеризующий "временное" окно. Идентифицируется атомом XA_WM_TRANSIENT_FOR и имеет тип XA_STRING. "Свойство" задается для окон, появляющихся на экране для выполнения вспомогательных функций (диалоги, меню). Такие объекты рассматриваются менеджером по особому. Например, он может не добавлять к окну заголовок и рамку. Данные "свойства" - идентификатор окна родительского по отношению к данному. Задается "свойство" с понощью процедуры XSetTransientForHint( ) (см. подробнее, например [8]Ссылка).

    Имена программы и ее класса, идентифицируется атомом XA_WM_CLASS и имеет тип XA_STRING. Данные "свойства" - структура типа XClassHints. Задается "свойство" с помощью процедуры XSetClassHints( ) и может быть получено с помощью XGetClassHints( ).

    Если окно (окна) программы имеют собственную цветовую палитру, то приложение должно соответствующим образом задать для него атрибут colormap. Далее, в X11R3 и ниже при получении окном фокуса ввода, программа сама обязана перенести логическую палитру в аппаратную. В X11R4 и выше последний шаг выполняется менеджером окон. Программа только эаносит идентификатор окна (идентификаторы окон) в список, ассоциированный со "свойством", имя которого WM_COLORMAP_WINDOWS. Делается это процедурой XSetWMColormapWindows( ). Получить список, уже находящийся в "свойстве", можно, обратившись к XGetWMColormapWindows( ).

    Когда окно открыто, пользователь посредством менеджера совершает над ним разные действия. Программе может быть желательно "перехватывать" некоторые из них. Так, например, если окно представляет собой редактор текста, и пользователь пытается его закрыть, то разумно спросить у сидящего за компьютером человека, а не желает ли он предварительно сохранить результаты редакции. Начиная с X11R4 системой предусматривается "свойство" с именем WM_PROTOCOLS. Оно содержит список атомов, и каждый из них идентифицирует "свойство" , связанное с действиями, о которых надо оповещать программу. Эти "свойства" следующие:

WM_TAKE_FOCUS - задается, если программа хочет передавать фокус ввода между своими окнами самостоятельно; в этом случае менеджер не будет управлять фокусом, ввода, а пошлет приложению событие ClientMessage, у которого поле message_type равно атому, соответствующему "свойству" WM_PROTOCOLS, а поле data.l[0] равно атому, соответствующему "свойству" WM_TAKE_FOCUS; в ответ на это событие программа должна сама обратиться к XSetInputFocus( ) для задания окна, имеющего фокус ввода;

WM_SAVE_YOURSELF - задается, если программа хочет перехватить момент своего завершения; менеджер окон посылает приложению событие ClientMessage, у которого поле message_type равно атому, соответствующему "свойству" WM_PROTOCOLS, а поле data.l[0] равно атому, соответствующему "свойству" WM_SAVE_YOURSELF; в ответ программа может сохранить свое текущее состояние;

WM_DELETE_WINDOW - задается, если программа хочет перехватить моменты, когда менеджер окон закрывает принадлежащие ей окна; менеджер окон посылает приложению событие ClientMessage, у которого поле message_type равно атому, соответствующему "свойству" WM_PROTOCOLS, а поле data.l[0] равно атому, соответствующему "свойству" WM_DELETE_WINDOW; далее программа сама решает, оставить окно на экране или удалить его с помощью XDestroyWindow( ).

    "Свойство" WM_PROTOCOLS задается процедурой XSetWMProtocols( ) и может быть получено с помощью XGetWMProtocols( ) (см. приложение 1 Ссылка).

    Приведем фрагмент программы, задающей "свойство" WM_PROTOCOLS и производящей соответствующую обработку событий.

. . . . . . .
Display		*prDisplay;
int		nScreenNum;
GC		prGC;
XEvent		rEvent;
Window		nWnd;
Atom		pnProtocol[2];
Atom		nWMProtocols;

/*
 *Устанавливаем связь с сервером, получаем номер экрана,
 *создаем окно, выбираем события, обрабатываемые программой
 */
. . . . . . .

/* Задаем свойство WM_PROTOCOLS */

pnProtocol [0] = XInternAtom (prDisplay,
		     "WM_TAKE_FOCUS", True);

pnProtocol [1] = XInternAtom (prDisplay,
		     "WM_SAVE_YOURSELF", True);

nWMProtocols = XInternAtom (prDisplay, "WM_PROTOCOLS", True);

XSetWMProtocols (prDisplay, nWnd, pnProtocol, 2);

/* Показываем окно */

XMapWindow (prDisplay, nWnd);

/* Цикл получения и обработки событий */

while (1)  {
     XNextEvent (prDisplay, &rEvent);

switch (rEvent.type)  {
    . . . . . .
    case ClientMessage :
    if (rEvent.xclient.message_type == nWMProtocols)
    {
       if (rEvent.xclient.data.l[0] == pnProtocol[0])
          puts ("Receiving the input focus.\n");
       else
          if (rEvent.xclient.data.l[0] == pnProtocol[1])
          {
	XCloseDisplay (prDisplay);
	exit (0);
          } 
     }
     break;
     . . . . . . .
  }
}
. . . . . . .

    Заказывается реакция на два события: получение фокуса ввода (WM_TAKE_FOCUS) и завершение программы (WM_SAVE_YOURSELF). Когда сервер посылает событие первого типа, задача печатает соответствующее сообщение на устройства вывода. При приходе события второго типа, программа закрывает связь с сервером и завершается.