• focus: TBool - устанавливается в True, если окно имеет клавиатурный фокус, и False в противном случае.
   Обычно фокус ввода может свободно переходить от окна к окну. Но иногда программе необходимо запретить передачу фокуса. Это называется захватом клавиатуры. Для того, чтобы его реализовать, используется процедура XGrabKeyboard().
   Функция XGrabKey() запрещает передачу фокуса после нажатия определенной комбинации клавиш. Освободить клавиатуру можно, обратившись к процедуре XUngrabKeyboard() (XGrabKey()).
   Рассмотрим поведение системы при обработке событий от мыши. Как правило, если ее кнопка нажата в момент, когда ее курсор находится в неактивном окне, то последнее активизируется, и события от мыши передаются ему. Сказанное означает, что в нормальном состоянии окно получает только те события от мыши, которые соответствуют сигналам, пришедшим тогда, когда ее курсор находится в пределах окна. Но если программа вызывает
    function XGrabPointer(prDisplay: PDisplay; nGrabWnd: TWindow; nOwnerEvents: TBool; nEventMask: cardinal; nPointerMode: longint; nKeyboardMode: longint; nConfineTo: TWindow; nCursor: TCursor; nTime: TTime): longint; cdecl; external;
   то положение меняется. Теперь все события будут направляться окну с дескриптором nGrabWnd. Освобождается мышь вызовом XUngrabPointer(). Процедура XGrabButton() указывает, что курсор должен быть захвачен после нажатия определенной кнопки. Обратной к ней является процедура XUngrabButton().
   Процедуры, захватывающие устройство - мышь или клавиатуру - имеют ряд аргументов, влияющих на поведение системы.
   Так, параметр nConfineTo есть идентификатор окна, за пределы которого не должен выходить курсор мыши, если он захвачен.
   Если аргумент nOwnerEvents равен Тrue, то события мыши будут передаваться окнам программы. Если nOwnerEvents - False, или курсор находится в окне, не принадлежащем программе, то события мыши передаются окну nGrabWnd.
   Если nOwnerEvents равен False, то параметр nEventMask указывает, какие события следует передавать окну nGrabWnd.
   Обработка событий от клавиатуры или ныши может быть приостановлена, если nPointerMode или nKeyboardMode равен GrabModeSync. В этом случае события буферизуются сервером, пока устройство не будет освобождено с помощью XUngrabKeyboard(), XUngrabKey(), XUngrabPointer() или XUngrabButton().
   Параметр nCursor задает форму курсора во время того, как мышь захвачена. Аргумент nTime указывает, когда система должна активизировать режим захвата.

1.3.3 Лабораторная работа #3 "Работа с внешними устройствами"

   1. Используя функции XKeysymToString() и XKeycodeToKeysym(), напишите программу, которая реагирует на нажатие клавиш в окне выдачей в него кода символа, состояния модификаторов и символьной расшифровки нажатой клавиши.
 
   2. Напишите программу, определяющую координаты мыши в момент нажатия кнопки и печатающую в позицию мышиного курсора координаты мыши и номер нажатой кнопки.
 
   3. Модифицируйте предыдущую программу для рисования точек в местах нажатий мыши и при ее движении с нажатой кнопкой.
 
   4. Модифицируйте предыдущую программу для рисования отрезков между нажатиями мыши и при ее движении с нажатой кнопкой.
 
   5. Создайте программу, отображающую в окне содержимое текстового файла, имя которого задается в командной строке. Для скроллинга текста используйте клавиши Up, Down, Left, Right, PageUp, PageDown, Home, End.
 
   6. Составьте программу игры "Пятнашки", выбирая перемещаемую ячейку мышью.
 
   7. Составьте программу, которая по нажатию левой клавиши очищает рабочую область, при движении с нажатой левой клавишей рисует точку в позиции указателя мыши, а при отпускании левой клавиши соединяет все точки в рабочей области друг с другом.

1.4 Программы и их ресурсы

   Многие программы имеют различные заранее подготавливаемые данные, которые в терминах X называются - ресурсами. Это могут быть цвета окон приложения, строки сообщений пользователю и т.д.
   Как правило, программисты создают ресурсы каждый по-своему. В X Window сделана попытка унифицировать этот процесс.

