Менеджер окон - это специальный клиент, в задачи которого входит
интерактивное перемещение окон по экрану, изменение их размеров,
минимизация (превращение в пиктограмму) и многое другое.
Чтобы облегчить менеджеру его нелегкую жизнь, программам рекомендуется
при инициализации сообщить о себе определенную информацию.
Передается она через предопределенные свойства,
которые известны менеджеру и могут быть им прочитаны.
Некоторые из свойств (так называемые стандартные) задавать обязательно.
Все остальное определяется по усмотрению программы.
Наиболее простой способ задать стандартные свойства - обратиться
к функциям XSetStandardProperties()
или XSetWMProperties().
Свойства, создаваемые для менеджера окон программами, а также функции для работы с ними.
XA_WM_NAME и имеет тип "TEXT".
Данные свойства - структура XTextProperty.
Для задания свойства используется функция XStoreName()
(XSetWMName()). Получить его можно с помощью
XFetchName() (XGetWMName()).
XA_WM_ICONNAME и имеет тип "TEXT".
Данные свойства - структура XTextProperty.
Для задания свойства используется функция XSetIconName()
(XSetWMIconName()). Получить его можно с помощью
XGetIconName() (XGetWMIconName()).
XA_WM_NORMAL_HINTS и имеет тип
XA_WM_SIZE_HINTS. Данные свойства - структура типа
XSizeHints. Для задания свойства используется функция
XSetNormalHints().
В ряде случаев стоит сообщить оконному менеджеру о том, какой размер
окна нужен, и в каких пределах будут изменяться его размеры.
Например, для терминальной программы (такой, как xterm),
хотелось бы, чтобы окно всегда содержало полное количество строк и столбцов.
В других случаях нежелательно давать возможность менять размер окна
(например, в диалоговых окнах). Эти пожелания можно передать оконному
менеджеру, хотя ничто не помешает ему их проигнорировать.
Для этого необходимо создать структуру данных, заполнить ее необходимыми
данными и затем использовать функцию XSetWMNormalHints():
/* указатель на структуру рекомендаций о размерах. */
XSizeHints* size_hints = XAllocSizeHints();
if (!size_hints) {
  fprintf(stderr, "XAllocSizeHints - нет памяти\n");
  exit(1);
}
/* Инициализация структуры */
/* Вначале укажем, что передаются пожелания о размерах: */
/* установим минимальный и начальный размеры. */
size_hints->flags = PSize | PMinSize;
/* Затем указываем требуемые границы.              */
/*создаем окно минимальным размером 300x200 пикселей */
/* и устанавливаем начальный размер в 400x250.          */
size_hints->min_width = 300;
size_hints->min_height = 200;
size_hints->base_width = 400;
size_hints->base_height = 250;
/* Передаем пожелания о размерах оконному менеджеру. */
XSetWMNormalHints(display, win, size_hints);
/* В конце необходимо освободить память из-под структуры. */
XFree(size_hints);
Дополнительные параметры окна: способ работы с клавиатурой,
вид и положение пиктограммы. Идентифицируется атомом
XA_WM_HINTS и имеет тип XA_WM_HINTS.
Данные свойства - структура типа XWMHints.
Для задания свойства используется функция XSetWMHints().
Структура типа XWMHints, передаваемая функции
XSetWMHints(), должна быть подготовлена с помощью
XAllocWMHints():
XWMHints* win_hints = XAllocWMHints();
if (!win_hints) {
  fprintf(stderr, "XAllocWMHints - нет памяти\n");
  exit(1);
}
/* установим пожелания о состоянии окна, позиции его иконки */
/* и ее виде                        */
win_hints->flags = StateHint | IconPositionHint | IconPixmapHint;
/* Определим битовое изображение в формате Х - */
/* оно может быть создано программой xpaint  */
#define icon_bitmap_width 20
#define icon_bitmap_height 20
static char icon_bitmap_bits[] = {
 0x60, 0x00, 0x01, 0xb0, 0x00, 0x07, 0x0c, 0x03, 0x00, 0x04, 0x04, 0x00,
 0xc2, 0x18, 0x00, 0x03, 0x30, 0x00, 0x01, 0x60, 0x00, 0xf1, 0xdf, 0x00,
 0xc1, 0xf0, 0x01, 0x82, 0x01, 0x00, 0x02, 0x03, 0x00, 0x02, 0x0c, 0x00,
 0x02, 0x38, 0x00, 0x04, 0x60, 0x00, 0x04, 0xe0, 0x00, 0x04, 0x38, 0x00,
 0x84, 0x06, 0x00, 0x14, 0x14, 0x00, 0x0c, 0x34, 0x00, 0x00, 0x00, 0x00
};
/* Загрузим заданное битовое изображение */
/* и создадим из него пиксельную карту Х. */
Pixmap icon_pixmap = XCreateBitmapFromData(display,
                      win,
                      icon_bitmap_bits,
                      icon_bitmap_width,
                      icon_bitmap_height);
