13 KiB
DVX Core Library (libdvx.lib)
The core GUI infrastructure for DVX, built as a DXE3 module. Provides
VESA video setup, 2D drawing primitives, dirty-rectangle compositing,
a window manager with Motif-style chrome, and the widget infrastructure
(layout engine, event dispatch, class registration). Individual widget
type implementations live in ../widgets/ as separate .wgt DXE
modules that register themselves at runtime via wgtRegisterClass().
Core knows nothing about individual widget types. There is no WidgetTypeE enum, no widget union, and no per-widget structs in dvxWidget.h. All widget-specific behavior is dispatched through the WidgetClassT vtable.
5-Layer Architecture
| Layer | Header | Source | Description |
|---|---|---|---|
| 1. Video | dvxVideo.h |
dvxVideo.c |
VESA VBE init, LFB mapping, backbuffer, pixel format, packColor() |
| 2. Draw | dvxDraw.h |
dvxDraw.c |
Rect fills, bevels, text, bitmap cursors, focus rects, lines |
| 3. Compositor | dvxComp.h |
dvxComp.c |
Dirty rect tracking, merge, clip, LFB flush |
| 4. Window Manager | dvxWm.h |
dvxWm.c |
Window stack, chrome, drag/resize, menus, scrollbars, hit test |
| 5. Application | dvxApp.h |
dvxApp.c |
Event loop, input polling, color schemes, wallpaper, public API |
Additional modules built into libdvx.lib:
| Header | Source | Description |
|---|---|---|
dvxDialog.h |
dvxDialog.c |
Modal message box and file open/save dialogs |
dvxPrefs.h |
dvxPrefs.c |
INI-based preferences (read/write with typed accessors) |
dvxWidget.h |
widgetClass.c, widgetCore.c, widgetEvent.c, widgetLayout.c, widgetOps.c, widgetScrollbar.c |
Widget infrastructure |
dvxWidgetPlugin.h |
(header only) | Plugin API for widget DXE modules |
| -- | dvxImage.c |
Image loading via stb_image (BMP, PNG, JPEG, GIF) |
| -- | dvxImageWrite.c |
PNG export via stb_image_write |
Source Files
| File | Description |
|---|---|
dvxVideo.c |
VESA mode negotiation, LFB mapping via DPMI, backbuffer alloc, packColor() |
dvxDraw.c |
rectFill(), rectCopy(), drawBevel(), drawText(), drawTextN(), drawTermRow(), cursor rendering |
dvxComp.c |
dirtyListAdd(), dirtyListMerge(), flushRect(), rectIntersect() |
dvxWm.c |
Window create/destroy, Z-order, chrome drawing, drag/resize, menu bar, scrollbars, minimize/maximize |
dvxApp.c |
dvxInit(), dvxRun(), dvxUpdate(), dvxCreateWindow(), color schemes, wallpaper, screenshots |
dvxDialog.c |
dvxMessageBox(), dvxFileDialog() -- modal dialogs with own event loops |
dvxPrefs.c |
prefsLoad(), prefsSave(), typed get/set for string/int/bool |
dvxImage.c |
dvxLoadImage() -- stb_image loader, converts to native pixel format |
dvxImageWrite.c |
dvxSaveImage() -- PNG writer for screenshots |
widgetClass.c |
wgtRegisterClass(), wgtRegisterApi(), wgtGetApi(), class table |
widgetCore.c |
Widget allocation, tree ops, focus management, clipboard, hit testing, cursor blink |
widgetEvent.c |
widgetOnMouse(), widgetOnKey(), widgetOnPaint(), widgetOnResize(), scrollbar management |
widgetLayout.c |
Two-pass flexbox layout: bottom-up calcMinSize, top-down space allocation with weights |
widgetOps.c |
wgtPaint(), wgtLayout(), wgtInitWindow(), text get/set, invalidation |
widgetScrollbar.c |
Scrollbar drawing (H/V), thumb calculation, hit testing, drag update |
Public Headers
| Header | Purpose |
|---|---|
dvxTypes.h |
All shared types: DisplayT, RectT, BlitOpsT, BevelStyleT, BitmapFontT, ColorSchemeT, WindowT, MenuT, ScrollbarT, CursorT, PopupStateT |
dvxVideo.h |
videoInit(), videoShutdown(), packColor(), setClipRect(), resetClipRect() |
dvxDraw.h |
All drawing functions: rectFill(), drawBevel(), drawText(), drawTextN(), drawTermRow(), etc. |
dvxComp.h |
Dirty list operations: dirtyListAdd(), dirtyListMerge(), flushRect(), rectIntersect() |
dvxWm.h |
Window management: wmCreateWindow(), wmDestroyWindow(), wmRaiseWindow(), menus, scrollbars, chrome |
dvxApp.h |
Application API: dvxInit(), dvxRun(), dvxUpdate(), dvxCreateWindow(), color schemes, wallpaper, image I/O |
dvxDialog.h |
Modal dialogs: dvxMessageBox(), dvxFileDialog() |
dvxPrefs.h |
INI preferences: prefsLoad(), prefsSave(), typed accessors |
dvxWidget.h |
Widget system public API: WidgetT, WidgetClassT, size tags, layout, API registry |
dvxWidgetPlugin.h |
Plugin API for widget DXE authors: tree ops, focus, scrollbar helpers, shared state |
dvxFont.h |
Embedded 8x14 and 8x16 bitmap font data (CP437) |
dvxCursor.h |
Mouse cursor AND/XOR mask data (arrow, resize H/V/diag, busy) |
dvxPalette.h |
Default 256-color VGA palette for 8-bit mode |
Platform Layer
| File | Description |
|---|---|
platform/dvxPlatform.h |
Platform abstraction API (video, input, spans, DXE, crash recovery) |
platform/dvxPlatformDos.c |
DJGPP/DPMI implementation (VESA VBE, INT 33h mouse, INT 16h keyboard, asm spans) |
The platform layer is compiled into dvx.exe (the loader), not into
libdvx.lib. Platform functions are exported to all DXE modules via
platformRegisterDxeExports().
Third-Party Libraries
| File | Description |
|---|---|
thirdparty/stb_image.h |
Image loading (implementation compiled into dvxImage.c) |
thirdparty/stb_image_write.h |
PNG writing (implementation compiled into dvxImageWrite.c) |
thirdparty/stb_ds.h |
Dynamic arrays/hash maps (implementation in loader, exported to all DXEs) |
WidgetT Structure
The WidgetT struct is generic -- no widget-specific fields or union:
typedef struct WidgetT {
int32_t type; // assigned by wgtRegisterClass()
const struct WidgetClassT *wclass; // vtable pointer
char name[32];
// Tree linkage
struct WidgetT *parent, *firstChild, *lastChild, *nextSibling;
WindowT *window;
// Geometry (relative to window content area)
int32_t x, y, w, h;
int32_t calcMinW, calcMinH; // computed minimum size
// Size hints (tagged: wgtPixels/wgtChars/wgtPercent, 0 = auto)
int32_t minW, minH, maxW, maxH;
int32_t prefW, prefH;
int32_t weight; // extra-space distribution (0 = fixed)
// Container properties
WidgetAlignE align;
int32_t spacing, padding; // tagged sizes
// Colors (0 = use color scheme defaults)
uint32_t fgColor, bgColor;
// State
bool visible, enabled, readOnly, focused;
char accelKey;
// User data and callbacks
void *userData;
void *data; // widget-private data (allocated by widget DXE)
const char *tooltip;
MenuT *contextMenu;
void (*onClick)(struct WidgetT *w);
void (*onDblClick)(struct WidgetT *w);
void (*onChange)(struct WidgetT *w);
void (*onFocus)(struct WidgetT *w);
void (*onBlur)(struct WidgetT *w);
} WidgetT;
WidgetClassT Vtable
Each widget type defines a static WidgetClassT with flags and function pointers. The vtable has 26 function slots plus a flags field:
| Slot | Signature | Purpose |
|---|---|---|
flags |
uint32_t |
Static properties (see Flags below) |
paint |
(w, d, ops, font, colors) |
Render the widget |
paintOverlay |
(w, d, ops, font, colors) |
Render overlay (dropdown popup) |
calcMinSize |
(w, font) |
Compute minimum size (bottom-up pass) |
layout |
(w, font) |
Position children (top-down pass) |
getLayoutMetrics |
(w, font, pad, gap, extraTop, borderW) |
Return padding/gap for box layout |
onMouse |
(w, root, vx, vy) |
Handle mouse click |
onKey |
(w, key, mod) |
Handle keyboard input |
onAccelActivate |
(w, root) |
Handle accelerator key match |
destroy |
(w) |
Free widget-private data |
onChildChanged |
(parent, child) |
Notification when a child changes |
getText |
(w) |
Return widget text |
setText |
(w, text) |
Set widget text |
clearSelection |
(w) |
Clear text/item selection |
dragSelect |
(w, root, vx, vy) |
Handle drag selection |
openPopup |
(w) |
Open dropdown popup |
closePopup |
(w) |
Close dropdown popup |
getPopupItemCount |
(w) |
Return number of popup items |
getPopupRect |
(w, font, contentH, popX, popY, popW, popH) |
Compute popup rectangle |
setPressed |
(w, pressed) |
Set button press visual state |
reorderDrop |
(w) |
Complete drag-reorder operation |
reorderUpdate |
(w, root, x, y) |
Update drag-reorder position |
getCursorShape |
(w, vx, vy) |
Return cursor ID for this position |
poll |
(w, win) |
Periodic polling (AnsiTerm comms) |
quickRepaint |
(w, outY, outH) |
Fast incremental repaint |
getTextFieldWidth |
(w) |
Text field width for scroll calc |
scrollDragUpdate |
(w, orient, dragOff, mouseX, mouseY) |
Scrollbar drag update |
WidgetClassT Flags
| Flag | Value | Description |
|---|---|---|
WCLASS_FOCUSABLE |
0x0001 | Can receive keyboard focus |
WCLASS_BOX_CONTAINER |
0x0002 | Uses VBox/HBox layout algorithm |
WCLASS_HORIZ_CONTAINER |
0x0004 | Lays out children horizontally |
WCLASS_PAINTS_CHILDREN |
0x0008 | Widget handles child rendering |
WCLASS_NO_HIT_RECURSE |
0x0010 | Hit testing stops here |
WCLASS_FOCUS_FORWARD |
0x0020 | Accel hit forwards focus to next focusable |
WCLASS_HAS_POPUP |
0x0040 | Has dropdown popup overlay |
WCLASS_SCROLLABLE |
0x0080 | Accepts mouse wheel events |
WCLASS_SCROLL_CONTAINER |
0x0100 | Scroll container (ScrollPane) |
WCLASS_NEEDS_POLL |
0x0200 | Needs periodic polling |
WCLASS_SWALLOWS_TAB |
0x0400 | Tab key goes to widget, not focus nav |
WCLASS_RELAYOUT_ON_SCROLL |
0x0800 | Full relayout on scrollbar drag |
WCLASS_PRESS_RELEASE |
0x1000 | Click = press+release (buttons) |
WCLASS_ACCEL_WHEN_HIDDEN |
0x2000 | Accel matching works when invisible |
Widget Registration
Each widget DXE exports wgtRegister(), called by the loader after
dlopen. A typical registration:
static int32_t sButtonType;
static const WidgetClassT sButtonClass = {
.flags = WCLASS_FOCUSABLE | WCLASS_PRESS_RELEASE,
.paint = buttonPaint,
.calcMinSize = buttonCalcMinSize,
.onMouse = buttonOnMouse,
.onKey = buttonOnKey,
.destroy = buttonDestroy,
.getText = buttonGetText,
.setText = buttonSetText,
.setPressed = buttonSetPressed,
.onAccelActivate = buttonAccelActivate,
};
static const ButtonApiT sApi = { .create = buttonCreate };
void wgtRegister(void) {
sButtonType = wgtRegisterClass(&sButtonClass);
wgtRegisterApi("button", &sApi);
}
Per-Widget API Registry
The monolithic WidgetApiT is gone. Each widget registers a small API
struct under a name via wgtRegisterApi(). Callers retrieve it via
wgtGetApi() and cast to the widget-specific type. Per-widget headers
(e.g. widgetButton.h) provide typed accessors and convenience macros:
// widgetButton.h
typedef struct {
WidgetT *(*create)(WidgetT *parent, const char *text);
} ButtonApiT;
static inline const ButtonApiT *dvxButtonApi(void) {
static const ButtonApiT *sApi;
if (!sApi) { sApi = (const ButtonApiT *)wgtGetApi("button"); }
return sApi;
}
#define wgtButton(parent, text) dvxButtonApi()->create(parent, text)
Tagged Size Values
Size hints encode both unit type and numeric value in a single int32_t:
| Macro | Encoding | Example |
|---|---|---|
wgtPixels(v) |
Bits 31:30 = 00 | w->minW = wgtPixels(200); |
wgtChars(v) |
Bits 31:30 = 01 | w->minW = wgtChars(40); |
wgtPercent(v) |
Bits 31:30 = 10 | w->minW = wgtPercent(50); |
0 |
-- | Auto (use computed minimum) |
Layout Algorithm
Two-pass flexbox-like layout:
- Bottom-up (
calcMinSize): Each widget computes its minimum size. Containers sum children along the main axis, max across the cross axis. - Top-down (
layout): Available space is allocated to children. Extra space beyond minimum is distributed proportionally to weights.weight=0means fixed size,weight=100is the default flexible weight.
Exported Symbols
libdvx.lib exports symbols matching these prefixes:
dvx*, wgt*, wm*, prefs*, rect*, draw*, pack*, text*, setClip*,
resetClip*, stbi*, dirtyList*, widget*, accelParse*, clipboard*,
multiClick*, sCursor*, sDbl*, sDebug*, sClosed*, sFocused*, sKey*,
sOpen*, sPressed*, sDrag*, sDrawing*, sResize*, sListView*,
sSplitter*, sTreeView*
Build
make # builds bin/libs/libdvx.lib + bin/libs/libdvx.dep
make clean # removes objects and library
Depends on: libtasks.lib (via libdvx.dep).