1.4.1 Формат файла ресурсов

   В X файл ресурсов есть обычный текстовый файл, каждая строка которого задает тот или иной параметр (ресурс) программы. (При этом предполагается, что программу "населяют" именованные объекты, связанные в некоторую иерархию). Общий вид строки следующий:
    ‹имя программы›.‹подобъект1›.‹подобъект2›. . .‹подобъектN›.‹имя ресурса›: ‹значение ресурса›
   Подобная строка задает значение ресурса для подобъектов иерархии объектов программы. Например, запись
    myprog.dialogwnd.background: Red
   говорит, что в программе myprog у объекта с именем dialogwnd параметр background (цвет фона) имеет значение Red (красный цвет).
   Вместо имен объектов могут указываться их классы. Обычно класс имеет то же самое имя, что и объект, но начинается с заглавной буквы, например,
    Myprog.dialogwnd.Background: Red
   Часть объектов или классов в левой части строки, задающей ресурс, может заменяться символом '*', например, строка
    myprog*background: Red
   указывает, что для всех объектов программы myprog ресурс background имеет значение Red.
   Связка с помощью символа '.' имеет больший приоритет, чем связка с помощью '*'. Так, если в файле, задающем ресурсы, есть две строки
    myprog*background: Red
    myprog.dialogwnd.background: Green
   то все объекты программы будут иметь ресурс background равный Red, кроме объекта dialogwnd, для которого этот параметр есть Green.

1.4.2 Доступ к ресурсам программ

   Пусть ресурсный файл подготовлен. Как получить доступ к его данным во время работы программы? Для этого X предоставляет набор процедур, которые совокупно называются менеджер ресурсов(Resource Manager), и специальную программу xrdb, которая позволяет считать любой ресурсный файл и включить его в общую таблицу ресурсов сервера. Последняя называется базой данных ресурсов сервера, и представляет собой область памяти, ассоциированную со свойством (property) XA_RESOURCE_MANAGER корневого окна экрана дисплея.
   Наиболее простой является процедура XGetDefault(). Она получает имя программы, имя ресурса и определяет значение последнего. При этом она последовательно совершает следующие шаги:
   • сначала ресурс ищется в базе данных сервера (в свойстве XA_RESOURCE_MANAGER);
   • если он не найден, то значение ресурса определяется по файлу ".Xdefaults", который ищется в домашней (home) директории пользователя;
   • если задана переменная среды XENVIRONMENT, то ресурс ищется в файле, на который указывает эта переменная.
   Если ресурс одновременно встречается в ".Xdefaults" и файле, определяемом XENVIRONMENT, то берется последнее значение.
   В примере, приводимом ниже, используется XGetDefault(), чтобы получить строку, которую надо напечатать в окне программы. Предполагается, что имя программы - "hello", а строка - ресурс с именем "helloWorld", т.е. в файле ".Xdefaults" должна быть помещена, например, следующая запись:
   …
    hello.helloWorld: Hello, World!
   …
   Фрагмент программы, выполняющий чтение из файла ресурсов, будет выглядеть следующим образом:
   …
   prDisplay: PDisplay;
   prGC: TGC;
   nWnd: TWindow;
    psString: PChar;
   ….
    (* Устанавливаем связь с сервером, получаем номер экрана…*)
   ….
    (* Выбираем события, обрабатываемые программой *)
    XSelectInput (prDisplay, nWnd, ExposureMask ORKeyPressMask);
 
    (* Получаем рисуемую строку *)
    psString:= XGetDefault (prDisplay, 'hello', 'helloWorld');
   ….
    XDrawString (prDisplay, nWnd, prGC, 10, 50, psString,
    strlen (psString));
   ….
   Обратите внимание на то, что после изменения файла ".Xdefaults" он должен быть обработан программой xrdb для того, чтобы X сервер включил в свою таблицу обновленные ресурсы.
   Функция XGetDefault() проста в обращении, но недостаточно гибка. Так, например, с ее помощью нельзя прочитать содержимое произвольного файла ресурсов. Рассмотрим другие более развитые возможности.
   Вызов XrmInitialize() инициализирует менеджер ресурсов. Обращение к этой функции предшествует вызовам остальных процедур.
    procedure XrmParseCommand(
     prDB: TXrmDatabase {database};
     prOptRec: TXrmOptionDescList {table};
     nOptRecNum: integer {table_count};
     psProgName: pchar {name};
     argc: pointer {argc_in_out};
     argv: ppchar {argv_in_out}
    ); cdecl; external;
   сканирует строку, с помощью которой вызвана программа, и "достает" из нее ресурсы и их значения, при этом создается специальная структура данных - база данных ресурсов. Ресурсы и их значения помещаются в нее. Указатель на базу данных передается программе через переменную prDB. Параметр psProgName содержит имя программы, argc - число опций в командной строке, argv - сами опции. Аргумент prOptRec определяет, как разбирать командную строку. nOptRecNum задает число элементов массива prOptRec.
   В примере, приводимом ниже, определяется, что в командной строке опция "-bg" задает цвет фона; "-fg" - цвет переднего плана, а опция "-xrm" позволяет задать в командной строке любой ресурс программы.
   ….
    const
    rOptRec: array [0…2] of TXrmOptionDescRec = ( ('-bg', '*background', XrmoptionSepArg, 'Red'), ('-fg', '*foreground', XrmoptionSepArg, 'White'), ('-xrm', NIL, XrmoptionResArg, NIL), );
    var
     rDB: TXrmDatabase;
   …
    //void main (int argc, char **argv)
    begin
   …
    XrmInitialize();
    XrmParseCommand (rDB, rOptRec,
    sizeof (rOptRec) / sizeof (rOptRec[0]),
    argv[0], @argc, argv);
   …
    end.
   Процедура XrmGetFileDataBase() позволяет считать указанный ресурсный файл и создать по нему в памяти базу данных ресурсов. Функция
    function XrmGetResource(
     prDB: TXrmDatabase {database};
     psResName: pchar {str_name};
     psResClass: pchar {str_class};
     psResType: ppchar {str_type_return};
     psResVal: PXrmValue {value_return}
    ): Tbool; cdecl; external;
   считывает ресурс с именем psResName и классом psResClass из базы данных *prDB. После возврата psResType есть указатель на строку, указывающую тип ресурса. На само значение ресурса указывает psResVal.
   Функция XrmPutResource() сохраняет ресурс в базе данных. XrmPutFileDatabase() записывает базу данных ресурсов в файл.

