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