Рассмотрим способы манипуляций окнами можно не только с помощью атрибутов: 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