1.4.3 Лабораторная работа #4 "Программы и их ресурсы"

   1. Составьте программу, считывающую из файла ресурсов маску шрифта, строку, координаты х, у и отображающую окно с текстом согласно полученной информации.

1.5 Межклиентское взаимодействие

1.5.1 Механизм свойств

   Как мы уже упоминали ранее, свойство есть набор данных, ассоциированных с окном. Они хранятся в специальных таблицах в памяти компьютера, на котором работает сервер. Каждое свойство имеет имя. Разные окна могут иметь свойства с одинаковыми именами.
   Поскольку передача имен - строк произвольной длины - от клиента к серверу может увеличить нагрузку на сеть, X идентифицирует свойства с помощью целых чисел - атомов. Процедура XInternAtom() включает свойство с указанным именем в таблицу сервера и возвращает соответствующий атом. Полный список реализуемых X протоколом атомов можно найти в файле /usr/include/X11/Xatom.h.
   Данные свойства рассматриваются сервером как массив единиц длиной 8, 16 или 32 бита. Их конкретная интерпретация осуществляется программами-клиентами.
   Каждое свойство имеет тип, который, в свою очередь, также задается тем или иным свойством. Например, свойство, соответствующее атому XA_STRING, задает тип "строка".
   Для работы со свойствами кроме XInternAtom() используются следующие процедуры: XChangeProperty() - меняет данные свойства: XGetWindowProperty() - позволяет получить данные свойства.
   Особую роль играют свойства, данные которых содержат строки текста. Они так и называются текстовыми и имеют тип "TEXT". Таковыми являются, например, имена (заголовки) окно, имена пиктограмм и т.д. Данные текстового свойства описываются структурой TXTextProperty. Процедура XStringListToTextProperty() переводит список строк в набор данных типа TXTextProperty:
    (* Эта переменная будет хранить созданное свойство. *)
    var
     window_title_property: TXTextProperty;
     rc: TStatus;
 
    (* Строка, преобразуемая в свойство. *)
    const
     window_title: PChar = 'hello, world';
 
    (* перевод строки в свойство X. *)
     rc:= XStringListToTextProperty(@window_title, 1, @window_title_property);
    (* проверка успешности преобразования. *)
     if (rc = 0) then begin
     writeln('XStringListToTextProperty - нет памяти');
     halt(1);
     end;
   XTextPropertyToString() выполняет обратное преобразование.

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

   Менеджер окон - это специальный клиент, в задачи которого входит интерактивное перемещение окон по экрану, изменение их размеров, минимизация (превращение в пиктограмму) и многое другое. Чтобы облегчить менеджеру его нелегкую жизнь, программам рекомендуется при инициализации сообщить о себе определенную информацию. Передается она через предопределенные свойства, которые известны менеджеру и могут быть им прочитаны. Некоторые из свойств (так называемые стандартные) задавать обязательно. Все остальное определяется по усмотрению программы. Наиболее простой способ задать стандартные свойства - обратиться к процедурам XSetStandardProperties() или XSetWMProperties().
   Ниже перечисляются свойства, создаваемые для менеджера окон программами, а также процедуры для работы с ними.
    Имя (заголовок) окна.Идентифицируется атомом XA_WM_NAME и имеет тип "TEXT". Данные свойства - структура TXTextProperty. Для задания свойства используется процедура XStoreName() (XSetWMName()). Получить его можно с помощью XFetchName() (XGetWMName()).
    Имя пиктограммы.Идентифицируется атомом XA_WM_ICONNAME и имеет тип "TEXT". Данные свойства - структура TXTextProperty. Для задания свойства используется процедура XSetIconName() (XSetWMIconName()). Получить его можно с помощью XGetIconName() (XGetWMIconName()).
    Рекомендации (hints) о геометрии окна.Идентифицируется атомом XA_WM_NORMAL_HINTS и имеет тип XA_WM_SIZE_HINTS. Данные свойства - структура типа TXSizeHints. Для задания свойства используется процедура XSetNormalHints().
   В ряде случаев стоит сообщить оконному менеджеру о том, какой размер окна мы хотим получить, и в каких пределах будут изменяться его размеры. Например, для терминальной программы (такой, как xterm), хотелось бы, чтобы окно всегда содержало полное количество строк и столбцов. В других случаях нежелательно давать возможность менять размер окна (например, в диалоговых окнах). Эти пожелания можно передать оконному менеджеру, хотя ничто не помешает ему их проигнорировать. Для этого необходимо создать структуру данных, заполнить ее необходимыми данными и затем использовать функцию XSetWMNormalHints():
    (* указатель на структуру рекомендаций о размерах. *)
    var
     win_size_hints: PXSizeHints;
     win_size_hints:= XAllocSizeHints();
 
     if (win_size_hints=nil) then begin
      writeln('XAllocSizeHints - нет памяти');
      halt(1);
     end;
 
     (* Инициализация структуры *)
     (* Вначале укажем, что передаются пожелания о размерах:  установим минимальный и начальный размеры. *)
     win_size_hints^.flags:= PSize OR PMinSize;
     (* Затем указываем требуемые границы. В нашем случае - создаем окно минимальным размером 300x200  пикселей и устанавливаем начальный размер в 400x250.*)
     win_size_hints^.min_width:= 300;
     win_size_hints^.min_height:= 200;
     win_size_hints^.base_width:= 400;
     win_size_hints^.base_height:= 250;
 
     (* Передаем пожелания о размерах оконному менеджеру. *)
     XSetWMNormalHints(display, win, win_size_hints);
 
     (* В конце необходимо освободить память из-под структуры. *)
     XFree(win_size_hints);
    Дополнительные параметры окна:способ работы с клавиатурой, вид и положение пиктограммы. Идентифицируется атомом XA_WM_HINTS и имеет тип XA_WM_HINTS. Данные свойства - структура типа TXWMHints. Для задания свойства используется процедура XSetWMHints(). Структура типа XWMHints, передаваемая функции XSetWMHints(), должна быть подготовлена с помощью XAllocWMHints():
    var
     win_hints: PXWMHints;
     icon_pixmap: TPixmap;
 
    const
     icon_bitmap_width=20;
     icon_bitmap_height=20;
    (* Определим битовое изображение в формате Х -  оно может быть создано программой xpaint *)
     icon_bitmap_bits: array [0…59] of byte = (
      $60, $00, $01, $b0, $00, $07, $0c, $03, $00, $04, $04, $00,
      $c2, $18, $00, $03, $30, $00, $01, $60, $00, $f1, $df, $00,
      $c1, $f0, $01, $82, $01, $00, $02, $03, $00, $02, $0c, $00,
      $02, $38, $00, $04, $60, $00, $04, $e0, $00, $04, $38, $00,
      $84, $06, $00, $14, $14, $00, $0c, $34, $00, $00, $00, $00
     );
 
     win_hints:= XAllocWMHints();
     if (win_hints=nil) then begin
      writeln('XAllocWMHints - нет памяти');
      halt(1);
     end;
 
     (* установим пожелания о состоянии окна, позиции его иконки  и ее виде*)
     win_hints^.flags:= StateHint OR IconPositionHint OR IconPixmapHint;
 
     (* Загрузим заданное битовое изображение  и создадим из него пиксельную карту Х. *)
     icon_pixmap:= XCreateBitmapFromData(display,  win, PChar(icon_bitmap_bits), icon_bitmap_width, icon_bitmap_height);
     if (icon_pixmap=nil) then begin
      writeln('XCreateBitmapFromData: ошибка создания пиксмапа');
      halt(1);
     end;
 
     (* Затем детализируем желаемые изменения. *)
    (* в нашем случае - сворачиваем окно, определяем его иконку  и устанавливаем позицию иконки в левом верхнем углу экрана.*)
     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. Данные свойства - структура типа TXClassHints. Задается свойство с помощью процедуры 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 amp;mdash задается, если программа хочет перехватить момент своего завершения; менеджер окон посылает приложению событие 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 и производящей соответствующую обработку событий.
   …
    var
     prDisplay: PDisplay;
     nScreenNum: integer;
     prGC: TGC;
     rEvent: TXEvent;
     nWnd: TWindow;
     pnProtocol: array [0…1] of TAtom;
     nWMProtocols: TAtom;
 
     ( * Устанавливаем связь с сервером, получаем номер экрана, создаем окно, выбираем события, обрабатываемые программой *)
   …
     (* Задаем свойство 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 true do
     begin
      XNextEvent (prDisplay, @rEvent);
      case (rEvent.type) of
   …
      ClientMessage:
      begin
       if (rEvent.xclient.message_type = nWMProtocols) then
       begin
        if (rEvent.xclient.data.l[0] = pnProtocol[0]) then
         writeln('Receiving the input focus.')
        else
         if (rEvent.xclient.data.l[0] = pnProtocol[1]) then
         begin
          XCloseDisplay (prDisplay);
          halt(0);
         end;
        end;
       end;
   …
      end;
     end;
   …
   Заказывается реакция на два события: получение фокуса ввода (WM_TAKE_FOCUS) и завершение программы (WM_SAVE_YOURSELF). Когда сервер посылает событие первого типа, задача печатает соответствующее сообщение на устройства вывода. При приходе события второго типа, программа закрывает связь с сервером и завершается.

1.5.3 Лабораторная работа #5 "Межклиентское взаимодействие"

   1. Составьте программу, которая при получении фокуса ввода перекрашивает свое окно в другой цвет.
   2. Составьте программу, порождающую два расположенных рядом дочерних окна, в которых отображаются графики функций sin(x) на отрезке [0; 2?] и exp(x) на отрезке [-2; 2]. Графики масштабировать по размеру окон.
 
   3. Создайте окно, изменяющее свои размеры таким образом, чтобы мышь всегда была в его центре.
   4. Создайте окно, "убегающее" от указателя мыши.
 
   5. Создайте программу, которая по нажатию клавиши мыши в основном окне создает новое окно (не более 100 одновременно), а по нажатию клавиши мыши в дочернем окне удаляет его. Если дочернее окно существует более одной минуты, оно должно самоудаляться.
 
   6. Создайте программу моделирования эволюции клеточного автомата "Жизнь", ячейки которого имею два состояния: пусто и заполнено. Если рядом с пустой ячейкой три заполненных, она заполняется. Если рядом с заполненной ячейкой меньше двух или больше трех заполненных, ячейка становится пустой. Размеры модельного поля - 64Ч64 ячейки, вначале поле пустое. По нажатию любой кнопки мыши состояние ячейки меняется на противоположное, по нажатию пробела осуществляется один шаг эволюции, а по нажатии Escape - выход из программы.

Литература

   Полищук А.П., Семериков С.А. Программирование в X Window. - Кривой Рог: Издательский отдел КГПУ, 2003. - 192 с.
   Полищук А.П., Семериков С.А. Событийно-ориентированное программирование. - Кривой Рог: КГПУ, 2001. - 336 с.
   Робачевский А.М. Операционная система UNIX. - К.: БХВ, 2000. - 518 с.
   Adrian Nye. Volume 0: X Protocol Reference Manual, 4rd Edition. - O'Reilly & Associates, 1990. - 446 p.
   Adrian Nye. Volume 1: Xlib Programming Manual, 3rd Edition. - O'Reilly & Associates, 1992. - 821 p.
   Adrian Nye. Volume 2: Xlib Reference Manual. - O'Reilly & Associates, 1992. - 935 p.
   Robert W. Scheifler & James Gettys. X Window System: The Complete Reference to Xlib, X Protocol, ICCCM, XLFD. X Version 11, Release 4. - Digital Press, 1992. - 711 p.