: Программирование в среде X Window на основе библиотеки Xlib :

С о д е р ж а н и е

Введение

I. Базовые понятия X Window
Характеристики X-окна
Менеджер окон
Свойства и атомы
Первый пример
События
Атрибуты окна
Операции над окнами

II. Текст и графика
Графический контекст
Характеристики графического контекста
Вывод текста, работа с шрифтами
Использование цвета
Битовые и пиксельные карты
Изменяем курсор мыши

III. Работа с внешними устройствами
Клавиатура
Мышь

IV. Ресурсы программ
Формат файла ресурсов
Доступ к ресурсам программ

V. Взаимодействие клиентов
Механизм свойств
Работаем с менеджером окон

VI. Дополнительная информация

VII. Литература

Работа с внешними устройствами

Клавиатура

Клавиатура используется в большинстве программ, которые пишутся пользователями и для пользователей. В X Window, когда пользователь нажимает(отпускает) клавишу, сервер получает соответствующий сигнал, который преобразуется в событие и отправляется в очередь программы, имеющей фокус ввода (input focus).

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

Когда окно получает фокус, соответствующей программе посылается событие FocusIn, при потере - приходит событие FocusOut.

Когда пользователь нажимает клавишу клавиатуры, программа получает событие KeyPress. Сервер также может послать событие KeyRelease, когда клавиша отпускается, но это справедливо не для всех типов компьютеров.

Оба этих события сопровождаются структурой типа XKeyEvent. Ее поле keycode содержит код нажатой клавиши, а поле state - состояние клавиш-модификаторов и кнопок мыши. Модификаторами называются такие клавиши, как Shift, Ctrl, Caps Lock. Кроме этого, X предусматривает наличие дополнительных модификаторов, которые обозначаются Mod1, ..., Mod5. Каждой нажатой клавише-модификатору и кнопке мыши соответствует флаг в поле state.

Коды, передаваемые через поле keycode структуры XKeyEvent, однозначно идентифицируют клавиши. Их конкретные значения зависят от типа машины и клавиатуры. Эти коды можно назвать физическими. Чтобы обеспечить переносимость программ, сервер устанавливает соответствие между физическими кодами клавиш, которые могут меняться от компьютера к компьютеру, и целочисленными константами - логическими кодами (символами). Они имеют предопределенные значения, которые приведены в файле /usr/include/X11/keysymdef.h и начинаются с префикса "XK_". Так, букве "a" соответствует символ XK_a, клавише <Return> (<Enter>) - символ XK_Return и т.д.

Для разных алфавитов X поддерживает разные множества логических кодов. Возможные типы алфавитов перечисляются в файле /usr/include/X11/keysym.h.

Одному коду клавиши может соответствовать несколько символов в зависимости от состояния клавиш-модификаторов. Функция

KeySym XKeycodeToKeysym (Display* display, KeyCode keycode,
    int index);

позволяет по коду keycode получить соответствующий ему символ с номером index. Если index равен 0, то полученный символ соответствует просто нажатой клавише. Если index равен 1, то возвращается символ,соответствующий ситуации, когда клавиша нажата одновременно с Shift.

Функция XKeysymToKeycode() осуществляет обратное преобразование.

Программа может получить карту соответствия кодов и символов, обратившись к функции XGetKeyboardMapping().

Изменяется соответствие физических и логических кодов функцией XChangeKeyboardMapping(). Следующая последовательность операторов ставит клавише <F2> в соответствие символ XK_F3.

........
Keysym	F2sym, F3symbol;
int	nF2Keycode;
Display	*display;
........
F2symbol = XStringToKeysym ("F2");
F3symbol = XStringToKeysym ("F3");
nF2Keycode = XKeysymToKeycode (display, F2symbol);
XChangeKeyboardMapping (display, F2keycode, 1, &F3symbol, 1);
........

Здесь использована функция XStringToKeysym(), которая по строке "str" возвращает соответствующий символ XK_str.

Когда соответствие кодов меняется, всем работающим в настоящее время клиентам посылается событие MappingNotify.

Клавиши-модификаторы также имеют логические коды. Клавишам Shift сопоставлены символы XK_Shift_L и XK_Shift_R; Caps Lock соответствует XK_CapsLock; Control - XK_Control_L; Mod1 - XK_Meta_L и XK_Meta_R. Символы остальных модификаторов (Mod2 - Mod5) не определены. X содержит набор специальных функций, которые позволяют получить и установить соответствие код-символ для модификаторов. Эти функции следующие: XGetModifierMapping(), XInsertModifiermapEntry(), XDeleteModifiermapEntry(), XSetModifierMapping().

X не останавливается на задании соответствия код клавиши - символы, а идет дальше. Система позволяет программе сопоставить любой комбинации модификаторов и клавиш (например,<Shift+Ctrl+A>) ASCII строку (например, "EXIT"). Для некоторых клавиш соответствующие строки задаются сервером по умолчанию. Так, символу XK_A соответствует строка "A".

Макрос XRebindKeysym() берет символ, список модификаторов и сопоставляет им строку.

