Менеджер окон - это специальный клиент, в задачи которого входит
интерактивное перемещение окон по экрану, изменение их размеров,
минимизация (превращение в пиктограмму) и многое другое.
Чтобы облегчить менеджеру его нелегкую жизнь, программам рекомендуется
при инициализации сообщить о себе определенную информацию.
Передается она через предопределенные свойства,
которые известны менеджеру и могут быть им прочитаны.
Некоторые из свойств (так называемые стандартные) задавать обязательно.
Все остальное определяется по усмотрению программы.
Наиболее простой способ задать стандартные свойства - обратиться
к функциям 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
).
Когда сервер посылает событие первого типа,
задача печатает соответствующее сообщение на устройства вывода. При приходе
события второго типа, программа закрывает связь с сервером и
завершается.