ВВЕДЕНИЕ
Темой данной проектной работы является создание своего оконного менеджера для Linux.
Оконный менеджер является важным для пользователя, так как с его
помощью можно запускать графические приложения. Эта тема интересна для нас, в первую очередь, тем, что я сам пользуюсь Linux и хотел попробовать создать оконный менеджер, используя Framebuffer.
Целью проектной работы является создание своего оконного менеджера, который будет стабильно и полно функционировать.
Задачами данной работы являются:
- Написать библиотеку для взаимодействия с пользователем в терминале Linux.
- Создать свой оконный менеджер для Linux.
ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
Что такое LINUX
Linux— это семейство Unix-подобных ОС на базе ядра Linux, включающих тот или иной набор утилит и программ проекта GNU, и, возможно, другие компоненты. Как и ядро Linux, системы на его основе, как правило, создаются и распространяются в соответствии с моделью разработки свободного и открытого программного обеспечения. Linux-системы распространяются в основном бесплатно в виде различных дистрибутивов - в форме готовой для распространения.
Операционная система Linux, в отличии от Windows, не имеет единой графической среды. Она позволяет менять окружения, из наиболее популярных Mutter (Gnome), Kwin (KDE) и тайловый менеджер окон i3.
Различные оконные менеджеры предоставляют разные функции, разный вид, разную производительность и иногда различные api для взаимодействием с приложениями. Остановимся поподробнее на видах оконных менеджеров.
Виды оконных менеджеров
Mutter
Оконный менеджер Mutter (рабочая среда - GNOME) использует графическую библиотеку Clutter, что дает ему возможность использовать OpenGL.
Mutter может функционировать как автономный оконный менеджер для рабочих столов, подобных GNOME, и служит основным оконным менеджером для оболочки GNOME, которая является неотъемлемой частью GNOME 3. Сам GNOME является лишь дополнением(расширением) для Mutter.
Kwin
Оконный менеджер для рабочей среды KDE. Поддерживает множество цветовых схем (которые можно создать в том числе и самому), поддерживает настройку с помощью QtScript, QML. Одной из самых популярных тем является «Windows-like».
Может работать с помощью OpenGL 1.2, OpenGL 2.0, OpenGL 3.1 и OpenGL ES 2.0. Главное отличие в огромном количестве настроек, которые оценит каждый пользователь.
I3
Это «тайловый» менеджер окон. Он не подразумевает наложения окон друг на друга, а позволяет настраивать размеры окон. Управляется при помощью простых текстовых конфигурационных файлов. Для него же были созданы простые меню, которые позволяют сильно изменить взаимодействие системы с пользователем.
Виды графических рендереров
X11
X11 — это база для всех оконных менеджеров. Именно он предоставляет методы для создания окон, причем он не взаимодействует с фреймбуффером, а реализует свою систему Xserver. Вся его система поддерживается уже около 20-ти лет, и поэтому она очень громоздкая.
Framebuffer (фреймбуффер)
Однако в Linux существует и Framebuffer. Он существовал с самого начала ОС Linux, и специально для него существует библиотека Framebuffer для C/C++. Она позволяет манипулировать пикселями, читать пиксели - в этом и есть ее функционал.
Framebuffer — это специальный файл в который можно писать (или читать из него), чтение происходит дольше, чем запись, поэтому гораздо эффективнее будет наложение файла на определенный участок памяти (на память нашей программы).
Библиотеки, используемые при написании оконного сервиса
Библиотека mouse поможет считывать состояния мыши. Используется для просмотра передвижения мышки, с помощью этой библиотеки программа отрисовывает курсор, поддерживает нажатие кнопок мыши (правая, левая, средняя) и многое другое. Она не умеет работать с координатами, однако это можно сделать самостоятельно.
Библиотека keyboard позволяет считывать нажатия клавиш, геймпада и прочих устройств с клавишами (сенсорные нажатия тоже входят в эту категорию). Некоторые события нажатия на кнопки считаются устаревшими.
Теория оконного менеджера
Менеджер окон — компьютерная программа, управляющая размещением и определяющая внешний вид окон в оконной системе графического пользовательского интерфейса. Оконные менеджеры работают «поверх» существующей оконной системы, обеспечивающей требуемую функциональность, такую как поддержку графического оборудования, манипуляторов, клавиатуры.
Для создания, часто используются библиотеки, который предоставляют базовый функционал для пользователя(такой как обработка нажатий/мыши/клавиатуры.
Оконный менеджер должен уметь:
- Запускать приложения;
- Отображать окна корректно;
- Работать со вводом.
ПРАКТИЧЕСКАЯ ЧАСТЬ
1. Написание библиотеки.
Для начала нам нужно было написать библиотеку для взаимодействия с Framebuffer. Она должна уметь рисовать пиксели, примитивные фигуры, уметь работать с клавиатурой и мышкой.
Для записи пикселя в Framebuffer нужно наложить Framebuffer на массив. После этого изменяя цифры в массиве, мы будем изменять пиксели в Framebuffer.
Используя данную функцию, мы можем создать функцию для рисования графических примитивов.
void drawpixel(uint32_t x, uint32_t y, const char *rgb) {
int pixel = hextorgb(rgb);
uint32_t location = x*vinfo_t.bits_per_pixel/8 + y*finfo_t.line_length;
*((uint32_t*) (fbp + location)) = pixel;
}
void drawrect(int x, int y, int x2, int y2, const char *rgb){
for ( int i_x=x; i_x<x2; i_x++){
for ( int i_y=y; i_y<y2; i_y++){
drawpixel(i_x, i_y, rgb);
}
}
}
Функции для рисования обычной линии (вертикальной или горизонтальной).
void draw_horizontal_line(int x1, int x2, int y, const char *rgb)
{
int i;
for (i=x1;i<x2;i++)
drawpixel(i,y,rgb);
}
void draw_vertical_line(int x, int y1, int y2, const char *rgb)
{
int i;
for (i=y1;i<y2;i++)
drawpixel(x,i,rgb);
}
После этого мы реализовали обработку нажатий на кнопки мыши, ее передвижение по оси x и y. Библиотека mouse предоставляет большое количество кодов ивентов, например, нажатие на левую кнопку мыши обозначается BUTTON_MOUSE, движение по оси x/y — REL_X, REL_Y.
2. Написание оконного менеджера.
Общение между клиентом и сервером происходит через пайпы:
- Сервер → Клиент. Сервер может отсылать события нажатия на клавиши, принимать соединения от клиента.
- Клиент → Сервер. Клиент отсылает действия по типу отрисовки пикселей/примитивов в окне, а сервер их принимает.
Программа ради неблокирующего приема соединений от клиента работает в потоках. Один поток на прием запросов от клиента и второй на считывание кодов мышки. Они соединяются с основным и в итоге работают параллельно.
Сама программа разделена на две функции: mouse_handler и client_thread.
В mouse_handler считываются нажатия на кнопки мыши / передвижение мыши. С помощью этих данных отрисовывается курсор и отсылаются события нажатия клиенту (приложениям). При грамотной поддержке при помощи данного функционала можно реализовать кнопки в приложении.
В client_thread читаются действия клиента, например, если клиент захотел создать окно, то он добавляется в список окон, после этого всем существующим окном отправляется событие о перерисовке окон. Они в свою очередь отправляют необходимые события серверу и в случае необходимости перерисовывают окно на новую позицию или с новыми пикселями.
Для отсылания ивентов клиенту мы используем продвинутые структуры по типу server_event, или client_event. Через них мы можем универсально передавать любое действие сервера, например, если код действия равен 1, то клиент свободно может прочитать нажатия на кнопки мыши, если код действия равен 2, то это ивент, направленный на перерисовку всех окон.
struct client_event {
int type;
int need_redraw;
struct window win;
};
struct server_event {
int id;
int type;
struct input_event_improved inputEventImproved;
struct window win;
};
ЗАКЛЮЧЕНИЕ
Итак, в результате работы все задачи, поставленные нами, были
выполнены. В процессе создания библиотеки для взаимодействия с Linux, мы познакомились с системным программированием подробнее. В проектной части мы написали свой оконный менеджер и считаем, что написать свой оконный менеджер и создать небольшую рабочую оболочку возможно.
В настоящее время системное программирование является таким же важным, а специалистов все меньше, поэтому я считаю, что работа практически ценная.
Данная работа для нас является очень интересной, поэтому
планируется и дальше поддерживать код созданного менеджера, исправлять
возникающие ошибки и улучшать ее. В данной работе оболочка была
написана с использованием библиотеки Framebuffer, и хотелось бы также попробовать написать ее с использованием библиотеки DRM.
СПИСОК ЛИТЕРАТУРЫ
https://github.com/8l/fbui
https://github.com/deniskropp/DirectFB
http://betteros.org/tut/graphics1.php
https://github.com/drmad/rpi-framebuffer