Minimal GUI toolkit for Linux (X11) and Windows (Win32). Software rendered, unity build (#include "mkgui.c"). Breeze-inspired styling. No third-party dependencies beyond FreeType2 and Xlib/GDI. The X11/Win32 windowing layer lives in a small sibling library, mkwin, pulled in as a git submodule.
This is a personal project by a single developer. It works well for what it does, but it has not been exhaustively tested across every platform, hardware configuration, or edge case. Use it, enjoy it, file issues if something breaks -- but don't expect the test coverage of a toolkit backed by a corporation. There are no guarantees, no roadmap, and no promises.
mkgui is in beta. The author has used it to ship several working applications, so the core widget set, layout engine, and rendering pipeline are stable in practice. The public API is not frozen -- naming, flags, and signatures may still change between tags if something turns out to be a bad idea.
master is the development branch. It can change behaviour, break API, or introduce regressions between commits without notice -- that's what it's for.
For anything you intend to ship, pin to a release tag. Tags are the stability anchor; master is not.
# direct clone pinned to a tag
git clone https://github.com/<user>/mkgui.git
cd mkgui
git checkout v0.5.0-beta
git submodule update --init --recursive # fetch the mkwin platform-layer submodule
# or as a submodule of your own project
git submodule add https://github.com/<user>/mkgui.git mkgui
cd mkgui && git checkout v0.5.0-beta && git submodule update --init --recursivemkgui's own platform layer, mkwin, is itself a submodule, so the git submodule update --init --recursive step is required after any clone or checkout -- mkgui.c #includes the mkwin sources and will not compile without them. (Tags before v0.5.0-beta predate the submodule and simply skip that step.)
If you need a fix that only exists on master, open an issue so it can be cherry-picked into the next tag rather than silently depending on a moving target.
- 45+ widget types: buttons, inputs, checkboxes, dropdowns, sliders, spinboxes, treeviews, listviews, gridviews, tabs, menus, toolbars, statusbars, toggles, comboboxes, datepickers, and more
- Auto-layout containers: VBox, HBox, Form, Group, Tabs, Splitters
- Software rendering via XShm (Linux) and GDI (Windows) -- no GPU required
- Built-in file dialogs, message boxes, input dialogs, color picker
- SVG icon system via PlutoSVG (Freedesktop icon naming, theme-aware monochrome)
- Toolbar display modes: icons only, text only, icons + text
- DPI scaling with auto-detection and
MKWIN_SCALEenvironment variable override - Keyboard accelerators with automatic menu shortcut display
- Undo/redo in text input and textarea widgets
- External file drag-and-drop (XDnd on Linux, WM_DROPFILES on Windows)
- Visual editor with drag-and-drop, property editing, and C code generation
- Unity build:
#include "mkgui.c"and compile - ~260KB stripped binary, ~5MB BSS, instant startup
The editor generates complete, compilable C source files. Design your UI visually, set events, and hit Generate -- the output compiles and runs immediately.
See documentation/editor.md for the full editor guide.
mkgui pulls its X11/Win32 windowing layer from the mkwin git submodule, so make sure it is checked out -- mkgui.c #includes the mkwin sources and will not compile without them.
- Get the mkgui source with its submodule:
git clonethe repo, thengit submodule update --init --recursive(or copy bothmkgui/and itsmkwin/subdirectory into your project). #include "mkgui.c"in your application.- Compile and link, adding the mkwin submodule to the include path with
-Imkwin:# Linux gcc -std=c99 -O2 -Imkwin myapp.c -o myapp \ $(pkg-config --cflags freetype2 fontconfig) -lX11 -lXext \ $(pkg-config --libs freetype2 fontconfig) -lm # Windows (MinGW) x86_64-w64-mingw32-gcc -std=c99 -O2 -Imkwin myapp.c -o myapp.exe -lgdi32 -mwindows
-Imkwinpoints at the submodule directory; adjust the path ifmkwin/is not a subdirectory of your build directory. NoMKWIN_*defines are needed --mkgui.cenables the mkwin font and glview modules itself. - Place an
icons/directory next to your executable with SVG icons (see Icon section below)
OpenGL is only required if the application uses the MKGUI_GLVIEW widget (add -lGL on Linux or -lopengl32 on Windows). The core library, editor, and all other widgets have no GPU dependency.
#include "mkgui.c"
enum { ID_WIN = 0, ID_BTN = 1, ID_LBL = 2 };
static void on_event(struct mkgui_window *win, struct mkgui_event *ev, void *userdata) {
(void)userdata;
switch(ev->type) {
case MKGUI_EVENT_CLOSE: {
mkgui_ctx_quit(mkgui_window_get_ctx(win));
} break;
case MKGUI_EVENT_CLICK: {
if(ev->id == ID_BTN) {
mkgui_label_set(win, ID_LBL, "Clicked!");
}
} break;
}
}
int main(void) {
struct mkgui_widget widgets[] = {
MKGUI_W(MKGUI_WINDOW, ID_WIN, "Hello", "", 0, 400, 300, 0, 0, 0),
MKGUI_W(MKGUI_BUTTON, ID_BTN, "Click", "", ID_WIN, 100, 0, MKGUI_FIXED, 0, 0),
MKGUI_W(MKGUI_LABEL, ID_LBL, "Ready", "", ID_WIN, 0, 0, 0, 0, 0),
};
struct mkgui_ctx *ctx = mkgui_ctx_create();
if(!ctx) return 1;
struct mkgui_window *win = mkgui_window_create(ctx, NULL, widgets, 3, NULL, 0, 0);
if(!win) {
mkgui_ctx_destroy(ctx);
return 1;
}
mkgui_ctx_run(ctx, on_event, NULL);
mkgui_window_destroy(win);
mkgui_ctx_destroy(ctx);
return 0;
}mkgui uses SVG icons via PlutoSVG, following the Freedesktop icon naming standard. Icons are loaded at runtime from a flat directory:
mkgui_icon_load_svg_dir(win, "icons"); // load all SVGs from icons/
mkgui_icon_load_svg(win, "my-icon", "path.svg"); // load a single iconMonochrome icons using currentColor automatically follow the theme text color and update on theme switch.
- Linux: if no bundled
icons/directory is found, mkgui automatically falls back to the user's installed system icon theme (Papirus, Breeze, Adwaita, ...). Applications can run without shipping any icons and still display correct visuals. The editor's icon browser also scans system theme directories. - Windows: there is no system icon theme. Both end-user applications and the editor require a bundled
icons/directory (or an unpacked Freedesktop theme next to the binary for the editor's icon browser). Without one, widgets fall back to a magenta-diamond placeholder and the icon browser appears empty.
Windows users must therefore download a Freedesktop icon theme (e.g. Papirus, Breeze) and either drop it next to the editor as ./Papirus/ for browsing, or run extract_icons to produce an icons/ directory to ship with the application.
# extract_icons <icons_list.txt> <output_dir> [theme_dir] [size]
./out/extract_icons myapp_icons.txt icons/ ./Papirus 16The icons list is produced by the editor; dynamically-loaded icons can be added to myapp_icons_extra.txt. See the getting started guide for the full workflow.
./build.sh # normal (debug symbols)
./build.sh release # optimized, stripped
./build.sh debug # -g -O0out/linux/mkguibench measures layout, full rendering, dirty rendering, completed presentation, and complete frames independently:
out/linux/mkguibench layout mixed 2048 1920 1080 10000
out/linux/mkguibench render buttons 256 1920 1080 1000
out/linux/mkguibench dirty mixed 256 1920 1080 10000
out/linux/mkguibench present fill 0 1920 1080 1000
out/linux/mkguibench frame mixed 256 1920 1080 1000The output is one machine-readable row containing total time, time per iteration, time per widget or pixel, a minimum effective framebuffer bandwidth, and a framebuffer checksum. Use a real X server for presentation measurements. Xvfb is suitable for correctness and repeatability checks but does not represent display-server or hardware presentation cost.
For hardware counters, run a sufficiently long case pinned to one CPU:
taskset -c 2 perf stat -r 5 -e cycles,instructions,branches,branch-misses,cache-references,cache-misses out/linux/mkguibench render mixed 256 1920 1080 5000mkgui targets C99 and builds with either MinGW GCC or clang-cl (LLVM's MSVC-compatible driver). Plain MSVC cl.exe is not tested but the source should be compatible; please report issues.
The easiest option is MSYS2, which gives you a native MinGW GCC on Windows:
- Install MSYS2
- Open the MSYS2 UCRT64 terminal
- Install the toolchain and FreeType:
pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-freetype
- Build your application (Windows uses GDI for fonts, so no fontconfig is needed):
Add
gcc -std=c99 -O2 -Imkwin myapp.c -o myapp.exe -lgdi32 -mwindows
-lopengl32only if the application usesMKGUI_GLVIEW. Buildingdemo.crequires-lopengl32since the demo showcases the GL view widget.
Cross-compiling from Linux also works. The included build.sh automatically builds Windows executables if x86_64-w64-mingw32-gcc is available.
mkgui also compiles cleanly with clang-cl against the MSVC runtime. On Windows, install the Build Tools for Visual Studio (or the full IDE) and the Windows SDK, then from a Developer Command Prompt:
clang-cl /O2 /I mkwin ^
-DMKGUI_MAX_ICONS=32768 -D_CRT_SECURE_NO_WARNINGS ^
myapp.c ^
/link /subsystem:windows /entry:mainCRTStartup ^
gdi32.lib user32.lib kernel32.lib shell32.lib advapi32.libAdd opengl32.lib if the application uses MKGUI_GLVIEW. /entry:mainCRTStartup keeps int main(void) as the entry point under /subsystem:windows (equivalent to MinGW's -mwindows).
Cross-compiling from Linux with clang-cl is also possible if you have a copy of the MSVC CRT headers/libraries and the Windows SDK. Point clang at them with /imsvc for each include directory and /libpath: for each library directory, and use -fuse-ld=lld-link so the LLVM linker handles the COFF output:
clang-cl /O2 /I mkwin -fuse-ld=lld-link \
/imsvc <msvc-crt>/include \
/imsvc <winsdk>/Include/ucrt \
/imsvc <winsdk>/Include/um \
/imsvc <winsdk>/Include/shared \
-DMKGUI_LIBRARY -DMKGUI_MAX_ICONS=32768 \
-D_CRT_SECURE_NO_WARNINGS \
mkgui.c demo.c \
/Fedemo.exe \
/link /subsystem:windows /entry:mainCRTStartup \
/libpath:<msvc-crt>/lib/x86_64 \
/libpath:<winsdk>/Lib/ucrt/x86_64 \
/libpath:<winsdk>/Lib/um/x86_64 \
gdi32.lib user32.lib kernel32.lib opengl32.lib shell32.lib advapi32.lib- API reference and widget guide
- Visual editor guide
- Adding new widgets
- Layout engine reference
- Benchmark harness and current baseline
- Latin-1 (ISO 8859-1) text only -- covers Western European languages. No CJK, Arabic, or complex text shaping
- No right-to-left (RTL) layout support
- No accessibility API integration (tab navigation and keyboard accelerators are supported)
Solo project with a strict C style (hard tabs, if( not if (, unity build, no const, no forward declarations, etc. - see the source for the full flavour). Bug reports with a minimal reproducer are very welcome; please file an issue. Pull requests are disabled by choice - any fixes will be applied in-house from a good report. Security-sensitive reports: see SECURITY.md.
MIT

