Рассмотрим способы манипуляций окнами можно не только с помощью атрибутов: Xlib предоставляет набор функций для изменения их размеров, перемещения на экране и в стеке окон, сворачивания и т.п.
Первая пара операций, которые можно применить к окну - отображение или скрытие. Отображение окна заставляют окно появиться на экране, скрытие приводит к удалению с экрана (хотя логическое окно в памяти все еще существует). Например, если в вашей программе есть диалоговое окно, вместо создания его каждый раз по запросу пользователя, мы можем создать окно один раз в скрытом режиме и, когда пользователь запросит открыть диалог, просто отобразить окно на экране. Когда пользователь нажимает
"OK
" или "Cancel
", окно скрывается. Это значительно быстрее создания и уничтожения окна, однако стоит ресурсов, как на стороне клиента, так и на стороне X сервера.
Отображение окна может быть выполнено с помощью XMapWindow()
, скрытие - с помощью XUnmapWindow()
. Функция отображения заставит событие Expose
послаться программе, если только окно полностью не закрыто другими окнами.
Другое действие, которое можно выполнить над окнами - переместить их в другую позиции. Это может быть выполнено функцией XMoveWindow()
, которая принимает новые координаты окна. Имейте в виду, что после перемещения окно
может быть частично скрытым другими окнами (или наоборот, открыто ими), и таким образом, может быть сгенерировано сообщение Expose
.
Изменить размер окна можно с помощью функции XResizeWindow()
. Мы можем также объединить перемещение и изменение размеров, используя одну функцию XMoveResizeWindow()
.
Все приведенные выше функции изменяли свойства одного окна. Существует ряд свойств, связанных с данным окном и другими окнами. Одно из них - порядок засылки в стек: порядок, в котором окна располагаются друг над другом. Говорят, что окно переднего плана находится на верхе стека, а окно заднего плана - на дне стека. Перемещение окна на вершину стека осуществляет функция XRaiseWindow()
, перемещение окна на дно стека - функция XLowerWindow()
.
С помощью функции XIconifyWindow()
окно может быть свернуто, а с помощью XMapWindow()
- восстановлено. Для того, чтобы понять, почему для XIconifyWindow()
нет обратной функции, необходимо заметить, что, когда окно сворачивается, на самом деле оно скрывается, а вместо него отображается окно иконки. Таким образом, чтобы восстановить исходное окно, нужно просто отобразить его снова. Иконка является на самом деле другим окном, которое просто тесно связано сильно с нашим нормальным окном - это не другое состояние нашего окна.
Следующий пример демонстрирует использование операций над окнами:
#include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> Window create_simple_window(Display* display, int width, int height, int x, int y) { int scr_number = DefaultScreen(display); int win_border_width = 2; Window window; window = XCreateSimpleWindow(display, RootWindow(display, scr_number), x, y, width, height, window_border_width, BlackPixel(display, scr_number), WhitePixel(display, scr_number)); XMapWindow(display, window); XFlush(display); return window; } int main(int argc, char* argv[]) { Display* display; /* указатель на структуру дисплея Х */ int scr_number; /* количество экранов для размещения окон */ Window window; /* дескриптор создаваемого окна */ unsigned int display_width, display_height; /* высота и ширина Х дисплея */ unsigned int window_width, window_height; /* высота и ширина нового окна */ char *display_name = getenv("DISPLAY"); /* имя Х дисплея */ /* устанавливаем соединение с Х сервером */ display = XOpenDisplay(display_name); if (display == NULL) { fprintf(stderr, "%s: не могу соединиться с Х сервером '%s'\n", argv[0], display_name); exit(1); } /* получаем геометрию экрана по умолчанию для нашего дисплея */ scr_number = DefaultScreen(display); display_width = DisplayWidth(display, scr_number); display_height = DisplayHeight(display, scr_number); /* создаем новое окно */ window_width = (display_width / 6); window_height = (display_height / 6); /* печать в стандартный вывод */ printf("ширина окна - '%d'; высота - '%d'\n", window_width, window_height); /* создаем простое окно как прямой потомок корневого окна экрана, */ /* используя черный и белый цвета в качестве основного и фонового, и*/ /* размещая новое окно в верхнем левом углу по заданным координатам */ window = create_simple_Window(display, window_width, window_height, 0, 0); XFlush(display); /* отдохнем после трудов праведных */ sleep(3); /* пример изменения размеров окна */ { int i; /* в цикле уменьшаем окно */ for (i=0; i<40; i++) { window_width -= 3; window_height -= 3; XResizeWindow(display, window, window_width, window_height); XFlush(display); usleep(20000); } /* в цикле увеличиваем окно */ for (i=0; i<40; i++) { window_width += 3; window_height += 3; XResizeWindow(display, window, window_width, window_height); XFlush(display); usleep(20000); } } sleep(1); /* пример перемещения окна */ { int i; XWindowAttributes window_attr; int x, y; int scr_x, scr_y; Window child_window; /* переменная для хранения дескриптора родительского окна */ Window parent_window; /* вначале получаем текущие атрибуты окна */ XGetWindowAttributes(display, window, &window_attr); x = window_attr.x; y = window_attr.y; /* затем находим окно родителя */ { /* эта переменная будет хранить дескриптор корневого окна */ /* экрана, на котором отображено наше окно */ Window root_window; /* эта переменная будет хранить массив дескрипторов */ /* дочерних окон нашего окна, */ Window* child_win; /* а эта - их количество */ int num_child_win; /* выполним запрос необходимых значений */ XQueryTree(display, window, &root_window, &parent_window, &child_win, &num_child_win); /* мы должны освободить список дочерних дескрипторов, */ /* так как он был динамически выделен XQueryTree() */ XFree(child_win); } /* Транслируем локальные координаты в экранные, используя */ /* корневое окно как окно, относительно которого выполняется */ /* трансляция. Это работает потому, что корневое окно всегда */ /*занимает весь экран, и его левый верхний угол совпадает */ /* с левым верхним углом экрана */ XTranslateCoordinates(display, parent_window, window_attr.root, x, y, &scr_x, &scr_y, &child_window); /* перемещаем окно влево */ for (i=0; i<40; i++) { scr_x -= 3; XMoveWindow(display, window, scr_x, scr_y); XFlush(display); usleep(10000); } /* перемещаем окно вправо */ for (i=0; i<40; i++) { scr_x += 3; XMoveWindow(display, window, scr_x, scr_y); XFlush(display); usleep(10000); } } sleep(1); /* пример сворачивания и восстановления окна */ { /* сворачиваем окно */ XIconifyWindow(display, window, DefaultScreen(display)); XFlush(display); sleep(2); /* восстанавливаем окно */ XMapWindow(display, window); XFlush(display); sleep(2); } XFlush(display); /* короткая передышка */ sleep(2); /* закрываем соединение с Х сервером */ XCloseDisplay(display); return 0; }
Пример программы example3.c