Приход события KeyPress означает, что программу надо завершить: прекратить связь с сервером, для чего вызывать XCloseDisplay(prDisplay), и вызвать функцию halt().
   XCloseDisplay() закрывает соединение с Х сервером, закрывает все окна и удаляет идентификаторы ресурсов, созданных клиентом на дисплее. Для удаления только окна без разрыва связи с Х сервером необходимо использовать функции XDestroyWindow() и XDestroySubWindows().

1.1.7 События

   Когда пользователь нажимает на кнопку мыши или клавишу клавиатуры, или когда окно программы нуждается в перерисовке, или когда происходят другие изменения в системе, сервер подготавливает соответствующий пакет данных и отправляет его той или иной программе (или программам). Этот пакет данных называется событием.
   Типичная GUI программа имеет следующую структуру:
   1. Выполняются инициализационные процедуры.
   2. Устанавливается соединение с Х сервером.
   3. Выполняются инициализационные процедуры, связанные с Х.
   4. Пока не завершились:
      1. Получаем следующее событие от Х сервера.
      2. Обрабатываем событие, возможно посылая различные запросы на рисование к Х серверу.
      3. Если событие было завершающим, заканчиваем цикл.
   5. Закрываем соединение с Х сервером.
   6. Выполняем завершающие действия.
   Возможных событий достаточно много; их список можно найти в файле X.pp. Каждое из них имеет свой тип и соответствующую структуру данных. Все они вместе, как было сказано выше, описываются объединением XEvent.
   Как мы видели из примера в предыдущем пункте, программа для каждого из своих окон может выбрать события, которые будут ему передаваться. Делается это с помощью функции XSelectInput(). При вызове этой процедуры требуемые события идентифицируются соответствующими флагами. Так событию, ButtonPress (нажатие кнопки мыши) соответствует флаг ButtonPressMask. Когда кнопка отпускается, сервер порождает событие ButtonRelease, которому соответствует флаг - ButtonReleaseMask.
   Маска выбираемых событий может составляться с помощью побитового "ИЛИ" из таких значений:
   • 0 - не ожидать никаких событий
   • KeyPressMask - ожидать событие нажатия клавиши
   • KeyReleaseMask - ожидать событие отпускания клавиши
   • ButtonPressMask - ожидать событие нажатия кнопки мыши
   • ButtonReleaseMask - ожидать событие отпускания кнопки мыши
   • EnterWindowMask - ожидать событие входа в окно
   • LeaveWindowMask - ожидать событие выхода из окна
   • PointerMotionMask - ожидать событие движения мышиного курсора
   • PointerMotionHintMask - ожидать событие движения мышиного курсора с дополнительными указаниями
   • Button1MotionMask - ожидать событие движения мышиного курсора при нажатой первой кнопке
   • Button2MotionMask - ожидать событие движения мышиного курсора при нажатой второй кнопке
   • Button3MotionMask - ожидать событие движения мышиного курсора при нажатой третьей кнопке
   • ButtonMotionMask - ожидать событие движения мышиного курсора при любой нажатой кнопке
   • ExposureMask - ожидать событие необходимости перерисовки окна
   • VisibilityChangeMask - ожидать событие изменения видимости
   • ResizeRedirectMask - ожидать событие изменения размеров окна
   • FocusChangeMask - ожидать событие изменения фокуса ввода
   Некоторые события посылаются окну независимо от того, выбраны они или нет. Это:
   • MappingNotify - посылается, когда изменяется состояние клавиатуры (соответствие физических и логических кодов;
   • ClientMessage - так идентифицируются события, посылаемые от клиента к клиенту с помощью процедуры XSendEvent();
   • SelectionClear, SelectionNotify, SelectionRequest - эти события используются в стандартном механизме общения между программами, работающими в X;
   • Expose, NoExpose - эти события могут посылаться, когда клиент пытается копировать содержимое одного окна в другое.
   Частой ошибкой начинающих программистов является добавление кода для обработки нового события без добавления маски для этого события в XSelectInput(). Можно часам сидеть и отлаживать программу в недоумении, почему она не реагирует на отпускание кнопки, только из-за того, что для кнопок событие нажатия зарегистрировано, а событие отпускания - нет.
   Программа получает события в своем основном цикле. Для этого можно использовать ряд процедур. Наиболее простая из них:
    functionXNextEvent(prDisplay: PDisplay; prEvent: PXEvent): longint; cdecl; external;
   Она "вынимает" из очереди событие, находящееся в ее "голове", сохраняет информацию о нем в переменной, на которую указывает параметр prEvent, и возвращается. При этом само событие удаляется из очереди. Функция XPeekEvent() также возвращает переданное сервером событие, но не удаляет его из очереди.
   Процедура XPending() возвращает общее число событий в очереди программы.
   Итак, если событие выбрано для окна, то оно будет передано ему на обработку. А если нет? В этом случае событие передается родителю окна. Если и тот не желает обращать внимание на данное событие, то оно отправляется дальше, вверх по иерархии окон, и так до тех пор, пока либо не будет найдено окно, выбравшее это событие, либо событие не потеряется.
   Задача может влиять на этот процесс продвижения события по иерархии окон. Если программа включает флаг, соответствующий событию, в специальный атрибут окна, то оно, достигнув это окно, не будет передано родителю, а будет тут же "снято с повестки дня". Этот атрибут - do_not_propagate.

1.1.8 Атрибуты окна

   Многие атрибуты окна задаются при его создании с помощью процедуры XCreateWindow() или XCreateSimpleWindow(). Впоследствии параметры можно изменить, обратившись к процедуре XChangeWindowAttributes().
   Характеристики окна описываются структурами типа TXSetWindowAttributes и TXWindowAttributes. Получить их можно с помощью процедуры XGetWindowAttributes().
   Все они делятся на две группы. В первую входят параметры, доступные "на чтение" и "на запись". Вторая группа представляет собой внутренние данные. Программа может прочитать их, но не может менять.
   Сначала перечислим поля этих структур, которые относятся к "изменяемым" параметрам.
    Фон окнаопределяется атрибутами background_pixmap и background_pixel. Первый из них задает картинку (карту пикселей), которая используется для заливки фона окна. При необходимости картина повторяется слева направо и сверху вниз. Если параметр background_pixmap равен None (задается по умолчанию), то он игнорируется. Если же при этом поле background_pixel не задано (установлено по умолчанию), то окно считается "прозрачным", в противном случае его фон заливается цветом background_pixel. Атрибуты background_pixmap и background_pixel могут также принимать значение ParentRelative. В этом случае характеристики фона заимствуются у родительского окна.
    Вид края окнаопределяется полями border_pixmap и border_pixel. Первый атрибут определяет карту пикселей, используемую для заполнения края. Если он равен None, то край заполняется цветом border_pixel. Если же и поле border_pixel не задано, то для изображения края используются соответствующие характеристики родителя. То же самое происходит, если параметр border_pixmap равен CopyFromParent (взять у родителя). Последнее значение есть значение по умолчанию.
   На перерисовкуокна после изменения его размеров влияют атрибуты bit_gravity и win_gravity. Когда окно меняет размер, например, увеличивается или уменьшается, то, в принципе, нет необходимости перерисовывать все его содержимое. Часть окна остается неизменной. Правда, эта часть может поменять свое положение: переместиться вправо, влево, вверх или вниз. Поле bit_gravity говорит серверу, что делать с оставшейся частью изображения. Возможные значения параметра следующие:
   • ForgetGravity - содержимое окна перерисовывается (считается значением по умолчанию);
   • StaticGravity - остающаяся часть не должна менять положение по отношению к главному (корневому - root) окну сервера;
   • NorthWestGravity - остающаяся часть смещается к левому верхнему углу;
   • NorthGravity - остающаяся часть смещается к верху окна;
   • NorthEastGravity - остающаяся часть смещается к правому верхнему углу;
   • WestGravity - остающаяся часть смещается к левому краю окна;
   • CenterGravity - остающаяся часть смещается к центру окна;
   • EastGravity - остающаяся часть смещается к правому краю окна;
   • SouthWestGravity - остающаяся часть смещается к левому нижнему углу;
   • SouthGravity - остающаяся часть смещается к нижнему краю окна;
   • SouthEastGravity - остающаяся часть смещается к правому нижнему углу.
   Параметр win_gravity говорит о том, что делать с подокнамиокна после изменения размеров последнего. Возможные значения параметра следующие (при перечислении используются следующие обозначения: H - изменение размеров окна по горизонтали, V - изменение размеров по вертикали, (H, V) - смещение подокна на H пикселей по горизонтали и на V пикселей по вертикали):
   • UnmapGravity - подокна удаляются с экрана; окну посылается событие UnmapNotify, в ответ на которое оно может переместить свои подокна и показать их с помощью процедуры XMapSubWindow();
   • StaticGravity - подокна остаются на месте по отношению к главному (корневому) окну сервера;
   • NorthWestGravity - устанавливается по умолчанию; соответствует смещению (0, 0);
   • NorthGravity - смещение (H/2, 0);
   • NorthEastGravity - смещение (H, 0);
   • WestGravity - смещение (0, V/2);
   • CenterGravity - смещение (H/2, V/2);
   • EastGravity - смещение (H, V/2);
   • SouthWestGravity - смещение (0, V);
   • SouthGravity - смещение (H/2, V);
   • SouthEastGravity - смещение (H, V).
    Автоматическое сохранение содержимого окна, когда его часть перекрывается другими окнами, или, когда окно удаляется с экрана, определяется параметрами backing_store, backing_planes и backing_pixel. Сохраненные данные могут использоваться для восстановления окна, что значительно быстрее, чем его перерисовка программой в ответ на событие Expose. Параметр backing_store имеет следующие возможные значения:
   • NotUseful (устанавливается по умолчанию) - серверу не рекомендуется сохранять содержимое окна;
   • WhenMapped - серверу рекомендуется спасти содержимое невидимых частей окна, когда окно показывается на экране;
   • Always - серверу рекомендуется сохранить содержимое окна даже, если оно не показано на экране.
   Сохранение изображений требует, как правило, довольно большого расхода памяти. Атрибуты backing_planes и backing_pixel призваны уменьшить этот расход. Первый из указанных параметров говорит серверу, какие плоскости изображения надо сохранять; backing_pixel означает, какой цвет использовать при восстановлении изображения в тех плоскостях, которые не сохранялись. По умолчанию backing_planes - маска, состоящая из единиц, а backing_pixel равно 0.
   Иногда при показе окна полезно сохранить содержимое экрана под окном. Если окно невелико, и показывается ненадолго, то это позволяет экономить время, которое надо будет затратить на перерисовку экрана после того, как окно будет закрыто. Если атрибут save_under равен True, то сервер будет пытаться сохранить изображение под окном. Если же он равен False (по умолчанию), то сервер ничего не предпринимает.
   Когда обрабатывает (или не обрабатывает) событие, последнее может быть передано его родительскому окну. Атрибут do_not_propagate_mask (по умолчанию 0) говорит и о том, какие события не должны доходить до родителей.
    Изменение размеров окна и его положения на экранеконтролируется атрибутом override_redirect. Если он равен False, то размер окна и его положение меняются с помощью менеджера окон. Если же он равен True, то окно само решает, где ему быть, и какую ширину и высоту иметь.
    Цветовую гаммуокна задает параметр colormap. Значение по умолчанию - CopyFromParent, которое говорит, что окно использует палитру своего непосредственного родителя.
   Теперь рассмотрим "неизменяемые" параметры окна. Строго говоря, атрибуты, о которых пойдет речь, нельзя назвать неизменяемыми. Некоторые из них могут меняться сервером или менеджером окон. Но для обычных программ-клиентов они действительно являются таковыми.
    Положение окна и его размерысообщают поля x, y, width и height. Они дают координаты левого верхнего угла, ширину и высоту окна соответственно. Координаты измеряются в пикселях по отношению к родительскому окну.
    Ширина края окнаопределяется параметром border_width.
   Маска, говорящая о том, какие события выбраны для передачи окнупородившим его клиентом, содержится в поле флагов your_event_mask. Значение параметра образуется комбинацией флагов, идентифицирующих события.
    Информация о дисплее, на котором показано окно, содержится в структуре Visual, на которую показывает поле visual. Эти данные, как правило, не обрабатываются обычными программами-клиентами (заметим, что для получения информации о дисплее, в системе предусмотрена процедура XGetVisualInfo()).
    Класс окнасообщает поле class. Возможные значения: InputOutput и InputOnly.
    Число цветовых плоскостей дисплея(число бит-на-пиксел) помещается в поле depth.
   На информацию об экране, на котором помещается окно, указывает поле screen. Она, как правило, не используется обычными программами.
    Идентификатор главного (корневого) окна экрана, на котором помещается окно, находится в поле root.
    Если окно имеет палитру, и она в настоящее время активна, то поле map_installed равно True, в противном случае - False.
    Видно в настоящее время окно на экранеили нет, сообщает атрибут map_state.
    Маска всех событий, выбранных всеми программами для данного окна, содержится в атрибуте all_event_mask. Дело в том, что окно обрабатывается не только порождающим его клиентом, но, возможно, и другими приложениями, например, менеджером окон.
   Мы рассказали о том, как получить атрибуты окна, и что они означают. Теперь рассмотрим, как их изменить. Для этого можно использовать несколько процедур X Window, основной из которых является XChangeWindowAttributes(), имеющая следующий прототип:
    functionXChangeWindowAttributes(prDisplay: PDisplay; nWnd: TWindow; nValueMask: cardinal; prWinAttr: PXSetWindowAttributes): longint; cdecl; external;
   Требуемые установки атрибутов передаются через аргумент prWinAttr. Он указывает на переменную типа TXSetWindowAttributes. Ее поля те же, что и соответствующие поля TXWindowAttributes. Разница заключается лишь в разных именах некоторых из них. Так, поле your_event_mask в TXWindowAttributes соответствует полю event_mask в TXSetWindowAttributes.
   Структура TXSetWindowAttributes содержит дополнительное поле cursor. Оно определяет вид курсора мыши, когда последний находится в окне. Если поле равно None (значение по умолчанию), то используется курсор родительского окна, в противном случае значением параметра должен быть идентификатор того или иного курсора.
   Параметр nValueMask при вызове указанной процедуры представляет комбинацию флагов, говорящих о том, какие из полей переменной prWinAttr принимать во внимание.
   В следующем примере приведен фрагмент кода, в котором изменяются параметры border_pixmap и win_gravity некоторого окна:
   …
    var
     prDisplay: PDisplay;
     prWnd: TWindow;
     rWndAttr: TXSetWindowAttributes;
     nValMask: cardinal;
    const
     nPixmap: TPixmap = 0;
   …
     nValMask:= CWBorderPixmap orCWWinGravity;
     rWndAttr.border_pixmap:= nPixmap;
     rWndAttr.win_gravity:= StaticGravity;
   …
     XChangeWindowAttributes (prDisplay, prWnd, nValMask, @rWndAttr);
   …
   Отдельные атрибуты окна можно изменить более просто с помощью специальных процедур. Так, например, функция XSetWindowBackground() меняет фон окна, XSetWindowBorder() - его край.

1.1.9 Операции над окнами

   Манипулировать окнами можно не только с помощью атрибутов: Xlib предоставляет набор функций для изменения их размеров, перемещения на экране и в стеке окон, сворачивания и т.п.
   Первая пара операций, которые можно применить к окну - отображение или скрытие. Отображение окна заставляют окно появиться на экране, скрытие приводит к удалению с экрана (хотя логическое окно в памяти все еще существует). Например, если в вашей программе есть диалоговое окно, вместо создания его каждый раз по запросу пользователя, мы можем создать окно один раз в скрытом режиме и, когда пользователь запросит открыть диалог, просто отобразить окно на экране. Когда пользователь нажимает "OK" или "Cancel", окно скрывается. Это значительно быстрее создания и уничтожения окна, однако стоит ресурсов, как на стороне клиента, так и на стороне X сервера.
   Отображение окна может быть выполнено с помощью XMapWindow(), скрытие - с помощью XUnmapWindow(). Функция отображения заставит событие Expose послаться программе, если только окно полностью не закрыто другими окнами.
   Другое действие, которое можно выполнить над окнами - переместитьих в другую позицию. Это может быть выполнено функцией XMoveWindow(), которая принимает новые координаты окна. Имейте в виду, что после перемещения окно может быть частично скрытым другими окнами (или наоборот, открыто ими), и таким образом, может быть сгенерировано сообщение Expose.
    Изменить размер окнаможно с помощью функции XResizeWindow(). Мы можем также объединить перемещение и изменение размеров, используя одну функцию XMoveResizeWindow().
   Все приведенные выше функции изменяли свойства одного окна. Существует ряд свойств, связанных с данным окном и другими окнами. Одно из них - порядок засылки в стек: порядок, в котором окна располагаются друг над другом. Говорят, что окно переднего плана находится на верхе стека, а окно заднего плана - на дне стека. Перемещение окна на вершину стека осуществляет функция XRaiseWindow(), перемещение окна на дно стека - функция XLowerWindow().
   С помощью функции XIconifyWindow() окно может быть свернуто, а с помощью XMapWindow() - восстановлено. Для того, чтобы понять, почему для XIconifyWindow() нет обратной функции, необходимо заметить, что, когда окно сворачивается, на самом деле оно скрывается, а вместо него отображается окно иконки. Таким образом, чтобы восстановить исходное окно, нужно просто отобразить его снова. Иконка является на самом деле другим окном, которое просто тесно связано сильно с нашим нормальным окном - это не другое состояние нашего окна.
   Следующий пример демонстрирует использование операций над окнами:
    uses x,xlib,xutil,crt,dos;
 
    (* create_simple_window - создает окно с белым фоном заданного размера.
     Принимает в качестве параметров дисплей, размер окна (в пикселях) и положение окна (также в пикселях). Возвращает дескриптор окна.
     Окно создается с черной рамкой шириной в 2 пикселя и автоматичсеки отображается после создания.*)
    function create_simple_window(display: PDisplay; width, height, x, y: integer): TWindow;
    var
     screen_num, win_border_width: integer;
     win: TWindow;
    begin
     screen_num:= XDefaultScreen(display);
     win_border_width:= 2;
 
    (* создаем простое окно как прямой потомок корневого окна экрана, используя черный и белый цвета в качестве основного и фонового, и размещая новое окно в верхнем левом углу по заданным координатам *)
 
     win:= XCreateSimpleWindow(display, XRootWindow(display, screen_num),  x, y, width, height, win_border_width, XBlackPixel(display, screen_num), XWhitePixel(display, screen_num));
 
    (* Отображаем окно на экране. *)
     XMapWindow(display, win);
 
    (* Заставляем выполниться все запросы к Х серверу. *)
     XFlush(display);
 
     create_simple_window:=win;
    end;
 
    //void main(int argc, char* argv[])
    var
     display: PDisplay; (* указатель на структуру дисплея Х *)
     screen_num: integer; (* количество экранов для размещения окон *)
     win: TWindow; (* дескриптор создаваемого окна *)
     display_width, display_height: word; (* высота и ширина Х дисплея *)
     win_width, win_height: word; (* высота и ширина нового окна *)
     display_name: array [0…30] of Char;
     name: string;
     i: integer;
     win_attr: TXWindowAttributes;
     xx, y, scr_x, scr_y: integer;
     child_win: TWindow; (* переменная для хранения дескриптора родительского окна *)
     parent_win: TWindow; (* эта переменная будет хранить дескриптор корневого окна  экрана, на котором отображено наше окно *)
     root_win: TWindow; (* эта переменная будет хранить массив дескрипторов дочерних окон нашего окна, *)
     child_windows: PWindow; (* а эта - их количество *)
     num_child_windows: integer;
 
    begin
     name:= getenv('DISPLAY'); (* имя Х дисплея *)
     for i:=1 to byte(name[0]) do  display_name[i-1]:=name[i];
     display_name[byte(name[0])]:=#0;
     (* устанавливаем соединение с Х сервером *)
     display:= XOpenDisplay(display_name);
     if (display = NIL) then begin
      writeln(paramstr(0),': не могу соединиться с Х сервером ',   display_name);
      halt(1);
     end;
 
     (* получаем геометрию экрана по умолчанию для нашего дисплея *)
     screen_num:= XDefaultScreen(display);
     display_width:= XDisplayWidth(display, screen_num);
     display_height:= XDisplayHeight(display, screen_num);
 
     (* создаем новое окно в 1/9 площади экрана *)
     win_width:= (display_width div 3);
     win_height:= (display_height div 3);
     (* отладочная печать в стандартный вывод *)
     writeln('ширина окна - ', win_width, '; высота - ', win_height);
 
    (* создаем простое окно как прямой потомок корневого окна экрана, используя черный и белый цвета в качестве основного и фонового, и размещая новое окно в верхнем левом углу по заданным координатам *)
     win:= create_simple_window(display, win_width, win_height, 0, 0);
     XFlush(display);
 
     (* отдохнем после трудов праведных *)
     delay(3000);
 
     (* пример изменения размеров окна *)
     begin
 
      (* в цикле уменьшаем окно *)
      for i:=0 to 39 do begin
       dec(win_width,3);
       dec(win_height,3);
       XResizeWindow(display, win, win_width, win_height);
       XFlush(display);
       delay(20);
      end;
 
      (* в цикле увеличиваем окно *)
      for i:=0 to 39 do begin
       inc(win_width,3);
       inc(win_height,3);
       XResizeWindow(display, win, win_width, win_height);
       XFlush(display);
       delay(20);
      end;
     end;
 
     delay(1000);
 
     (* пример перемещения окна *)
     begin
 
      (* вначале получаем текущие атрибуты окна *)
      XGetWindowAttributes(display, win, @win_attr);
 
      xx:= win_attr.x;
      y:= win_attr.y;
 
      (* затем находим окно родителя *)
      begin
 
       (* выполним запрос необходимых значений *)
       XQueryTree(display, win, @root_win, @parent_win, @child_windows, @num_child_windows);
 
       (* мы должны освободить список дочерних дескрипторов, так как он был динамически выделен XQueryTree() *)
       XFree(child_windows);
      end;
 
      (* Транслируем локальные координаты в экранные, используя корневое окно как окно, относительно которого выполняется трансляция. Это работает потому, что корневое окно всегда занимает весь экран, и его левый верхний угол совпадает с левым верхним углом экрана *)
      XTranslateCoordinates(display, parent_win, win_attr.root, xx, y, @scr_x, @scr_y, @child_win);
 
      (* перемещаем окно влево *)
      for i:=0 to 39 do begin
       dec(scr_x,3);
       XMoveWindow(display, win, scr_x, scr_y);
       XFlush(display);
       delay(20);
      end;
 
      (* перемещаем окно вниз *)
      for i:=0 to 39 do begin
       inc(scr_y,3);
       XMoveWindow(display, win, scr_x, scr_y);
       XFlush(display);
       delay(20);
      end;
 
      (* перемещаем окно вправо *)
      for i:=0 to 39 do begin
       inc(scr_x,3);
       XMoveWindow(display, win, scr_x, scr_y);
       XFlush(display);
       delay(20);
      end;
 
      (* перемещаем окно вверх *)
      for i:=0 to 39 do begin
       dec(scr_y,3);
       XMoveWindow(display, win, scr_x, scr_y);
       XFlush(display);
       delay(20);
      end;
     end;
 
     delay(1000);
 
     (* пример сворачивания и восстановления окна *)
     begin
      (* сворачиваем окно *)
      XIconifyWindow(display, win, XDefaultScreen(display));
      XFlush(display);
      delay(2000);
      (* восстанавливаем окно *)
      XMapWindow(display, win);
      XFlush(display);
      delay(2000);
     end;
 
     XFlush(display);
 
     (* короткая передышка *)
     delay(2000);
 
     (* закрываем соединение с Х сервером *)
     XCloseDisplay(display);
    end.

1.1.10 Лабораторная работа #1 "Основные понятия Xlib"

   1. Используя компилятор командной строки, выполните компиляцию примера из п. 1.1 и выполните полученную программу.
   2. Настройте интегрированную среду Анюта для работы с кириллицей и выполните компиляцию в ней предыдущей программы.
   3. На основе примера напишите программу, которая при нажатии клавиши мыши пишет сообщение Pressed, а при отпускании - Released.
   4. Используя функции XFlush() / XSync() и delay(), напишите программу без цикла обработки сообщений, отображающую черное окно размером 100х100 пикселей в течение 5 секунд.

1.2 Текст и графика

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

1.2.1 Графический контекст

   Прежде чем начать работу с графикой, программа должна выделить себе специальную структуру данных и получить указатель на нее. Эта структура называется графическим контекстом(Graphic Context (GC)). Указатель на GC используется в качестве одного из параметров при вызове "рисующих" функций X. Графический контекст содержит ряд атрибутов, влияющих на отображение объектов: текста, линий, фигур и др. Выделенный GC должен быть освобожден до завершения работы программы.
   Графический контекст создается процедурой XCreateGC(), имеющей следующий прототип:
    functionXCreateGC(prDisplay: PDisplay; nDrawable: TDrawable; nValueMask: cardinal; prValues: PXGCValues): TGC; cdecl; external;
   Первый аргумент - это указатель на структуру типа TDisplay, который программа получает после вызова XOpenDisplay(); второй - идентификатор окна (или карты пикселей), в котором программа будет рисовать; третий - битовая маска, определяющая, какие атрибуты GC задаются; последний аргумент - структура типа TXGCValues, определяемая следующим образом:
    TXGCValues = record
     Xfunction: longint; {Renamed function to Xfunction}
     plane_mask: cardinal;
     foreground: cardinal;
     background: cardinal;
     line_width: longint;
     line_style: longint;
     cap_style: longint;