663 lines
20 KiB
Markdown
663 lines
20 KiB
Markdown
# DV/X GUI
|
|
|
|
A DESQview/X-style windowed GUI compositor for DOS, targeting DJGPP/DPMI with
|
|
VESA VBE 2.0+ linear framebuffer.
|
|
|
|
Motif-style beveled chrome, dirty-rectangle compositing, draggable and
|
|
resizable windows, dropdown menus, scrollbars, and a declarative widget/layout
|
|
system.
|
|
|
|
## Building
|
|
|
|
Requires the DJGPP cross-compiler (`i586-pc-msdosdjgpp-gcc`).
|
|
|
|
The GUI is built as a static library (`lib/libdvx.a`). The demo links
|
|
against it.
|
|
|
|
```
|
|
cd dvxdemo
|
|
make # builds lib/libdvx.a then bin/demo.exe
|
|
make clean # removes obj/ and bin/
|
|
```
|
|
|
|
Set `DJGPP_PREFIX` in the Makefile if your toolchain is installed somewhere
|
|
other than `~/djgpp/djgpp`.
|
|
|
|
## Architecture
|
|
|
|
The library is organized in five layers. Each layer is a `.h`/`.c` pair.
|
|
Application code only needs to include `dvxApp.h` (which pulls in the rest)
|
|
and optionally `dvxWidget.h`.
|
|
|
|
```
|
|
Layer 1 dvxVideo VESA init, LFB mapping, backbuffer, pixel format
|
|
Layer 2 dvxDraw Spans, rects, bevels, text, bitmaps (asm inner loops)
|
|
Layer 3 dvxComp Dirty rectangle list, merge, LFB flush
|
|
Layer 4 dvxWm Window stack, chrome, drag, resize, focus, menus, scrollbars
|
|
Layer 5 dvxApp Event loop, mouse/keyboard input, public API
|
|
dvxWidget Widget/layout system (optional, standalone)
|
|
```
|
|
|
|
Supporting files:
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `dvxTypes.h` | Shared type definitions used by all layers |
|
|
| `dvxFont.h` | Built-in 8x14 bitmap font glyph data |
|
|
| `dvxCursor.h` | Mouse cursor bitmask data (5 shapes) |
|
|
| `dvxPalette.h` | Default VGA palette for 8-bit mode |
|
|
| `dvxIcon.c` | stb_image implementation unit (BMP/PNG/JPEG/GIF) |
|
|
| `dvxImageWrite.c` | stb_image_write implementation unit (PNG export) |
|
|
| `thirdparty/stb_image.h` | Third-party single-header image loader |
|
|
| `thirdparty/stb_image_write.h` | Third-party single-header image writer |
|
|
|
|
## Quick start
|
|
|
|
```c
|
|
#include "dvxApp.h"
|
|
|
|
static void onPaint(WindowT *win, RectT *dirty) {
|
|
AppContextT *ctx = (AppContextT *)win->userData;
|
|
const BlitOpsT *ops = dvxGetBlitOps(ctx);
|
|
const DisplayT *d = dvxGetDisplay(ctx);
|
|
uint32_t blue = packColor(d, 0, 0, 200);
|
|
|
|
for (int32_t y = 0; y < win->contentH; y++) {
|
|
ops->spanFill(win->contentBuf + y * win->contentPitch,
|
|
blue, win->contentW);
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
AppContextT ctx;
|
|
|
|
if (dvxInit(&ctx, 1024, 768, 16) != 0) {
|
|
return 1;
|
|
}
|
|
|
|
WindowT *win = dvxCreateWindow(&ctx, "Hello", 100, 100, 300, 200, true);
|
|
win->userData = &ctx;
|
|
win->onPaint = onPaint;
|
|
|
|
RectT r = {0, 0, win->contentW, win->contentH};
|
|
win->onPaint(win, &r);
|
|
|
|
dvxRun(&ctx);
|
|
dvxShutdown(&ctx);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
## Quick start (widgets)
|
|
|
|
```c
|
|
#include "dvxApp.h"
|
|
#include "dvxWidget.h"
|
|
|
|
static void onButtonClick(WidgetT *w) {
|
|
WidgetT *root = w;
|
|
while (root->parent) root = root->parent;
|
|
|
|
WidgetT *lbl = wgtFind(root, "status");
|
|
if (lbl) {
|
|
wgtSetText(lbl, "Clicked!");
|
|
wgtInvalidate(lbl);
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
AppContextT ctx;
|
|
dvxInit(&ctx, 1024, 768, 16);
|
|
|
|
WindowT *win = dvxCreateWindow(&ctx, "Widgets", 100, 100, 260, 200, true);
|
|
win->userData = &ctx;
|
|
|
|
WidgetT *root = wgtInitWindow(&ctx, win);
|
|
|
|
WidgetT *lbl = wgtLabel(root, "Ready.");
|
|
strncpy(lbl->name, "status", MAX_WIDGET_NAME);
|
|
|
|
wgtHSeparator(root);
|
|
|
|
WidgetT *row = wgtHBox(root);
|
|
wgtLabel(row, "Name:");
|
|
wgtTextInput(row, 64);
|
|
|
|
WidgetT *btn = wgtButton(root, "Go");
|
|
btn->onClick = onButtonClick;
|
|
|
|
wgtInvalidate(root); // initial layout + paint
|
|
|
|
dvxRun(&ctx);
|
|
dvxShutdown(&ctx);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Application API (`dvxApp.h`)
|
|
|
|
### Lifecycle
|
|
|
|
```c
|
|
int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH,
|
|
int32_t preferredBpp);
|
|
```
|
|
Initialize VESA video, input, fonts, color scheme, and cursors. Finds a mode
|
|
matching the requested resolution and bit depth (8, 15, 16, or 32). Returns
|
|
0 on success, -1 on failure.
|
|
|
|
```c
|
|
void dvxRun(AppContextT *ctx);
|
|
```
|
|
Enter the main event loop. Handles mouse movement, button clicks, keyboard
|
|
input, window management, dirty-rectangle compositing, and LFB flush.
|
|
Returns when `dvxQuit()` is called or ESC is pressed.
|
|
|
|
```c
|
|
bool dvxUpdate(AppContextT *ctx);
|
|
```
|
|
Process one iteration of the event loop: poll input, dispatch events,
|
|
composite dirty regions, and flush. Returns `true` if the GUI is still
|
|
running, `false` when exit has been requested. Use this instead of
|
|
`dvxRun()` when embedding the GUI inside an existing main loop.
|
|
|
|
```c
|
|
void dvxShutdown(AppContextT *ctx);
|
|
```
|
|
Restore text mode, release LFB mapping, and free the backbuffer.
|
|
|
|
```c
|
|
void dvxQuit(AppContextT *ctx);
|
|
```
|
|
Request exit from the main loop. `dvxRun()` returns on the next iteration.
|
|
|
|
### Windows
|
|
|
|
```c
|
|
WindowT *dvxCreateWindow(AppContextT *ctx, const char *title,
|
|
int32_t x, int32_t y, int32_t w, int32_t h,
|
|
bool resizable);
|
|
```
|
|
Create a window at screen position (`x`, `y`) with outer dimensions `w` x `h`.
|
|
If `resizable` is true, the window gets resize handles and a maximize button.
|
|
The window is raised to the top and given focus. Returns NULL on failure.
|
|
|
|
After creation, set `win->userData` and install callbacks:
|
|
|
|
| Callback | Signature | When called |
|
|
|----------|-----------|-------------|
|
|
| `onPaint` | `void (WindowT *win, RectT *dirtyArea)` | Content needs redrawing |
|
|
| `onKey` | `void (WindowT *win, int32_t key, int32_t mod)` | Key press (focused window) |
|
|
| `onMouse` | `void (WindowT *win, int32_t x, int32_t y, int32_t buttons)` | Mouse event in content area |
|
|
| `onResize` | `void (WindowT *win, int32_t newW, int32_t newH)` | Window resized |
|
|
| `onClose` | `void (WindowT *win)` | Close button double-clicked |
|
|
| `onMenu` | `void (WindowT *win, int32_t menuId)` | Menu item selected |
|
|
| `onScroll` | `void (WindowT *win, ScrollbarOrientE orient, int32_t value)` | Scrollbar moved |
|
|
|
|
Mouse/key coordinates are relative to the content area. `buttons` is a
|
|
bitmask (bit 0 = left, bit 1 = right, bit 2 = middle).
|
|
|
|
```c
|
|
void dvxDestroyWindow(AppContextT *ctx, WindowT *win);
|
|
```
|
|
Remove a window from the stack and free its resources.
|
|
|
|
```c
|
|
void dvxSetTitle(AppContextT *ctx, WindowT *win, const char *title);
|
|
```
|
|
Change the title bar text.
|
|
|
|
```c
|
|
int32_t dvxSetWindowIcon(AppContextT *ctx, WindowT *win, const char *path);
|
|
```
|
|
Load a BMP, TGA, or PNG image and assign it as the window's minimized icon.
|
|
The image is converted to the display pixel format and scaled to 64x64.
|
|
Returns 0 on success.
|
|
|
|
### Invalidation
|
|
|
|
```c
|
|
void dvxInvalidateRect(AppContextT *ctx, WindowT *win,
|
|
int32_t x, int32_t y, int32_t w, int32_t h);
|
|
void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);
|
|
```
|
|
Mark a region (or the entire content area) as needing repaint. The
|
|
compositor flushes dirty rectangles to the LFB on the next frame.
|
|
|
|
### Accessors
|
|
|
|
```c
|
|
DisplayT *dvxGetDisplay(AppContextT *ctx);
|
|
const BlitOpsT *dvxGetBlitOps(const AppContextT *ctx);
|
|
const BitmapFontT *dvxGetFont(const AppContextT *ctx);
|
|
const ColorSchemeT *dvxGetColors(const AppContextT *ctx);
|
|
```
|
|
|
|
### Window properties
|
|
|
|
Set these directly on the `WindowT` struct after creation:
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `maxW` | `int32_t` | -1 | Maximum width when maximized (-1 = screen width) |
|
|
| `maxH` | `int32_t` | -1 | Maximum height when maximized (-1 = screen height) |
|
|
| `userData` | `void *` | NULL | Application data pointer, passed through to callbacks |
|
|
|
|
### Content buffer
|
|
|
|
Each window has a persistent content backbuffer:
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| `contentBuf` | Pixel data in display format |
|
|
| `contentPitch` | Bytes per scanline |
|
|
| `contentW` | Width in pixels |
|
|
| `contentH` | Height in pixels |
|
|
|
|
Paint callbacks write directly into `contentBuf`. The compositor copies
|
|
visible portions to the screen backbuffer, then flushes dirty rects to
|
|
the LFB.
|
|
|
|
---
|
|
|
|
## Menu bars
|
|
|
|
```c
|
|
MenuBarT *wmAddMenuBar(WindowT *win);
|
|
```
|
|
Add a menu bar to a window. Call `wmUpdateContentRect()` and
|
|
`wmReallocContentBuf()` after adding the menu bar (the menu bar reduces
|
|
the content area).
|
|
|
|
```c
|
|
MenuT *wmAddMenu(MenuBarT *bar, const char *label);
|
|
```
|
|
Add a top-level menu to the bar. Returns a `MenuT *` to populate with items.
|
|
|
|
```c
|
|
void wmAddMenuItem(MenuT *menu, const char *label, int32_t id);
|
|
void wmAddMenuSeparator(MenuT *menu);
|
|
```
|
|
Add items to a menu. `id` is an application-defined command passed to
|
|
`onMenu`. Up to 16 items per menu, 8 menus per bar.
|
|
|
|
---
|
|
|
|
## Scrollbars
|
|
|
|
```c
|
|
ScrollbarT *wmAddVScrollbar(WindowT *win, int32_t min, int32_t max,
|
|
int32_t pageSize);
|
|
ScrollbarT *wmAddHScrollbar(WindowT *win, int32_t min, int32_t max,
|
|
int32_t pageSize);
|
|
```
|
|
Add a scrollbar to a window. `pageSize` controls the thumb size relative to
|
|
the range. Call `wmUpdateContentRect()` and `wmReallocContentBuf()` afterward.
|
|
|
|
The `onScroll` callback fires when the user drags the thumb or clicks the
|
|
arrow buttons / trough.
|
|
|
|
Widget windows manage their own scrollbars automatically -- do not add them
|
|
manually.
|
|
|
|
---
|
|
|
|
## Video and drawing (`dvxVideo.h`, `dvxDraw.h`)
|
|
|
|
These are lower-level APIs. Application code typically only needs `packColor`.
|
|
|
|
```c
|
|
uint32_t packColor(const DisplayT *d, uint8_t r, uint8_t g, uint8_t b);
|
|
```
|
|
Pack an RGB triple into the display's pixel format.
|
|
|
|
```c
|
|
void rectFill(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
|
|
```
|
|
Fill a rectangle with a solid color (clipped to the display clip rect).
|
|
|
|
```c
|
|
void drawBevel(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, int32_t h,
|
|
const BevelStyleT *style);
|
|
```
|
|
Draw a beveled frame. `BevelStyleT` specifies highlight, shadow, face colors
|
|
and border width.
|
|
|
|
```c
|
|
void drawText(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font,
|
|
int32_t x, int32_t y, const char *text,
|
|
uint32_t fg, uint32_t bg, bool opaque);
|
|
int32_t drawChar(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font,
|
|
int32_t x, int32_t y, char ch,
|
|
uint32_t fg, uint32_t bg, bool opaque);
|
|
int32_t textWidth(const BitmapFontT *font, const char *text);
|
|
```
|
|
Draw text using the built-in 8-pixel-wide bitmap font. `opaque` controls
|
|
whether background pixels are drawn. `drawChar` returns the advance width.
|
|
|
|
```c
|
|
void drawHLine(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, uint32_t color);
|
|
void drawVLine(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t h, uint32_t color);
|
|
```
|
|
|
|
```c
|
|
void rectCopy(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t dstX, int32_t dstY,
|
|
const uint8_t *srcBuf, int32_t srcPitch,
|
|
int32_t srcX, int32_t srcY, int32_t w, int32_t h);
|
|
```
|
|
Blit from a source buffer to the backbuffer with clipping.
|
|
|
|
```c
|
|
void setClipRect(DisplayT *d, int32_t x, int32_t y, int32_t w, int32_t h);
|
|
void resetClipRect(DisplayT *d);
|
|
```
|
|
|
|
---
|
|
|
|
## Widget system (`dvxWidget.h`)
|
|
|
|
An optional declarative layout system inspired by Amiga MUI and PC GEOS.
|
|
Widgets are arranged in a tree of VBox/HBox containers. A two-pass layout
|
|
engine (measure minimum sizes, then distribute space) handles geometry
|
|
automatically. Scrollbars appear when the window is too small for the
|
|
content.
|
|
|
|
### Initialization
|
|
|
|
```c
|
|
WidgetT *wgtInitWindow(AppContextT *ctx, WindowT *win);
|
|
```
|
|
Attach the widget system to a window. Returns the root container (a VBox
|
|
filling the content area). Installs `onPaint`, `onMouse`, `onKey`, and
|
|
`onResize` handlers on the window. Build the widget tree by passing the
|
|
returned root (or its children) as `parent` to the widget creation
|
|
functions below.
|
|
|
|
Call `wgtInvalidate(root)` after the tree is fully built to trigger the
|
|
initial layout and paint.
|
|
|
|
### Containers
|
|
|
|
```c
|
|
WidgetT *wgtVBox(WidgetT *parent); // vertical stack
|
|
WidgetT *wgtHBox(WidgetT *parent); // horizontal stack
|
|
WidgetT *wgtFrame(WidgetT *parent, const char *title); // titled border
|
|
```
|
|
Containers hold child widgets and control layout direction. `wgtFrame`
|
|
draws a styled border with a title label and lays out children vertically.
|
|
|
|
Frame styles (set `w->as.frame.style` after creation):
|
|
|
|
| Style | Description |
|
|
|-------|-------------|
|
|
| `FrameInE` | Beveled inward / sunken (default) |
|
|
| `FrameOutE` | Beveled outward / raised |
|
|
| `FrameFlatE` | Solid color line; set `w->as.frame.color` (0 = windowShadow) |
|
|
|
|
The title text is vertically centered on the top border line.
|
|
|
|
Container properties (set directly on the returned `WidgetT *`):
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `align` | `WidgetAlignE` | `AlignStartE` | Main-axis alignment when no children have weight |
|
|
| `spacing` | `int32_t` | 0 (4px) | Tagged size: gap between children |
|
|
| `padding` | `int32_t` | 0 (4px) | Tagged size: internal padding |
|
|
|
|
Alignment values:
|
|
|
|
| Value | HBox meaning | VBox meaning |
|
|
|-------|-------------|-------------|
|
|
| `AlignStartE` | left | top |
|
|
| `AlignCenterE` | center | center |
|
|
| `AlignEndE` | right | bottom |
|
|
|
|
### Widgets
|
|
|
|
```c
|
|
WidgetT *wgtLabel(WidgetT *parent, const char *text);
|
|
```
|
|
Static text label. Sized to fit its text.
|
|
|
|
```c
|
|
WidgetT *wgtButton(WidgetT *parent, const char *text);
|
|
```
|
|
Beveled push button. Set `onClick` to handle clicks.
|
|
|
|
```c
|
|
WidgetT *wgtCheckbox(WidgetT *parent, const char *text);
|
|
```
|
|
Toggle checkbox. Read/write `w->as.checkbox.checked`. Set `onChange` to
|
|
be notified.
|
|
|
|
```c
|
|
WidgetT *wgtRadioGroup(WidgetT *parent);
|
|
WidgetT *wgtRadio(WidgetT *parent, const char *text);
|
|
```
|
|
Radio buttons. Create a group, then add options as children. The group
|
|
tracks the selected index in `w->as.radioGroup.selectedIdx`. Set
|
|
`onChange` on the group to be notified. Radio indices are auto-assigned.
|
|
|
|
```c
|
|
WidgetT *wgtTextInput(WidgetT *parent, int32_t maxLen);
|
|
```
|
|
Single-line text input field. Supports typing, cursor movement (arrows,
|
|
Home, End), backspace, and delete. `maxLen` is the buffer capacity.
|
|
Default weight is 100 (stretches to fill). Set `onChange` to be notified
|
|
on edits.
|
|
|
|
```c
|
|
WidgetT *wgtListBox(WidgetT *parent);
|
|
```
|
|
List box (basic -- set items with `wgtListBoxSetItems()`).
|
|
|
|
```c
|
|
WidgetT *wgtTextArea(WidgetT *parent, int32_t maxLen);
|
|
```
|
|
Multi-line text area (basic).
|
|
|
|
### Canvas
|
|
|
|
```c
|
|
WidgetT *wgtCanvas(WidgetT *parent, int32_t w, int32_t h);
|
|
```
|
|
Drawable bitmap canvas with a sunken bevel border. Supports freehand
|
|
drawing with Bresenham-interpolated strokes.
|
|
|
|
```c
|
|
void wgtCanvasClear(WidgetT *w, uint32_t color);
|
|
void wgtCanvasSetPenColor(WidgetT *w, uint32_t color);
|
|
void wgtCanvasSetPenSize(WidgetT *w, int32_t size);
|
|
int32_t wgtCanvasSave(WidgetT *w, const char *path);
|
|
int32_t wgtCanvasLoad(WidgetT *w, const char *path);
|
|
```
|
|
`wgtCanvasSave` writes the canvas to a PNG file (converting from display
|
|
pixel format to RGB). `wgtCanvasLoad` reads any image format supported by
|
|
stb_image and converts it to display pixel format.
|
|
|
|
### Spacing and dividers
|
|
|
|
```c
|
|
WidgetT *wgtSpacer(WidgetT *parent);
|
|
```
|
|
Invisible spacer. Default weight is 100 -- pushes siblings apart.
|
|
|
|
```c
|
|
WidgetT *wgtHSeparator(WidgetT *parent); // horizontal line
|
|
WidgetT *wgtVSeparator(WidgetT *parent); // vertical line
|
|
```
|
|
Visual divider lines (shadow + highlight, 2px).
|
|
|
|
### Size specifications
|
|
|
|
Size fields (`minW`, `minH`, `maxW`, `maxH`, `prefW`, `prefH`, `spacing`,
|
|
`padding`) accept tagged values created with:
|
|
|
|
```c
|
|
wgtPixels(120) // 120 pixels
|
|
wgtChars(15) // 15 character widths
|
|
wgtPercent(50) // 50% of parent
|
|
```
|
|
|
|
A raw `0` means auto (use the widget's natural/computed size).
|
|
|
|
### Weight
|
|
|
|
The `weight` field controls how extra space is distributed among siblings.
|
|
When a container is larger than its children's combined minimum size, the
|
|
surplus is divided proportionally by weight.
|
|
|
|
- `weight = 0` -- fixed size, does not stretch (default for most widgets)
|
|
- `weight = 100` -- normal stretch (default for spacers and text inputs)
|
|
- Relative values work: weights of 100, 200, 100 give a 1:2:1 split
|
|
|
|
When all children have weight 0, the container's `align` property
|
|
determines where children are placed within the extra space.
|
|
|
|
### Operations
|
|
|
|
```c
|
|
void wgtSetText(WidgetT *w, const char *text);
|
|
const char *wgtGetText(const WidgetT *w);
|
|
```
|
|
Get/set text for labels, buttons, checkboxes, radios, and text inputs.
|
|
|
|
```c
|
|
void wgtSetEnabled(WidgetT *w, bool enabled);
|
|
void wgtSetVisible(WidgetT *w, bool visible);
|
|
```
|
|
Disabled widgets are drawn grayed out and ignore input. Hidden widgets
|
|
are excluded from layout.
|
|
|
|
```c
|
|
void wgtInvalidate(WidgetT *w);
|
|
```
|
|
Trigger a full relayout and repaint of the widget tree. Call after
|
|
modifying widget properties, adding/removing widgets, or changing text.
|
|
|
|
```c
|
|
WidgetT *wgtFind(WidgetT *root, const char *name);
|
|
```
|
|
Search the subtree for a widget by name. Set `w->name` (up to 31 chars)
|
|
to make a widget findable.
|
|
|
|
```c
|
|
void wgtDestroy(WidgetT *w);
|
|
```
|
|
Remove a widget and all its children from the tree and free memory.
|
|
|
|
```c
|
|
void wgtSetDebugLayout(bool enabled);
|
|
```
|
|
When enabled, draws 1px neon-colored borders around all layout containers
|
|
so their bounds are visible. Each container gets a distinct color derived
|
|
from its pointer.
|
|
|
|
### List box operations
|
|
|
|
```c
|
|
void wgtListBoxSetItems(WidgetT *w, const char **items, int32_t count);
|
|
int32_t wgtListBoxGetSelected(const WidgetT *w);
|
|
void wgtListBoxSetSelected(WidgetT *w, int32_t idx);
|
|
```
|
|
|
|
---
|
|
|
|
## Types reference (`dvxTypes.h`)
|
|
|
|
### WindowT
|
|
|
|
Core window structure. Key fields:
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | `int32_t` | Unique window identifier |
|
|
| `x`, `y`, `w`, `h` | `int32_t` | Outer frame position and size |
|
|
| `contentX`, `contentY` | `int32_t` | Content area offset within frame |
|
|
| `contentW`, `contentH` | `int32_t` | Content area dimensions |
|
|
| `contentBuf` | `uint8_t *` | Pixel buffer (display format) |
|
|
| `contentPitch` | `int32_t` | Bytes per scanline in content buffer |
|
|
| `title` | `char[128]` | Title bar text |
|
|
| `visible` | `bool` | Window is shown |
|
|
| `focused` | `bool` | Window has input focus |
|
|
| `minimized` | `bool` | Window is minimized to icon |
|
|
| `maximized` | `bool` | Window is maximized |
|
|
| `resizable` | `bool` | Window has resize handles |
|
|
| `maxW`, `maxH` | `int32_t` | Max dimensions for maximize (-1 = screen) |
|
|
| `userData` | `void *` | Application data pointer |
|
|
|
|
### ColorSchemeT
|
|
|
|
All colors are pre-packed via `packColor()`:
|
|
|
|
| Field | Usage |
|
|
|-------|-------|
|
|
| `desktop` | Desktop background |
|
|
| `windowFace` | Window frame fill |
|
|
| `windowHighlight` | Bevel light edge |
|
|
| `windowShadow` | Bevel dark edge |
|
|
| `activeTitleBg/Fg` | Focused title bar |
|
|
| `inactiveTitleBg/Fg` | Unfocused title bar |
|
|
| `contentBg/Fg` | Window content area |
|
|
| `menuBg/Fg` | Menu bar and popups |
|
|
| `menuHighlightBg/Fg` | Highlighted menu item |
|
|
| `buttonFace` | Button interior |
|
|
| `scrollbarBg/Fg/Trough` | Scrollbar elements |
|
|
|
|
### BitmapFontT
|
|
|
|
Fixed-width bitmap font (8px wide, 14 or 16px tall). Glyphs are packed
|
|
1bpp, `charHeight` bytes per glyph, MSB-first.
|
|
|
|
### BevelStyleT
|
|
|
|
```c
|
|
typedef struct {
|
|
uint32_t highlight; // top/left edge color
|
|
uint32_t shadow; // bottom/right edge color
|
|
uint32_t face; // interior fill (0 = no fill)
|
|
int32_t width; // border thickness in pixels
|
|
} BevelStyleT;
|
|
```
|
|
|
|
---
|
|
|
|
## Window chrome
|
|
|
|
Windows use a Motif/GEOS-style frame:
|
|
|
|
- 4px beveled outer border with perpendicular groove breaks
|
|
- 20px title bar (dark charcoal background when focused)
|
|
- Close button on the left edge (requires double-click)
|
|
- Minimize button on the right edge (always present)
|
|
- Maximize button to the left of minimize (resizable windows only)
|
|
- Optional menu bar below the title bar (20px)
|
|
- Optional scrollbars along the right and bottom edges (16px)
|
|
|
|
Minimized windows appear as 64x64 beveled icons along the bottom of the
|
|
screen. If a window has an icon image set via `dvxSetWindowIcon()`, that
|
|
image is shown; otherwise a nearest-neighbor-scaled thumbnail of the
|
|
window's content buffer is used. Thumbnails are refreshed automatically
|
|
when the window's content changes, with updates staggered across frames
|
|
so only one icon redraws per interval. Double-click an icon to restore.
|
|
|
|
---
|
|
|
|
## Hardware requirements
|
|
|
|
- 486 or later CPU
|
|
- VESA VBE 2.0+ compatible video card with linear framebuffer support
|
|
- PS/2 mouse (or compatible mouse driver)
|
|
- DPMI host (CWSDPMI, Windows DOS box, DOSBox, 86Box)
|
|
|
|
Tested on 86Box with PCI video cards. DOSBox is a trusted reference
|
|
platform.
|