Foundations
Architecture Notes
This page is the code-grounded architecture summary for the current nappgui_src checkout.
It explains the real library graph, startup path, backend seam, layout model, data binding path,
and platform/runtime boundaries as they exist in the repository today.
Relevant Source Files
What NAppGUI Is
NAppGUI is a cross-platform C SDK for native desktop applications on Windows, macOS, and Linux.
At the public include level, src/nappgui.h exposes the application bootstrap surface from
osapp and the high-level widget surface from gui.
The repository is not just one GUI library. It is a stack of runtime, drawing, GUI, backend, packaging, and helper libraries plus a build-time resource compiler. That distinction matters because the public API feels unified while the internal module graph is deliberately split.
- Base/runtime:
sewer,osbs,core - Graphics and GUI:
geom2d,draw2d,osgui,gui,osapp - Optional support:
encode,inet,ogl3d - Build-time tooling:
tools/nrc
Real Library Stack
The checked-in CMake targets show a layered dependency chain rather than one monolithic framework.
The important edge is that gui does not directly depend on osgui;
both depend on draw2d, and osapp is the layer that joins them.
| Library | Main Role | Depends On |
|---|---|---|
sewer |
Low-level utilities, assertions, memory helpers, and support code. | None |
osbs |
OS basic services. | sewer |
core |
Containers, heap, streams, events, DBind, and resource packs. | osbs |
geom2d |
Geometry primitives and math. | core |
draw2d |
Drawing types, images, fonts, and the base GuiCtx interface. |
geom2d |
osgui |
Native GUI backend implementation. | draw2d |
gui |
High-level GUI composition and controls. | draw2d |
osapp |
Application bootstrap and platform runloop integration. | osgui, gui |
encode |
Serialization and encoding helpers. | core |
inet |
HTTP and network layer. | encode |
ogl3d |
Platform OpenGL context management. | sewer |
Public Bootstrap and Runtime Ownership
The canonical desktop application shape is the osmain(...) macro family, not a hand-written
sequence ending in osapp_run(). The demos define creation and destruction callbacks,
include osapp/osmain.h, and end the translation unit with osmain(...).
At runtime, osmain_imp performs the real bootstrap: osgui_start(),
gui_start(), native GUI context creation through osguictx(),
guictx_set_current(...), and entry into the internal _osapp_run(...) loop.
Shutdown unwinds in the reverse order through gui_finish() and osgui_finish().
- Write
i_createandi_destroycallbacks. - Include
osapp/osmain.h. - Use
osmain(i_create, i_destroy, "", App). - Let the runtime own backend startup, context install, runloop entry, and shutdown.
GuiCtx: The Backend Abstraction Layer
GuiCtx is the key seam that explains how the high-level gui library avoids a direct
dependency on one platform backend. The interface lives under draw2d and consists of function-pointer
tables for control creation, sizing, windows, menus, cursors, drawing, and event/listener hooks.
In practice this is an internal backend contract, not a standalone public subsystem. The repository currently
ships one concrete provider: the native backend created by osguictx() in osgui.
References to possible future alternative contexts are architectural direction, not second shipped backends.
guiowns composition: widget trees, layouts, and higher-level behavior.GuiCtxowns backend hooks: native controls, sizing, window operations, and event bridge points.osguisupplies the implementation: the real shipped context is the native one.
UI Composition Model
Layout
Layout is the core recursive composition structure. Each cell can hold either a
GuiComponent or a nested Layout, and the internal state tracks row and column dimensions,
cell padding, alignment, visibility, background/stroke colors, DBind metadata, and bound objects.
The internal comments above _layout_compose() describe a two-phase sizing model:
_layout_natural() computes natural sizes and _layout_expand() distributes the
available space. After composition, _layout_locate() applies the final geometry to controls and sublayouts.
Panel
A Panel is a layout host, not just a single-layout wrapper. Internally it owns
ArrPt(Layout) *layouts plus visible_layout and active_layout,
which allows one panel to keep multiple layout trees and switch the visible one.
Window
window_panel(...) wraps the supplied panel in an internal 1x1 layout and installs that
as the window's root layout. Resize behavior then flows through the layout engine:
the sizing event composes the constrained result size, and the size event locates the layout tree.
Events and Data Binding
Event System
NAppGUI uses a lightweight typed listener model from core/event.h and core/event.cpp.
Events carry sender, parameter, result, and type information, and debug builds track type names and assert correctness.
This is not a generic reactive graph; it is a callback system used broadly across the GUI and runtime layers.
DBind and Layout Binding
DBind is runtime metadata for structs, enums, binary payloads, and containers. The GUI layer builds on it through
layout_dbind(...), layout_dbind_obj(...), cell_dbind(...), and
layout_dbind_update(...) to connect controls and layout cells to object fields.
When a bound control edits a field, gbind.c raises ekGUI_EVENT_OBJCHANGE.
Handlers can inspect the pending edit through EvBind, accept or reject it, and trigger a revert when needed.
Accepted changes then refresh the affected bound controls through the layout binding machinery.
Native Controls vs Custom-Drawn Controls
NAppGUI is not only a thin wrapper over native widgets. Many controls map directly onto platform controls in
osgui, including common buttons, edits, combos, popups, sliders, progress bars, and windows.
Several visible controls are instead implemented as custom View-based widgets using the
ekGUI_TYPE_CUSTOMVIEW backend slot. Verified examples in this checkout include
label, imageview, listbox, and tableview.
That distinction matters when documenting behavior, portability, and styling expectations.
Platform Backends
Windows
The current Windows backend is Win32 plus GDI and GDI+ drawing. This checkout contains extensive
Gdiplus:: usage and explicit comments describing GDI/GDI+ paths rather than a Direct2D renderer.
Optional web support uses WebView2 when enabled.
macOS
The macOS backend is native Cocoa/AppKit. Drawing lives in the Objective-C draw2d path,
and optional web content support uses WKWebView when the deployment target and build options allow it.
Linux
The Linux backend uses GTK3 for the native widget layer. Drawing and text go through the GTK, Cairo, and Pango path, and optional web support uses WebKitGTK when found at configure time.
Build, Packaging, and Resources
The root build uses CMake and exposes the main options NAPPGUI_SHARED, NAPPGUI_DEMO,
and NAPPGUI_WEB. The tree also includes the nrc resource compiler under
tools/nrc, which the build invokes to generate embedded resource code and, in packed mode, runtime bundles.
Resource handling supports two delivery modes: embedded resources compiled into generated C code and packed resource
bundles loaded at runtime. The GUI layer exposes registration through gui_respack(...) and language
selection through gui_language(...).
One packaging detail is easy to miss in the exported CMake config: NAPPGUI_LIBRARIES covers the main
application stack, but not every optional repository target. In this checkout, inet and ogl3d
exist as build targets without being part of that exported convenience variable.
Key Verified Architecture Points
Panelcan host multiple layouts and switch the visible one.window_panel(...)wraps the panel in an internal1x1layout.guidoes not directly depend onosgui; both depend ondraw2d, andosappjoins them.- The canonical desktop app entry is
osmain(...), while_osapp_run(...)is internal. - The Windows backend in this checkout uses GDI/GDI+, not Direct2D.
- The shipped
GuiCtxprovider is the nativeosguiimplementation. - The repository includes
encode,inet,ogl3d, and thenrctool as practical architecture subsystems. - Several visible controls are custom-drawn
View-based widgets rather than native controls. - The resource system is a first-class subsystem with embedded and packed modes.
Recommended Reading Order In The Source Tree
For a fast codebase walkthrough, this order gives a reliable mental model from public surface down to runtime and tooling:
src/nappgui.hdemo/hello/main.csrc/osapp/osapp.handsrc/osapp/osapp.csrc/draw2d/guictx.hxxandsrc/osgui/osguictx.csrc/gui/layout.c,src/gui/panel.c, andsrc/gui/window.csrc/core/event.h,src/core/dbind.h,src/gui/layout.h, andsrc/gui/gbind.cprj/NAppTarget.cmakeandtools/nrc
That path moves from public API, to actual app startup, to backend abstraction, to layout/composition, to binding/events, and finally to build/resource tooling.