Продолжается работа над OS System 6 (ранее Systemicus). Немного разобрался с GUI – кроме некоторых недочетов, она уже близка к рабочему варианту. О чем эта краткая статья.
Забегая вперед, выкладываю ( github.com/omegicus/System6 ) образ HDD для тестирования на QEMU (экспериментировать с мин. значением памяти рано – задайте от 64 Мб, хотя должно работать и на меньших значениях). Если кто захочет открыть образ – вот ссылка на GitHub с кратким описанием файловой системы и Windows-tool для его монтирования. github.com/omegicus/OMFS3
Итак, просто поделюсь своим опытом (еще далеко не окончательным) создания GUI для операционной среды. За всё отвечают по-сути два файла – explorer.exe ( 9 килобайт) и user32.dll (31 Кб).
Собственно, мы уже должны уметь выводить графические примитивы и описывать данную тему не буду, более интересна на мой взгляд именно «подноготная».
Основной структурой оконного менеджера является страктура окон. Каждая запись представлена следующей структурой (в моей реализации):
WNDLIST_ITEM:
.handle dd 0 ; +00
.x dd 0 ; +04
.y dd 0 ; +08
.width dd 0 ; +12
.height dd 0 ; +16
.flags dd 0 ; +20
.rsrc dd 0 ; +24
.parent dd 0 ; +28
.wbmp dd 0 ; +32
.caption dd 0 ; +36
;
.clickx dw 0 ; +40
.clicky dw 0 ; +42
.winstyle dd 0 ; +44
.icon dd 0 ; +48
;
.message dd 0 ; +52
.processid dd 0 ; +56
.res dd 0 ; +60
WNDLIST_ITEM_SZ = 64
Интерес представляет .rsrc содержащий .gui секцию PE-исполняемого файла (некоторая аналогия rsrc Windows PE-файла). При загрузке PE в память под секцию .gui выделяется стандартный блок памяти в 64Кб и туда копируется указанная секция.
.parent указывает на родительское окно (обычно = 0, т.е. родитель это рабочий стол)
.wbmp указывает на память, где содержится 8-битное изображение окна. 256 цветов может показаться мало, но для моей реализации этого вполне хватает. Т.е. окно прорисовуется в данном буфере и только потом выводится на экран. Т.е. это теневой буфер.
.clickx, .clicky – содержат координаты окна, где сейчас находится курсор (даже если клавиша не нажата).
Чтобы отследить события (в т.ч. нажатия на клавиатуру или мышь) существует поле .message – сюда помещается указатель на запись в структуре сообщений. Сама структура сообщений и их реализация у всех может быть разной, поэтому тут о ней не пишу.
Пример отправки сообщения активному приложению:
invoke SendMessage, [activeHndlr], WM_LBUTTONDOWN, param1, param2
Отдельная история с некоем подобием Ddraw. Не стал ограничиваться обычным выведением картинки. Программа должна инициировать создание DDraw области и писать туда напрямую. Пока это реализовано через промежуточный буфер, но тру-подход заключается, конечно же, в ремаппинге виртуальной памяти, дабы буфер указывал напрямую в видеопамять. Это впереди. А пока используется структура Ddraw-окон, в которую записываются координаты и размеры окна вывода, адрес видеопамяти (точнее смещения в ней с которого начинается вывод) и адрес буфера, куда пишет приложения. Адрес смещения видеопамяти – вещь необязательная, т.е. его может вычислить и система, но сделано это для ускорения, чтобы при каждом выводе кадра на экран не вычислять данное смещение.
Теперь о композиции. В принципе, самая большая проблема, с которой столкнулся при создании графического окружения – это клиппинг пикселей при перекрытии окон друг другом. В данной демонстрации всего одно окно, но рабочую реализацию можно увидеть в одном из предыдущих моих постов. В остальном принцип работы такой:
1) отрисовка фона
2) отрисовка окон в теневых буферах (в т.ч. элементов окна)
3) вывод данных буферов на экран.
Далее отслеживаем изменения, а именно клавиатуру и клики мышкой, передаем эти сообщения соответствующим окнам. Происходит некоторые изменения в теневых буферах (либо само приложение что-то отрисовало, либо мы изменили состояние кнопок (этим занимается система)) и после этого рабочий стол обновляется, т.е. идет перерисовка всего. Это происходит достаточно быстро, потому как просто копируются скрытые буферы на экран.
Всё достаточно просто и очевидно, но это на первый взгляд. Документации вменяемой по данной теме очень мало и для тех, кто пишет что-то с нуля (как я) многие вещи открываются путем проб и ошибок.
Автор: omegicus