[ Назад ] [ Содержание ] [ Далее ]

Полноценное окно приложения

     Если программа, как в предыдущем примере открывает окно с помощью функции XCreateSimpleWindow, то потом придется дополнительно настраивать слишком много параметров. Поэтому XCreateSimpleWindow используется не так уж часто.

     Воспользуемся для создания окна функцией XCreateWindow. Однако, кроме параметров, указываемых функции структурой XSetWindowAttributes у окна существуют параметры, относящиеся к оконному менеджеру. Сразу все параметры можно установить при помощи функции XSetWMProperties, либо установить лишь самые необходимые, вызывая отдельные функции.

     Следует иметь ввиду, что не все оконные менеджеры принимают во внимание все атрибуты. Это порождает некоторые проблемы в том плане, что одно и тоже приложение в разных менеджерах может работать по-разному. Подчастую програмист устанавливает значения доверяясь лишь своей интуиции. Атрибуты оконного менеджера были рассчитаны на тот интерфейс, который был в моде многие годы назад. С тех пор графический интерфейс функционально изменился и некоторые атрибуты стали для оконных менеджеров ненужными. В качестве наглядного примера можно привести участок исходного кода библиотеки GTK:

  size_hints.flags = PSize;
  size_hints.width = private->width;
  size_hints.height = private->height;
       
  /* FIXME: Is there any point in doing this? Do any WM's pay
   * attention to PSize, and even if they do, is this the
   * correct value???
   */
  XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);

     Программист в комментариях выражает неуверенность в правильности установки значений ширины и высоты окна, поскольку не смог обнаружить реакции в каком-либо оконном менеджере на указанные значения.

     Помимо этого менеджеры очень активно вмешиваются в параметры окон верхнего уровня и подчастую подменяют некоторые указанные значения атрибутов окон верхнего уровня на свои. Примером тому может служить первоначальные координаты окна верхнего уровня. Менеджер может использовать свою подсистему первоначального расположения окон и указанные значения координат главного окна в нижеприведенном примере будут проигнорированы. Если необходимо расположить окно в каком-то конкретном месте рабочего стола, необходимо принудительно переместить окно на нужную позицию после его создания, но перед тем, как сделать его видимым. Также примерами могут служить невозможность установки бордюра для окон уровня - менеджеры как правило не дают его установить и блокирование менеджером функции смены порядка расположения окон верхнего уровня XRestackWindows.

    Чтобы исключить влияние менеджера на окно верхнего уровня необходимо при создании или изменении параметров окна в структуре XSetWindowAttributes в поле override_redirect записать значение true и включить в маске использование этого поля, но при этом все управление окном приложение должно взять на себя.

Пример ex002.c:
#include <stdio.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

int main(int argc, char **argv)
 {
  Display *ourDisplay;
  int ourScreen;
  Window  myWindow, rootWindow, childWindow;
  unsigned long bgcolor;
  int myDepth;
  XSetWindowAttributes myAttr;
  Visual *myVisual;  
  XSizeHints mySizeHints;
  XClassHint myClassHint;
  char *myPropertyData;
  char *myClassName="example";
  char *myResName="example";
  char *iconName;
  
  ourDisplay=XOpenDisplay(NULL);
  if (ourDisplay==NULL)
    {
      printf("Не удалось установить соединение с графическим терминалом.\n");
      return 1;
    };

  /* Получим предварительные сведения */
  ourScreen=DefaultScreen(ourDisplay);           /* Экран по-умолчанию        */
  rootWindow=RootWindow(ourDisplay, ourScreen);  /* Корневое окно             */
  bgcolor=WhitePixel(ourDisplay, ourScreen);     /* Белый цвет экрана         */
  myDepth=DefaultDepth(ourDisplay, ourScreen);   /* Глубина цветности экрана  */
  myVisual=DefaultVisual(ourDisplay, ourScreen); /* Визуальные характеристики */

  /* Заполняем атрибуты окна */
  myAttr.background_pixel=bgcolor;

  /* Создаем окно */
  myWindow=XCreateWindow(ourDisplay,rootWindow,100, 100, 320, 200,
    0, myDepth, InputOutput, myVisual, CWBackPixel, &myAttr);
    
  /* Устанавливаем заголовок окна */
  XStoreName(ourDisplay,myWindow,"Example window");

  /* Устанавливаем заголовок иконки */
  XSetIconName(ourDisplay,myWindow,"example");

  /* Устанавливаем ограничения на размеры окна */
  mySizeHints.flags=PMinSize | PMaxSize | PResizeInc;
  mySizeHints.min_width=192; mySizeHints.min_height=128;
  mySizeHints.max_width=640; mySizeHints.max_height=480;
  mySizeHints.width_inc=10; mySizeHints.height_inc=10;
  XSetWMNormalHints(ourDisplay, myWindow, &mySizeHints);

  /* Устанавливаем атрибут командной строки */
  XSetCommand(ourDisplay, myWindow, argv, argc);

  /* Устанавливаем атрибут класса */
  myClassHint.res_name=myResName;
  myClassHint.res_class=myClassName;
  XSetClassHint(ourDisplay,myWindow,&myClassHint);

  /* Создаём дочерние окна */
  myAttr.background_pixel=BlackPixel(ourDisplay, ourScreen);
  childWindow=XCreateWindow(ourDisplay,myWindow,10, 10, 40, 30,
    0, myDepth, InputOutput, myVisual, CWBackPixel, &myAttr);

  myAttr.win_gravity=NorthEastGravity;
  childWindow=XCreateWindow(ourDisplay,myWindow,270, 10, 40, 30,
    0, myDepth, InputOutput, myVisual, CWBackPixel | CWWinGravity, &myAttr);

  myAttr.win_gravity=SouthWestGravity;
  childWindow=XCreateWindow(ourDisplay,myWindow,10, 160, 40, 30,
    0, myDepth, InputOutput, myVisual, CWBackPixel | CWWinGravity, &myAttr);

  myAttr.win_gravity=SouthEastGravity;
  childWindow=XCreateWindow(ourDisplay,myWindow,270, 160, 40, 30,
    0, myDepth, InputOutput, myVisual, CWBackPixel | CWWinGravity, &myAttr);

  myAttr.win_gravity=CenterGravity;
  childWindow=XCreateWindow(ourDisplay,myWindow,140, 85, 40, 30,
    0, myDepth, InputOutput, myVisual, CWBackPixel | CWWinGravity, &myAttr);

  /* Делаем окна видимыми */
  XMapWindow(ourDisplay, myWindow);
  XMapSubwindows(ourDisplay, myWindow);
  
  /* Все сформированные команды принудительно сбрасываем на сервер */
  XFlush(ourDisplay);

  /* Спим 50 секунд */
  sleep(10);
  
  /* Уничтожаем окно */
  XDestroyWindow(ourDisplay, myWindow);

  /* Закрываем соединение с сервером */
  XCloseDisplay(ourDisplay);

  return 0;
 };

    Эта программа создает окно, у которого уже есть заголовок, максимальный и минимальный размеры, а также шаг, с которым окно будет изменяться в размере.

     У созданного окна имеется пять дочерних окон с установленными привязками к элементам периметра родительского окна. Они будут автоматически перемещаться при смене размера главного окна.

     Большинство атрибутов главного окна в этой программе заполняются необходимыми значениями и в итоге это окно можно считать полноценным окном приложения.


[ Назад ] [ Содержание ] [ Далее ]