Содержание
- 2. Рисунок конфигурации двухцентрового завитка спирали
- 3. Задание на разработку программы динамического построения спирали в графическом окне Разработать программу динамического построения спирали в
- 4. Задание на разработку программы динамического построения спирали в графическом окне (продолжение) Каждое нажатие указанных клавиш должно
- 5. Код программы мультипликации завитка Исходный код программы мультипликации завитка спирали составляют два модуля из прикладных функций
- 6. Структура завитка XPiAr2 В этой завитковой структуре радиальное (R) и угловое (А) поля обозначают полярные координаты
- 7. Значения радиального и дугового (полу)шагов и их синхронизация друг с другом Знаки значений радиального и дугового
- 8. Превентивное объявление прототипов завершает заголовочный файл следующими спецификациями: int maxisize(XPiAr2*, char*); /* Размаха спирали */ int
- 9. Стандартные заголовки Х-графики Прикладной модуль составляют все завитковые и управляющие прикладные функции программы, которые вызывает ее
- 10. Исходные данные программы Исходными данными программы являются модуль полушага завитка, равный радиусу начального завитка R0 и
- 11. Исходный текст функции maxisize () /* Контроль максимального радиуса внешнего завитка */ int maxisize(XPiAr2* pr, char*
- 12. Описание функции decent () Для продолжения инициализации функция main переадресует завитковую структуру XPiAr2 функции decent. Она
- 13. Исходный текст функции decent () Исходный текст функции decent имеет следующий вид. int decent(XPiAr2* pr) {
- 14. Описание функции reset() Чтобы начать построение спирали с внутреннего завитка вызывается функция reset. Ей адресуется структура
- 15. Исходный код функции reset () Исходный код функции reset имеет следующий вид. int reset(XPiAr2* pr) {
- 16. Описание функции reverse () Рассмотренные прикладные функции maxisize, decent и reset вызываются для инициализации спирали. Другие
- 17. Исходный текст функции reverse () Исходный текст функции reverse имеет следующий вид: int reverse(XPiAr2* pr) {
- 18. Определение индекса центра полукруга завитка Функция recent адресует структуру завитка XPiAr2 для контроля центра его полукруга
- 19. Исходный текст функции recent () Исходный текст функции recent , который реализует эту таблицу, имеет следующий
- 20. Функция amod2pi () Функция amod2pi адресует структуру завитка XPiAr2 для циклического изменения угловой координаты (А) полукругов
- 21. Описание функции twist () Обращение к функциям amod2pi и recent происходит из функции twist, которая вызывается
- 22. Исходный текст функции twist () Исходный текст рассмотренной функции twist имеет следующий вид. /* Отобразить 1
- 23. Перерисовка спирали Для перерисовки спирали сначала создается копия адресованной структуры завитков, чтобы получить координаты их центров
- 24. Оптимизация серийных перерисовок Для оптимизации серийных перерисовок функция redraw использует технику отсечения графического вывода. Область отсечения
- 25. Перерисовка фрагмента спирали из центра Рассмотренная функция redraw имеет исходный код: int redraw(Display* dpy, XEvent* ev,
- 26. Интерактивное управление циклом мультипликации 3 прикладные функции overlap, rapid и rep5355 обеспечивают интерактивное управление циклом мультипликации.
- 27. Исходный код функции overlap() int overlap(XEvent* ev) { /* Контроль перекрытий спирали */ return((ev−>xvisibility.state != VisibilityUnobscured)
- 28. Управляющая функция rep5355() Другая управляющая функция rep5355 предназначена для переключения режима автоповтора клавиш "+" и "−"
- 29. Исходный текст функции rep5355() int rep5355(Display* dpy, int r) { /* Автоповтор +/− */ XKeyboardControl kbval;
- 30. Клавиатурная функция rapid() Еще 1 клавиатурная функция rapid реализует управление темпом мультипликаций. При вызове ей адресуется
- 31. Задача клавиатурной обработки функции rapid() Основной задачей клавиатурной обработки функции rapid является регулировка темпа мультипликации клавишами
- 32. Дополнительная обработка функции rapid() Кроме того, предусмотрен возврат отрицательного значения (−32) при нажатии клавиши пробела с
- 33. /* Клавиатурное управление темпом мультипликации */ int rapid(XEvent* ev, int t) { char sym[1]; /* ASCII
- 34. Основная функция main() Рассмотренные прикладные функции вызывает основная функция main , которая одна занимает отдельный основной
- 35. Исходный код функции main() int main(int argc, char* argv[]) { Display *dpy; /* адрес дисплейной структуры
- 36. Описание аргументов функции main() При вызове программы формальные аргументы функции main argc и argv обеспечивают передачу
- 37. Дисплейный блок Дисплейный блок начинается графическим запросом XOpenDisplay , чтобы установить контакт с Х-сервером по дисплейному
- 38. Дисплейный блок { /* Дисплейный блок */ Font fn; /* идентификатор шрифта надписи */ unsigned long
- 39. Оконный блок В следующем оконном блоке создается графическое окно программы. Его габаритные размеры определяются по параметрам
- 40. Оконная переменная (Window) внешнего блока Идентификатор созданного окна записывается в оконную переменную (Window) внешнего блока вместо
- 41. Исходный код оконного блока { /* Оконный блок */ unsigned w, h; /* габариты окна спирали
- 42. Мульти-блок функции main() Мульти-блок функции main реализует цикл асинхронной обработки событий на фоне периодического процесса мультипликации
- 43. Мульти-блок функции main() В частности, при потере изображения в окне по событию типа Expose, его структура
- 44. Мульти-блок функции main() Положительное значение мульти-кода устанавливает степень задержки мультипликации delay по счетчику итераций count цикла
- 45. Исходный текст мульти-блока { /* Мульти-блок */ unsigned long emask; /* маска событий */ XEvent event;
- 47. Скачать презентацию
Слайд 2Рисунок конфигурации двухцентрового завитка спирали
Рисунок конфигурации двухцентрового завитка спирали
Слайд 3Задание на разработку программы динамического построения спирали в графическом окне
Разработать программу динамического
Задание на разработку программы динамического построения спирали в графическом окне
Разработать программу динамического
Слайд 4Задание на разработку программы динамического построения спирали в графическом окне (продолжение)
Каждое нажатие
Задание на разработку программы динамического построения спирали в графическом окне (продолжение)
Каждое нажатие
Слайд 5Код программы мультипликации завитка
Исходный код программы мультипликации завитка спирали составляют два
Код программы мультипликации завитка
Исходный код программы мультипликации завитка спирали составляют два
typedef struct {
int Rm; /* Максимальный радиус полукруга завитка */
int A; /* Угловая координата 0 < A < 360 градусов */
int R; /* Радиус полукруга 0 < R < Rm */
int dA; /* Дуговой шаг завитка |dA| = 1 */
int dR; /* Радиальный полушаг |dR| = R0 */
XPoint C[2]; /* Координаты центров C[1].x − C[0].x = |dR| */
} XPiAr2;
Слайд 6Структура завитка XPiAr2
В этой завитковой структуре радиальное (R) и угловое (А)
Структура завитка XPiAr2
В этой завитковой структуре радиальное (R) и угловое (А)
Слайд 7Значения радиального и дугового (полу)шагов и их синхронизация друг с другом
Знаки
Значения радиального и дугового (полу)шагов и их синхронизация друг с другом
Знаки
Слайд 8Превентивное объявление прототипов завершает заголовочный файл следующими спецификациями:
int maxisize(XPiAr2*, char*); /*
Превентивное объявление прототипов завершает заголовочный файл следующими спецификациями:
int maxisize(XPiAr2*, char*); /*
int reset(XPiAr2*); /* Начальная установка спирали */
int decent(XPiAr2*); /* Координаты центров завитков */
int redraw(XEvent*, GC, XPiAr2*); /* перерисовка спирали */
int reverse(XPiAr2*); /* Реверс мультипликации */
int amod2pi(XPiAr2*); /* Ограничить угловой диапазон */
int recent(XPiAr2*); /* Смена центра полукруга завитка */
int twist(Display*, Window, GC, XPiAr2*); /* Рас(за)крутка */
int rep5355(Display*, int); /* Автоповтор клавиш + и − */
int rapid(XEvent*, int); /* Темп мультипликаций */
int overlap(XEvent*); /* Перекрытие окна спирали */
Слайд 9Стандартные заголовки Х-графики
Прикладной модуль составляют все завитковые и управляющие прикладные функции
Стандартные заголовки Х-графики
Прикладной модуль составляют все завитковые и управляющие прикладные функции
#include
#include
#include
#include
#include "spiral2x.h"
Слайд 10Исходные данные программы
Исходными данными программы являются модуль полушага завитка, равный радиусу начального
Исходные данные программы
Исходными данными программы являются модуль полушага завитка, равный радиусу начального
Слайд 11Исходный текст функции maxisize ()
/* Контроль максимального радиуса внешнего завитка */
int maxisize(XPiAr2*
Исходный текст функции maxisize ()
/* Контроль максимального радиуса внешнего завитка */
int maxisize(XPiAr2*
int R0; /* Радиус внутреннего завитка */
int N; /* Число витков спирали */
int empty; /* Пустое поле для координат x и y */
XParseGeometry(R0xN, &empty, &empty, &R0, &N);
if(((pr−>dR = pr->R = R0) < 1) || (N < 1))
N = R0 = 0;
return(pr->Rm = 2*R0*N); /* возврат max радиуса */
} /* maxisize */
Слайд 12Описание функции decent ()
Для продолжения инициализации функция main переадресует завитковую структуру XPiAr2
Описание функции decent ()
Для продолжения инициализации функция main переадресует завитковую структуру XPiAr2
Слайд 13Исходный текст функции decent ()
Исходный текст функции decent имеет следующий вид.
int decent(XPiAr2*
Исходный текст функции decent ()
Исходный текст функции decent имеет следующий вид.
int decent(XPiAr2*
int w = 2*(pr−>Rm + pr−>R) + (8 + 8); /* R = R0 = dR now */
pr−>c[0].x = w/2 - (pr−>R/2);
pr−>c[1].x = pr−>c[0].x + pr−>R; /* = w/2 + (pr−>R/2); */
pr−>c[0].y = pr−>c[1].y = w/2 + 8;
return(w); /* возврат ширины рамки спирали */
} /* decent */
Слайд 14Описание функции reset()
Чтобы начать построение спирали с внутреннего завитка вызывается функция reset.
Описание функции reset()
Чтобы начать построение спирали с внутреннего завитка вызывается функция reset.
Слайд 15Исходный код функции reset ()
Исходный код функции reset имеет следующий вид.
int reset(XPiAr2*
Исходный код функции reset ()
Исходный код функции reset имеет следующий вид.
int reset(XPiAr2*
pr−>A = (0*64); pr−>dA = (1*64); pr−>R = 0;
if(pr−>dR < 0)
pr−>dR = -pr−>dR;
return(2*(pr−>c[0].y)); /* возврат высоты рамки спирали */
} /* reset */
Слайд 16Описание функции reverse ()
Рассмотренные прикладные функции maxisize, decent и reset вызываются для
Описание функции reverse ()
Рассмотренные прикладные функции maxisize, decent и reset вызываются для
Слайд 17Исходный текст функции reverse ()
Исходный текст функции reverse имеет следующий вид:
int reverse(XPiAr2*
Исходный текст функции reverse ()
Исходный текст функции reverse имеет следующий вид:
int reverse(XPiAr2*
int g = 2; /* индекс графического контекста спирали */
if((pr−>R > pr−>Rm) || (pr−>R == 0)) {
pr−>dR = -pr->dR; pr−>dA = -pr−>dA;
g = (pr−>dA > 0) ? 0 : 1;
} /* if */
return(g);
} /* reverse */
Слайд 18Определение индекса центра полукруга завитка
Функция recent адресует структуру завитка XPiAr2 для контроля
Определение индекса центра полукруга завитка
Функция recent адресует структуру завитка XPiAr2 для контроля
Слайд 19Исходный текст функции recent ()
Исходный текст функции recent , который реализует эту
Исходный текст функции recent ()
Исходный текст функции recent , который реализует эту
int recent(XPiAr2* pr) {/* Смена центра полукруга завитка */
if((pr−>A % (180*64)) != 0)
return(pr->A / (180*64));
pr->R += pr->dR;
return((pr−>A + pr−>dA) / (180*64));
} /* recent */
Слайд 20Функция amod2pi ()
Функция amod2pi адресует структуру завитка XPiAr2 для циклического изменения угловой
Функция amod2pi ()
Функция amod2pi адресует структуру завитка XPiAr2 для циклического изменения угловой
/* Ограничить дуговой угол диапазоном от 0 до 360 */
int amod2pi(XPiAr2* pr) {
pr->A += (pr->dA);
if(pr->A == (360*64))
return(pr->A = (0 * 64));
if(pr->A == (0*64))
pr->A = (360*64);
return(pr->A);
} /* amod2pi */
Слайд 21Описание функции twist ()
Обращение к функциям amod2pi и recent происходит из функции
Описание функции twist ()
Обращение к функциям amod2pi и recent происходит из функции
Слайд 22Исходный текст функции twist ()
Исходный текст рассмотренной функции twist имеет следующий вид.
/*
Исходный текст функции twist ()
Исходный текст рассмотренной функции twist имеет следующий вид.
/*
int twist(Display* dpy, Window win, GC gc, XPiAr2* pr) {
int i = recent(pr); /* индекс центра полукруга завитка */
int R2 = (2*pr->R); /* двойной радиус завитка */
XDrawArc(dpy, win, gc, pr->c[i].x - pr->R, pr->c[i].y - pr->R, R2, R2, pr->A, pr->dA);
XFlush(dpy);
amod2pi(pr);
return(pr->R); } /* twist */
Кроме основного вызова в цикле мультипликаций, функция twist используется в функции redraw для перерисовки завитков спирали при потере изображения в графическом окне. Эта функция предусмотрена для отработки соответствующих событий типа Expose и адресует их стандартную структуру XEvent вместе с завитковой структурой XPiAr2 и графическим контекстом рисования изображения спирали GC(0).
Слайд 23Перерисовка спирали
Для перерисовки спирали сначала создается копия адресованной структуры завитков, чтобы получить
Перерисовка спирали
Для перерисовки спирали сначала создается копия адресованной структуры завитков, чтобы получить
Кроме спирали, функция redraw осуществляет перерисовку подсказки строки выхода "ALT-X" в юго-западном углу окна по запросу XDrawString. Вертикальный габарит окна, который нужен для позиционирования подсказки, устанавливается по возврату функции reset при инициализации перерисовки копии спирали.
Слайд 24Оптимизация серийных перерисовок
Для оптимизации серийных перерисовок функция redraw использует технику отсечения
Оптимизация серийных перерисовок
Для оптимизации серийных перерисовок функция redraw использует технику отсечения
Слайд 25Перерисовка фрагмента спирали из центра
Рассмотренная функция redraw имеет исходный код:
int redraw(Display*
Перерисовка фрагмента спирали из центра
Рассмотренная функция redraw имеет исходный код:
int redraw(Display*
int y; /* y-смещение подсказки ALT-X */
XPiAr2 r; /* для копии спирали */
static XRectangle clip[32]; /* буфер отсечения */
static int n = 0; /* счетчик отсечений */
clip[n].x = ev->xexpose.x; clip[n].y = ev->xexpose.y;
clip[n].width = ev->xexpose.width;
clip[n++].height = ev->xexpose.height;
if((ev->xexpose.count > 0) && (n < 32))
return(0);
XSetClipRectangles(dpy, gc, 0, 0, clip, n, Unsorted);
r = *pr; /* = memcpy(&r, pr, (sizeof(XPiAr2))); */
y = reset(&r) - 8; . /* инициализация копии спирали */
while(twist(dpy, ev->xexpose.window, gc, &r) < pr->R);
r.dA = (pr->A - r.A);
twist(dpy, ev->xexpose.window, gc, &r);
XDrawString(dpy, ev->xexpose.window, gc, 8, y, "ALT-X", 5);
XSetClipMask(dpy, gc, None);
return(n=0); } /* redraw */
Слайд 26Интерактивное управление циклом мультипликации
3 прикладные функции overlap, rapid и rep5355 обеспечивают
Интерактивное управление циклом мультипликации
3 прикладные функции overlap, rapid и rep5355 обеспечивают
Самая короткая из них функция overlap() вызывается при любых изменениях статуса видимости графического окна программы по событию VisibilityNotify, структуру XEvent которого адресует ее аргумент. Для контроля указанных изменений проверяется поле состояния state этой структуры. Любая величина в нем, кроме визуальной константы VisibilityUnObscured , означает, что окно становится полностью или частично невидимо. В этом случае возвращается отрицательный стоп-код = (−32), чтобы приостановить мультипликации спирали. Когда окно станет полностью видимо, функции overlap адресуется структура XEvent, значение поля состояния которой равно VisibilityUnObscured. В этом случае предусмотрен возврат 0, чтобы сбросить стоп-код и возобновить мультипликации. Исходный текст функции имеет вид.
Слайд 27Исходный код функции overlap()
int overlap(XEvent* ev) {
/* Контроль перекрытий спирали */
return((ev−>xvisibility.state !=
Исходный код функции overlap()
int overlap(XEvent* ev) {
/* Контроль перекрытий спирали */
return((ev−>xvisibility.state !=
} /* overlap */
Слайд 28Управляющая функция rep5355()
Другая управляющая функция rep5355 предназначена для переключения режима автоповтора клавиш
Управляющая функция rep5355()
Другая управляющая функция rep5355 предназначена для переключения режима автоповтора клавиш
Слайд 29Исходный текст функции rep5355()
int rep5355(Display* dpy, int r) { /* Автоповтор +/−
Исходный текст функции rep5355()
int rep5355(Display* dpy, int r) { /* Автоповтор +/−
XKeyboardControl kbval; /* структура контроля клавиатуры */
unsigned long kbmask = (KBKey | KBAutoRepeatMode);
kbval.key = XKeysymToKeycode(dpy, XK_KP_Add);
kbval.auto_repeat_mode = r;
XChangeKeyboardControl(dpy, kbmask, &kbval);
kbval.key = XKeysymToKeycode(dpy, XK_KP_Subtract);
XChangeKeyboardControl(dpy, kbmask, &kbval);
return(r);
} /* rep5355 */
Слайд 30Клавиатурная функция rapid()
Еще 1 клавиатурная функция rapid реализует управление темпом мультипликаций.
Клавиатурная функция rapid()
Еще 1 клавиатурная функция rapid реализует управление темпом мультипликаций.
Слайд 31Задача клавиатурной обработки функции rapid()
Основной задачей клавиатурной обработки функции rapid является
Задача клавиатурной обработки функции rapid()
Основной задачей клавиатурной обработки функции rapid является
Слайд 32Дополнительная обработка функции rapid()
Кроме того, предусмотрен возврат отрицательного значения (−32) при нажатии
Дополнительная обработка функции rapid()
Кроме того, предусмотрен возврат отрицательного значения (−32) при нажатии
Специальная обработка предусмотрена на случай одновременного нажатия ком клавиш Х и ALT. Распознавание клавиатурной комбинации ALT-Х обеспечивает маскировка поля состояния state структуры XEvent полученного события по альтернативе логических кодов XK_X(x) клавиши Х. При соответствии значения этого поля маске Mod1Mask модификатора ALT функция rapid возвращает 0. Такой 0-возврат используется в функции main для установки нулевого значения мульти-кода, которое прерывает цикл обработки событий и мультипликаций, чтобы корректно завершить выполнение программы. Рассмотренная функция rapid имеет следующий исходный код.
Слайд 33/* Клавиатурное управление темпом мультипликации */
int rapid(XEvent* ev, int t) {
char
/* Клавиатурное управление темпом мультипликации */
int rapid(XEvent* ev, int t) {
char
KeySym code[1]; /* X-код клавиши */
XLookupString((XKeyEvent* ) ev, NULL, 0, code, NULL);
switch(code[0]) { case XK_plus:
/* ускорить темп мультипликаций */
case XK_KP_Add: /* (уменьшить задержку) */
if(t > 1)
t >>= 1;
break;
case XK_minus: /* замедлить темп мультипликаций */
case XK_KP_Subtract: /* (увеличить задержку) */
if(t < (1 << 30))
t <<= 1;
break;
case XK_space: /* остановить спираль пробелом */
t = (-32);
break;
case XK_x:
case XK_X: /* выход по ALT-X */
if(ev->xkey.state & Mod1Mask)
t = 0;
break;
default: /* разморозить спираль */
break;
} /* switch */
return(t);
} /* rapid */
Слайд 34Основная функция main()
Рассмотренные прикладные функции вызывает основная функция main , которая
Основная функция main()
Рассмотренные прикладные функции вызывает основная функция main , которая
#include
#include
#include "spiral2x.h"
Остальную часть основного модуля занимает исходный код основной функции main. Он делится на логические блоки, информационную связь которых обеспечивают формальные параметры стандартных командных аргументов функции main(argc, argv[]) и автоматические переменные системных графических типов {Display, Window, GC}, а также прикладной завитковой структуры XPiAr2. Блочную организацию функции main иллюстрирует следующий макро-код:
Слайд 35Исходный код функции main()
int main(int argc, char* argv[]) {
Display *dpy; /* адрес
Исходный код функции main()
int main(int argc, char* argv[]) {
Display *dpy; /* адрес
Window win; /* корневое окно спирали */
GC gc[2]; /* черный и белый графические контексты */
XPiAr2 helix; /* структура завитка спирали */
{ /* Дисплейный блок */ }
{ /* Оконный блок */ }
{ /* Мульти блок */ }
{ /* Блок выхода */ }
} /*main*/
Слайд 36Описание аргументов функции main()
При вызове программы формальные аргументы функции main argc и
Описание аргументов функции main()
При вызове программы формальные аргументы функции main argc и
4 автоматические переменные внешнего main-блока определяют адрес структуры графического дисплея (Display), идентификатор корневого и основного окна программы (Window), пару графических контекстов (GC) для рисования и стирания изображения спирали, а также структуру ее завитков XPiAr2. Значения этих автоматических переменных будут доступны всем блокам.
Слайд 37Дисплейный блок
Дисплейный блок начинается графическим запросом XOpenDisplay , чтобы установить контакт
Дисплейный блок
Дисплейный блок начинается графическим запросом XOpenDisplay , чтобы установить контакт
В стандартной структуре графического контекста рисования переустанавливается белый цвет изображения по графическому макросу WhitePixel и запросу XsetForeground (для контраста с черным по умолчанию цветом фона, который имеет пиксельный код 0). В этом графическом контексте также загружается и устанавливается шрифт надписей с размером (и алиасом названия) 9x15. С этой целью применяются графические запросы XLoadFont и XSetFont. Как правило стандартный шрифт "9x15" имеется в дистрибутиве X Window System, поэтому соответствующая проверка результата его загрузки не производится. Первый в паре графический контекст стирания, который имеет по умолчанию черный цвет изображения и фона, не изменяется. Исходный текст рассмотренного дисплейного блока имеет следующий вид:
Слайд 38Дисплейный блок
{ /* Дисплейный блок */
Font fn; /* идентификатор шрифта надписи
Дисплейный блок
{ /* Дисплейный блок */
Font fn; /* идентификатор шрифта надписи
unsigned long tone; /* пиксельный тон для белого цвета */
dpy = XOpenDisplay(NULL); /* Контакт с Х-сервером */
scr = DefaultScreen(dpy); /* Номер экрана по умолчанию */
win = DefaultRootWindow(dpy); /* Корневое окно экрана */
gc[0] = XCreateGC(dpy, win, 0, 0); /* Пара графических */
gc[1] = XCreateGC(dpy, win, 0, 0); /* контекстов */
tone = WhitePixel(dpy, scr); /* Белый код = 0xFFFFFF; */
XSetForeground(dpy, gc[0], tone); /* Задать белый цвет и */
fn = XLoadFont(dpy, "9x15"); /* Загрузить шрифт */
XSetFont(dpy, gc[0], fn); /* Установить шрифт в GC */
} /* Display block */
Слайд 39Оконный блок
В следующем оконном блоке создается графическое окно программы. Его габаритные размеры
Оконный блок
В следующем оконном блоке создается графическое окно программы. Его габаритные размеры
Полученные значения передаются запросу XCreateWindow, по которому создается графическое окно необходимого размера для отображения спирали. Оно становится подокном корневого окна экрана, наследуя его визуальный класс и глубину цветовых плоскостей по паре параметров CopyFromParent. Кроме того, формально задаются нулевые координаты и толщина рамки 1, а через структуру оконных атрибутов XSetWindowAttributes адресуются пиксельный код фона окна в ее поле background_pixel и внешнее обрамление оконного менеджера, установкой значения False в ее поле override_redirect. При этом (черный по умолчанию) цвет фона определяется из структуры XGCValues любого графического контекста спирали по запросу XGetGCValues.
Слайд 40Оконная переменная (Window) внешнего блока
Идентификатор созданного окна записывается в оконную переменную (Window)
Оконная переменная (Window) внешнего блока
Идентификатор созданного окна записывается в оконную переменную (Window)
Слайд 41Исходный код оконного блока
{ /* Оконный блок */
unsigned w, h; /* габариты
Исходный код оконного блока
{ /* Оконный блок */
unsigned w, h; /* габариты
XSetWindowAttributes attr; /* структура атрибутов окна */
XGCValues gval; /* структура графического контекста */
unsigned long amask; /* маска атрибутов окна */
Window root = win; /* идентификатор корневого окна */
XSizeHints hint; /* Геометрические свойства WM */
Atom wdw[1]; /* WM-атом удаления окна по Х */
if(argc < 2)
argv[1] = "16x8"; /* Параметры спирали по умолчанию */
while(1) { /* Установка габарита окна и параметров спирали */
if(maxisize(&r, argv[1]) == 0)
maxisize(&r, argv[1] = "16x8");
w = decent(&r);
if((h = reset(&r)) < DisplayHeight(dpy, scr))
break;
argv[1] = "16x8";
} /* while */
amask = (CWOverrideRedirect | CWBackPixel); /* фон и WM */
XGetGCValues(dpy, gc[1], GCBackground, &gval);
attr.background_pixel = gval.background; /* Черный фон = 0 */
attr.override_redirect = False; /* WM-контроль окна */
win = XCreateWindow(dpy, root, 0, 0, w, h, 1, CopyFromParent,
InputOutput, CopyFromParent, amask, &attr);
hint.flags = (PMinSize | PMaxSize); /* фиксировать габариты */
hint.min_width = hint.max_width = w; /* окна спирали для */
hint.min_height = hint.max_height = h; /* для WM */
XSetNormalHints(dpy, win, &hint);
XStoreName(dpy, win, "spiral"); /* задать название окна */
wdw[0] = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
XSetWMProtocols(dpy, win, wdw, 1); /* отключить Х окна */
XMapWindow(dpy, win); /* отобразить окно спирали */
} /* window block */
Слайд 42Мульти-блок функции main()
Мульти-блок функции main реализует цикл асинхронной обработки событий на фоне
Мульти-блок функции main()
Мульти-блок функции main реализует цикл асинхронной обработки событий на фоне
Слайд 43Мульти-блок функции main()
В частности, при потере изображения в окне по событию типа
Мульти-блок функции main()
В частности, при потере изображения в окне по событию типа
Для обработки события VisibilityNotify вызывается функция overlap, которая адресует его структуру XEvent. Своим отрицательным возвратом она обеспечивает остановку мультипликаций спирали, пока окно программы не будет полностью видимо на экране. Как только это произойдет, новый вызов функции overlap сбросит ее стоп-код мультипликации freeze своим нулевым возвратом.
События FocusIn и FocusOut программа получает, когда меняется фокус ввода ее окна. Для их обработки вызывается функция rep5355 с аргументом AutoRepeatModeOff или AutoRepeatModeOn, чтобы выключить или включить режим автоповтора нажатия клавиш '+' и '−' на клавиатуре, когда окно программы получает или, соответственно, передает (теряет) фокус ввода.
Обработку клавиатурных событий типа KeyPress при нажатии клавиш реализует функция rapid , которой адресуется их структура XEvent и параметр темпа мультипликации. Ее возврат фиксирует управляющий мульти-код multi, который используется в зависимости от своей величины. Его равно 0 при выходе или больше 0 в процессе мультипликаций.
Слайд 44Мульти-блок функции main()
Положительное значение мульти-кода устанавливает степень задержки мультипликации delay по счетчику
Мульти-блок функции main()
Положительное значение мульти-кода устанавливает степень задержки мультипликации delay по счетчику
Продолжительность задержки может быть переустановлена регулировкой положительного мульти кода возврата функции rapid по клавиатурным событиям нажатия клавиш '+' и '−' для ускорения или замедления темпа мультипликации, соответственно. Возврат отрицательного мульти-кода (по нажатию клавиши пробела) фиксирует спираль, аналогично событию VisibilityNotify. В обоих случаях требуемый эффект достигается обнулением счетчика итераций count на каждой итерации цикла обработки событий перед сравнением с задержкой delay. Это исключает вызов функции twist. Поэтому спираль не может изменяться до перезаписи мульти-кода положительным возвратом функции rapid при нажатии любой клавиши, чтобы возобновить мультипликацию. Нулевой мульти-код возврата функции rapid (при нажатии комбинации клавиш ALT-X на клавиатуре) прерывает цикл обработки событий в мульти-блоке функции main. Исходный текст мульти-блока имеет следующий вид.
Слайд 45Исходный текст мульти-блока
{ /* Мульти-блок */
unsigned long emask; /* маска событий
Исходный текст мульти-блока
{ /* Мульти-блок */
unsigned long emask; /* маска событий
XEvent event; /* структура событий */
int freeze = 0; /* визи-стоп спирали */
unsigned delay = (1<<12); /* период мульти-задержки */
int multi = (1<<12); /* мульти-код */
int count = 0; /* счетчик мульти-задержки */
int g = 0; /* индекс графического контекста */
emask = (ExposureMask | KeyPressMask | FocusChangeMask |
VisibilityChangeMask); /* задать маску событий */
XSelectInput(dpy, win, emask); /* для обработки */
while(multi != 0) { /* асинхронная обработка событий */
event.type = 0; /* сбросить тип предыдущего события */
XCheckWindowEvent(dpy, win, emask, &event);
switch(event.type) { /* анализ типа события */
case Expose: redraw(&event, gc[0], &r); /* перерисовка */
break; /*при потере изображения */
case VisibilityNotify: freeze = overlap(&event);
break; /* визи−стоп код спирали */
case FocusIn: rep5355(dpy, AutoRepeatModeOff);
break; /* отключить авто-повтор + и − */
case FocusOut: rep5355(dpy, AutoRepeatModeOn);
break; /* включить авто-повтор */
case KeyPress: if((multi = rapid(&event, delay)) > 0)
count = delay = multi;
break; /* контроль мульти-темпа */
default: break;
} /* switck */
if((multi < 0) || (freeze < 0)) /* мульти-стоп спирали */
continue;
if(count++ < delay) /* мульти-задержка спирали */
continue;
count = 0; /* сбросить счетчик задержки */
twist(dpy, win, gc[g], &r); /* проход на 1 градус спирали */
if((argc = reverse(&r)) < 2) /* мульти-реверс спирали */
twist(dpy, win, gc[g = argc], &r);
} /* while event */
} /* multi block */