Функция XLookupString(), наоборот, берет событие о нажатии (отпускании) клавиши и возвращает соответствующие ему символ и строку. Последний ее параметр - указатель на структуру типа XComposeStatus. Дело в том, что некоторые клавиатуры имеют специальную клавишу Compose, которая позволяет печатать символы, которым нет соответствия среди клавиш. Специальная таблица указывает, какой символ должен быть создан, если обычна клавиша нажимается одновременно с Compose. Ссылка на эту информацию и возвращается в структуре XComposeStatus.

Ниже приводится фрагмент программы, которая распознает функциональные клавиши <F1>-<F5>, и при их нажатии печатает соответствующую строку. Программа также сопоставляет комбинации <Shift+Control+A> строку "EXIT". Эта комбинация используется для завершения программы.

........
Display	*display;
int	screenNumber;
GC	gc;
XEvent	report;
Window	window;
char	keyStr[20];
KeySym	keySym, modList[2];
int	n;

/* Устанавливаем связь с сервером, получаем номер экрана . . . */
.........
/* Задаем соответствие символ-строка */
modList[0] = XK_Control_L;
modList[1] = XK_Shift_L;
XRebindKeysym (display, XK_F6, modList, 2, "EXIT",
   strlen ("EXIT"));
  /* Цикл получения и обработки событий */

while (1) {
  XNextEvent (display, &report);
  switch (report.type) {
   ......
   case KeyPress :
     /* Очищаем строку */
     memset (keyStr, 0, sizeof (keyStr));

     /* Получаем строку, соответствующую событию */
     XLookupString (&report.xkey, keyStr),
       sizeof (keyStr), &keySym, NULL);
     if ( !strcmp (keyStr, "EXIT"))
     {
      XFreeGC (display, gc);
      XCloseDisplay (display);
      exit (0);
     }

     n = keySym == XK_F1 ? 1 :
       keySym == XK_F2 ? 2 :
       keySym == XK_F3 ? 3 :
       keySym == XK_F4 ? 4 :
       keySym == XK_F5 ? 5 : 0;

     if (n) {
      sprintf (keyStr, "F%d pressed.", n);
      XClearWindow (display, window);
      XDrawString (display, window, gc, 10, 50,
          keyStr, strlen (keyStr));
     }
     break;
  }
}
........

Сервер имеет ряд атрибутов, воздействующих на обработку сигналов клавиатуры. Получить их можно с помощью функции XGetKeyboardControl(). Она возвращает указанные параметры в переменной, имеющей тип XKeyboardState, определенный следующим образом:

typedef struct {
 int key_click_percent;
 int bell_percent;
 unsigned int bell_pitch, bell_duration;
 unsigned long led_mask;
 int global_auto_repeat;
 char auto_repeats[32];
} XKeyboardsState;

Поле key_click_percent указывает, имеет ли нажатие клавиши звуковое сопровождение; значения поля задаются в %; 0 - звукового сопровождения нет, 100 - громкий звук. Поле bell_percent, bell_pitch и bell_duration указывают, какую силу, частоту и продолжительность имеет предупреждающий сигнал, возникающий при нажатии некоторых клавиш.

Некоторые клавиатуры используют для клавиш-модификаторов световую подсветку. Поле led_mask представляет собой комбинацию флагов, показывающую, для каких клавиш эта подсветка используется.

Когда клавиша нажата и удерживается, то сервер может автоматически имитировать ее повторное нажатие. Поле global_auto_repeat определяет, делает это сервер или нет. Особенностью X является то, что автоматическую генерацию событий о нажатии можно разрешать или запрещать для отдельных клавиш. Массив auto_repeats содержит информацию о том, для каких клавиш автоповтор включен, а для каких нет. Каждый бит массива соответствует клавише с определенным физическим кодом. Если бит установлен, то генерация разрешена, если сброшен, то запрещена. Каждый байт N массива содержит биты для клавиш с кодами от 8N до 8N+7.

Изменить параметры клавиатуры можно с помощью XChangeKeyboardControl().

Желаемые установки передаются через переменную, которая указывает на структуру типа XKeyboardControl, определяемую следующим образом:

typedef struct {
 int key_click_percnet;
 int bell_percent;
 int bell_pitch;
 int bell_duration;
 int led;
 int led_mode;
 int key;
 int auto_repeat_mode;
} XKeyboardControl;

Первые четыре поля совпадают с аналогичными полями структуры XKeyboardState. Поля led и led_mode позволяют сообщить серверу, какие из клавиш-модификаторов должны сопровождаться подсветкой. Если поле led не задано, и led_mode равно LedModeOn, то изменяется состояние всех клавиш, для которых поддерживается световое сопровождение. Если led_mode равно LedModeOff, то состояние клавиш не меняется. Если поле led задано, то это есть комбинация флагов, указывающих, для каких клавиш подсветку включить (led_mode равно LedModeOn) или выключить (led_mode равно LedModeOff).

Поля key и auto_repeat_mode определяют, для какой клавиши (клавиш) включить (auto_repeat_mode равно AutoRepeatModeOn) или выключить (auto_repeat_mode равно AutoRepeatModeOff) режим автоматического повтора. Если поле key задано, то автоматический повтор включается или выключается только для клавиши с кодом key.

<<< Содержание >>>