if (!icon_pixmap) {
 fprintf(stderr, "XCreateBitmapFromData: ошибка создания pixmap\n");
 exit(1);
}
/* Затем детализируем желаемые изменения.             */
/* в нашем случае - сворачиваем окно, определяем его иконку    */
/* и устанавливаем позицию иконки в левом верхнем углу экрана.   */
win_hints->initial_state = IconicState;
win_hints->icon_pixmap = icon_pixmap;
win_hints->icon_x = 0;
win_hints->icon_y = 0;
/* Передаем пожелания оконному менеджеру. */
XSetWMHints(display, win, win_hints);
/* В конце необходимо освободить память из-под структуры. */
XFree(win_hints);
Получить данные свойства можно с помощью XGetWMHints().
Атрибут, характеризующий "временное" окно.
Идентифицируется атомом XA_WM_TRANSIENT_FOR и имеет тип
XA_STRING. Свойство задается для окон, появляющихся на экране
для выполнения вспомогательных функций (диалоги, меню).
Такие объекты рассматриваются менеджером по особому.
Например, он может не добавлять к окну заголовок и рамку.
Данные свойства - идентификатор окна родительского по отношению к данному.
Задается свойство с помощью функции XSetTransientForHint().
Имена программы и ее класса, идентифицируется атомом
XA_WM_CLASS и имеет тип XA_STRING.
Данные свойства - структура типа XClassHints.
Задается свойство с помощью функции XSetClassHint()
и может быть получено с помощью XGetClassHint().
Если окно (окна) программы имеют собственную цветовую палитру,
то приложение должно соответствующим образом задать для него
атрибут colormap. Программа заносит идентификатор окна
(идентификаторы окон) в список, ассоциированный со свойством,
имя которого 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().
Приведем фрагмент программы, задающей свойство WM_PROTOCOLS
и производящей соответствующую обработку событий.
. . . . . . .
Display		*display;
int		screenNumber;
GC		gc;
XEvent		report;
Window		window;
Atom		pnprotocol[2];
Atom		wmprotocols;
/*
 *Устанавливаем связь с сервером, получаем номер экрана,
 *создаем окно, выбираем события, обрабатываемые программой
 */
. . . . . . .
/* Задаем свойство WM_PROTOCOLS */
pnprotocol [0] = XInternAtom (display, "WM_TAKE_FOCUS", True);
pnprotocol [1] = XInternAtom (display, "WM_SAVE_YOURSELF", True);
wmprotocols = XInternAtom (display, "WM_PROTOCOLS", True);
XSetWMProtocols (display, window, pnprotocol, 2);
/* Покажем окно */
XMapWindow (display, window);
/* Цикл обработки событий */
while (1) {
   XNextEvent (display, &report);
switch (report.type) {
  . . . . . .
  case ClientMessage :
  if (report.xclient.message_type == wmprotocols)
  {
    if (report.xclient.data.l[0] == pnprotocol[0])
     puts ("Receiving the input focus.\n");
    else
     if (report.xclient.data.l[0] == pnprotocol[1])
     {
	XCloseDisplay (display);
	exit (0);
     } 
   }
   break;
   . . . . . . .
 }
}
. . . . . . .
Заказывается реакция на два события: получение фокуса
ввода (WM_TAKE_FOCUS) и
завершение программы (WM_SAVE_YOURSELF).
Когда сервер посылает событие первого типа,
задача печатает соответствующее сообщение на устройства вывода. При приходе
события второго типа, программа закрывает связь с сервером и
завершается.