X11 GUI Library
Лёгкая GUI-библиотека для C++20 на X11: программный рендеринг, частичная перерисовка (dirty rectangles), TTF-шрифты (FreeType), две темы (WIN11 / TERMINAL), плавные анимации и встроенная отладка как в Android Studio.
✨ Возможности
- Частичная перерисовка — обновляются только изменённые области, а не весь экран
- Двойная буферизация — без мерцания
- TTF/TTC шрифты через FreeType с кешированием (быстрый текст)
- Две темы:
WIN11(скругления, синий акцент) иTERMINAL(квадратная, зелёная) + полная кастомизация - Анимации: hover, нажатие (push-down), галочки, dropdown, мигающий курсор
- EventBus + колбэки на виджетах
- Отладка: оверлей FPS, визуализация dirty-областей, маркеры кликов, границы виджетов (F1–F6)
- Только активная страница рендерится — остальные не жгут CPU
🖼 Скриншоты
Темы
| WIN11 | TERMINAL |
|---|---|
![]() |
![]() |
Переключение на лету — клавиша F6.
Виджеты
| Controls (кнопки, ввод, чекбоксы, слайдер, прогресс) | Lists (список, dropdown, дерево, скролл) |
|---|---|
![]() |
![]() |
| Graphics (RawPicture: круги, полигоны, текст) |
|---|
![]() |
Отладка
| Debug overlay (F1) — FPS, виджеты, partial updates, лог событий | Dirty rectangles (F2) — подсветка перерисованных областей |
|:---:|
|
|
🚀 Быстрый старт
#include "gui.h"
int main() {
gui::set_theme(gui::ThemeStyle::WIN11);
gui::window win("My App");
win.set_font("SGr-Iosevka-Regular.ttc"); // любой TTF/TTC рядом с бинарником
win.set_default_icon();
win.configur_page("main", [](gui::page& p) {
gui::WidgetData b;
b.id = "btn"; b.text = "Hello";
b.x = 100; b.y = 100; b.width = 300; b.height = 70;
b.primary = true; // акцентная кнопка
p.Button(b);
}, true);
gui::EventBus::get().on("button.click", [](const gui::EventData& e) {
std::cout << "clicked: " << e.source_id << "\n";
});
while (win.running()) win.update();
return 0;
}
Или просто запусти демо со всеми виджетами:
#include "gui.h"
int main() { gui::run_demo(); }
🛠 Сборка
Зависимости
# Ubuntu/Debian
sudo apt install libx11-dev libfreetype-dev cmake g++
# Fedora
sudo dnf install libX11-devel freetype-devel cmake gcc-c++
# Arch
sudo pacman -S libx11 freetype2 cmake
CMake
cmake_minimum_required(VERSION 3.10)
project(host)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(X11 REQUIRED)
find_package(Freetype REQUIRED)
add_executable(host
main.cpp
libs/gui/core/event_bus.cpp
libs/gui/core/raw_picture.cpp
libs/gui/core/font_manager.cpp
libs/gui/core/theme.cpp
libs/gui/widgets/widget.cpp
libs/gui/widgets/draw_basic.cpp
libs/gui/widgets/draw_toggles.cpp
libs/gui/widgets/draw_lists.cpp
libs/gui/window.cpp
libs/gui/demo.cpp
)
target_include_directories(host PRIVATE libs/gui ${X11_INCLUDE_DIR})
target_link_libraries(host PRIVATE ${X11_LIBRARIES} Freetype::Freetype)
mkdir build && cd build
cmake ..
make -j$(nproc)
./host
Положи
SGr-Iosevka-Regular.ttc(или любой TTF) рядом с бинарником. Если шрифт не найден — используется фолбэк на X11 core font.
🧩 Виджеты
| Метод | Тип | Описание |
|---|---|---|
Button(d) |
BUTTON | Кнопка (primary = true — акцентная) |
Label(d) |
LABEL | Текстовая метка |
Input(d) |
INPUT | Поле ввода: клик — фокус, нижняя линия, мигающий курсор, Enter — input.submit |
Checkbox(d) |
CHECKBOX | Флажок с анимированной галочкой |
Radiobutton(d) |
RADIO | Радио-кнопка (группа по id) |
Slider(d) |
SLIDER | Ползунок 0..1, перетаскивание |
Progressbar(d) |
PROGRESS | Прогресс (+ indeterminate — бегущий) |
Listbox(d) |
LISTBOX | Список с прокруткой и выделением |
Dropdown(d) |
DROPDOWN | Выпадающий список с анимацией |
TreeView(d) + TreeNode(d) |
TREE_VIEW / TREE | Дерево с раскрытием [+]/[-] |
ScrollView(d) |
SCROLL | Контейнер с прокруткой |
RawPictureWidget(d) |
RAW_PIC | Картинка из RawPicture |
SpriteButton(d) |
SPRITE_BTN | Кликабельный спрайт |
Основные поля WidgetData
std::string id, text; // идентификатор и подпись
int x, y, width, height; // геометрия (масштаб x2)
unsigned long bg_color, fg_color, frame_color; // 0 = из темы, иначе override
int font_size; // 0 = системный, иначе свой
bool primary; // акцентная кнопка
bool checked; // checkbox / radio
float value, target_value; // slider / progress (0..1)
std::vector<std::string> items;// listbox / dropdown
std::shared_ptr<RawPicture> picture;
// колбэки:
on_change / on_page_click / on_window_click
🐞 Отладка
Горячие клавиши
| Клавиша | Действие |
|---|---|
| F1 | Debug overlay: FPS, кол-во виджетов, счётчик partial updates, координаты мыши, лог последних событий |
| F2 | Визуализация dirty rectangles — мигание перерисованных областей (как «Show screen updates» в Android) |
| F3 | Маркеры кликов — красный крестик в точке нажатия |
| F4 | Границы всех виджетов (magenta) |
| F5 | Логирование событий в консоль |
| F6 | Переключение темы WIN11 ↔ TERMINAL |
Как читать оверлей (F1)
- FPS — реальная частота перерисовок (в простое ~0, при анимациях до
max_fps) - Widgets — виджетов на активной странице
- Partial updates — сколько dirty-областей перерисовано всего. Растёт медленно = оптимизация работает
- Mouse — координаты курсора
- EVENT LOG — последние 5 событий шины
Что показывает F2
Каждая перерисованная область на 0.2 сек подсвечивается XOR-цветом. Наведи на кнопку — мигнёт только она. Двинь слайдер — мигнёт только слайдер. Если мигает весь экран — значит ты сам позвал mark_all_dirty().
Программное управление
win.debug().show_debug_overlay = true; // F1
win.debug().show_dirty_rects = true; // F2
win.debug().show_click_markers = true; // F3
win.debug().show_widget_bounds = true; // F4
win.debug().log_to_console = true; // F5
win.debug().max_log_size = 30;
win.mark_dirty(x, y, w, h); // пометить область как грязную
win.mark_all_dirty(); // перерисовать всё
win.set_max_fps(144); // лимит кадров
- Что снять (имена файлов = ссылки в README):
| Файл | Что показать |
|---|---|
theme_win11.png |
демо в теме WIN11 |
theme_terminal.png |
нажми F6 → тема TERMINAL |
widgets_controls.png |
страница controls |
widgets_lists.png |
страница lists |
widgets_graphics.png |
страница graphics |
debug_overlay.png |
нажми F1 |
debug_dirty.png |
F2 + покликай кнопки |
debug_clicks.png |
F3 + покликай |
debug_bounds.png |
F4 |
- Закоммить папку
docs/screenshots/— и картинки появятся на Gitea.
📁 Структура проекта
/
├── README.md
├── docs/
│ ├── index.html ← интерактивная документация
│ └── screenshots/ ← скриншоты для README
└── gui/
├── gui.h ← umbrella-заголовок
├── demo.h / demo.cpp ← run_demo()
├── window.h / window.cpp ← окно, dirty-рендер, оверлей, иконка
├── core/
│ ├── common.h ← EventData, DebugInfo, DirtyRegion, easing
│ ├── event_bus.h/.cpp
│ ├── raw_picture.h/.cpp ← пиксельный буфер + примитивы + BMP/PPM
│ ├── font_manager.h/.cpp ← TTF + кеш текста
│ └── theme.h/.cpp ← WIN11 / TERMINAL
└── widgets/
├── widget.h / widget.cpp ← WidgetData, Widget, combat, page
├── draw_basic.cpp ← Button, Label, Input, Sprite
├── draw_toggles.cpp ← Checkbox, Radio, Slider, Progress
└── draw_lists.cpp ← Listbox, Dropdown, Tree, Scroll
📚 Документация
Полная интерактивная документация (9 страниц: старт, окно, виджеты, темы, свои виджеты, события, анимации, отладка, API):
👉 docs/index.html — открой в браузере
📄 Лицензия
MIT.
👤 Автор
KoDer — git.bipfr.ru/KoDer/gui




