Книга: Программирование в X Window средствами Free Pascal

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

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.228. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз